diff --git a/neo/doom3/game/Camera.cpp b/neo/doom3/game/Camera.cpp index 63651701..52c4901f 100644 --- a/neo/doom3/game/Camera.cpp +++ b/neo/doom3/game/Camera.cpp @@ -229,11 +229,13 @@ void idCameraView::GetViewParms( renderView_t *view ) { const idEventDef EV_Camera_Start( "start", NULL ); const idEventDef EV_Camera_Stop( "stop", NULL ); +const idEventDef EV_Camera_SetAnim( "setAnim", "s" ); CLASS_DECLARATION( idCamera, idCameraAnim ) EVENT( EV_Thread_SetCallback, idCameraAnim::Event_SetCallback ) EVENT( EV_Camera_Stop, idCameraAnim::Event_Stop ) EVENT( EV_Camera_Start, idCameraAnim::Event_Start ) + EVENT( EV_Camera_SetAnim, idCameraAnim::Event_SetAnim ) EVENT( EV_Activate, idCameraAnim::Event_Activate ) END_CLASS @@ -704,6 +706,25 @@ void idCameraAnim::Event_Stop( void ) { Stop(); } +/* +=============== +idCameraAnim::Event_SetAnim +=============== +*/ +void idCameraAnim::Event_SetAnim( const char *animName ) { + if ( !animName || !animName[ 0 ] ) { + gameLocal.Warning( "idCameraAnim::setAnim called with an empty anim on '%s'", name.c_str() ); + return; + } + + spawnArgs.Set( "anim", animName ); + LoadAnim(); + + if ( gameLocal.GetCamera() == this ) { + starttime = gameLocal.time; + } +} + /* ================ idCameraAnim::Event_SetCallback diff --git a/neo/doom3/game/Camera.h b/neo/doom3/game/Camera.h index 8bed080e..929d8d7a 100644 --- a/neo/doom3/game/Camera.h +++ b/neo/doom3/game/Camera.h @@ -125,6 +125,7 @@ private: void LoadAnim( void ); void Event_Start( void ); void Event_Stop( void ); + void Event_SetAnim( const char *animName ); void Event_SetCallback( void ); void Event_Activate( idEntity *activator ); }; diff --git a/neo/doom3/game/Entity.cpp b/neo/doom3/game/Entity.cpp index d9f04d7f..20148fdf 100644 --- a/neo/doom3/game/Entity.cpp +++ b/neo/doom3/game/Entity.cpp @@ -1497,6 +1497,7 @@ renderView_t *idEntity::GetRenderView( void ) { for( int i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) { renderView->shaderParms[ i ] = gameLocal.globalShaderParms[ i ]; } + renderView->globalFog = gameLocal.globalFogParms; renderView->globalMaterial = gameLocal.GetGlobalMaterial(); diff --git a/neo/doom3/game/Game_local.cpp b/neo/doom3/game/Game_local.cpp index 4f1f6e4c..86637081 100644 --- a/neo/doom3/game/Game_local.cpp +++ b/neo/doom3/game/Game_local.cpp @@ -181,6 +181,11 @@ void idGameLocal::Clear( void ) { sortTeamMasters = false; persistentLevelInfo.Clear(); memset( globalShaderParms, 0, sizeof( globalShaderParms ) ); + memset( &globalFogParms, 0, sizeof( globalFogParms ) ); + globalFogParms.mode = RENDER_GLOBAL_FOG_EXP; + globalFogParms.density = 1.0f; + globalFogParms.end = 1.0f; + globalFogParms.color.Set( 0.0f, 0.0f, 0.0f, 1.0f ); random.SetSeed( 0 ); world = NULL; frameCommandThread = NULL; @@ -500,6 +505,12 @@ void idGameLocal::SaveGame( idFile *f ) { for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) { savegame.WriteFloat( globalShaderParms[ i ] ); } + savegame.WriteBool( globalFogParms.enabled ); + savegame.WriteInt( globalFogParms.mode ); + savegame.WriteFloat( globalFogParms.density ); + savegame.WriteFloat( globalFogParms.start ); + savegame.WriteFloat( globalFogParms.end ); + savegame.WriteVec4( globalFogParms.color ); savegame.WriteInt( random.GetSeed() ); savegame.WriteObject( frameCommandThread ); @@ -888,6 +899,11 @@ void idGameLocal::LoadMap( const char *mapName, int randseed ) { globalMaterial = NULL; memset( globalShaderParms, 0, sizeof( globalShaderParms ) ); + memset( &globalFogParms, 0, sizeof( globalFogParms ) ); + globalFogParms.mode = RENDER_GLOBAL_FOG_EXP; + globalFogParms.density = 1.0f; + globalFogParms.end = 1.0f; + globalFogParms.color.Set( 0.0f, 0.0f, 0.0f, 1.0f ); // always leave room for the max number of clients, // even if they aren't all used, so numbers inside that @@ -1331,6 +1347,12 @@ bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWo for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) { savegame.ReadFloat( globalShaderParms[ i ] ); } + savegame.ReadBool( globalFogParms.enabled ); + savegame.ReadInt( (int &)globalFogParms.mode ); + savegame.ReadFloat( globalFogParms.density ); + savegame.ReadFloat( globalFogParms.start ); + savegame.ReadFloat( globalFogParms.end ); + savegame.ReadVec4( globalFogParms.color ); savegame.ReadInt( i ); random.SetSeed( i ); @@ -4434,4 +4456,4 @@ idEntity* idGameLocal::Spawn(const char* classname) dict.Set("classname", classname); gameLocal.SpawnEntityDef(dict, &ent); return ent; -} \ No newline at end of file +} diff --git a/neo/doom3/game/Game_local.h b/neo/doom3/game/Game_local.h index 178a36c3..b6ce6ea5 100644 --- a/neo/doom3/game/Game_local.h +++ b/neo/doom3/game/Game_local.h @@ -268,7 +268,8 @@ public: idDict persistentLevelInfo; // contains args that are kept around between levels // can be used to automatically effect every material in the world that references globalParms - float globalShaderParms[ MAX_GLOBAL_SHADER_PARMS ]; + float globalShaderParms[ MAX_GLOBAL_SHADER_PARMS ]; + renderGlobalFog_t globalFogParms; idRandom random; // random number generator used throughout the game diff --git a/neo/doom3/game/Game_network.cpp b/neo/doom3/game/Game_network.cpp index a2c7cb1a..c37dbcfb 100644 --- a/neo/doom3/game/Game_network.cpp +++ b/neo/doom3/game/Game_network.cpp @@ -531,6 +531,14 @@ void idGameLocal::WriteGameStateToSnapshot( idBitMsgDelta &msg ) const { for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) { msg.WriteFloat( globalShaderParms[i] ); } + msg.WriteBits( globalFogParms.enabled ? 1 : 0, 1 ); + msg.WriteBits( globalFogParms.mode, 2 ); + msg.WriteFloat( globalFogParms.density ); + msg.WriteFloat( globalFogParms.start ); + msg.WriteFloat( globalFogParms.end ); + for( i = 0; i < 4; i++ ) { + msg.WriteFloat( globalFogParms.color[i] ); + } mpGame.WriteToSnapshot( msg ); } @@ -546,6 +554,14 @@ void idGameLocal::ReadGameStateFromSnapshot( const idBitMsgDelta &msg ) { for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) { globalShaderParms[i] = msg.ReadFloat(); } + globalFogParms.enabled = msg.ReadBits( 1 ) != 0; + globalFogParms.mode = (renderGlobalFogMode_t)msg.ReadBits( 2 ); + globalFogParms.density = msg.ReadFloat(); + globalFogParms.start = msg.ReadFloat(); + globalFogParms.end = msg.ReadFloat(); + for( i = 0; i < 4; i++ ) { + globalFogParms.color[i] = msg.ReadFloat(); + } mpGame.ReadFromSnapshot( msg ); } @@ -1909,4 +1925,4 @@ void idGameLocal::AlertBots(idPlayer* player, idVec3 alert_position) bot->SetEnemy(player, player->GetOrigin()); } } -} \ No newline at end of file +} diff --git a/neo/doom3/game/Player.cpp b/neo/doom3/game/Player.cpp index 738c48ef..469a438e 100644 --- a/neo/doom3/game/Player.cpp +++ b/neo/doom3/game/Player.cpp @@ -7315,6 +7315,7 @@ void idPlayer::CalculateRenderView( void ) { for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) { renderView->shaderParms[ i ] = gameLocal.globalShaderParms[ i ]; } + renderView->globalFog = gameLocal.globalFogParms; renderView->globalMaterial = gameLocal.GetGlobalMaterial(); renderView->time = gameLocal.time; @@ -8556,4 +8557,4 @@ float idPlayer::GetViewHeight(void) } return newEyeOffset; -} \ No newline at end of file +} diff --git a/neo/doom3/game/Target.cpp b/neo/doom3/game/Target.cpp index 0e9fb510..5a8d8f3a 100644 --- a/neo/doom3/game/Target.cpp +++ b/neo/doom3/game/Target.cpp @@ -254,7 +254,7 @@ void idTarget_WaitForButton::Think( void ) { if ( thinkFlags & TH_THINK ) { player = gameLocal.GetLocalPlayer(); - if ( player && ( !player->oldButtons & BUTTON_ATTACK ) && ( player->usercmd.buttons & BUTTON_ATTACK ) ) { + if ( player && !( player->oldButtons & BUTTON_ATTACK ) && ( player->usercmd.buttons & BUTTON_ATTACK ) ) { player->usercmd.buttons &= ~BUTTON_ATTACK; BecomeInactive( TH_THINK ); ActivateTargets( player ); @@ -1762,4 +1762,3 @@ void idTarget_FadeSoundClass::Event_RestoreVolume() { // restore volume gameSoundWorld->FadeSoundClasses( 0, fadeDB, fadeTime ); } - diff --git a/neo/doom3/game/WorldSpawn.cpp b/neo/doom3/game/WorldSpawn.cpp index 96a6b98c..7b0afeb3 100644 --- a/neo/doom3/game/WorldSpawn.cpp +++ b/neo/doom3/game/WorldSpawn.cpp @@ -49,6 +49,41 @@ CLASS_DECLARATION( idEntity, idWorldspawn ) EVENT( EV_SafeRemove, idWorldspawn::Event_Remove ) END_CLASS +static renderGlobalFogMode_t ParseGlobalFogMode( const char *mode ) { + if ( !idStr::Icmp( mode, "linear" ) ) { + return RENDER_GLOBAL_FOG_LINEAR; + } + if ( !idStr::Icmp( mode, "exp2" ) ) { + return RENDER_GLOBAL_FOG_EXP2; + } + return RENDER_GLOBAL_FOG_EXP; +} + +static void SetWorldspawnGlobalFogParms( const idDict &spawnArgs ) { + idVec3 color; + idStr mode; + + memset( &gameLocal.globalFogParms, 0, sizeof( gameLocal.globalFogParms ) ); + gameLocal.globalFogParms.mode = RENDER_GLOBAL_FOG_EXP; + gameLocal.globalFogParms.density = 1.0f; + gameLocal.globalFogParms.end = 1.0f; + gameLocal.globalFogParms.color.Set( 0.0f, 0.0f, 0.0f, 1.0f ); + + gameLocal.globalFogParms.enabled = spawnArgs.GetBool( "globalFog", spawnArgs.GetString( "fog_global", "0" ) ); + + if ( spawnArgs.GetString( "globalFogMode", "", mode ) || spawnArgs.GetString( "fog_mode", "", mode ) ) { + gameLocal.globalFogParms.mode = ParseGlobalFogMode( mode.c_str() ); + } + + gameLocal.globalFogParms.density = spawnArgs.GetFloat( "globalFogDensity", spawnArgs.GetString( "fog_density", va( "%f", gameLocal.globalFogParms.density ) ) ); + gameLocal.globalFogParms.start = spawnArgs.GetFloat( "globalFogStart", spawnArgs.GetString( "fog_start", va( "%f", gameLocal.globalFogParms.start ) ) ); + gameLocal.globalFogParms.end = spawnArgs.GetFloat( "globalFogEnd", spawnArgs.GetString( "fog_end", va( "%f", gameLocal.globalFogParms.end ) ) ); + + if ( spawnArgs.GetVector( "globalFogColor", spawnArgs.GetString( "fog_color", "0 0 0" ), color ) ) { + gameLocal.globalFogParms.color.Set( color.x, color.y, color.z, spawnArgs.GetFloat( "globalFogAlpha", spawnArgs.GetString( "fog_alpha", "1" ) ) ); + } +} + /* ================ idWorldspawn::Spawn @@ -64,6 +99,7 @@ void idWorldspawn::Spawn( void ) { gameLocal.world = this; g_gravity.SetFloat( spawnArgs.GetFloat( "gravity", va( "%f", DEFAULT_GRAVITY ) ) ); + SetWorldspawnGlobalFogParms( spawnArgs ); // disable stamina on hell levels if ( spawnArgs.GetBool( "no_stamina" ) ) { @@ -115,6 +151,7 @@ void idWorldspawn::Restore( idRestoreGame *savefile ) { assert( gameLocal.world == this ); g_gravity.SetFloat( spawnArgs.GetFloat( "gravity", va( "%f", DEFAULT_GRAVITY ) ) ); + SetWorldspawnGlobalFogParms( spawnArgs ); // disable stamina on hell levels if ( spawnArgs.GetBool( "no_stamina" ) ) { diff --git a/neo/doom3/game/anim/Anim_Blend.cpp b/neo/doom3/game/anim/Anim_Blend.cpp index 3bc58efb..4d6a59bf 100644 --- a/neo/doom3/game/anim/Anim_Blend.cpp +++ b/neo/doom3/game/anim/Anim_Blend.cpp @@ -307,7 +307,8 @@ const char *idAnim::AddFrameCommand( const idDeclModelDef *modelDef, int framenu fc.type = FC_SCRIPTFUNCTION; fc.function = gameLocal.program.FindFunction( token ); if ( !fc.function ) { - return va( "Function '%s' not found", token.c_str() ); + gameLocal.Warning( "Ignoring frame command call to missing function '%s' on anim '%s'", token.c_str(), FullName() ); + return NULL; } } else if ( token == "object_call" ) { if( !src.ReadTokenOnLine( &token ) ) { diff --git a/neo/doom3/game/gamesys/GameTypeInfo.h b/neo/doom3/game/gamesys/GameTypeInfo.h index 3b41c5e6..3713c514 100644 --- a/neo/doom3/game/gamesys/GameTypeInfo.h +++ b/neo/doom3/game/gamesys/GameTypeInfo.h @@ -7,9 +7,9 @@ This file has been generated with the Type Info Generator v1.1 (c) 2004 id Software - 1182 constants - 132 enums - 578 classes/structs/unions + 1185 constants + 133 enums + 579 classes/structs/unions 38 templates 7 max inheritance level for 'idAI_Vagary' @@ -596,6 +596,9 @@ static constantInfo_t constantInfo[] = { { "const int", "SHADERPARM_SPRITE_HEIGHT", "9" }, { "const int", "SHADERPARM_PARTICLE_STOPTIME", "8" }, { "const int", "MAX_RENDERENTITY_GUI", "3" }, + { "int", "RENDER_GLOBAL_FOG_LINEAR", "0" }, + { "int", "RENDER_GLOBAL_FOG_EXP", "1" }, + { "int", "RENDER_GLOBAL_FOG_EXP2", "2" }, { "static const int", "NUM_PORTAL_ATTRIBUTES", "3" }, { "int", "PS_BLOCK_NONE", "0" }, { "int", "PS_BLOCK_VIEW", "1" }, @@ -1916,6 +1919,13 @@ static enumValueInfo_t dxrWorldId_t_typeInfo[] = { { NULL, 0 } }; +static enumValueInfo_t renderGlobalFogMode_t_typeInfo[] = { + { "RENDER_GLOBAL_FOG_LINEAR", 0 }, + { "RENDER_GLOBAL_FOG_EXP", 1 }, + { "RENDER_GLOBAL_FOG_EXP2", 2 }, + { NULL, 0 } +}; + static enumValueInfo_t portalConnection_t_typeInfo[] = { { "PS_BLOCK_NONE", 0 }, { "PS_BLOCK_VIEW", 1 }, @@ -1925,21 +1935,21 @@ static enumValueInfo_t portalConnection_t_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t idDeviceContext_enum_66_typeInfo[] = { +static enumValueInfo_t idDeviceContext_enum_67_typeInfo[] = { { "CURSOR_ARROW", 0 }, { "CURSOR_HAND", 1 }, { "CURSOR_COUNT", 2 }, { NULL, 0 } }; -static enumValueInfo_t idDeviceContext_enum_67_typeInfo[] = { +static enumValueInfo_t idDeviceContext_enum_68_typeInfo[] = { { "ALIGN_LEFT", 0 }, { "ALIGN_CENTER", 1 }, { "ALIGN_RIGHT", 2 }, { NULL, 0 } }; -static enumValueInfo_t idDeviceContext_enum_68_typeInfo[] = { +static enumValueInfo_t idDeviceContext_enum_69_typeInfo[] = { { "SCROLLBAR_HBACK", 0 }, { "SCROLLBAR_VBACK", 1 }, { "SCROLLBAR_THUMB", 2 }, @@ -1974,7 +1984,7 @@ static enumValueInfo_t escReply_t_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t enum_72_typeInfo[] = { +static enumValueInfo_t enum_73_typeInfo[] = { { "TEST_PARTICLE_MODEL", 0 }, { "TEST_PARTICLE_IMPACT", 1 }, { "TEST_PARTICLE_MUZZLE", 2 }, @@ -2036,7 +2046,7 @@ static enumValueInfo_t idVarDef_initialized_t_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t statement_s_enum_77_typeInfo[] = { +static enumValueInfo_t statement_s_enum_78_typeInfo[] = { { "FLAG_OBJECTCALL_IMPL_NOT_PARSED_YET", 1 }, { NULL, 0 } }; @@ -2102,7 +2112,7 @@ static enumValueInfo_t AFJointModType_t_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t enum_81_typeInfo[] = { +static enumValueInfo_t enum_82_typeInfo[] = { { "PATHTYPE_WALK", 0 }, { "PATHTYPE_WALKOFFLEDGE", 1 }, { "PATHTYPE_BARRIERJUMP", 2 }, @@ -2204,7 +2214,7 @@ static enumValueInfo_t idMultiplayerGame_vote_result_t_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t enum_90_typeInfo[] = { +static enumValueInfo_t enum_91_typeInfo[] = { { "GAME_RELIABLE_MESSAGE_INIT_DECL_REMAP", 0 }, { "GAME_RELIABLE_MESSAGE_REMAP_DECL", 1 }, { "GAME_RELIABLE_MESSAGE_SPAWN_PLAYER", 2 }, @@ -2327,7 +2337,7 @@ static enumValueInfo_t constraintType_t_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t enum_100_typeInfo[] = { +static enumValueInfo_t enum_101_typeInfo[] = { { "TH_ALL", -1 }, { "TH_THINK", 1 }, { "TH_PHYSICS", 2 }, @@ -2352,26 +2362,26 @@ static enumValueInfo_t signalNum_t_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t idEntity_enum_102_typeInfo[] = { +static enumValueInfo_t idEntity_enum_103_typeInfo[] = { { "EVENT_STARTSOUNDSHADER", 0 }, { "EVENT_STOPSOUNDSHADER", 1 }, { "EVENT_MAXEVENTS", 2 }, { NULL, 0 } }; -static enumValueInfo_t idAnimatedEntity_enum_103_typeInfo[] = { +static enumValueInfo_t idAnimatedEntity_enum_104_typeInfo[] = { { "EVENT_ADD_DAMAGE_EFFECT", 2 }, { "EVENT_MAXEVENTS", 3 }, { NULL, 0 } }; -static enumValueInfo_t idPlayerStart_enum_104_typeInfo[] = { +static enumValueInfo_t idPlayerStart_enum_105_typeInfo[] = { { "EVENT_TELEPORTPLAYER", 2 }, { "EVENT_MAXEVENTS", 3 }, { NULL, 0 } }; -static enumValueInfo_t idProjectile_enum_105_typeInfo[] = { +static enumValueInfo_t idProjectile_enum_106_typeInfo[] = { { "EVENT_DAMAGE_EFFECT", 2 }, { "EVENT_MAXEVENTS", 3 }, { NULL, 0 } @@ -2386,7 +2396,7 @@ static enumValueInfo_t idProjectile_projectileState_t_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t idWeapon_enum_107_typeInfo[] = { +static enumValueInfo_t idWeapon_enum_108_typeInfo[] = { { "EVENT_RELOAD", 2 }, { "EVENT_ENDRELOAD", 3 }, { "EVENT_CHANGESKIN", 4 }, @@ -2394,13 +2404,13 @@ static enumValueInfo_t idWeapon_enum_107_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t idLight_enum_108_typeInfo[] = { +static enumValueInfo_t idLight_enum_109_typeInfo[] = { { "EVENT_BECOMEBROKEN", 2 }, { "EVENT_MAXEVENTS", 3 }, { NULL, 0 } }; -static enumValueInfo_t idItem_enum_109_typeInfo[] = { +static enumValueInfo_t idItem_enum_110_typeInfo[] = { { "EVENT_PICKUP", 2 }, { "EVENT_RESPAWN", 3 }, { "EVENT_RESPAWNFX", 4 }, @@ -2415,7 +2425,7 @@ static enumValueInfo_t playerIconType_t_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t enum_111_typeInfo[] = { +static enumValueInfo_t enum_112_typeInfo[] = { { "BERSERK", 0 }, { "INVISIBILITY", 1 }, { "MEGAHEALTH", 2 }, @@ -2424,7 +2434,7 @@ static enumValueInfo_t enum_111_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t enum_112_typeInfo[] = { +static enumValueInfo_t enum_113_typeInfo[] = { { "SPEED", 0 }, { "PROJECTILE_DAMAGE", 1 }, { "MELEE_DAMAGE", 2 }, @@ -2432,7 +2442,7 @@ static enumValueInfo_t enum_112_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t enum_113_typeInfo[] = { +static enumValueInfo_t enum_114_typeInfo[] = { { "INFLUENCE_NONE", 0 }, { "INFLUENCE_LEVEL1", 1 }, { "INFLUENCE_LEVEL2", 2 }, @@ -2440,7 +2450,7 @@ static enumValueInfo_t enum_113_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t idPlayer_enum_114_typeInfo[] = { +static enumValueInfo_t idPlayer_enum_115_typeInfo[] = { { "EVENT_IMPULSE", 2 }, { "EVENT_EXIT_TELEPORTER", 3 }, { "EVENT_ABORT_TELEPORTER", 4 }, @@ -2497,7 +2507,7 @@ static enumValueInfo_t moverState_t_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t idExplodingBarrel_enum_120_typeInfo[] = { +static enumValueInfo_t idExplodingBarrel_enum_121_typeInfo[] = { { "EVENT_EXPLODE", 2 }, { "EVENT_MAXEVENTS", 3 }, { NULL, 0 } @@ -2511,7 +2521,7 @@ static enumValueInfo_t idExplodingBarrel_explode_state_t_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t idSecurityCamera_enum_122_typeInfo[] = { +static enumValueInfo_t idSecurityCamera_enum_123_typeInfo[] = { { "SCANNING", 0 }, { "LOSINGINTEREST", 1 }, { "ALERT", 2 }, @@ -2519,7 +2529,7 @@ static enumValueInfo_t idSecurityCamera_enum_122_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t idBrittleFracture_enum_123_typeInfo[] = { +static enumValueInfo_t idBrittleFracture_enum_124_typeInfo[] = { { "EVENT_PROJECT_DECAL", 2 }, { "EVENT_SHATTER", 3 }, { "EVENT_MAXEVENTS", 4 }, @@ -2586,7 +2596,7 @@ static enumValueInfo_t stopEvent_t_typeInfo[] = { { NULL, 0 } }; -static enumValueInfo_t enum_129_typeInfo[] = { +static enumValueInfo_t enum_130_typeInfo[] = { { "OP_RETURN", 0 }, { "OP_UINC_F", 1 }, { "OP_UINCP_F", 2 }, @@ -2797,23 +2807,24 @@ static enumTypeInfo_t enumTypeInfo[] = { { "dynamicModel_t", dynamicModel_t_typeInfo }, { "jointHandle_t", jointHandle_t_typeInfo }, { "dxrWorldId_t", dxrWorldId_t_typeInfo }, + { "renderGlobalFogMode_t", renderGlobalFogMode_t_typeInfo }, { "portalConnection_t", portalConnection_t_typeInfo }, - { "idDeviceContext::enum_66", idDeviceContext_enum_66_typeInfo }, { "idDeviceContext::enum_67", idDeviceContext_enum_67_typeInfo }, { "idDeviceContext::enum_68", idDeviceContext_enum_68_typeInfo }, + { "idDeviceContext::enum_69", idDeviceContext_enum_69_typeInfo }, { "contactType_t", contactType_t_typeInfo }, { "allowReply_t", allowReply_t_typeInfo }, { "escReply_t", escReply_t_typeInfo }, - { "enum_72", enum_72_typeInfo }, + { "enum_73", enum_73_typeInfo }, { "msgBoxType_t", msgBoxType_t_typeInfo }, { "stateResult_t", stateResult_t_typeInfo }, { "etype_t", etype_t_typeInfo }, { "idVarDef::initialized_t", idVarDef_initialized_t_typeInfo }, - { "statement_s::enum_77", statement_s_enum_77_typeInfo }, + { "statement_s::enum_78", statement_s_enum_78_typeInfo }, { "jointModTransform_t", jointModTransform_t_typeInfo }, { "frameCommandType_t", frameCommandType_t_typeInfo }, { "AFJointModType_t", AFJointModType_t_typeInfo }, - { "enum_81", enum_81_typeInfo }, + { "enum_82", enum_82_typeInfo }, { "pvsType_t", pvsType_t_typeInfo }, { "gameType_t", gameType_t_typeInfo }, { "playerVote_t", playerVote_t_typeInfo }, @@ -2822,7 +2833,7 @@ static enumTypeInfo_t enumTypeInfo[] = { { "idMultiplayerGame::msg_evt_t", idMultiplayerGame_msg_evt_t_typeInfo }, { "idMultiplayerGame::vote_flags_t", idMultiplayerGame_vote_flags_t_typeInfo }, { "idMultiplayerGame::vote_result_t", idMultiplayerGame_vote_result_t_typeInfo }, - { "enum_90", enum_90_typeInfo }, + { "enum_91", enum_91_typeInfo }, { "gameState_t", gameState_t_typeInfo }, { "idEventQueue::outOfOrderBehaviour_t", idEventQueue_outOfOrderBehaviour_t_typeInfo }, { "gameSoundChannel_t", gameSoundChannel_t_typeInfo }, @@ -2832,36 +2843,36 @@ static enumTypeInfo_t enumTypeInfo[] = { { "pmtype_t", pmtype_t_typeInfo }, { "waterLevel_t", waterLevel_t_typeInfo }, { "constraintType_t", constraintType_t_typeInfo }, - { "enum_100", enum_100_typeInfo }, + { "enum_101", enum_101_typeInfo }, { "signalNum_t", signalNum_t_typeInfo }, - { "idEntity::enum_102", idEntity_enum_102_typeInfo }, - { "idAnimatedEntity::enum_103", idAnimatedEntity_enum_103_typeInfo }, - { "idPlayerStart::enum_104", idPlayerStart_enum_104_typeInfo }, - { "idProjectile::enum_105", idProjectile_enum_105_typeInfo }, + { "idEntity::enum_103", idEntity_enum_103_typeInfo }, + { "idAnimatedEntity::enum_104", idAnimatedEntity_enum_104_typeInfo }, + { "idPlayerStart::enum_105", idPlayerStart_enum_105_typeInfo }, + { "idProjectile::enum_106", idProjectile_enum_106_typeInfo }, { "idProjectile::projectileState_t", idProjectile_projectileState_t_typeInfo }, - { "idWeapon::enum_107", idWeapon_enum_107_typeInfo }, - { "idLight::enum_108", idLight_enum_108_typeInfo }, - { "idItem::enum_109", idItem_enum_109_typeInfo }, + { "idWeapon::enum_108", idWeapon_enum_108_typeInfo }, + { "idLight::enum_109", idLight_enum_109_typeInfo }, + { "idItem::enum_110", idItem_enum_110_typeInfo }, { "playerIconType_t", playerIconType_t_typeInfo }, - { "enum_111", enum_111_typeInfo }, { "enum_112", enum_112_typeInfo }, { "enum_113", enum_113_typeInfo }, - { "idPlayer::enum_114", idPlayer_enum_114_typeInfo }, + { "enum_114", enum_114_typeInfo }, + { "idPlayer::enum_115", idPlayer_enum_115_typeInfo }, { "idMover::moveStage_t", idMover_moveStage_t_typeInfo }, { "idMover::moverCommand_t", idMover_moverCommand_t_typeInfo }, { "idMover::moverDir_t", idMover_moverDir_t_typeInfo }, { "idElevator::elevatorState_t", idElevator_elevatorState_t_typeInfo }, { "moverState_t", moverState_t_typeInfo }, - { "idExplodingBarrel::enum_120", idExplodingBarrel_enum_120_typeInfo }, + { "idExplodingBarrel::enum_121", idExplodingBarrel_enum_121_typeInfo }, { "idExplodingBarrel::explode_state_t", idExplodingBarrel_explode_state_t_typeInfo }, - { "idSecurityCamera::enum_122", idSecurityCamera_enum_122_typeInfo }, - { "idBrittleFracture::enum_123", idBrittleFracture_enum_123_typeInfo }, + { "idSecurityCamera::enum_123", idSecurityCamera_enum_123_typeInfo }, + { "idBrittleFracture::enum_124", idBrittleFracture_enum_124_typeInfo }, { "moveType_t", moveType_t_typeInfo }, { "moveCommand_t", moveCommand_t_typeInfo }, { "talkState_t", talkState_t_typeInfo }, { "moveStatus_t", moveStatus_t_typeInfo }, { "stopEvent_t", stopEvent_t_typeInfo }, - { "enum_129", enum_129_typeInfo }, + { "enum_130", enum_130_typeInfo }, { "botMoveFlags_t", botMoveFlags_t_typeInfo }, { "botChat_t", botChat_t_typeInfo }, { NULL, NULL } @@ -4410,6 +4421,16 @@ static classVariableInfo_t idRenderSystem_typeInfo[] = { { NULL, 0 } }; +static classVariableInfo_t renderGlobalFog_t_typeInfo[] = { + { "bool", "enabled", (intptr_t)(&((renderGlobalFog_t *)0)->enabled), sizeof( ((renderGlobalFog_t *)0)->enabled ) }, + { "renderGlobalFogMode_t", "mode", (intptr_t)(&((renderGlobalFog_t *)0)->mode), sizeof( ((renderGlobalFog_t *)0)->mode ) }, + { "float", "density", (intptr_t)(&((renderGlobalFog_t *)0)->density), sizeof( ((renderGlobalFog_t *)0)->density ) }, + { "float", "start", (intptr_t)(&((renderGlobalFog_t *)0)->start), sizeof( ((renderGlobalFog_t *)0)->start ) }, + { "float", "end", (intptr_t)(&((renderGlobalFog_t *)0)->end), sizeof( ((renderGlobalFog_t *)0)->end ) }, + { "idVec4", "color", (intptr_t)(&((renderGlobalFog_t *)0)->color), sizeof( ((renderGlobalFog_t *)0)->color ) }, + { NULL, 0 } +}; + static classVariableInfo_t renderEntity_t_typeInfo[] = { { "idRenderModel *", "hModel", (intptr_t)(&((renderEntity_t *)0)->hModel), sizeof( ((renderEntity_t *)0)->hModel ) }, { "int", "entityNum", (intptr_t)(&((renderEntity_t *)0)->entityNum), sizeof( ((renderEntity_t *)0)->entityNum ) }, @@ -4482,6 +4503,7 @@ static classVariableInfo_t renderView_t_typeInfo[] = { { "int", "time", (intptr_t)(&((renderView_t *)0)->time), sizeof( ((renderView_t *)0)->time ) }, { "float[12]", "shaderParms", (intptr_t)(&((renderView_t *)0)->shaderParms), sizeof( ((renderView_t *)0)->shaderParms ) }, { "const idMaterial *", "globalMaterial", (intptr_t)(&((renderView_t *)0)->globalMaterial), sizeof( ((renderView_t *)0)->globalMaterial ) }, + { "renderGlobalFog_t", "globalFog", (intptr_t)(&((renderView_t *)0)->globalFog), sizeof( ((renderView_t *)0)->globalFog ) }, { NULL, 0 } }; @@ -5141,11 +5163,11 @@ static classVariableInfo_t frameLookup_t_typeInfo[] = { { NULL, 0 } }; -static classVariableInfo_t class_282_class_282_typeInfo[] = { -// { "const idSoundShader *", "soundShader", (intptr_t)(&((class_282::class_282 *)0)->soundShader), sizeof( ((class_282::class_282 *)0)->soundShader ) }, -// { "const function_t *", "function", (intptr_t)(&((class_282::class_282 *)0)->function), sizeof( ((class_282::class_282 *)0)->function ) }, -// { "const idDeclSkin *", "skin", (intptr_t)(&((class_282::class_282 *)0)->skin), sizeof( ((class_282::class_282 *)0)->skin ) }, -// { "int", "index", (intptr_t)(&((class_282::class_282 *)0)->index), sizeof( ((class_282::class_282 *)0)->index ) }, +static classVariableInfo_t class_283_class_283_typeInfo[] = { +// { "const idSoundShader *", "soundShader", (intptr_t)(&((class_283::class_283 *)0)->soundShader), sizeof( ((class_283::class_283 *)0)->soundShader ) }, +// { "const function_t *", "function", (intptr_t)(&((class_283::class_283 *)0)->function), sizeof( ((class_283::class_283 *)0)->function ) }, +// { "const idDeclSkin *", "skin", (intptr_t)(&((class_283::class_283 *)0)->skin), sizeof( ((class_283::class_283 *)0)->skin ) }, +// { "int", "index", (intptr_t)(&((class_283::class_283 *)0)->index), sizeof( ((class_283::class_283 *)0)->index ) }, { NULL, 0 } }; @@ -5509,6 +5531,7 @@ static classVariableInfo_t idGameLocal_typeInfo[] = { { "bool", "sortTeamMasters", (intptr_t)(&((idGameLocal *)0)->sortTeamMasters), sizeof( ((idGameLocal *)0)->sortTeamMasters ) }, { "idDict", "persistentLevelInfo", (intptr_t)(&((idGameLocal *)0)->persistentLevelInfo), sizeof( ((idGameLocal *)0)->persistentLevelInfo ) }, { "float[12]", "globalShaderParms", (intptr_t)(&((idGameLocal *)0)->globalShaderParms), sizeof( ((idGameLocal *)0)->globalShaderParms ) }, + { "renderGlobalFog_t", "globalFogParms", (intptr_t)(&((idGameLocal *)0)->globalFogParms), sizeof( ((idGameLocal *)0)->globalFogParms ) }, { "idRandom", "random", (intptr_t)(&((idGameLocal *)0)->random), sizeof( ((idGameLocal *)0)->random ) }, { "idProgram", "program", (intptr_t)(&((idGameLocal *)0)->program), sizeof( ((idGameLocal *)0)->program ) }, { "idThread *", "frameCommandThread", (intptr_t)(&((idGameLocal *)0)->frameCommandThread), sizeof( ((idGameLocal *)0)->frameCommandThread ) }, @@ -8708,6 +8731,7 @@ static classTypeInfo_t classTypeInfo[] = { { "fontInfo_t", "", sizeof(fontInfo_t), fontInfo_t_typeInfo }, { "fontInfoEx_t", "", sizeof(fontInfoEx_t), fontInfoEx_t_typeInfo }, { "idRenderSystem", "", sizeof(idRenderSystem), idRenderSystem_typeInfo }, + { "renderGlobalFog_t", "", sizeof(renderGlobalFog_t), renderGlobalFog_t_typeInfo }, { "renderEntity_t", "", sizeof(renderEntity_t), renderEntity_t_typeInfo }, { "renderLight_t", "", sizeof(renderLight_t), renderLight_t_typeInfo }, { "renderView_t", "", sizeof(renderView_t), renderView_t_typeInfo }, @@ -8787,7 +8811,7 @@ static classTypeInfo_t classTypeInfo[] = { { "jointAnimInfo_t", "", sizeof(jointAnimInfo_t), jointAnimInfo_t_typeInfo }, { "jointMod_t", "", sizeof(jointMod_t), jointMod_t_typeInfo }, { "frameLookup_t", "", sizeof(frameLookup_t), frameLookup_t_typeInfo }, -// { "class_282::class_282", "", sizeof(class_282::class_282), class_282_class_282_typeInfo }, +// { "class_283::class_283", "", sizeof(class_283::class_283), class_283_class_283_typeInfo }, { "frameCommand_t", "", sizeof(frameCommand_t), frameCommand_t_typeInfo }, { "animFlags_t", "", sizeof(animFlags_t), animFlags_t_typeInfo }, { "idModelExport", "", sizeof(idModelExport), idModelExport_typeInfo }, diff --git a/neo/doom3/game/gamesys/SaveGame.cpp b/neo/doom3/game/gamesys/SaveGame.cpp index 7df52578..37ca51b7 100644 --- a/neo/doom3/game/gamesys/SaveGame.cpp +++ b/neo/doom3/game/gamesys/SaveGame.cpp @@ -638,6 +638,13 @@ void idSaveGame::WriteRenderView( const renderView_t &view ) { for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) { WriteFloat( view.shaderParms[ i ] ); } + + WriteBool( view.globalFog.enabled ); + WriteInt( view.globalFog.mode ); + WriteFloat( view.globalFog.density ); + WriteFloat( view.globalFog.start ); + WriteFloat( view.globalFog.end ); + WriteVec4( view.globalFog.color ); } /* @@ -1409,6 +1416,13 @@ void idRestoreGame::ReadRenderView( renderView_t &view ) { for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) { ReadFloat( view.shaderParms[ i ] ); } + + ReadBool( view.globalFog.enabled ); + ReadInt( (int &)view.globalFog.mode ); + ReadFloat( view.globalFog.density ); + ReadFloat( view.globalFog.start ); + ReadFloat( view.globalFog.end ); + ReadVec4( view.globalFog.color ); } /* diff --git a/neo/engine/doomdll.vcxproj.user b/neo/engine/doomdll.vcxproj.user index 41ce83ab..a02f32d6 100644 --- a/neo/engine/doomdll.vcxproj.user +++ b/neo/engine/doomdll.vcxproj.user @@ -17,7 +17,7 @@ WindowsLocalDebugger +set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 +set fs_game e3 D:\projects\Doom3 - +set r_fullscreen0 +set r_mode 9|+set r_fullscreen 0 +set r_mode 9|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 |+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 +set fs_game e3| + +set r_fullscreen 0 +set r_mode 9|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 |+set r_fullscreen 1 +set r_mode 9 +set sv_pure 0 +set fs_game e3|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 +set fs_game e3| D:\projects\Doom3\Quake4.exe diff --git a/neo/engine/opengl/gl_d3d12arb.cpp b/neo/engine/opengl/gl_d3d12arb.cpp index fba28ae0..516b0b1e 100644 --- a/neo/engine/opengl/gl_d3d12arb.cpp +++ b/neo/engine/opengl/gl_d3d12arb.cpp @@ -1114,7 +1114,7 @@ cbuffer DrawCB : register(b0) float gFogEnd; float gPointSize; float gMaterialType; - float gFogPad2; + float gAlphaFunc; float4 gFogColor; @@ -1123,17 +1123,61 @@ cbuffer DrawCB : register(b0) float2 gJitterPixels; float2 gPrevJitterPixels; float4 gMotionPad; + float4 gMaterialMapPad; + float4 gTexComb0RGB; + float4 gTexComb0Alpha; + float4 gTexComb0Operand; + float4 gTexEnvColor0; + float4 gTexComb1RGB; + float4 gTexComb1Alpha; + float4 gTexComb1Operand; + float4 gTexEnvColor1; + float4 gCameraPomPad; + float4 gNeuralPomPad; float4 gARBEnv[128]; float4 gARBLocalVP[128]; float4 gARBLocalFP[128]; }; +#define gCameraWorldPos gCameraPomPad.xyz +#define gCameraPomValid gCameraPomPad.w + float3 QD3D12ARB_NormalizeSafe(float3 v) { return v * rsqrt(max(dot(v, v), 1e-20)); } +float QD3D12ARB_ComputeFogFactor(float fogCoord) +{ + if (gFogEnabled < 0.5) + return 1.0; + + float f; + if (gFogMode < 0.5) + { + float denom = max(gFogEnd - gFogStart, 0.00001); + f = (gFogEnd - fogCoord) / denom; + } + else if (gFogMode < 1.5) + { + f = exp(-gFogDensity * fogCoord); + } + else + { + float d = gFogDensity * fogCoord; + f = exp(-(d * d)); + } + return saturate(f); +} + +float4 QD3D12ARB_ApplyFog(float4 color, float fogCoord) +{ + float fogFactor = QD3D12ARB_ComputeFogFactor(fogCoord); + color.rgb = lerp(gFogColor.rgb, color.rgb, fogFactor); + return color; +} + )HLSL"; } @@ -1172,6 +1216,7 @@ VSOut VSMain(VSIn i) { VSOut o = (VSOut)0; o.pos = mul(gMVP, float4(i.pos, 1.0)); + float4 worldPos = mul(gModelMatrix, float4(i.pos, 1.0)); o.tc0 = float4(i.uv0, 0.0, 1.0); o.tc1 = float4(i.uv1, 0.0, 1.0); o.tc2 = float4(0.0, 0.0, 0.0, 1.0); @@ -1181,7 +1226,9 @@ VSOut VSMain(VSIn i) o.tc6 = float4(0.0, 0.0, 0.0, 1.0); o.tc7 = float4(0.0, 0.0, 0.0, 1.0); o.col = i.col; - o.fog = float4(0.0, 0.0, 0.0, 0.0); + o.fog = float4((gCameraPomValid > 0.5) + ? length(worldPos.xyz - gCameraWorldPos) + : abs(o.pos.z / max(abs(o.pos.w), 0.00001)), 0.0, 0.0, 1.0); float4 vertex_position = float4(i.pos, 1.0); float4 vertex_color = i.col; @@ -1251,7 +1298,7 @@ float4 PSMain(PSIn i) : SV_Target0 for (const std::string& d : m_tempDecls) ss << d; for (const std::string& d : m_paramDecls) ss << d; for (const std::string& i : m_instructions) ss << i; - ss << " return result_color;\n}\n"; + ss << " return QD3D12ARB_ApplyFog(result_color, i.fog.x);\n}\n"; return ss.str(); } }; @@ -1749,4 +1796,4 @@ GLboolean APIENTRY glIsProgramARB(GLuint program) return (g_vertexPrograms.find(program) != g_vertexPrograms.end() || g_fragmentPrograms.find(program) != g_fragmentPrograms.end()) ? GL_TRUE : GL_FALSE; -} \ No newline at end of file +} diff --git a/neo/engine/opengl/gl_d3d12shim.cpp b/neo/engine/opengl/gl_d3d12shim.cpp index 8ecb92a1..86b8a442 100644 --- a/neo/engine/opengl/gl_d3d12shim.cpp +++ b/neo/engine/opengl/gl_d3d12shim.cpp @@ -455,9 +455,9 @@ static const UINT QD3D12_UploadBufferSize = 128 * 1024 * 1024; // MSAA has been removed from the G-buffer path. Temporal AA now owns edge cleanup // after lighting, so all scene/deferred render targets remain single-sample. static const UINT QD3D12_RequestedGBufferSampleCount = 1; -static constexpr UINT QD3D12_PostSrvCount = 9; +static constexpr UINT QD3D12_PostSrvCount = 11; static constexpr UINT QD3D12_PostRootConstants = QD3D12_PostSrvCount; -static constexpr UINT QD3D12_PostConstantDwords = 8; +static constexpr UINT QD3D12_PostConstantDwords = 24; static constexpr UINT QD3D12_ToneMapTileDim = 64; enum QD3D12RTVSlotGroup @@ -834,6 +834,12 @@ struct BatchKey float tex1IsLightmap = 0.0f; float texEnvMode0 = 0.0f; float texEnvMode1 = 0.0f; + float fogEnabled = 0.0f; + float fogMode = 1.0f; + float fogDensity = 1.0f; + float fogStart = 0.0f; + float fogEnd = 1.0f; + float fogColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; GLenum blendSrc = GL_ONE; GLenum blendDst = GL_ZERO; @@ -913,6 +919,12 @@ static bool BatchKeyEquals(const BatchKey& a, const BatchKey& b) a.tex1IsLightmap == b.tex1IsLightmap && a.texEnvMode0 == b.texEnvMode0 && a.texEnvMode1 == b.texEnvMode1 && + a.fogEnabled == b.fogEnabled && + a.fogMode == b.fogMode && + a.fogDensity == b.fogDensity && + a.fogStart == b.fogStart && + a.fogEnd == b.fogEnd && + memcmp(a.fogColor, b.fogColor, sizeof(a.fogColor)) == 0 && a.colorWriteMask == b.colorWriteMask && a.cullFaceEnabled == b.cullFaceEnabled && a.cullMode == b.cullMode && @@ -1262,6 +1274,14 @@ struct GLState bool sceneResolvedThisFrame = false; bool gbufferResolvedThisFrame = false; bool raytracedLightingReadyThisFrame = false; + bool sceneFogValidThisFrame = false; + float sceneFogMode = 1.0f; + float sceneFogDensity = 1.0f; + float sceneFogStart = 0.0f; + float sceneFogEnd = 1.0f; + float sceneFogColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + float sceneFogCameraWorldPos[3] = { 0.0f, 0.0f, 0.0f }; + float sceneFogCameraValid = 0.0f; float upscalerSharpness = 1.0f; float toneMapBrightness = 1.0f; @@ -3606,7 +3626,9 @@ VSOut VSMain(VSIn i) o.prevClip = prevClip; o.objPos = i.pos; o.objNormal = i.normal; - o.fogCoord = abs(currClip.z / max(abs(currClip.w), 0.00001)); + o.fogCoord = (gCameraPomValid > 0.5) + ? length(worldPos.xyz - gCameraWorldPos) + : abs(currClip.z / max(abs(currClip.w), 0.00001)); o.uv0 = i.uv0; o.uv1 = i.uv1; o.col = i.col; @@ -3838,7 +3860,9 @@ VSOut DSMain(HSConstOut tessFactors, float3 bary : SV_DomainLocation, const Outp o.prevClip = prevClip; o.objPos = displacedObjPos; o.objNormal = objNormal; - o.fogCoord = abs(currClip.z / max(abs(currClip.w), 0.00001)); + o.fogCoord = (gCameraPomValid > 0.5) + ? length(worldPos.xyz - gCameraWorldPos) + : abs(currClip.z / max(abs(currClip.w), 0.00001)); o.uv0 = i.uv0; o.uv1 = i.uv1; o.col = i.col; @@ -3930,14 +3954,22 @@ Texture2DMS gEmissiveMS : register(t5); Texture2DMS gSpecularMS : register(t6); Texture2D gTaaHistory : register(t7); Texture2D gTaaVelocity : register(t8); +Texture2D gFogPosition : register(t9); +Texture2D gFogDepth : register(t10); SamplerState gSamp0 : register(s0); cbuffer PostCB : register(b0) { // gPostParams0: x = sharpen strength, y = history weight, z = TAA reset flag. // gPostParams1: x = tone-map exposure, y = white-point scale, z = display brightness. + // gPostParams2: x = fog enabled, y = fog mode, z = fog density, w = fog start. + // gPostParams3: x = fog end, y = fog camera valid. float4 gPostParams0; float4 gPostParams1; + float4 gPostParams2; + float4 gPostParams3; + float4 gPostFogColor; + float4 gPostFogCameraWorldPos; }; #define gPostSharpness gPostParams0.x @@ -3946,6 +3978,12 @@ cbuffer PostCB : register(b0) #define gToneMapExposure gPostParams1.x #define gToneMapWhiteScale gPostParams1.y #define gToneMapBrightness gPostParams1.z +#define gPostFogEnabled gPostParams2.x +#define gPostFogMode gPostParams2.y +#define gPostFogDensity gPostParams2.z +#define gPostFogStart gPostParams2.w +#define gPostFogEnd gPostParams3.x +#define gPostFogCameraValid gPostParams3.y #define QD3D12_TONEMAP_TILE_DIM 64u struct VSOut @@ -3967,9 +4005,49 @@ VSOut VSMain(uint vid : SV_VertexID) return o; } +float QD3D12_PostFogFactor(float fogCoord) +{ + if (gPostFogEnabled < 0.5) + return 1.0; + + float f; + if (gPostFogMode < 0.5) + { + float denom = max(gPostFogEnd - gPostFogStart, 0.00001); + f = (gPostFogEnd - fogCoord) / denom; + } + else if (gPostFogMode < 1.5) + { + f = exp(-gPostFogDensity * fogCoord); + } + else + { + float d = gPostFogDensity * fogCoord; + f = exp(-(d * d)); + } + return saturate(f); +} + +float4 QD3D12_ApplyPostFog(float4 color, float2 uv) +{ + if (gPostFogEnabled < 0.5 || gPostFogCameraValid < 0.5) + return color; + + float sceneDepth = gFogDepth.SampleLevel(gSamp0, uv, 0.0); + if (sceneDepth >= 0.99999) + return color; + + float3 worldPos = gFogPosition.SampleLevel(gSamp0, uv, 0.0).xyz; + float fogCoord = length(worldPos - gPostFogCameraWorldPos.xyz); + float fogFactor = QD3D12_PostFogFactor(fogCoord); + float3 fogged = lerp(gPostFogColor.rgb, color.rgb, fogFactor); + color.rgb = lerp(color.rgb, fogged, saturate(gPostFogColor.a)); + return color; +} + float4 PSCopy(VSOut i) : SV_Target0 { - return gTex0.Sample(gSamp0, i.uv); + return QD3D12_ApplyPostFog(gTex0.Sample(gSamp0, i.uv), i.uv); } float4 PSSharpen(VSOut i) : SV_Target0 @@ -3992,7 +4070,7 @@ float4 PSSharpen(VSOut i) : SV_Target0 // Sharpen strictly after temporal reconstruction. Keep it conservative so // the TAA resolve is not undone by ringing on high-contrast UI/geometry edges. float3 sharp = center.rgb + (center.rgb - blur) * amount; - return float4(saturate(sharp), center.a); + return QD3D12_ApplyPostFog(float4(saturate(sharp), center.a), i.uv); } @@ -4108,7 +4186,7 @@ float4 PSToneMap(VSOut i) : SV_Target0 // UNORM, not sRGB formats, and the legacy renderer already authored/displayed // color in that space. A gamma conversion here is what made the prior patch // look blown out. - return float4(mapped, saturate(center.a)); + return QD3D12_ApplyPostFog(float4(mapped, saturate(center.a)), i.uv); } float4 PSTAA(VSOut i) : SV_Target0 @@ -4848,6 +4926,21 @@ static BatchKey BuildCurrentBatchKey(GLenum originalMode, const TextureResource* key.tex1IsLightmap = useTex1 ? 1.0f : 0.0f; key.texEnvMode0 = MapTexEnvMode(g_gl.texEnvMode[0]); key.texEnvMode1 = MapTexEnvMode(g_gl.texEnvMode[1]); + key.fogEnabled = g_gl.fog ? 1.0f : 0.0f; + switch (g_gl.fogMode) + { + case GL_LINEAR: key.fogMode = 0.0f; break; + case GL_EXP: key.fogMode = 1.0f; break; + case GL_EXP2: key.fogMode = 2.0f; break; + default: key.fogMode = 1.0f; break; + } + key.fogDensity = g_gl.fogDensity; + key.fogStart = g_gl.fogStart; + key.fogEnd = g_gl.fogEnd; + key.fogColor[0] = g_gl.fogColor[0]; + key.fogColor[1] = g_gl.fogColor[1]; + key.fogColor[2] = g_gl.fogColor[2]; + key.fogColor[3] = g_gl.fogColor[3]; QD3D12_FillTexCombineKey(key, 0); QD3D12_FillTexCombineKey(key, 1); key.colorWriteMask = QD3D12_CurrentColorWriteMask(); @@ -6320,32 +6413,60 @@ static void QD3D12_SetPostConstants( float taaReset, float toneMapExposure = 1.0f, float toneMapWhiteScale = 1.0f, - float toneMapBrightness = 1.0f) + float toneMapBrightness = 1.0f, + bool applySceneFog = false) { if (!cl) return; - float constants[QD3D12_PostConstantDwords] = + float constants[QD3D12_PostConstantDwords] = {}; + constants[0] = sharpness; + constants[1] = taaHistoryWeight; + constants[2] = taaReset; + constants[4] = toneMapExposure; + constants[5] = toneMapWhiteScale; + constants[6] = toneMapBrightness; + if (applySceneFog && g_gl.sceneFogValidThisFrame) { - sharpness, - taaHistoryWeight, - taaReset, - 0.0f, - toneMapExposure, - toneMapWhiteScale, - toneMapBrightness, - 0.0f - }; + constants[8] = 1.0f; + constants[9] = g_gl.sceneFogMode; + constants[10] = g_gl.sceneFogDensity; + constants[11] = g_gl.sceneFogStart; + constants[12] = g_gl.sceneFogEnd; + constants[13] = g_gl.sceneFogCameraValid; + constants[16] = g_gl.sceneFogColor[0]; + constants[17] = g_gl.sceneFogColor[1]; + constants[18] = g_gl.sceneFogColor[2]; + constants[19] = g_gl.sceneFogColor[3]; + constants[20] = g_gl.sceneFogCameraWorldPos[0]; + constants[21] = g_gl.sceneFogCameraWorldPos[1]; + constants[22] = g_gl.sceneFogCameraWorldPos[2]; + } cl->SetGraphicsRoot32BitConstants(QD3D12_PostRootConstants, QD3D12_PostConstantDwords, constants, 0); } +static void QD3D12_BindPostFogResources(ID3D12GraphicsCommandList* cl, QD3D12Window& w, bool applySceneFog) +{ + if (!cl || !applySceneFog || !g_gl.sceneFogValidThisFrame) + return; + if (!w.positionBuffers[w.frameIndex] || !w.depthBuffer) + return; + if (w.positionSrvIndex[w.frameIndex] == UINT_MAX || w.depthSrvIndex == UINT_MAX) + return; + + cl->SetGraphicsRootDescriptorTable(9, w.positionSrvGpu[w.frameIndex]); + cl->SetGraphicsRootDescriptorTable(10, w.depthSrvGpu); +} + static void QD3D12_PostFullscreenPass(ID3D12GraphicsCommandList* cl, ID3D12PipelineState* pso, D3D12_GPU_DESCRIPTOR_HANDLE inputSrv, D3D12_CPU_DESCRIPTOR_HANDLE outputRtv, const D3D12_VIEWPORT& viewport, const D3D12_RECT& scissor, - float sharpnessOverride = -1.0f) + float sharpnessOverride = -1.0f, + bool applySceneFog = false, + QD3D12Window* fogWindow = nullptr) { if (!cl || !pso) return; @@ -6354,13 +6475,15 @@ static void QD3D12_PostFullscreenPass(ID3D12GraphicsCommandList* cl, cl->SetDescriptorHeaps(_countof(heaps), heaps); cl->SetGraphicsRootSignature(g_gl.postRootSig.Get()); const float passSharpness = (sharpnessOverride >= 0.0f) ? sharpnessOverride : g_gl.upscalerSharpness; - QD3D12_SetPostConstants(cl, passSharpness, 0.0f, 1.0f); + QD3D12_SetPostConstants(cl, passSharpness, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, applySceneFog); cl->SetPipelineState(pso); cl->OMSetRenderTargets(1, &outputRtv, FALSE, nullptr); cl->RSSetViewports(1, &viewport); cl->RSSetScissorRects(1, &scissor); cl->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); cl->SetGraphicsRootDescriptorTable(0, inputSrv); + if (fogWindow) + QD3D12_BindPostFogResources(cl, *fogWindow, applySceneFog); cl->DrawInstanced(3, 1, 0, 0); } @@ -6455,7 +6578,8 @@ static bool QD3D12_ToneMapFullscreenPass( D3D12_CPU_DESCRIPTOR_HANDLE outputRtv, const D3D12_VIEWPORT& viewport, const D3D12_RECT& scissor, - float sharpnessOverride = -1.0f) + float sharpnessOverride = -1.0f, + bool applySceneFog = true) { ID3D12GraphicsCommandList* cl = g_gl.cmdList.Get(); const UINT frame = w.frameIndex; @@ -6470,7 +6594,7 @@ static bool QD3D12_ToneMapFullscreenPass( cl->SetDescriptorHeaps(_countof(heaps), heaps); cl->SetGraphicsRootSignature(g_gl.postRootSig.Get()); const float passSharpness = (sharpnessOverride >= 0.0f) ? sharpnessOverride : g_gl.upscalerSharpness; - QD3D12_SetPostConstants(cl, passSharpness, 0.0f, 1.0f, 1.0f, 1.0f, g_gl.toneMapBrightness); + QD3D12_SetPostConstants(cl, passSharpness, 0.0f, 1.0f, 1.0f, 1.0f, g_gl.toneMapBrightness, applySceneFog); cl->SetPipelineState(g_gl.postToneMapPSO.Get()); cl->OMSetRenderTargets(1, &outputRtv, FALSE, nullptr); cl->RSSetViewports(1, &viewport); @@ -6478,6 +6602,7 @@ static bool QD3D12_ToneMapFullscreenPass( cl->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); cl->SetGraphicsRootDescriptorTable(0, hdrInputSrv); cl->SetGraphicsRootDescriptorTable(7, w.toneMapSceneMaxSrvGpu[frame]); + QD3D12_BindPostFogResources(cl, w, applySceneFog); cl->DrawInstanced(3, 1, 0, 0); return true; } @@ -6633,7 +6758,10 @@ static bool QD3D12_FinalBlitToBackBuffer( inputSrv, CurrentBackBufferRTV(), outputViewport, - outputScissor); + outputScissor, + -1.0f, + true, + &w); return true; } @@ -8733,6 +8861,7 @@ void QD3D12_BeginFrame() g_gl.sceneResolvedThisFrame = false; g_gl.gbufferResolvedThisFrame = false; g_gl.raytracedLightingReadyThisFrame = false; + g_gl.sceneFogValidThisFrame = false; QD3D12_UpdateViewportState(); FrameResources& fr = w.frames[w.frameIndex]; @@ -8811,6 +8940,7 @@ void QD3D12_EndFrame() g_gl.sceneResolvedThisFrame = false; g_gl.gbufferResolvedThisFrame = false; g_gl.raytracedLightingReadyThisFrame = false; + g_gl.sceneFogValidThisFrame = false; QD3D12_UpdateViewportState(); } @@ -10670,6 +10800,27 @@ static void QD3D12_FlushQueuedBatches() if (count <= 0) continue; + if (batch.key.fogEnabled > 0.5f && + batch.key.cameraValid > 0.5f && + batch.key.depthTest && + batch.key.depthWrite && + batch.key.colorWriteMask != 0) + { + g_gl.sceneFogValidThisFrame = true; + g_gl.sceneFogMode = batch.key.fogMode; + g_gl.sceneFogDensity = batch.key.fogDensity; + g_gl.sceneFogStart = batch.key.fogStart; + g_gl.sceneFogEnd = batch.key.fogEnd; + g_gl.sceneFogColor[0] = batch.key.fogColor[0]; + g_gl.sceneFogColor[1] = batch.key.fogColor[1]; + g_gl.sceneFogColor[2] = batch.key.fogColor[2]; + g_gl.sceneFogColor[3] = batch.key.fogColor[3]; + g_gl.sceneFogCameraWorldPos[0] = batch.key.cameraWorldPos[0]; + g_gl.sceneFogCameraWorldPos[1] = batch.key.cameraWorldPos[1]; + g_gl.sceneFogCameraWorldPos[2] = batch.key.cameraWorldPos[2]; + g_gl.sceneFogCameraValid = batch.key.cameraValid; + } + const UINT vbBytes = (UINT)(count * sizeof(GLVertex)); const UINT cbBytes = (UINT)sizeof(DrawConstants); @@ -10725,23 +10876,15 @@ static void QD3D12_FlushQueuedBatches() memcpy(dc->texComb1Operand, batch.key.texComb1Operand, sizeof(dc->texComb1Operand)); memcpy(dc->texEnvColor1, batch.key.texEnvColor1, sizeof(dc->texEnvColor1)); - dc->fogEnabled = g_gl.fog ? 1.0f : 0.0f; - - switch (g_gl.fogMode) - { - case GL_LINEAR: dc->fogMode = 0.0f; break; - case GL_EXP: dc->fogMode = 1.0f; break; - case GL_EXP2: dc->fogMode = 2.0f; break; - default: dc->fogMode = 1.0f; break; - } - - dc->fogDensity = g_gl.fogDensity; - dc->fogStart = g_gl.fogStart; - dc->fogEnd = g_gl.fogEnd; - dc->fogColor[0] = g_gl.fogColor[0]; - dc->fogColor[1] = g_gl.fogColor[1]; - dc->fogColor[2] = g_gl.fogColor[2]; - dc->fogColor[3] = g_gl.fogColor[3]; + dc->fogEnabled = batch.key.fogEnabled; + dc->fogMode = batch.key.fogMode; + dc->fogDensity = batch.key.fogDensity; + dc->fogStart = batch.key.fogStart; + dc->fogEnd = batch.key.fogEnd; + dc->fogColor[0] = batch.key.fogColor[0]; + dc->fogColor[1] = batch.key.fogColor[1]; + dc->fogColor[2] = batch.key.fogColor[2]; + dc->fogColor[3] = batch.key.fogColor[3]; const float activeWidth = (float)QD3D12_ActiveRasterWidth(*g_currentWindow); const float activeHeight = (float)QD3D12_ActiveRasterHeight(*g_currentWindow); dc->renderSize[0] = activeWidth; @@ -13056,6 +13199,7 @@ void QD3D12_Resize() g_gl.sceneResolvedThisFrame = false; g_gl.gbufferResolvedThisFrame = false; g_gl.raytracedLightingReadyThisFrame = false; + g_gl.sceneFogValidThisFrame = false; QD3D12_UpdateViewportState(); } @@ -13106,6 +13250,7 @@ static void QD3D12_ReconfigureCurrentWindowForUpscalerChange() g_gl.sceneResolvedThisFrame = false; g_gl.gbufferResolvedThisFrame = false; g_gl.raytracedLightingReadyThisFrame = false; + g_gl.sceneFogValidThisFrame = false; QD3D12_UpdateViewportState(); } @@ -15095,6 +15240,7 @@ static void QD3D12_ResolveSceneToOutputAndEnterNativePhase(QD3D12Window& w) QD3D12_CompositeEmissiveIntoSceneColor(w); QD3D12_TransitionResource(cl, w.sceneColorBuffers[w.frameIndex].Get(), w.sceneColorState[w.frameIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + QD3D12_TransitionResource(cl, w.positionBuffers[w.frameIndex].Get(), w.positionBufferState[w.frameIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); QD3D12_TransitionResource(cl, w.velocityBuffers[w.frameIndex].Get(), w.velocityBufferState[w.frameIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); QD3D12_TransitionResource(cl, w.specularBuffers[w.frameIndex].Get(), w.specularBufferState[w.frameIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); QD3D12_TransitionResource(cl, w.depthBuffer.Get(), w.depthState, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); @@ -15368,7 +15514,8 @@ void glLightScene(glRaytracingSceneHandle_t sceneHandle) CurrentResolvedSceneColorRTV(), viewport, scissor, - 0.0f)) + 0.0f, + false)) { QD3D12_PostFullscreenPass( cl, @@ -17185,4 +17332,4 @@ void glUpdateTopLevelAceelStructure( instDesc.mask = 0xFFu; topLevelHandle = glRaytracingCreateInstanceInScene(scene, &instDesc); } -} \ No newline at end of file +} diff --git a/neo/engine/opengl/x64/Debug/gl_d3d12arb.obj b/neo/engine/opengl/x64/Debug/gl_d3d12arb.obj index 82ea52e1..c21ff961 100644 Binary files a/neo/engine/opengl/x64/Debug/gl_d3d12arb.obj and b/neo/engine/opengl/x64/Debug/gl_d3d12arb.obj differ diff --git a/neo/engine/opengl/x64/Debug/gl_d3d12shim.obj b/neo/engine/opengl/x64/Debug/gl_d3d12shim.obj index 8624ee1e..0600ef80 100644 Binary files a/neo/engine/opengl/x64/Debug/gl_d3d12shim.obj and b/neo/engine/opengl/x64/Debug/gl_d3d12shim.obj differ diff --git a/neo/engine/opengl/x64/Debug/opengl.log b/neo/engine/opengl/x64/Debug/opengl.log index f1a32998..188f2cbb 100644 --- a/neo/engine/opengl/x64/Debug/opengl.log +++ b/neo/engine/opengl/x64/Debug/opengl.log @@ -1,50 +1,13 @@ - DirectInputShim.cpp - gl_d3d12arb.cpp - gl_d3d12raylight.cpp - gl_d3d12shim.cpp -D:\projects\Doom3\neo\engine\opengl\gl_d3d12shim.cpp(4730,18): warning C4083: expected '('; found identifier 'off' -D:\projects\Doom3\neo\engine\opengl\gl_d3d12shim.cpp(4905,18): warning C4083: expected '('; found identifier 'on' -D:\projects\Doom3\neo\engine\opengl\gl_d3d12shim.cpp(11451,18): warning C4083: expected '('; found identifier 'off' -D:\projects\Doom3\neo\engine\opengl\gl_d3d12shim.cpp(11809,18): warning C4083: expected '('; found identifier 'on' -D:\projects\Doom3\neo\engine\opengl\gl_d3d12shim.cpp(14082,13): warning C4273: 'wglShareLists': inconsistent dll linkage + gl_d3d12shim.cpp +D:\projects\Doom3\neo\engine\opengl\gl_d3d12shim.cpp(4808,18): warning C4083: expected '('; found identifier 'off' +D:\projects\Doom3\neo\engine\opengl\gl_d3d12shim.cpp(4998,18): warning C4083: expected '('; found identifier 'on' +D:\projects\Doom3\neo\engine\opengl\gl_d3d12shim.cpp(11594,18): warning C4083: expected '('; found identifier 'off' +D:\projects\Doom3\neo\engine\opengl\gl_d3d12shim.cpp(11952,18): warning C4083: expected '('; found identifier 'on' +D:\projects\Doom3\neo\engine\opengl\gl_d3d12shim.cpp(14227,13): warning C4273: 'wglShareLists': inconsistent dll linkage C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um\wingdi.h(6338,24): see previous definition of 'wglShareLists' -D:\projects\Doom3\neo\engine\opengl\gl_d3d12shim.cpp(14279,4): warning C4390: ';': empty controlled statement found; is this the intent? - gl_d3d12tess.cpp -D:\projects\Doom3\neo\engine\opengl\tess\tess.h(59,8): warning C4099: 'GLUtesselator': type name first seen using 'class' now seen using 'struct' - (compiling source file 'opengl/gl_d3d12tess.cpp') - D:\projects\Doom3\neo\engine\opengl\tess\tess.h(59,8): - see declaration of 'GLUtesselator' - - gl_d3d12wgl.cpp -D:\projects\Doom3\neo\engine\opengl\gl_d3d12wgl.cpp(207,36): warning C4273: 'wglUseFontBitmapsA': inconsistent dll linkage - C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um\wingdi.h(6339,24): - see previous definition of 'wglUseFontBitmapsA' - -D:\projects\Doom3\neo\engine\opengl\gl_d3d12wgl.cpp(208,37): warning C4273: 'wglUseFontBitmapsW': inconsistent dll linkage - C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um\wingdi.h(6340,24): - see previous definition of 'wglUseFontBitmapsW' - - nn_mattrain.cpp -D:\projects\Doom3\neo\engine\opengl\nn_mattrain.cpp(140,1): warning C4010: single-line comment contains line-continuation character - Generating Code... - dict.c - geom.c - memalloc.c - mesh.c - normal.c - priorityq-heap.c - priorityq.c - render.c - sweep.c - tess.c - tessellate.c -D:\projects\Doom3\neo\engine\opengl\tess\tessellate.c(210,66): warning C4113: 'GLvoid (__cdecl *)()' differs in parameter lists from '_GLUfuncptr' -D:\projects\Doom3\neo\engine\opengl\tess\tessellate.c(211,66): warning C4113: 'GLvoid (__cdecl *)()' differs in parameter lists from '_GLUfuncptr' -D:\projects\Doom3\neo\engine\opengl\tess\tessellate.c(212,66): warning C4113: 'GLvoid (__cdecl *)()' differs in parameter lists from '_GLUfuncptr' - tessmono.c - Generating Code... +D:\projects\Doom3\neo\engine\opengl\gl_d3d12shim.cpp(14424,4): warning C4390: ';': empty controlled statement found; is this the intent? priorityq-heap.obj : warning LNK4006: __gl_pqHeapNewPriorityQ already defined in priorityq.obj; second definition ignored priorityq-heap.obj : warning LNK4006: __gl_pqHeapDeletePriorityQ already defined in priorityq.obj; second definition ignored priorityq-heap.obj : warning LNK4006: __gl_pqHeapInit already defined in priorityq.obj; second definition ignored diff --git a/neo/engine/opengl/x64/Debug/opengl.tlog/CL.command.1.tlog b/neo/engine/opengl/x64/Debug/opengl.tlog/CL.command.1.tlog index 898672ec..3c01c74f 100644 Binary files a/neo/engine/opengl/x64/Debug/opengl.tlog/CL.command.1.tlog and b/neo/engine/opengl/x64/Debug/opengl.tlog/CL.command.1.tlog differ diff --git a/neo/engine/opengl/x64/Debug/opengl.tlog/CL.read.1.tlog b/neo/engine/opengl/x64/Debug/opengl.tlog/CL.read.1.tlog index e942de9d..e4eafe2c 100644 Binary files a/neo/engine/opengl/x64/Debug/opengl.tlog/CL.read.1.tlog and b/neo/engine/opengl/x64/Debug/opengl.tlog/CL.read.1.tlog differ diff --git a/neo/engine/opengl/x64/Debug/opengl.tlog/CL.write.1.tlog b/neo/engine/opengl/x64/Debug/opengl.tlog/CL.write.1.tlog index 59787db2..b613154d 100644 Binary files a/neo/engine/opengl/x64/Debug/opengl.tlog/CL.write.1.tlog and b/neo/engine/opengl/x64/Debug/opengl.tlog/CL.write.1.tlog differ diff --git a/neo/engine/renderer/RenderWorld.h b/neo/engine/renderer/RenderWorld.h index 8bc8eaba..a67a5490 100644 --- a/neo/engine/renderer/RenderWorld.h +++ b/neo/engine/renderer/RenderWorld.h @@ -146,6 +146,21 @@ enum { // guis const int MAX_RENDERENTITY_GUI = 3; +typedef enum renderGlobalFogMode_s { + RENDER_GLOBAL_FOG_LINEAR, + RENDER_GLOBAL_FOG_EXP, + RENDER_GLOBAL_FOG_EXP2 +} renderGlobalFogMode_t; + +typedef struct renderGlobalFog_s { + bool enabled; + renderGlobalFogMode_t mode; + float density; + float start; + float end; + idVec4 color; +} renderGlobalFog_t; + #ifdef QUAKE4 enum { RD_MISC = 0, @@ -517,6 +532,7 @@ typedef struct renderView_s { int time; float shaderParms[MAX_GLOBAL_SHADER_PARMS]; // can be used in any way by shader const idMaterial* globalMaterial; // used to override everything draw + renderGlobalFog_t globalFog; // fixed-function global depth fog #ifdef QUAKE4 // RAVEN BEGIN @@ -1010,4 +1026,4 @@ ID_INLINE void idRenderWorld::DebugFOV(const idVec4& color, const idVec3& origin #endif /* QUAKE4 */ -#endif /* !__RENDERWORLD_H__ */ \ No newline at end of file +#endif /* !__RENDERWORLD_H__ */ diff --git a/neo/engine/renderer/RenderWorld_demo.cpp b/neo/engine/renderer/RenderWorld_demo.cpp index 56399a68..4c839e57 100644 --- a/neo/engine/renderer/RenderWorld_demo.cpp +++ b/neo/engine/renderer/RenderWorld_demo.cpp @@ -139,6 +139,12 @@ bool idRenderWorldLocal::ProcessDemoCommand( idDemoFile *readDemo, renderView_t readDemo->ReadInt( renderView->time ); for ( int i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) readDemo->ReadFloat( renderView->shaderParms[i] ); + readDemo->ReadBool( renderView->globalFog.enabled ); + readDemo->ReadInt( (int&)renderView->globalFog.mode ); + readDemo->ReadFloat( renderView->globalFog.density ); + readDemo->ReadFloat( renderView->globalFog.start ); + readDemo->ReadFloat( renderView->globalFog.end ); + readDemo->ReadVec4( renderView->globalFog.color ); if ( !readDemo->ReadInt( (int&)renderView->globalMaterial ) ) { return false; @@ -355,6 +361,12 @@ void idRenderWorldLocal::WriteRenderView( const renderView_t *renderView ) { session->writeDemo->WriteInt( renderView->time ); for ( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) session->writeDemo->WriteFloat( renderView->shaderParms[i] ); + session->writeDemo->WriteBool( renderView->globalFog.enabled ); + session->writeDemo->WriteInt( renderView->globalFog.mode ); + session->writeDemo->WriteFloat( renderView->globalFog.density ); + session->writeDemo->WriteFloat( renderView->globalFog.start ); + session->writeDemo->WriteFloat( renderView->globalFog.end ); + session->writeDemo->WriteVec4( renderView->globalFog.color ); session->writeDemo->WriteInt( (int&)renderView->globalMaterial ); if ( r_showDemo.GetBool() ) { diff --git a/neo/engine/renderer/tr_backend.cpp b/neo/engine/renderer/tr_backend.cpp index 678c441e..0b39e8bc 100644 --- a/neo/engine/renderer/tr_backend.cpp +++ b/neo/engine/renderer/tr_backend.cpp @@ -69,6 +69,7 @@ void RB_SetDefaultGLState( void ) { glEnable( GL_SCISSOR_TEST ); glEnable( GL_CULL_FACE ); glDisable( GL_LIGHTING ); + glDisable( GL_FOG ); glDisable( GL_LINE_STIPPLE ); glDisable( GL_STENCIL_TEST ); diff --git a/neo/engine/renderer/tr_render.cpp b/neo/engine/renderer/tr_render.cpp index b0163c27..616f9094 100644 --- a/neo/engine/renderer/tr_render.cpp +++ b/neo/engine/renderer/tr_render.cpp @@ -544,6 +544,39 @@ void RB_DetermineLightScale( void ) { } +/* +================= +RB_SetGlobalFog +================= +*/ +static void RB_SetGlobalFog( const renderGlobalFog_t &fog ) { + if ( !fog.enabled || !backEnd.viewDef->viewEntitys ) { + glDisable( GL_FOG ); + return; + } + + switch( fog.mode ) { + case RENDER_GLOBAL_FOG_LINEAR: + glFogi( GL_FOG_MODE, GL_LINEAR ); + break; + case RENDER_GLOBAL_FOG_EXP2: + glFogi( GL_FOG_MODE, GL_EXP2 ); + break; + case RENDER_GLOBAL_FOG_EXP: + default: + glFogi( GL_FOG_MODE, GL_EXP ); + break; + } + + glFogf( GL_FOG_DENSITY, fog.density ); + glFogf( GL_FOG_START, fog.start ); + glFogf( GL_FOG_END, fog.end ); + + float color[4] = { fog.color[0], fog.color[1], fog.color[2], fog.color[3] }; + glFogfv( GL_FOG_COLOR, color ); + glEnable( GL_FOG ); +} + /* ================= RB_BeginDrawingView @@ -573,6 +606,7 @@ void RB_BeginDrawingView (void) { // ensures that depth writes are enabled for the depth clear GL_State( GLS_DEFAULT ); + RB_SetGlobalFog( backEnd.viewDef->renderView.globalFog ); // we don't have to clear the depth / stencil buffer for 2D rendering if ( backEnd.viewDef->viewEntitys ) { diff --git a/neo/engine/tools/radiant/CamWnd.cpp b/neo/engine/tools/radiant/CamWnd.cpp index aeadaa5b..4daef00f 100644 --- a/neo/engine/tools/radiant/CamWnd.cpp +++ b/neo/engine/tools/radiant/CamWnd.cpp @@ -1023,6 +1023,7 @@ static const char* CAMWND_PROP_FILTER_MASK = "QER_CamWnd_FilterMask"; #define CAMWND_MENU_CMD_RESET_FILTERS 62106 #define CAMWND_MENU_CMD_SHOW_TARGET_LINES 62107 #define CAMWND_MENU_CMD_SHOW_TRIGGER_BRUSHES 62108 +#define CAMWND_MENU_CMD_CUBIC_CLIPPING 62109 #define CAMWND_FILTER_HIDE_WORLD 0x00000001 #define CAMWND_FILTER_HIDE_PATCHES 0x00000002 @@ -1189,11 +1190,26 @@ static void CamWnd_ResetFilters(CCamWnd* cam) { CamWnd_RequestRedraw(cam); } +static void CamWnd_ToggleCubicClipping(CCamWnd* cam) { + if (g_pParentWnd) { + g_pParentWnd->SendMessage(WM_COMMAND, ID_VIEW_CUBICCLIPPING, 0); + } + else { + g_PrefsDlg.m_bCubicClipping ^= 1; + g_PrefsDlg.SavePrefs(); + Map_BuildBrushData(); + CamWnd_RequestRedraw(cam); + } +} + static void CamWnd_HandleMenuCommand(CCamWnd* cam, int command) { switch (command) { case CAMWND_MENU_CMD_REALTIME_LIGHTING: CamWnd_ToggleRealtimeLighting(cam); break; + case CAMWND_MENU_CMD_CUBIC_CLIPPING: + CamWnd_ToggleCubicClipping(cam); + break; case CAMWND_MENU_CMD_SHOW_WORLD: CamWnd_ToggleFilterBit(cam, CAMWND_FILTER_HIDE_WORLD); break; @@ -1264,6 +1280,8 @@ static void CamWnd_ShowFiltersMenu(HWND hWnd, CCamWnd* cam) { ClientToScreen(hWnd, &pt); menu = CreatePopupMenu(); + AppendMenu(menu, MF_STRING | (g_PrefsDlg.m_bCubicClipping ? MF_CHECKED : 0), CAMWND_MENU_CMD_CUBIC_CLIPPING, "Cubic clipping"); + AppendMenu(menu, MF_SEPARATOR, 0, NULL); CamWnd_AppendVisibleFilterItem(menu, mask, CAMWND_FILTER_HIDE_WORLD, CAMWND_MENU_CMD_SHOW_WORLD, "Show world geometry"); CamWnd_AppendVisibleFilterItem(menu, mask, CAMWND_FILTER_HIDE_PATCHES, CAMWND_MENU_CMD_SHOW_PATCHES, "Show patches"); CamWnd_AppendVisibleFilterItem(menu, mask, CAMWND_FILTER_HIDE_MODELS, CAMWND_MENU_CMD_SHOW_MODELS, "Show models"); @@ -2834,11 +2852,11 @@ void CCamWnd::OnPaint() { idGraphicsDeviceContextHelper context(dc.m_hDC, hglrc, true); g_pSplitList = NULL; - if (g_bClipMode) { - if (g_Clip1.Set() && g_Clip2.Set()) { - g_pSplitList = ((g_pParentWnd->ActiveXY()->GetViewType() == XZ) ? !g_bSwitch : g_bSwitch) ? &g_brBackSplits : &g_brFrontSplits; - } - } + //if (g_bClipMode) { + // if (g_Clip1.Set() && g_Clip2.Set()) { + // g_pSplitList = ((g_pParentWnd->ActiveXY()->GetViewType() == XZ) ? !g_bSwitch : g_bSwitch) ? &g_brBackSplits : &g_brFrontSplits; + // } + //} Cam_Draw(); } @@ -5369,6 +5387,45 @@ void CCamWnd::DrawEntityData() { This used the renderSystem to draw a fully lit view of the world ======================================================================================================================= */ +static renderGlobalFogMode_t Cam_ParseGlobalFogMode(const char* mode) { + if (idStr::Icmp(mode, "linear") == 0) { + return RENDER_GLOBAL_FOG_LINEAR; + } + if (idStr::Icmp(mode, "exp2") == 0) { + return RENDER_GLOBAL_FOG_EXP2; + } + return RENDER_GLOBAL_FOG_EXP; +} + +static void Cam_SetGlobalFogFromWorldspawn(renderView_t& refdef) { + renderGlobalFog_t& fog = refdef.globalFog; + + memset(&fog, 0, sizeof(fog)); + fog.mode = RENDER_GLOBAL_FOG_EXP; + fog.density = 1.0f; + fog.end = 1.0f; + fog.color.Set(0.0f, 0.0f, 0.0f, 1.0f); + + if (world_entity == NULL) { + return; + } + + const idDict& args = world_entity->epairs; + fog.enabled = args.GetBool("globalFog", args.GetString("fog_global", "0")); + fog.mode = Cam_ParseGlobalFogMode(args.GetString("globalFogMode", args.GetString("fog_mode", "exp"))); + fog.density = args.GetFloat("globalFogDensity", args.GetString("fog_density", "1")); + fog.start = args.GetFloat("globalFogStart", args.GetString("fog_start", "0")); + fog.end = args.GetFloat("globalFogEnd", args.GetString("fog_end", "1")); + + idVec3 color; + if (args.GetVector("globalFogColor", args.GetString("fog_color", "0 0 0"), color)) { + fog.color.x = color.x; + fog.color.y = color.y; + fog.color.z = color.z; + } + fog.color.w = args.GetFloat("globalFogAlpha", args.GetString("fog_alpha", "1")); +} + void CCamWnd::Cam_Render() { renderView_t refdef; @@ -5410,6 +5467,7 @@ void CCamWnd::Cam_Render() { if (animationMode) { refdef.time = eventLoop->Milliseconds(); } + Cam_SetGlobalFogFromWorldspawn(refdef); g_qeglobals.rw->RenderScene(&refdef); @@ -5482,4 +5540,3 @@ void CCamWnd::UpdateCameraView() { saveValid = false; } } -