Files
GTASource/game/renderer/Deferred/DeferredLighting.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

3629 lines
142 KiB
C++

// =============================================================================================== //
// INCLUDES
// =============================================================================================== //
// rage headers
#include "grcore/allocscope.h"
#include "grcore/image.h"
#include "grcore/device.h"
#include "grcore/im.h"
#include "grcore/stateblock.h"
#include "grcore/texture.h"
#include "grcore/viewport.h"
#include "grcore/config.h"
#include "grcore/effect_values.h"
#include "grcore/effect_typedefs.h"
#include "grcore/quads.h"
#if __PPU
#include "grcore/wrapper_gcm.h"
#include "grcore/texturegcm.h"
#endif
#include "grmodel/shader.h"
#include "grmodel/shaderfx.h"
#include "grmodel/shadergroup.h"
#include "rmcore/drawable.h"
#include "system/param.h"
#include "system/nelem.h"
#include "system/xtl.h"
#include "system/pad.h"
#include "system/filemgr.h"
#include "system/system.h"
#include "system/memory.h"
#include "vector/vector3.h"
#include "bank/bank.h"
#include "file/asset.h"
#include "Math/amath.h"
#if __D3D
#include "grcore/wrapper_d3d.h"
#include "system/d3d9.h"
#if __XENON
#include "system/xtl.h"
#define DBG 0 // yuck
#include <xgraphics.h>
#endif
#endif
// framework headers
#include "fwmaths/random.h"
#include "fwmaths/vector.h"
#include "fwmaths/angle.h"
#include "fwmaths/vectorutil.h"
#include "fwscene/stores/txdstore.h"
#include "fwsys/timer.h"
// game headers
#include "camera/CamInterface.h"
#include "camera/cutscene/CutsceneDirector.h"
#include "camera/viewports/Viewport.h"
#include "camera/viewports/ViewportManager.h"
#include "cutscene/CutSceneManagerNew.h"
#include "debug/BudgetDisplay.h"
#include "debug/debug.h"
#include "debug/debugglobals.h"
#include "debug/Rendering/DebugDeferred.h"
#include "debug/Rendering/DebugLighting.h"
#include "debug/TiledScreenCapture.h"
#include "game/clock.h" //CClock::ms_nGameClockHours
#include "game/modelindices.h"
#include "game/weather.h"
#include "modelinfo/VehicleModelInfo.h"
#include "peds/Ped.h"
#include "physics/GtaArchetype.h"
#include "physics/WorldProbe/worldprobe.h"
#include "scene/world/gameWorld.h"
#include "scene/FileLoader.h"
#include "Shaders/ShaderLib.h"
#include "streaming/streaming.h"
#include "vehicles/Boat.h"
#include "vehicles/vehicle.h"
#include "renderer/Deferred/DeferredLighting.h"
#include "renderer/Deferred/GBuffer.h"
#include "renderer/lights/lights.h"
#include "renderer/lights/LightSource.h"
#include "renderer/Lights/TiledLighting.h"
#include "renderer/PostProcessFX.h"
#include "renderer/RenderPhases/RenderPhaseCascadeShadows.h"
#include "renderer/RenderPhases/RenderPhaseHeightMap.h"
#include "renderer/RenderPhases/RenderPhaseReflection.h"
#include "renderer/rendertargets.h"
#include "renderer/river.h"
#include "renderer/sprite2d.h" //CSprite2d::DrawTxRect()...
#include "renderer/SpuPM/SpuPmMgr.h"
#include "renderer/SSAO.h"
#include "renderer/Util/ShaderUtil.h"
#include "renderer/Util/Util.h"
#include "renderer/water.h"
#include "renderer/zonecull.h"
#include "renderer/RenderListBuilder.h"
#include "TimeCycle/TimeCycle.h"
#include "TimeCycle/TimeCycleConfig.h"
#include "vfx/misc/Puddles.h"
#include "vfx/VfxHelper.h"
// =============================================================================================== //
// DEFINES
// =============================================================================================== //
RENDER_OPTIMISATIONS()
#define DUMP_GBUFFER_TARGETS (0 && __DEV)
// ----------------------------------------------------------------------------------------------- //
//DECAL FLAGS
#define DECAL_BLEND_COLOUR (0x1<<0)
#define DECAL_BLEND_SPEC (0x1<<1)
#define DECAL_BLEND_AMB (0x1<<2)
#define DECAL_WRITE_DEPTH (0x1<<3)
#define DECAL_WRITE_NORM (0x1<<4)
#define DECAL_ALPHA_TO_MASK_WRITE_ALL (0x1<<5) //assumes write all
// ----------------------------------------------------------------------------------------------- //
// Static member creation/initialization.
grcTexture* DeferredLighting::m_volumeTexture = NULL;
s32 DECLARE_MTR_THREAD DeferredLighting::m_previousGroupId = - 1;
s32 DeferredLighting::m_deferredTechniqueGroupId;
s32 DeferredLighting::m_deferredCutsceneTechniqueGroupId= - 1;
s32 DeferredLighting::m_deferredAlphaClipTechniqueGroupId = -1;
s32 DeferredLighting::m_deferredSSAAlphaClipTechniqueGroupId = -1;
s32 DECLARE_MTR_THREAD DeferredLighting::m_prevDeferredPedTechnique = - 1;
s32 DECLARE_MTR_THREAD DeferredLighting::m_previousGroupAlphaClipId = -1;
s32 DeferredLighting::m_deferredSubSampleWriteAlphaTechniqueGroupId = -1;
s32 DeferredLighting::m_deferredSubSampleAlphaTechniqueGroupId = -1;
grmShader* DeferredLighting::m_deferredShaders[MM_TOTAL][NUM_DEFERRD_SHADERS];
#if DEVICE_EQAA
bool DECLARE_MTR_THREAD DeferredLighting::m_eqaaDisabledForCutout = false;
#endif // DEVICE_EQAA
#if GENERATE_SHMOO
int DeferredLighting::m_deferredShadersShmoos[NUM_DEFERRD_SHADERS];
#endif // GENERATE_SHMOO
grcEffectVar DeferredLighting::m_deferredShaderVars[MM_TOTAL][NUM_DEFERRD_SHADERS][NUM_DEFERRED_SHADER_VARS];
grcEffectGlobalVar DeferredLighting::m_deferredShaderGlobalVars[NUM_DEFERRED_SHADER_GLOBAL_VARS];
const char* m_deferredShaderVarNames[NUM_DEFERRED_SHADER_VARS] =
{
"deferredLightParams",
"deferredLightTexture",
"deferredLightTexture1",
"deferredLightTexture2",
"deferredLightScreenSize",
"deferredProjectionParams",
"deferredPerspectiveShearParams0",
"deferredPerspectiveShearParams1",
"deferredPerspectiveShearParams2",
"deferredLightVolumeParams",
"dLocalShadowData",
};
const char* m_deferredShaderGlobalVarNames[] =
{
"gbufferTexture0Global",
"gbufferTexture1Global",
"gbufferTexture2Global",
"gbufferTexture3Global",
"gbufferTextureDepthGlobal",
#if __XENON || __D3D11 || RSG_ORBIS
"gbufferStencilTextureGlobal",
#endif
#if DEVICE_EQAA
"gbufferFragmentMask0Global",
"gbufferFragmentMask1Global",
"gbufferFragmentMask2Global",
"gbufferFragmentMask3Global",
#endif // DEVICE_EQAA
};
CompileTimeAssert( NELEM(m_deferredShaderGlobalVarNames) == NUM_DEFERRED_SHADER_GLOBAL_VARS );
const bool m_deferredShaderGlobalVarRequired[] =
{
true,
true,
true,
true,
true,
#if __XENON || __D3D11 || RSG_ORBIS
true,
#endif
#if DEVICE_EQAA
false,
false,
false,
false,
#endif // DEVICE_EQAA
};
CompileTimeAssert( NELEM(m_deferredShaderGlobalVarRequired) == NUM_DEFERRED_SHADER_GLOBAL_VARS );
grcEffectTechnique DeferredLighting::m_shaderLightShaftVolumeTechniques[CExtensionDefLightShaftVolumeType_NUM_ENUMS];
grcEffectTechnique DeferredLighting::m_techniques[MM_TOTAL][DEFERRED_TECHNIQUE_NUM_TECHNIQUES];
#if MSAA_EDGE_PASS
# if MSAA_EDGE_USE_DEPTH_COPY
grcRenderTarget* DeferredLighting::m_edgeMarkDepthCopy;
# endif //MSAA_EDGE_USE_DEPTH_COPY
# if __DEV
grcRenderTarget* DeferredLighting::m_edgeMarkDebugTarget;
# endif //__BANK
# if MSAA_EDGE_PROCESS_FADING
grcRenderTarget* DeferredLighting::m_edgeCopyTarget;
grcEffectVar DeferredLighting::m_edgeCopyTextureVar;
# endif //MSAA_EDGE_PROCESS_FADING
grcEffectTechnique DeferredLighting::m_edgeMarkTechniqueIdx;
grcEffectVar DeferredLighting::m_edgeMarkParamsVar;
grcRasterizerStateHandle DeferredLighting::m_edgePass_R;
grcDepthStencilStateHandle DeferredLighting::m_edgePass_DS;
grcBlendStateHandle DeferredLighting::m_edgePass_B;
#endif //MSAA_EDGE_PASS
grcEffectVar DeferredLighting::m_shaderLightParameterID_skinColourTweak;
grcEffectVar DeferredLighting::m_shaderLightParameterID_skinParams;
#if __D3D11 || RSG_ORBIS
grcEffectVar DeferredLighting::m_shaderDownsampledDepthSampler=grcevNONE;
#endif
#if ENABLE_PED_PASS_AA_SOURCE
grcEffectVar DeferredLighting::m_shaderLightTextureAA=grcevNONE;
#endif // ENABLE_PED_PASS_AA_SOURCE
#if !__FINAL
grcEffectVar DeferredLighting::m_debugLightingParamsID;
#endif // !__FINAL
grcEffectVar DeferredLighting::m_shaderVolumeParameterID_deferredVolumePosition;
grcEffectVar DeferredLighting::m_shaderVolumeParameterID_deferredVolumeDirection;
grcEffectVar DeferredLighting::m_shaderVolumeParameterID_deferredVolumeTangentXAndShaftRadius;
grcEffectVar DeferredLighting::m_shaderVolumeParameterID_deferredVolumeTangentYAndShaftLength;
grcEffectVar DeferredLighting::m_shaderVolumeParameterID_deferredVolumeColour;
grcEffectVar DeferredLighting::m_shaderVolumeParameterID_deferredVolumeShaftPlanes;
grcEffectVar DeferredLighting::m_shaderVolumeParameterID_deferredVolumeShaftGradient;
grcEffectVar DeferredLighting::m_shaderVolumeParameterID_deferredVolumeShaftGradientColourInv;
grcEffectVar DeferredLighting::m_shaderVolumeParameterID_deferredVolumeShaftCompositeMtx;
grcEffectVar DeferredLighting::m_shaderVolumeParameterID_deferredVolumeDepthBuffer;
grcEffectVar DeferredLighting::m_shaderVolumeParameterID_deferredVolumeOffscreenBuffer;
#if LIGHT_VOLUME_USE_LOW_RESOLUTION
grcEffectVar DeferredLighting::m_shaderVolumeParameterID_deferredVolumeLowResDepthBuffer;
#endif
#if __BANK
grcEffectVar DeferredLighting::m_shaderVolumeParameterID_GBufferTextureDepth;
#endif
grcViewport* DeferredLighting::m_pPreviousViewport = NULL;
grcViewport* DeferredLighting::m_pOrthoViewport = NULL;
bool DeferredLighting::m_bIsViewportPerspective = false;
grcRenderTarget* DeferredLighting::m_paraboloidReflectionMap = NULL;
grcDepthStencilStateHandle DeferredLighting::m_defaultState_DS;
grcDepthStencilStateHandle DeferredLighting::m_defaultExitState_DS;
grcBlendStateHandle DeferredLighting::m_defaultExitState_B;
grcRasterizerStateHandle DeferredLighting::m_defaultExitState_R;
grcDepthStencilStateHandle DeferredLighting::m_geometryPass_DS;
grcBlendStateHandle DeferredLighting::m_geometryPass_B;
grcBlendStateHandle DeferredLighting::m_decalPass_B;
grcDepthStencilStateHandle DeferredLighting::m_decalPass_DS;
grcBlendStateHandle DeferredLighting::m_fadePass_B;
grcDepthStencilStateHandle DeferredLighting::m_fadePass_DS;
#if MSAA_EDGE_PROCESS_FADING
grcDepthStencilStateHandle DeferredLighting::m_fadePassAA_DS;
#endif
grcBlendStateHandle DeferredLighting::m_cutoutPass_B;
grcDepthStencilStateHandle DeferredLighting::m_cutoutPass_DS;
grcDepthStencilStateHandle DeferredLighting::m_treePass_DS;
grcDepthStencilStateHandle DeferredLighting::m_defaultPass_DS;
grcBlendStateHandle DeferredLighting::m_defaultPass_B;
grcBlendStateHandle DeferredLighting::m_directionalPass_B;
grcDepthStencilStateHandle DeferredLighting::m_directionalFullPass_DS;
grcDepthStencilStateHandle DeferredLighting::m_directionalAmbientPass_DS;
grcDepthStencilStateHandle DeferredLighting::m_directionalNoStencilPass_DS;
grcRasterizerStateHandle DeferredLighting::m_directionalPass_R;
#if MSAA_EDGE_PASS
grcDepthStencilStateHandle DeferredLighting::m_directionalEdgeMaskEqualPass_DS;
grcDepthStencilStateHandle DeferredLighting::m_directionalEdgeAllEqualPass_DS;
grcDepthStencilStateHandle DeferredLighting::m_directionalEdgeNotEqualPass_DS;
grcDepthStencilStateHandle DeferredLighting::m_directionalEdgeBit0EqualPass_DS;
grcDepthStencilStateHandle DeferredLighting::m_directionalEdgeBit2EqualPass_DS;
#endif //MSAA_EDGE_PASS
grcDepthStencilStateHandle DeferredLighting::m_foliagePrePass_DS;
grcDepthStencilStateHandle DeferredLighting::m_foliageMainPass_DS;
grcBlendStateHandle DeferredLighting::m_foliagePass_B;
grcDepthStencilStateHandle DeferredLighting::m_foliagePass_DS;
grcDepthStencilStateHandle DeferredLighting::m_foliageNoStencilPass_DS;
grcRasterizerStateHandle DeferredLighting::m_foliagePass_R;
grcBlendStateHandle DeferredLighting::m_skinPass_B;
grcDepthStencilStateHandle DeferredLighting::m_skinPass_DS;
grcDepthStencilStateHandle DeferredLighting::m_skinPass_UI_DS;
grcDepthStencilStateHandle DeferredLighting::m_skinPassForward_DS;
grcDepthStencilStateHandle DeferredLighting::m_skinNoStencilPass_DS;
grcRasterizerStateHandle DeferredLighting::m_skinPass_R;
grcDepthStencilStateHandle DeferredLighting::m_tiledLighting_DS;
grcBlendStateHandle DeferredLighting::m_SingleSampleSSABlendState;
grcBlendStateHandle DeferredLighting::m_SSABlendState;
DeferredLighting::LightingQuality DeferredLighting::m_LightingQuality;
#if SSA_USES_CONDITIONALRENDER
grcConditionalQuery DeferredLighting::m_SSAConditionalQuery = 0;
bool DeferredLighting::m_bSSAConditionalQueryIsValid = false;
#endif // SSA_USES_CONDITIONALRENDER
#if DEVICE_MSAA
bool DeferredLighting::m_bSupportMSAAandNonMSAA = false;
#endif
PARAM(pcTiledLighting, "Enables tiled lighting (PC defaults to non-tiled)");
// ----------------------------------------------------------------------------------------------- //
#if __WIN32PC
#define CheckVar(x)
#else
#define CheckVar(x) Assert(x)
#endif
#if RSG_PC
void DeferredLighting::DeleteShaders()
{
for (int aaMode = 0; aaMode != MM_TOTAL; ++aaMode)
{
#if DEVICE_MSAA
if (!m_bSupportMSAAandNonMSAA && aaMode != MM_DEFAULT)
continue;
#endif
for (int es = 0; es != NUM_DEFERRD_SHADERS; ++es)
{
// Look-up all the shared vars for all the deferred shaders
for (u32 j = 0; j < NUM_DEFERRED_SHADER_VARS; j++)
{
m_deferredShaderVars[aaMode][es][j] = grcevNONE;
}
// Delete shaders
if (m_deferredShaders[aaMode][es])
{
delete m_deferredShaders[aaMode][es];
m_deferredShaders[aaMode][es] = NULL;
}
}
}
for(u32 i = 0; i < NUM_DEFERRED_SHADER_GLOBAL_VARS; i++)
{
m_deferredShaderGlobalVars[i] = grcegvNONE;
}
memset(&m_techniques, NULL, sizeof(m_techniques));
}
#endif //RSG_PC
void DeferredLighting::InitShaders()
{
memset(&m_deferredShaders, 0, sizeof(m_deferredShaders));
// Create and set up the shaders.
ASSET.PushFolder("common:/shaders");
// Use the non-msaa shaders for 4s1f EQAA
MSAA_ONLY( m_bSupportMSAAandNonMSAA = GRCDEVICE.GetMSAA() > 1 );
// Create and load the shader.
for (int es = 0; es != NUM_DEFERRD_SHADERS; ++es)
{
m_deferredShaders[MM_DEFAULT][es] = grmShaderFactory::GetInstance().Create();
}
#if DEVICE_MSAA
if ( m_bSupportMSAAandNonMSAA )
{
m_deferredShaders[MM_SUPER_SAMPLE][DEFERRED_SHADER_LIGHTING] ->Load("deferred_lightingMS");
m_deferredShaders[MM_SUPER_SAMPLE][DEFERRED_SHADER_AMBIENT] ->Load("deferred_ambientMS");
m_deferredShaders[MM_SUPER_SAMPLE][DEFERRED_SHADER_DIRECTIONAL] ->Load("directionalMS");
m_deferredShaders[MM_SUPER_SAMPLE][DEFERRED_SHADER_SPOT] ->Load("spotMS");
m_deferredShaders[MM_SUPER_SAMPLE][DEFERRED_SHADER_POINT] ->Load("pointMS");
m_deferredShaders[MM_SUPER_SAMPLE][DEFERRED_SHADER_CAPSULE] ->Load("capsuleMS");
m_deferredShaders[MM_SUPER_SAMPLE][DEFERRED_SHADER_TILED] ->Load("tiled_lightingMS");
(m_deferredShaders[MM_SINGLE][DEFERRED_SHADER_LIGHTING] = grmShaderFactory::GetInstance().Create())->Load("deferred_lighting");
(m_deferredShaders[MM_SINGLE][DEFERRED_SHADER_VOLUME] = NULL);
(m_deferredShaders[MM_SINGLE][DEFERRED_SHADER_DIRECTIONAL] = grmShaderFactory::GetInstance().Create())->Load("directional");
(m_deferredShaders[MM_SINGLE][DEFERRED_SHADER_SPOT] = grmShaderFactory::GetInstance().Create())->Load("spot");
(m_deferredShaders[MM_SINGLE][DEFERRED_SHADER_POINT] = grmShaderFactory::GetInstance().Create())->Load("point");
(m_deferredShaders[MM_SINGLE][DEFERRED_SHADER_CAPSULE] = grmShaderFactory::GetInstance().Create())->Load("capsule");
(m_deferredShaders[MM_SINGLE][DEFERRED_SHADER_TILED] = NULL);
(m_deferredShaders[MM_SINGLE][DEFERRED_SHADER_AMBIENT] = NULL);
#if MSAA_EDGE_PASS
(m_deferredShaders[MM_TEXTURE_READS_ONLY][DEFERRED_SHADER_DIRECTIONAL] = grmShaderFactory::GetInstance().Create())->Load("directionalMS0");
(m_deferredShaders[MM_TEXTURE_READS_ONLY][DEFERRED_SHADER_LIGHTING] = grmShaderFactory::GetInstance().Create())->Load("deferred_lightingMS0");
(m_deferredShaders[MM_TEXTURE_READS_ONLY][DEFERRED_SHADER_SPOT] = grmShaderFactory::GetInstance().Create())->Load("spotMS0");
(m_deferredShaders[MM_TEXTURE_READS_ONLY][DEFERRED_SHADER_POINT] = grmShaderFactory::GetInstance().Create())->Load("pointMS0");
(m_deferredShaders[MM_TEXTURE_READS_ONLY][DEFERRED_SHADER_CAPSULE] = grmShaderFactory::GetInstance().Create())->Load("capsuleMS0");
(m_deferredShaders[MM_TEXTURE_READS_ONLY][DEFERRED_SHADER_TILED] = grmShaderFactory::GetInstance().Create())->Load("tiled_lightingMS0");
m_edgeMarkTechniqueIdx = m_deferredShaders[MM_TEXTURE_READS_ONLY][DEFERRED_SHADER_LIGHTING]->LookupTechnique("EdgeMark");
m_edgeMarkParamsVar = m_deferredShaders[MM_TEXTURE_READS_ONLY][DEFERRED_SHADER_LIGHTING]->LookupVar("EdgeMarkParams");
m_edgeCopyTextureVar = m_deferredShaders[MM_TEXTURE_READS_ONLY][DEFERRED_SHADER_LIGHTING]->LookupVar("StencilCopy");
#endif //MSAA_EDGE_PASS
}
else
#endif //DEVICE_MSAA
{
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_LIGHTING] ->Load("deferred_lighting");
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_AMBIENT] ->Load("deferred_ambient");
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_DIRECTIONAL] ->Load("directional");
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_SPOT] ->Load("spot");
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_POINT] ->Load("point");
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_CAPSULE] ->Load("capsule");
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_TILED] ->Load("tiled_lighting");
}
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_VOLUME]->Load("deferred_volume");
#if __BANK
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_DEBUG] = grmShaderFactory::GetInstance().Create();
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_DEBUG]->Load("debug_rendering");
#endif
// only for tiled_lighting until further notice.
#if GENERATE_SHMOO
for(int i=0;i<NUM_DEFERRD_SHADERS;i++)
{
m_deferredShadersShmoos[i] = -1;
}
#endif
GENSHMOO_ONLY(m_deferredShadersShmoos[DEFERRED_SHADER_TILED] = ) ShmooHandling::Register("tiled_lighting",m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_TILED],true,0.0f);
ASSET.PopFolder();
for(u32 i = 0; i < NUM_DEFERRED_SHADER_GLOBAL_VARS; i++)
{
m_deferredShaderGlobalVars[i] = grcEffect::LookupGlobalVar(m_deferredShaderGlobalVarNames[i], m_deferredShaderGlobalVarRequired[i]);
}
// Look-up all the shared vars for all the deferred shaders
for (int aaMode = 0; aaMode != MM_TOTAL; ++aaMode)
{
#if DEVICE_MSAA
if (!m_bSupportMSAAandNonMSAA && aaMode != MM_DEFAULT)
continue;
#endif
for (u32 i = 0; i < NUM_DEFERRD_SHADERS; i++)
{
for (u32 j = 0; j < NUM_DEFERRED_SHADER_VARS; j++)
{
if (m_deferredShaders[aaMode][i])
{
m_deferredShaderVars[aaMode][i][j] = m_deferredShaders[aaMode][i]->LookupVar(m_deferredShaderVarNames[j], false);
}
}
}
}
#if __D3D11 || RSG_ORBIS
m_shaderDownsampledDepthSampler = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_TILED]->LookupVar("downsampledDepthSampler");
#endif
#if ENABLE_PED_PASS_AA_SOURCE
m_shaderLightTextureAA = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_LIGHTING]->LookupVar("deferredLightTextureAA");
#endif
m_shaderLightParameterID_skinColourTweak = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_LIGHTING]->LookupVar("skinColourTweak", true);
m_shaderLightParameterID_skinParams = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_LIGHTING]->LookupVar("skinParams", true);
#if !__FINAL
m_debugLightingParamsID = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_DIRECTIONAL]->LookupVar("DebugLightingParams");
#endif // !__FINAL
// Volume shading techniques
{
grmShader *const volume = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_VOLUME];
m_shaderVolumeParameterID_deferredVolumePosition = volume->LookupVar("deferredVolumePosition", true);
m_shaderVolumeParameterID_deferredVolumeDirection = volume->LookupVar("deferredVolumeDirection", true);
m_shaderVolumeParameterID_deferredVolumeTangentXAndShaftRadius = volume->LookupVar("deferredVolumeTangentXAndShaftRadius", true);
m_shaderVolumeParameterID_deferredVolumeTangentYAndShaftLength = volume->LookupVar("deferredVolumeTangentYAndShaftLength", true);
m_shaderVolumeParameterID_deferredVolumeColour = volume->LookupVar("deferredVolumeColour", true);
m_shaderVolumeParameterID_deferredVolumeShaftPlanes = volume->LookupVar("deferredVolumeShaftPlanes", true);
m_shaderVolumeParameterID_deferredVolumeShaftGradient = volume->LookupVar("deferredVolumeShaftGradient", true);
m_shaderVolumeParameterID_deferredVolumeShaftGradientColourInv = volume->LookupVar("deferredVolumeShaftGradientColourInv", true);
m_shaderVolumeParameterID_deferredVolumeShaftCompositeMtx = volume->LookupVar("deferredVolumeShaftCompositeMtx", true);
m_shaderVolumeParameterID_deferredVolumeDepthBuffer = volume->LookupVar("deferredVolumeDepthBuffer", true);
m_shaderVolumeParameterID_deferredVolumeOffscreenBuffer = volume->LookupVar("gVolumeLightsTexture");
#if LIGHT_VOLUME_USE_LOW_RESOLUTION
m_shaderVolumeParameterID_deferredVolumeLowResDepthBuffer = volume->LookupVar("gLowResDepthTexture");
#endif
}
// Deferred lighting techniques: Spot, Point, Capsule
for (int aaMode = 0; aaMode != MM_TOTAL; ++aaMode)
{
#if DEVICE_MSAA
if (!m_bSupportMSAAandNonMSAA && aaMode != MM_DEFAULT)
continue;
#endif
m_techniques[aaMode][DEFERRED_TECHNIQUE_SPOTCM] = m_deferredShaders[aaMode][DEFERRED_SHADER_SPOT] ->LookupTechnique("spotCM");
m_techniques[aaMode][DEFERRED_TECHNIQUE_SPOTCM_VOLUME] = m_deferredShaders[aaMode][DEFERRED_SHADER_SPOT] ->LookupTechnique("spotCM_volume");
m_techniques[aaMode][DEFERRED_TECHNIQUE_POINTCM] = m_deferredShaders[aaMode][DEFERRED_SHADER_POINT] ->LookupTechnique("pointCM");
m_techniques[aaMode][DEFERRED_TECHNIQUE_POINTCM_VOLUME] = m_deferredShaders[aaMode][DEFERRED_SHADER_POINT] ->LookupTechnique("pointCM_volume");
m_techniques[aaMode][DEFERRED_TECHNIQUE_CAPSULE] = m_deferredShaders[aaMode][DEFERRED_SHADER_CAPSULE]->LookupTechnique("capsule");
m_techniques[aaMode][DEFERRED_TECHNIQUE_CAPSULE_VOLUME] = m_deferredShaders[aaMode][DEFERRED_SHADER_CAPSULE]->LookupTechnique("capsule_volume");
}
// Deferred lighting techniques: Ambient, Directional, Tiled
m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_AMBIENT_VOLUME] = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_LIGHTING] ->LookupTechnique("ambientScaleVolume");
m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_DIRECTIONAL] = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_DIRECTIONAL]->LookupTechnique("directional");
m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_TILED_DIRECTIONAL] = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_TILED] ->LookupTechnique("tiled_directional");
m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_TILED_AMBIENT] = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_TILED] ->LookupTechnique("tiled_ambient");
m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_TILED_SHADOW] = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_TILED] ->LookupTechnique("tiled_shadow");
m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_AMBIENT_LIGHT] = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_AMBIENT] ->LookupTechnique("ambientLight");
#if DEVICE_MSAA
if ( m_bSupportMSAAandNonMSAA )
{
m_techniques[MM_SINGLE][DEFERRED_TECHNIQUE_DIRECTIONAL] = m_deferredShaders[MM_SINGLE][DEFERRED_SHADER_DIRECTIONAL] ->LookupTechnique("directional");
m_techniques[MM_SINGLE][DEFERRED_TECHNIQUE_SSS_SKIN] = m_deferredShaders[MM_SINGLE][DEFERRED_SHADER_LIGHTING] ->LookupTechnique("sss_skin");
#if MSAA_EDGE_PASS
m_techniques[MM_TEXTURE_READS_ONLY][DEFERRED_TECHNIQUE_DIRECTIONAL] = m_deferredShaders[MM_TEXTURE_READS_ONLY][DEFERRED_SHADER_DIRECTIONAL] ->LookupTechnique("directional");
m_techniques[MM_TEXTURE_READS_ONLY][DEFERRED_TECHNIQUE_TILED_DIRECTIONAL] = m_deferredShaders[MM_TEXTURE_READS_ONLY][DEFERRED_SHADER_TILED] ->LookupTechnique("tiled_directional");
m_techniques[MM_TEXTURE_READS_ONLY][DEFERRED_TECHNIQUE_TILED_AMBIENT] = m_deferredShaders[MM_TEXTURE_READS_ONLY][DEFERRED_SHADER_TILED] ->LookupTechnique("tiled_ambient");
m_techniques[MM_TEXTURE_READS_ONLY][DEFERRED_TECHNIQUE_TILED_SHADOW] = m_deferredShaders[MM_TEXTURE_READS_ONLY][DEFERRED_SHADER_TILED] ->LookupTechnique("tiled_shadow");
#endif //MSAA_EDGE_PASS
}
#endif
m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_SSS_SKIN] = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_LIGHTING]->LookupTechnique("sss_skin");
m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_VOLUME_INTERLEAVE_RECONSTRUCTION] = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_VOLUME]->LookupTechnique("volume_Interleave_Reconstruction");
m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_SNOW] = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_LIGHTING]->LookupTechnique("snow");
m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_FOLIAGE_PREPROCESS] = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_LIGHTING]->LookupTechnique("foliage_preprocess");
// Deferred volume lighting techniques
m_shaderLightShaftVolumeTechniques[LIGHTSHAFT_VOLUMETYPE_SHAFT] = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_VOLUME]->LookupTechnique("volumeShaft_SHAFT");
m_shaderLightShaftVolumeTechniques[LIGHTSHAFT_VOLUMETYPE_CYLINDER] = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_VOLUME]->LookupTechnique("volumeShaft_CYLINDER");
// Try to find the default deferred technique group.
m_deferredTechniqueGroupId = grmShaderFx::FindTechniqueGroupId("deferred");
m_deferredAlphaClipTechniqueGroupId = grmShaderFx::FindTechniqueGroupId("deferredalphaclip");
m_deferredSSAAlphaClipTechniqueGroupId = grmShaderFx::FindTechniqueGroupId("deferredsubsamplealphaclip");
m_deferredSubSampleAlphaTechniqueGroupId = grmShaderFx::FindTechniqueGroupId("deferredsubsamplealpha");
m_deferredSubSampleWriteAlphaTechniqueGroupId = grmShaderFx::FindTechniqueGroupId("deferredsubsamplewritealpha");
// cutscene optimisation technique
m_deferredCutsceneTechniqueGroupId = grmShaderFx::FindTechniqueGroupId("deferredcutscene");
Assert(-1 != m_deferredTechniqueGroupId);
Assert(-1 != m_deferredCutsceneTechniqueGroupId);
Assert(-1 != m_deferredAlphaClipTechniqueGroupId);
Assert(-1 != m_deferredSSAAlphaClipTechniqueGroupId);
Assert(-1 != m_deferredSubSampleAlphaTechniqueGroupId);
Assert(-1 != m_deferredSubSampleWriteAlphaTechniqueGroupId);
// Setup render state blocks
}
void DeferredLighting::InitRenderStates()
{
// Default entry state
grcDepthStencilStateDesc defaultStateDS;
defaultStateDS.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_LESSEQUAL);
m_defaultState_DS = grcStateBlock::CreateDepthStencilState(defaultStateDS,"m_defaultState_DS");
// Exit state
grcRasterizerStateDesc defaultExitStateR;
defaultExitStateR.CullMode = grcRSV::CULL_NONE;
m_defaultExitState_R = grcStateBlock::CreateRasterizerState(defaultExitStateR,"m_defaultExitState_R");
grcBlendStateDesc defaultExitStateB;
defaultExitStateB.BlendRTDesc[0].BlendEnable = TRUE;
defaultExitStateB.BlendRTDesc[0].DestBlend = grcRSV::BLEND_INVSRCALPHA;
defaultExitStateB.BlendRTDesc[0].SrcBlend = grcRSV::BLEND_SRCALPHA;
m_defaultExitState_B = grcStateBlock::CreateBlendState(defaultExitStateB,"m_defaultExitState_B");
grcDepthStencilStateDesc defaultExitStateDS;
defaultExitStateDS.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_LESSEQUAL);
m_defaultExitState_DS = grcStateBlock::CreateDepthStencilState(defaultExitStateDS,"m_defaultExitState_DS");
const int colorMask = grcRSV::COLORWRITEENABLE_RGB;
// Geometry Pass
grcDepthStencilStateDesc geometryPassDS;
geometryPassDS.StencilEnable = TRUE;
geometryPassDS.FrontFace.StencilPassOp = grcRSV::STENCILOP_REPLACE;
geometryPassDS.BackFace.StencilPassOp = grcRSV::STENCILOP_REPLACE;
geometryPassDS.FrontFace.StencilFunc = grcRSV::CMP_ALWAYS;
geometryPassDS.BackFace.StencilFunc = grcRSV::CMP_ALWAYS;
geometryPassDS.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_LESSEQUAL);
m_geometryPass_DS = grcStateBlock::CreateDepthStencilState(geometryPassDS,"m_geometryPass_DS");
grcBlendStateDesc geometryPassB;
geometryPassB.IndependentBlendEnable = TRUE;
geometryPassB.BlendRTDesc[GBUFFER_RT_0].RenderTargetWriteMask = colorMask;
geometryPassB.BlendRTDesc[GBUFFER_RT_1].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;
geometryPassB.BlendRTDesc[GBUFFER_RT_2].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;
geometryPassB.BlendRTDesc[GBUFFER_RT_3].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;
m_geometryPass_B = grcStateBlock::CreateBlendState(geometryPassB,"m_geometryPass_B");
// Decal Pass
grcDepthStencilStateDesc decalPassDS;
decalPassDS.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_LESSEQUAL);
decalPassDS.DepthWriteMask = FALSE;
m_decalPass_DS = grcStateBlock::CreateDepthStencilState(decalPassDS,"m_decalPass_DS");
grcBlendStateDesc decalPassB;
decalPassB.IndependentBlendEnable = TRUE;
decalPassB.BlendRTDesc[GBUFFER_RT_0].BlendEnable = TRUE;
decalPassB.BlendRTDesc[GBUFFER_RT_0].DestBlend = grcRSV::BLEND_INVSRCALPHA;
decalPassB.BlendRTDesc[GBUFFER_RT_0].SrcBlend = grcRSV::BLEND_SRCALPHA;
decalPassB.BlendRTDesc[GBUFFER_RT_0].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_RGB;
decalPassB.BlendRTDesc[GBUFFER_RT_1].BlendEnable = TRUE;
decalPassB.BlendRTDesc[GBUFFER_RT_1].DestBlend = grcRSV::BLEND_INVSRCALPHA;
decalPassB.BlendRTDesc[GBUFFER_RT_1].SrcBlend = grcRSV::BLEND_SRCALPHA;
decalPassB.BlendRTDesc[GBUFFER_RT_1].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_NONE;
decalPassB.BlendRTDesc[GBUFFER_RT_2].BlendEnable = TRUE;
decalPassB.BlendRTDesc[GBUFFER_RT_2].DestBlend = grcRSV::BLEND_INVSRCALPHA;
decalPassB.BlendRTDesc[GBUFFER_RT_2].SrcBlend = grcRSV::BLEND_SRCALPHA;
decalPassB.BlendRTDesc[GBUFFER_RT_2].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_RED + grcRSV::COLORWRITEENABLE_GREEN;
decalPassB.BlendRTDesc[GBUFFER_RT_3].BlendEnable = TRUE;
decalPassB.BlendRTDesc[GBUFFER_RT_3].DestBlend = grcRSV::BLEND_INVSRCALPHA;
decalPassB.BlendRTDesc[GBUFFER_RT_3].SrcBlend = grcRSV::BLEND_SRCALPHA;
decalPassB.BlendRTDesc[GBUFFER_RT_3].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_RGB;
m_decalPass_B = grcStateBlock::CreateBlendState(decalPassB,"m_decalPass_B");
// Fade Pass
grcDepthStencilStateDesc fadePassDS;
fadePassDS.StencilEnable = TRUE;
fadePassDS.StencilWriteMask = 0xF;
fadePassDS.FrontFace.StencilPassOp = grcRSV::STENCILOP_REPLACE;
fadePassDS.BackFace.StencilPassOp = fadePassDS.FrontFace.StencilPassOp;
fadePassDS.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_LESSEQUAL);
m_fadePass_DS = grcStateBlock::CreateDepthStencilState(fadePassDS,"m_fadePass_DS");
#if MSAA_EDGE_PROCESS_FADING
fadePassDS.StencilWriteMask |= EDGE_FLAG;
m_fadePassAA_DS = grcStateBlock::CreateDepthStencilState(fadePassDS,"m_fadePassAA_DS");
#endif //MSAA_EDGE_PROCESS_FADING
grcBlendStateDesc fadePassB;
fadePassB.IndependentBlendEnable = TRUE;
fadePassB.BlendRTDesc[GBUFFER_RT_0].RenderTargetWriteMask = colorMask;
fadePassB.BlendRTDesc[GBUFFER_RT_1].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;//RGB
fadePassB.BlendRTDesc[GBUFFER_RT_2].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;//RGB
fadePassB.BlendRTDesc[GBUFFER_RT_3].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;//NONE
m_fadePass_B = grcStateBlock::CreateBlendState(fadePassB,"m_fadePass_B");
// Cutout Pass
grcBlendStateDesc cutoutPassB;
cutoutPassB.IndependentBlendEnable = TRUE;
cutoutPassB.BlendRTDesc[GBUFFER_RT_0].RenderTargetWriteMask = colorMask;
cutoutPassB.BlendRTDesc[GBUFFER_RT_1].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;//RGB; // go ahead and overwrite twiddle
cutoutPassB.BlendRTDesc[GBUFFER_RT_2].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;
cutoutPassB.BlendRTDesc[GBUFFER_RT_3].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL; //RGB - need for fresnel
cutoutPassB.AlphaToCoverageEnable = (GRCDEVICE.GetMSAA() ? TRUE : FALSE);
#if DEVICE_EQAA
cutoutPassB.AlphaToMaskOffsets = GRCDEVICE.GetMSAA().m_uFragments == 1 && false ? //enable dithering for S/1 modes? No
grcRSV::ALPHATOMASKOFFSETS_DITHERED : grcRSV::ALPHATOMASKOFFSETS_SOLID;
#endif //DEVICE_EQAA
m_cutoutPass_B = grcStateBlock::CreateBlendState(cutoutPassB,"m_cutoutPass_B");
grcDepthStencilStateDesc cutoutPassDS;
cutoutPassDS.StencilEnable = TRUE;
cutoutPassDS.FrontFace.StencilPassOp = grcRSV::STENCILOP_REPLACE;
cutoutPassDS.BackFace = cutoutPassDS.FrontFace;
cutoutPassDS.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_LESSEQUAL);
m_cutoutPass_DS= grcStateBlock::CreateDepthStencilState(cutoutPassDS,"m_cutoutPass_DS");
#if STENCIL_VEHICLE_INTERIOR
grcDepthStencilStateDesc treePassDS;
treePassDS.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_LESS);
treePassDS.StencilEnable = TRUE;
treePassDS.StencilReadMask = DEFERRED_MATERIAL_INTERIOR_VEH;
treePassDS.StencilWriteMask = DEFERRED_MATERIAL_NOT_INTERIOR_VEH;
treePassDS.FrontFace.StencilFunc = grcRSV::CMP_EQUAL;
treePassDS.FrontFace.StencilFailOp = grcRSV::STENCILOP_KEEP;
treePassDS.FrontFace.StencilPassOp = grcRSV::STENCILOP_REPLACE;
treePassDS.BackFace = treePassDS.FrontFace;
m_treePass_DS = grcStateBlock::CreateDepthStencilState(treePassDS);
#endif
// Default
grcDepthStencilStateDesc defaultPassDS;
defaultPassDS.StencilEnable = TRUE;
defaultPassDS.FrontFace.StencilPassOp = grcRSV::STENCILOP_REPLACE;
defaultPassDS.BackFace.StencilPassOp = grcRSV::STENCILOP_REPLACE;
defaultPassDS.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_LESSEQUAL);
m_defaultPass_DS = grcStateBlock::CreateDepthStencilState(defaultPassDS);
grcBlendStateDesc defaultPassB;
defaultPassB.IndependentBlendEnable = TRUE;
defaultPassB.BlendRTDesc[GBUFFER_RT_0].RenderTargetWriteMask = colorMask;
defaultPassB.BlendRTDesc[GBUFFER_RT_1].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;
defaultPassB.BlendRTDesc[GBUFFER_RT_2].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;
defaultPassB.BlendRTDesc[GBUFFER_RT_3].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;
m_defaultPass_B = grcStateBlock::CreateBlendState(defaultPassB, "m_defaultPass_B");
// Ambient Directional Pass
grcBlendStateDesc directionalPassBlendState;
directionalPassBlendState.BlendRTDesc[0].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_RGB;
m_directionalPass_B = grcStateBlock::CreateBlendState(directionalPassBlendState,"m_directionalPass_B");
grcDepthStencilStateDesc directionalFullPassDepthStencilState;
directionalFullPassDepthStencilState.DepthEnable = FALSE;
directionalFullPassDepthStencilState.DepthWriteMask = FALSE;
directionalFullPassDepthStencilState.DepthFunc = grcRSV::CMP_LESS;
directionalFullPassDepthStencilState.StencilEnable = TRUE;
directionalFullPassDepthStencilState.StencilWriteMask = 0;
directionalFullPassDepthStencilState.StencilReadMask = 0xfB;
directionalFullPassDepthStencilState.FrontFace.StencilFunc = grcRSV::CMP_NOTEQUAL;
directionalFullPassDepthStencilState.BackFace.StencilFunc = grcRSV::CMP_NOTEQUAL;
m_directionalFullPass_DS = grcStateBlock::CreateDepthStencilState(directionalFullPassDepthStencilState,"m_directionalFullPass_DS");
grcDepthStencilStateDesc directionalAmbientPassDepthStencilState;
directionalAmbientPassDepthStencilState.DepthEnable = FALSE;
directionalAmbientPassDepthStencilState.DepthWriteMask = FALSE;
directionalAmbientPassDepthStencilState.DepthFunc = grcRSV::CMP_LESS;
directionalAmbientPassDepthStencilState.StencilEnable = TRUE;
directionalAmbientPassDepthStencilState.StencilWriteMask = 0;
directionalAmbientPassDepthStencilState.StencilReadMask = 0xff;
directionalAmbientPassDepthStencilState.FrontFace.StencilFunc = grcRSV::CMP_NOTEQUAL;
directionalAmbientPassDepthStencilState.BackFace.StencilFunc = grcRSV::CMP_NOTEQUAL;
m_directionalAmbientPass_DS = grcStateBlock::CreateDepthStencilState(directionalAmbientPassDepthStencilState,"m_directionalAmbientPass_DS");
grcDepthStencilStateDesc directionalNoStencilPassDepthStencilState;
directionalNoStencilPassDepthStencilState.DepthEnable = FALSE;
directionalNoStencilPassDepthStencilState.DepthWriteMask = FALSE;
directionalNoStencilPassDepthStencilState.DepthFunc = grcRSV::CMP_LESS;
m_directionalNoStencilPass_DS = grcStateBlock::CreateDepthStencilState(directionalNoStencilPassDepthStencilState,"m_directionalNoStencilPass_DS");
#if MSAA_EDGE_PASS
grcDepthStencilStateDesc directionalEdgePassDSS;
directionalEdgePassDSS.DepthEnable = FALSE;
directionalEdgePassDSS.DepthWriteMask = FALSE;
directionalEdgePassDSS.StencilEnable = TRUE;
directionalEdgePassDSS.StencilWriteMask = 0;
directionalEdgePassDSS.StencilReadMask = EDGE_FLAG;
directionalEdgePassDSS.FrontFace.StencilFunc = grcRSV::CMP_EQUAL;
directionalEdgePassDSS.BackFace.StencilFunc = grcRSV::CMP_EQUAL;
m_directionalEdgeMaskEqualPass_DS = grcStateBlock::CreateDepthStencilState(directionalEdgePassDSS, "m_directionalEdgeMaskEqualPass_DS");
directionalEdgePassDSS.StencilReadMask = EDGE_FLAG | 0x7;
m_directionalEdgeAllEqualPass_DS = grcStateBlock::CreateDepthStencilState(directionalEdgePassDSS, "m_directionalEdgeAllEqualPass_DS");
directionalEdgePassDSS.FrontFace.StencilFunc = grcRSV::CMP_NOTEQUAL;
directionalEdgePassDSS.BackFace.StencilFunc = grcRSV::CMP_NOTEQUAL;
m_directionalEdgeNotEqualPass_DS = grcStateBlock::CreateDepthStencilState(directionalEdgePassDSS, "m_directionalEdgeNotEqualPass_DS");
directionalEdgePassDSS.StencilReadMask = EDGE_FLAG | 0x1;
directionalEdgePassDSS.FrontFace.StencilFunc = grcRSV::CMP_EQUAL;
directionalEdgePassDSS.BackFace.StencilFunc = grcRSV::CMP_EQUAL;
m_directionalEdgeBit0EqualPass_DS = grcStateBlock::CreateDepthStencilState(directionalEdgePassDSS, "m_directionalEdgeBit0EqualPass_DS");
directionalEdgePassDSS.StencilReadMask = EDGE_FLAG | 0x4;
m_directionalEdgeBit2EqualPass_DS = grcStateBlock::CreateDepthStencilState(directionalEdgePassDSS, "m_directionalEdgeBit2EqualPass_DS");
#endif //MSAA_EDGE_PASS
grcRasterizerStateDesc directionalPassRasterizerState;
directionalPassRasterizerState.CullMode = grcRSV::CULL_NONE;
m_directionalPass_R = grcStateBlock::CreateRasterizerState(directionalPassRasterizerState,"m_directionalPass_R");
// Foliage PrePass:
grcDepthStencilStateDesc foliagePrePassDSS;
foliagePrePassDSS.DepthEnable = FALSE;
foliagePrePassDSS.DepthWriteMask = FALSE;
foliagePrePassDSS.DepthFunc = grcRSV::CMP_LESS;
foliagePrePassDSS.StencilEnable = TRUE;
foliagePrePassDSS.StencilReadMask = DEFERRED_MATERIAL_TYPE_MASK;
foliagePrePassDSS.StencilWriteMask = DEFERRED_MATERIAL_SPECIALBIT;
foliagePrePassDSS.FrontFace.StencilFunc = grcRSV::CMP_EQUAL;
foliagePrePassDSS.FrontFace.StencilFailOp = grcRSV::STENCILOP_KEEP;
foliagePrePassDSS.FrontFace.StencilDepthFailOp = grcRSV::STENCILOP_KEEP;
foliagePrePassDSS.FrontFace.StencilPassOp = grcRSV::STENCILOP_REPLACE;
foliagePrePassDSS.BackFace.StencilFunc = grcRSV::CMP_EQUAL;
foliagePrePassDSS.BackFace.StencilFailOp = grcRSV::STENCILOP_KEEP;
foliagePrePassDSS.BackFace.StencilDepthFailOp = grcRSV::STENCILOP_KEEP;
foliagePrePassDSS.BackFace.StencilPassOp = grcRSV::STENCILOP_REPLACE;
m_foliagePrePass_DS = grcStateBlock::CreateDepthStencilState(foliagePrePassDSS,"m_foliagePrePass_DS");
grcDepthStencilStateDesc foliageMainPassDSS;
foliageMainPassDSS.DepthEnable = FALSE;
foliageMainPassDSS.DepthWriteMask = FALSE;
foliageMainPassDSS.DepthFunc = grcRSV::CMP_LESS;
foliageMainPassDSS.StencilEnable = TRUE;
foliageMainPassDSS.StencilReadMask = DEFERRED_MATERIAL_TREE|DEFERRED_MATERIAL_SPECIALBIT;
foliageMainPassDSS.StencilWriteMask = DEFERRED_MATERIAL_SPECIALBIT;
foliageMainPassDSS.FrontFace.StencilFunc = grcRSV::CMP_EQUAL;
foliageMainPassDSS.FrontFace.StencilFailOp = grcRSV::STENCILOP_KEEP;
foliageMainPassDSS.FrontFace.StencilDepthFailOp = grcRSV::STENCILOP_KEEP;
foliageMainPassDSS.FrontFace.StencilPassOp = grcRSV::STENCILOP_ZERO;
foliageMainPassDSS.BackFace.StencilFunc = grcRSV::CMP_EQUAL;
foliageMainPassDSS.BackFace.StencilFailOp = grcRSV::STENCILOP_KEEP;
foliageMainPassDSS.BackFace.StencilDepthFailOp = grcRSV::STENCILOP_KEEP;
foliageMainPassDSS.BackFace.StencilPassOp = grcRSV::STENCILOP_ZERO;
m_foliageMainPass_DS = grcStateBlock::CreateDepthStencilState(foliageMainPassDSS,"m_foliageMainPass_DS");
// Foliage Pass
grcBlendStateDesc foliagePassBlendState;
foliagePassBlendState.BlendRTDesc[0].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;
m_foliagePass_B = grcStateBlock::CreateBlendState(foliagePassBlendState,"m_foliagePass_B");
grcDepthStencilStateDesc foliagePassDepthStencilState;
foliagePassDepthStencilState.DepthEnable = FALSE;
foliagePassDepthStencilState.DepthWriteMask = FALSE;
foliagePassDepthStencilState.DepthFunc = grcRSV::CMP_LESS;
foliagePassDepthStencilState.StencilEnable = TRUE;
foliagePassDepthStencilState.StencilWriteMask = 0;
foliagePassDepthStencilState.StencilReadMask = 0x07;
foliagePassDepthStencilState.FrontFace.StencilFunc = grcRSV::CMP_EQUAL;
foliagePassDepthStencilState.BackFace.StencilFunc = grcRSV::CMP_EQUAL;
m_foliagePass_DS = grcStateBlock::CreateDepthStencilState(foliagePassDepthStencilState,"m_foliagePass_DS");
grcDepthStencilStateDesc foliageNoStencilPassDepthStencilState;
foliageNoStencilPassDepthStencilState.DepthEnable = FALSE;
foliageNoStencilPassDepthStencilState.DepthWriteMask = FALSE;
foliageNoStencilPassDepthStencilState.DepthFunc = grcRSV::CMP_LESS;
m_foliageNoStencilPass_DS = grcStateBlock::CreateDepthStencilState(foliageNoStencilPassDepthStencilState,"m_foliageNoStencilPass_DS");
grcRasterizerStateDesc foliagePassRasterizerState;
foliagePassRasterizerState.CullMode = grcRSV::CULL_NONE;
m_foliagePass_R = grcStateBlock::CreateRasterizerState(foliagePassRasterizerState,"m_foliagePass_R");
// Skin pass
grcBlendStateDesc skinPassBlendState;
skinPassBlendState.BlendRTDesc[0].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_RGB;
skinPassBlendState.BlendRTDesc[0].BlendEnable = true;
skinPassBlendState.BlendRTDesc[0].SrcBlend = grcRSV::BLEND_SRCALPHA;
skinPassBlendState.BlendRTDesc[0].DestBlend = grcRSV::BLEND_INVSRCALPHA;
skinPassBlendState.BlendRTDesc[0].BlendOp = grcRSV::BLENDOP_ADD;
m_skinPass_B = grcStateBlock::CreateBlendState(skinPassBlendState,"m_skinPass_B");
grcDepthStencilStateDesc skinPassDepthStencilState;
skinPassDepthStencilState.DepthEnable = FALSE;
skinPassDepthStencilState.DepthWriteMask = FALSE;
skinPassDepthStencilState.DepthFunc = grcRSV::CMP_LESS;
skinPassDepthStencilState.StencilEnable = TRUE;
skinPassDepthStencilState.StencilWriteMask = 0;
skinPassDepthStencilState.StencilReadMask = 0x07;
skinPassDepthStencilState.FrontFace.StencilFunc = grcRSV::CMP_EQUAL;
skinPassDepthStencilState.BackFace.StencilFunc = grcRSV::CMP_EQUAL;
m_skinPass_DS = grcStateBlock::CreateDepthStencilState(skinPassDepthStencilState,"m_skinPass_DS");
skinPassDepthStencilState.FrontFace.StencilFunc = grcRSV::CMP_NOTEQUAL;
skinPassDepthStencilState.BackFace.StencilFunc = grcRSV::CMP_NOTEQUAL;
m_skinPass_UI_DS = grcStateBlock::CreateDepthStencilState(skinPassDepthStencilState,"m_skinPass_UI_DS");
grcDepthStencilStateDesc dsdTest;
dsdTest.DepthEnable = TRUE;
dsdTest.DepthWriteMask = FALSE;
dsdTest.DepthFunc = grcRSV::CMP_ALWAYS;
dsdTest.StencilEnable = TRUE;
dsdTest.StencilReadMask = 0xff;
dsdTest.StencilWriteMask = 0x00;
dsdTest.FrontFace.StencilFunc = grcRSV::CMP_NOTEQUAL;
dsdTest.BackFace.StencilFunc = grcRSV::CMP_NOTEQUAL;
m_skinPassForward_DS = grcStateBlock::CreateDepthStencilState(dsdTest,"m_skinPassForward_DS");
grcDepthStencilStateDesc skinNoStencilPassDepthStencilState;
skinNoStencilPassDepthStencilState.DepthEnable = FALSE;
skinNoStencilPassDepthStencilState.DepthWriteMask = FALSE;
skinNoStencilPassDepthStencilState.DepthFunc = grcRSV::CMP_LESS;
m_skinNoStencilPass_DS = grcStateBlock::CreateDepthStencilState(skinNoStencilPassDepthStencilState,"m_skinNoStencilPass_DS");
grcRasterizerStateDesc skinPassRasterizerState;
skinPassRasterizerState.CullMode = grcRSV::CULL_NONE;
m_skinPass_R = grcStateBlock::CreateRasterizerState(skinPassRasterizerState,"m_skinPass_R");
// Tiled lighting
grcDepthStencilStateDesc tiledLightingDepthStencilState;
tiledLightingDepthStencilState.DepthEnable = FALSE;
tiledLightingDepthStencilState.DepthWriteMask = FALSE;
tiledLightingDepthStencilState.DepthFunc = grcRSV::CMP_LESS;
tiledLightingDepthStencilState.StencilEnable = TRUE;
tiledLightingDepthStencilState.StencilWriteMask = 0;
tiledLightingDepthStencilState.StencilReadMask = 0xfB;
tiledLightingDepthStencilState.FrontFace.StencilFunc = grcRSV::CMP_NOTEQUAL;
tiledLightingDepthStencilState.BackFace.StencilFunc = grcRSV::CMP_NOTEQUAL;
m_tiledLighting_DS = grcStateBlock::CreateDepthStencilState(tiledLightingDepthStencilState,"m_tiledLighting_DS");
// Sub Sample Alpha
grcBlendStateDesc bsDescSingleSampleSSA;
bsDescSingleSampleSSA.BlendRTDesc[GBUFFER_RT_0].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;
bsDescSingleSampleSSA.BlendRTDesc[GBUFFER_RT_1].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;
bsDescSingleSampleSSA.BlendRTDesc[GBUFFER_RT_2].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL;
bsDescSingleSampleSSA.BlendRTDesc[GBUFFER_RT_3].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_ALL; // should be RGB?
// we could use alpha-to-coverage for SSA, however it does not produce better results (see B#590459)
bsDescSingleSampleSSA.AlphaToCoverageEnable = (0 && GRCDEVICE.GetMSAA() ? TRUE : FALSE);
m_SingleSampleSSABlendState = grcStateBlock::CreateBlendState(bsDescSingleSampleSSA,"m_SingleSampleSSABlendState");
Assert(m_SingleSampleSSABlendState != grcStateBlock::BS_Invalid);
grcBlendStateDesc bsDescSSA = bsDescSingleSampleSSA;
bsDescSSA.IndependentBlendEnable = TRUE;
bsDescSSA.BlendRTDesc[0].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_RGB;
m_SSABlendState = grcStateBlock::CreateBlendState(bsDescSSA,"m_SSABlendState");
Assert(m_SSABlendState != grcStateBlock::BS_Invalid);
#if MSAA_EDGE_PASS
m_edgePass_R = grcStateBlock::RS_NoBackfaceCull;
grcDepthStencilStateDesc edgePassDsd;
edgePassDsd.DepthEnable = false;
edgePassDsd.StencilEnable = true;
edgePassDsd.StencilWriteMask = EDGE_FLAG;
edgePassDsd.StencilReadMask = 0xFF;
edgePassDsd.FrontFace.StencilPassOp = grcRSV::STENCILOP_REPLACE;
edgePassDsd.BackFace.StencilPassOp = grcRSV::STENCILOP_REPLACE;
# if MSAA_EDGE_PROCESS_FADING
// no benefit since we are discarding in the shader -> stencil goes after PS
edgePassDsd.StencilReadMask = EDGE_FLAG;
edgePassDsd.FrontFace.StencilFunc = grcRSV::CMP_NOTEQUAL;
# else
edgePassDsd.StencilReadMask = 0xFF;
# endif //MSAA_EDGE_PROCESS_FADING
edgePassDsd.FrontFace.StencilPassOp = grcRSV::STENCILOP_REPLACE;
edgePassDsd.BackFace = edgePassDsd.FrontFace;
m_edgePass_DS = grcStateBlock::CreateDepthStencilState(edgePassDsd, "m_edgePass_DS");
m_edgePass_B = grcStateBlock::BS_Default_WriteMaskNone;
#endif //MSAA_EDGE_PASS
#if SSA_USES_CONDITIONALRENDER
// Create the conditional query for SSA passes
m_SSAConditionalQuery = GRCDEVICE.CreateConditionalQuery();
Assert( m_SSAConditionalQuery != 0 );
#endif // SSA_USES_CONDITIONALRENDER
// Other setup
InitSetHiStencilCullState();
}
void DeferredLighting::TerminateRenderStates()
{
grcStateBlock::DestroyDepthStencilState(m_defaultState_DS);
grcStateBlock::DestroyRasterizerState(m_defaultExitState_R);
grcStateBlock::DestroyBlendState(m_defaultExitState_B);
grcStateBlock::DestroyDepthStencilState(m_defaultExitState_DS);
grcStateBlock::DestroyDepthStencilState(m_geometryPass_DS);
grcStateBlock::DestroyBlendState(m_geometryPass_B);
grcStateBlock::DestroyDepthStencilState(m_decalPass_DS);
grcStateBlock::DestroyBlendState(m_decalPass_B);
grcStateBlock::DestroyDepthStencilState(m_fadePass_DS);
#if MSAA_EDGE_PROCESS_FADING
grcStateBlock::DestroyDepthStencilState(m_fadePassAA_DS);
#endif
grcStateBlock::DestroyBlendState(m_fadePass_B);
grcStateBlock::DestroyBlendState(m_cutoutPass_B);
grcStateBlock::DestroyDepthStencilState(m_cutoutPass_DS);
grcStateBlock::DestroyDepthStencilState(m_treePass_DS);
grcStateBlock::DestroyDepthStencilState(m_defaultPass_DS);
grcStateBlock::DestroyBlendState(m_defaultPass_B);
grcStateBlock::DestroyBlendState(m_directionalPass_B);
grcStateBlock::DestroyDepthStencilState(m_directionalFullPass_DS);
grcStateBlock::DestroyDepthStencilState(m_directionalAmbientPass_DS);
grcStateBlock::DestroyDepthStencilState(m_directionalNoStencilPass_DS);
#if MSAA_EDGE_PASS
grcStateBlock::DestroyDepthStencilState(m_directionalEdgeMaskEqualPass_DS);
grcStateBlock::DestroyDepthStencilState(m_directionalEdgeAllEqualPass_DS);
grcStateBlock::DestroyDepthStencilState(m_directionalEdgeNotEqualPass_DS);
grcStateBlock::DestroyDepthStencilState(m_directionalEdgeBit0EqualPass_DS);
grcStateBlock::DestroyDepthStencilState(m_directionalEdgeBit2EqualPass_DS);
grcStateBlock::DestroyDepthStencilState(m_edgePass_DS);
#endif // MSAA_EDGE_PASS
grcStateBlock::DestroyDepthStencilState(m_foliagePrePass_DS);
grcStateBlock::DestroyDepthStencilState(m_foliageMainPass_DS);
grcStateBlock::DestroyRasterizerState(m_directionalPass_R);
grcStateBlock::DestroyBlendState(m_foliagePass_B);
grcStateBlock::DestroyDepthStencilState(m_foliagePass_DS);
grcStateBlock::DestroyDepthStencilState(m_foliageNoStencilPass_DS);
grcStateBlock::DestroyRasterizerState(m_foliagePass_R);
grcStateBlock::DestroyBlendState(m_skinPass_B);
grcStateBlock::DestroyDepthStencilState(m_skinPass_DS);
grcStateBlock::DestroyDepthStencilState(m_skinPass_UI_DS);
grcStateBlock::DestroyDepthStencilState(m_skinPassForward_DS);
grcStateBlock::DestroyDepthStencilState(m_skinNoStencilPass_DS);
grcStateBlock::DestroyRasterizerState(m_skinPass_R);
grcStateBlock::DestroyDepthStencilState(m_tiledLighting_DS);
grcStateBlock::DestroyBlendState(m_SingleSampleSSABlendState);
grcStateBlock::DestroyBlendState(m_SSABlendState);
TerminateHiStencilCullState();
}
void DeferredLighting::Init()
{
sysMemUseMemoryBucket b(MEMBUCKET_RENDER);
InitShaders();
InitRenderStates();
GBuffer::Init();
PuddlePassSingleton::Instantiate();
m_volumeTexture = CShaderLib::LookupTexture("volume");
#if MSAA_EDGE_PASS
grcTextureFactory::CreateParams params;
# if MSAA_EDGE_USE_DEPTH_COPY
params.Format = grctfD32FS8;
params.Multisample = GRCDEVICE.GetMSAA();
m_edgeMarkDepthCopy = CRenderTargets::CreateRenderTarget(RTMEMPOOL_NONE, "Depth Buffer Copy for EdgeMark pass", grcrtDepthBuffer,
GRCDEVICE.GetWidth(), GRCDEVICE.GetHeight(), 40, &params, 0, m_edgeMarkDepthCopy);
# endif //MSAA_EDGE_USE_DEPTH_COPY
# if __DEV
params.Format = grctfA8R8G8B8;
params.Multisample = grcDevice::MSAA_None;
m_edgeMarkDebugTarget = CRenderTargets::CreateRenderTarget(RTMEMPOOL_NONE, "Edge Mark", grcrtPermanent,
GRCDEVICE.GetWidth(), GRCDEVICE.GetHeight(), 32, &params, 0, m_edgeMarkDebugTarget);
# endif // __BANK
# if MSAA_EDGE_PROCESS_FADING
params.Format = grctfL8;
params.Multisample = grcDevice::MSAA_None;
m_edgeCopyTarget = CRenderTargets::CreateRenderTarget(RTMEMPOOL_NONE, "Edge Copy", grcrtPermanent,
GRCDEVICE.GetWidth(), GRCDEVICE.GetHeight(), 8, &params, 0, m_edgeCopyTarget);
# endif //MSAA_EDGE_PROCESS_FADING
#endif //MSAA_EDGE_PASS
}
void DeferredLighting::PushCutscenePedTechnique(){
Assert(m_prevDeferredPedTechnique == -1 );
int currentTech = grmShaderFx::GetForcedTechniqueGroupId();
if ( currentTech == m_deferredTechniqueGroupId)
{
m_prevDeferredPedTechnique = m_deferredTechniqueGroupId;
Assert(m_prevDeferredPedTechnique != -1 );
grmShaderFx::SetForcedTechniqueGroupId( m_deferredCutsceneTechniqueGroupId );
}
}
void DeferredLighting::PopCutscenePedTechnique(){
if (m_prevDeferredPedTechnique != -1)
{
Assert( m_prevDeferredPedTechnique == m_deferredTechniqueGroupId);
grmShaderFx::SetForcedTechniqueGroupId( m_prevDeferredPedTechnique );
m_prevDeferredPedTechnique = -1;
}
}
#if SSA_USES_CONDITIONALRENDER
void DeferredLighting::BeginSSAConditionalQuery()
{
PIXBegin(0,"SSA Pass");
m_bSSAConditionalQueryIsValid = false;
GRCDEVICE.BeginConditionalQuery(m_SSAConditionalQuery);
}
void DeferredLighting::EndSSAConditionalQuery()
{
Assert(!m_bSSAConditionalQueryIsValid);
GRCDEVICE.EndConditionalQuery(m_SSAConditionalQuery);
m_bSSAConditionalQueryIsValid = true;
PIXEnd(); // "SSA Pass"
}
void DeferredLighting::BeginSSAConditionalRender()
{
if (AssertVerify(m_bSSAConditionalQueryIsValid))
GRCDEVICE.BeginConditionalRender(m_SSAConditionalQuery);
}
void DeferredLighting::EndSSAConditionalRender()
{
if (AssertVerify(m_bSSAConditionalQueryIsValid))
GRCDEVICE.EndConditionalRender(m_SSAConditionalQuery);
m_bSSAConditionalQueryIsValid = false;
}
#endif // SSA_USES_CONDITIONALRENDER
// ----------------------------------------------------------------------------------------------- //
#if !__FINAL
void DeferredLighting::SetDebugLightingParamsV(Vec4f_In params)
{
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_DIRECTIONAL]->SetVar(m_debugLightingParamsID, params);
}
#endif // !__FINAL
// ----------------------------------------------------------------------------------------------- //
#if !__FINAL
void DeferredLighting::SetDebugLightingParams()
{
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_DIRECTIONAL]->SetVar(m_debugLightingParamsID, Vec4f(
1.0f, // not used anymore, but keep as 1 until everyone's rebuilt shaders
BANK_SWITCH(DebugLighting::GetDeferredDiffuseLightAmount(), 1.0f),
1.0f, // not used anymore, but keep as 1 until everyone's rebuilt shaders
0.0f
));
}
#endif // !__FINAL
#if __XENON
static bool debugSwitchZPassModeChange = true;
#endif
// ----------------------------------------------------------------------------------------------- //
#if __PPU && !__SPU
// ----------------------------------------------------------------------------------------------- //
char* DeferredLighting::GetTextureOffsetGcm(grcTextureGCM *texgcm)
{
char* finalTexAddr=NULL;
CellGcmTexture *cellTex = (CellGcmTexture*)texgcm->GetTexturePtr();
Assert(cellTex);
cellGcmIoOffsetToAddress(cellTex->offset, (void**)&finalTexAddr);
Assert(finalTexAddr);
return(finalTexAddr);
}
// ----------------------------------------------------------------------------------------------- //
#endif
// ----------------------------------------------------------------------------------------------- //
template<typename varType>
void DeferredLighting::SetDeferredVar(eDeferredShaders deferredShader, eDeferredShaderVars deferredShaderVar, const varType &var, MultisampleMode aaMode)
{
Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); // this command is forbidden outwith the render thread
#if DEVICE_MSAA
if (!m_bSupportMSAAandNonMSAA)
aaMode = MM_DEFAULT;
#endif
m_deferredShaders[aaMode][deferredShader]->SetVar(m_deferredShaderVars[aaMode][deferredShader][deferredShaderVar], var);
}
// forcing compiler to generate code for grcTexture*
typedef grcTexture* PTexture;
typedef grcRenderTarget* PRenderTarget;
template void DeferredLighting::SetDeferredVar(eDeferredShaders,eDeferredShaderVars,const PTexture&, MultisampleMode aaMode);
template void DeferredLighting::SetDeferredVar(eDeferredShaders,eDeferredShaderVars,const PRenderTarget&, MultisampleMode aaMode);
// ----------------------------------------------------------------------------------------------- //
template<typename varType>
void DeferredLighting::SetDeferredGlobalVar(eDeferredShaderGlobalVars deferredShaderGlobalVar, const varType &var)
{
Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); // this command is forbidden outwith the render thread
grcEffect::SetGlobalVar(m_deferredShaderGlobalVars[deferredShaderGlobalVar], var);
}
// forcing compiler to generate code for grcTexture*
typedef grcTexture* PTexture;
typedef grcRenderTarget* PRenderTarget;
template void DeferredLighting::SetDeferredGlobalVar(eDeferredShaderGlobalVars,const PTexture&);
template void DeferredLighting::SetDeferredGlobalVar(eDeferredShaderGlobalVars,const PRenderTarget&);
// ----------------------------------------------------------------------------------------------- //
template<typename varType>
void DeferredLighting::SetDeferredVarArray(eDeferredShaders deferredShader, eDeferredShaderVars deferredShaderVar, varType var, u32 count, MultisampleMode aaMode)
{
Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); // this command is forbidden outwith the render thread
#if DEVICE_MSAA
if (!m_bSupportMSAAandNonMSAA)
aaMode = MM_DEFAULT;
#endif
m_deferredShaders[aaMode][deferredShader]->SetVar(m_deferredShaderVars[aaMode][deferredShader][deferredShaderVar], var, count);
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::DefaultState()
{
grcStateBlock::SetRasterizerState(grcStateBlock::RS_Default);
grcStateBlock::SetBlendState(grcStateBlock::BS_Default);
grcStateBlock::SetDepthStencilState(m_defaultState_DS);
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::DefaultExitState()
{
grcStateBlock::SetDepthStencilState(m_defaultExitState_DS);
grcStateBlock::SetBlendState(m_defaultExitState_B);
grcStateBlock::SetRasterizerState(m_defaultExitState_R);
grcViewport::SetCurrent(NULL);
}
// ----------------------------------------------------------------------------------------------- //
/******************************************************************************************************************
Following GBuffer Samplers are set to global because there are many light shaders that use them.
If they are local, there is a good chance that they get alloted different sampler slots in each of
the shaders. By declaring them global, we assign specific slots to these samplers, and so it will
always be in the same slot for all shaders that use these samplers. Now we can set them once before
we start rendering the lights, instead of resetting them for each light source. We save around 0.15ms
on the 360 with this change. Following is how the slots are assigned:
GBuffer 0 = s7
GBuffer 1 = s8
GBuffer 2 = s9
GBuffer 3 = s10
GBuffer Stencil = s11
GBuffer Depth = s12
They have the word "Global" appended to their names because this will make sure there is no conflict with other
shaders that use the same name for a local sampler.
********************************************************************************************************************/
void DeferredLighting::SetShaderGBufferTarget(GBufferRT index, const grcTexture* texture)
{
Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER));
switch (index)
{
case GBUFFER_RT_0: // Color texture
case GBUFFER_RT_1:
case GBUFFER_RT_2:
case GBUFFER_RT_3:
grcEffect::SetGlobalVar(m_deferredShaderGlobalVars[DEFERRED_SHADER_GBUFFER_0_GLOBAL + index-GBUFFER_RT_0], texture);
break;
case GBUFFER_DEPTH: // Depth texture:
grcEffect::SetGlobalVar(m_deferredShaderGlobalVars[DEFERRED_SHADER_GBUFFER_DEPTH_GLOBAL], texture);
break;
#if __XENON || __D3D11 || RSG_ORBIS
case GBUFFER_STENCIL: // Stencil texture:
grcEffect::SetGlobalVar(m_deferredShaderGlobalVars[DEFERRED_SHADER_GBUFFER_STENCIL_GLOBAL], texture);
break;
#endif //__XENON || __D3D11 || RSG_ORBIS
#if DEVICE_EQAA
case GBUFFER_FMASK_0: // Fragment mask texture:
case GBUFFER_FMASK_1:
case GBUFFER_FMASK_2:
case GBUFFER_FMASK_3:
grcEffect::SetGlobalVar(m_deferredShaderGlobalVars[DEFERRED_SHADER_GBUFFER_0_FMASK_GLOBAL + index-GBUFFER_FMASK_0], texture);
break;
#endif // DEVICE_MSAA
default:
Assertf(0, "Unknown Gbuffer target %d", index);
}
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::SetShaderGBufferTargets(WIN32PC_ONLY(bool bindDepthCopy))
{
SetShaderGBufferTarget(GBUFFER_RT_0, GBuffer::GetTarget(GBUFFER_RT_0));
SetShaderGBufferTarget(GBUFFER_RT_1, GBuffer::GetTarget(GBUFFER_RT_1));
SetShaderGBufferTarget(GBUFFER_RT_2, GBuffer::GetTarget(GBUFFER_RT_2));
SetShaderGBufferTarget(GBUFFER_RT_3, GBuffer::GetTarget(GBUFFER_RT_3));
#if __PPU
SetShaderGBufferTarget(GBUFFER_DEPTH, CRenderTargets::GetDepthBufferAsColor());
#else // __PPU
#if RSG_PC
if (GRCDEVICE.GetDxFeatureLevel() <= 1000 && bindDepthCopy)
SetShaderGBufferTarget(GBUFFER_DEPTH, CRenderTargets::GetDepthBufferCopy());
else
SetShaderGBufferTarget(GBUFFER_DEPTH, CRenderTargets::GetDepthBuffer());
#else
SetShaderGBufferTarget(GBUFFER_DEPTH, CRenderTargets::GetDepthBuffer());
#endif
#endif // __PPU
#if __XENON
SetShaderGBufferTarget(GBUFFER_STENCIL, CRenderTargets::GetDepthBufferAsColor());
#elif __D3D11 || RSG_ORBIS
#if RSG_PC
if (GRCDEVICE.GetDxFeatureLevel() <= 1000 && bindDepthCopy)
SetShaderGBufferTarget(GBUFFER_STENCIL, CRenderTargets::GetDepthBufferCopy_Stencil());
else
SetShaderGBufferTarget(GBUFFER_STENCIL, CRenderTargets::GetDepthBuffer_Stencil());
#else
SetShaderGBufferTarget(GBUFFER_STENCIL, CRenderTargets::GetDepthBuffer_Stencil());
#endif
#endif
#if DEVICE_EQAA
for (GBufferRT i=GBUFFER_FMASK_0; GRCDEVICE.IsEQAA() && i<=GBUFFER_FMASK_3; i=static_cast<GBufferRT>(i+1))
{
SetShaderGBufferTarget(i, GBuffer::GetFragmentMaskTexture(i));
}
#endif // DEVICE_EQAA
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::SetShaderSSAOTarget(eDeferredShaders deferredShaders)
{
SetDeferredVar(deferredShaders, DEFERRED_SHADER_LIGHT_TEXTURE2, SSAO::GetSSAOTexture());
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::SetShaderDepthTargetsForDeferredVolume(const grcTexture* depthBuffer)
{
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_VOLUME]->SetVar(m_shaderVolumeParameterID_deferredVolumeDepthBuffer, depthBuffer);
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::SetShaderTargetsForVolumeInterleaveReconstruction()
{
#if LIGHT_VOLUME_USE_LOW_RESOLUTION
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_VOLUME]->SetVar(m_shaderVolumeParameterID_deferredVolumeOffscreenBuffer, CRenderTargets::GetVolumeOffscreenBuffer());
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_VOLUME]->SetVar(m_shaderVolumeParameterID_deferredVolumeLowResDepthBuffer, CRenderTargets::GetDepthBufferQuarter());
#else
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_VOLUME]->SetVar(m_shaderVolumeParameterID_deferredVolumeOffscreenBuffer, CRenderTargets::GetVolumeOffscreenBuffer());
#endif
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::Shutdown()
{
#if SSA_USES_CONDITIONALRENDER
GRCDEVICE.DestroyConditionalQuery(m_SSAConditionalQuery);
#endif // SSA_USES_CONDITIONALRENDER
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::Update()
{
QualityModeSelect();
}
// ----------------------------------------------------------------------------------------------- //
grcEffectTechnique DeferredLighting::GetTechnique(const u32 lightType, MultisampleMode aaMode)
{
#if DEVICE_MSAA
if (!m_bSupportMSAAandNonMSAA)
aaMode = MM_DEFAULT;
#endif
grcEffectTechnique *const t = m_techniques[aaMode];
switch(lightType)
{
case LIGHT_TYPE_SPOT: return t[DEFERRED_TECHNIQUE_SPOTCM];
case LIGHT_TYPE_POINT: return t[DEFERRED_TECHNIQUE_POINTCM];
case LIGHT_TYPE_CAPSULE: return t[DEFERRED_TECHNIQUE_CAPSULE];
case LIGHT_TYPE_DIRECTIONAL: return t[DEFERRED_TECHNIQUE_DIRECTIONAL];
default: break;
}
Assertf(false, "Tried to look-up light technique for light %d, which doesn't exist", lightType);
return grcetNONE;
}
// ----------------------------------------------------------------------------------------------- //
grcEffectTechnique DeferredLighting::GetTechnique(eDeferredTechnique deferredTechnique, MultisampleMode aaMode)
{
#if DEVICE_MSAA
if (!m_bSupportMSAAandNonMSAA)
aaMode = MM_DEFAULT;
#endif
return m_techniques[aaMode][deferredTechnique];
}
// ----------------------------------------------------------------------------------------------- //
grmShader* DeferredLighting::GetShader(const u32 lightType)
{
switch(lightType)
{
case LIGHT_TYPE_SPOT: return m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_SPOT];
case LIGHT_TYPE_POINT: return m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_POINT];
case LIGHT_TYPE_CAPSULE: return m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_CAPSULE];
case LIGHT_TYPE_DIRECTIONAL: return m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_DIRECTIONAL];
default:
{
Assertf(false, "Tried to look-up shader for light %d, which doesn't exist", lightType);
return NULL;
}
}
}
// ----------------------------------------------------------------------------------------------- //
grmShader* DeferredLighting::GetShader(eDeferredShaders deferredShader, MultisampleMode aaMode)
{
#if DEVICE_MSAA
if (!m_bSupportMSAAandNonMSAA)
aaMode = MM_DEFAULT;
#endif
return m_deferredShaders[aaMode][deferredShader];
}
// ----------------------------------------------------------------------------------------------- //
#if GENERATE_SHMOO
int DeferredLighting::GetShaderShmooIdx(eDeferredShaders deferredShader)
{
return m_deferredShadersShmoos[deferredShader];
}
#endif
// ----------------------------------------------------------------------------------------------- //
eDeferredShaders DeferredLighting::GetShaderType(const u32 lightType)
{
switch(lightType)
{
case LIGHT_TYPE_SPOT: return DEFERRED_SHADER_SPOT;
case LIGHT_TYPE_POINT: return DEFERRED_SHADER_POINT;
case LIGHT_TYPE_CAPSULE: return DEFERRED_SHADER_CAPSULE;
case LIGHT_TYPE_DIRECTIONAL: return DEFERRED_SHADER_DIRECTIONAL;
default:
{
Errorf("Tried to look-up shader type for light %d, which doesn't exist", lightType);
return DEFERRED_SHADER_LIGHTING;
}
}
}
// ----------------------------------------------------------------------------------------------- //
grcEffectTechnique DeferredLighting::GetVolumeTechnique(const u32 lightType, const MultisampleMode aaMode)
{
switch(lightType)
{
case LIGHT_TYPE_SPOT: return GetTechnique(DEFERRED_TECHNIQUE_SPOTCM_VOLUME, aaMode);
case LIGHT_TYPE_POINT: return GetTechnique(DEFERRED_TECHNIQUE_POINTCM_VOLUME, aaMode);
case LIGHT_TYPE_CAPSULE: return GetTechnique(DEFERRED_TECHNIQUE_CAPSULE_VOLUME, aaMode);
default:
{
Assertf(false, "Tried to look-up volume light technique for light %d, which doesn't exist", lightType);
return grcetNONE;
}
}
}
// ----------------------------------------------------------------------------------------------- //
s32 DeferredLighting::CalculatePass(const CLightSource *light, bool hasTexture, bool useShadows, bool useBackLighting )
{
s32 pass = -1;
switch(light->GetType())
{
case LIGHT_TYPE_POINT:
case LIGHT_TYPE_SPOT:
case LIGHT_TYPE_CAPSULE:
{
u32 passKey = light->GetPassKey();
if (!useShadows) { passKey &= ~LIGHTFLAG_CAST_SHADOWS; }
if (!hasTexture) { passKey &= ~LIGHTFLAG_TEXTURE_PROJECTION; }
// Don't support textures or shadows lights for capsules
if (light->GetType() == LIGHT_TYPE_CAPSULE)
{
passKey &= ~LIGHTFLAG_CAST_SHADOWS;
passKey &= ~LIGHTFLAG_TEXTURE_PROJECTION;
}
// spot lights can do caustics. light above water & camera below water.
u8 extraFlag = 0;
float waterLevel = Water::GetWaterLevel();
if(
//Caustics spots
(light->UsesCaustic() &&
light->GetType() == LIGHT_TYPE_SPOT &&
Water::IsCameraUnderwater() &&
(light->GetPosition().z-2.0f) > waterLevel
&& !(passKey & LIGHTFLAG_USE_VEHICLE_TWIN))
//Soft shadowed lights
|| (light->GetExtraFlags() & EXTRA_LIGHTFLAG_SOFT_SHADOWS)
)
{
extraFlag = light->GetExtraFlags();
}
pass = CalculateLightPass(passKey, extraFlag);
return pass;
}
case LIGHT_TYPE_DIRECTIONAL:
{
const bool noDirectional = (light->GetIntensity() == 0.0f) || (!useShadows);
const bool useUnderwater = Water::IsCameraUnderwater();
pass = DIRECTIONALPASS_STANDARD;
if (useUnderwater)
pass = DIRECTIONALPASS_UNDERWATER;
if (noDirectional)
pass = DIRECTIONALPASS_AMBIENT;
if (pass == DIRECTIONALPASS_STANDARD && useBackLighting)
pass = Lights::m_bUseSSS ? DIRECTIONALPASS_SCATTER : DIRECTIONALPASS_BACKLIT;
#if __BANK
if (TiledScreenCapture::IsEnabledOrthographic())
pass = DIRECTIONALPASS_ORTHOGRAPHIC;
#endif // __BANK
return pass;
}
case LIGHT_TYPE_AO_VOLUME:
case LIGHT_TYPE_NONE:
{
return pass;
}
}
return pass;
}
// ----------------------------------------------------------------------------------------------- //
eLightPass DeferredLighting::CalculateLightPass(u32 passFlags, u8 extraFlags)
{
bool softShadows = (extraFlags & EXTRA_LIGHTFLAG_SOFT_SHADOWS) != 0;
if( extraFlags & EXTRA_LIGHTFLAG_CAUSTIC )
{
switch(passFlags)
{
//for spot lights (caustic & vehicle twin)
case (0): return LIGHTPASS_STANDARD_CAUSTIC;
case (LIGHTFLAG_CAST_SHADOWS): return softShadows ? LIGHTPASS_SHADOW_CAUSTIC_SOFT : LIGHTPASS_SHADOW_CAUSTIC;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_TEXTURE_PROJECTION): return softShadows ? LIGHTPASS_SHADOW_TEXTURE_CAUSTIC_SOFT : LIGHTPASS_SHADOW_TEXTURE_CAUSTIC;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_NO_SPECULAR): return softShadows ? LIGHTPASS_SHADOW_TEXTURE_FILLER_CAUSTIC_SOFT : LIGHTPASS_SHADOW_TEXTURE_FILLER_CAUSTIC;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_EXTERIOR_ONLY): return softShadows ? LIGHTPASS_SHADOW_TEXTURE_EXTERIOR_CAUSTIC_SOFT : LIGHTPASS_SHADOW_TEXTURE_EXTERIOR_CAUSTIC;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_EXTERIOR_ONLY | LIGHTFLAG_NO_SPECULAR): return softShadows ? LIGHTPASS_SHADOW_TEXTURE_EXTERIOR_FILLER_CAUSTIC_SOFT : LIGHTPASS_SHADOW_TEXTURE_EXTERIOR_FILLER_CAUSTIC;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_INTERIOR_ONLY): return softShadows ? LIGHTPASS_SHADOW_TEXTURE_INTERIOR_CAUSTIC_SOFT : LIGHTPASS_SHADOW_TEXTURE_INTERIOR_CAUSTIC;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_INTERIOR_ONLY | LIGHTFLAG_NO_SPECULAR): return softShadows ? LIGHTPASS_SHADOW_TEXTURE_INTERIOR_FILLER_CAUSTIC_SOFT : LIGHTPASS_SHADOW_TEXTURE_INTERIOR_FILLER_CAUSTIC;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_EXTERIOR_ONLY): return softShadows ? LIGHTPASS_SHADOW_EXTERIOR_CAUSTIC_SOFT : LIGHTPASS_SHADOW_EXTERIOR_CAUSTIC;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_NO_SPECULAR): return softShadows ? LIGHTPASS_SHADOW_FILLER_CAUSTIC_SOFT : LIGHTPASS_SHADOW_FILLER_CAUSTIC;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_EXTERIOR_ONLY | LIGHTFLAG_NO_SPECULAR): return softShadows ? LIGHTPASS_SHADOW_EXTERIOR_FILLER_CAUSTIC_SOFT : LIGHTPASS_SHADOW_EXTERIOR_FILLER_CAUSTIC;
case (LIGHTFLAG_NO_SPECULAR): return LIGHTPASS_FILLER_CAUSTIC;
case (LIGHTFLAG_NO_SPECULAR | LIGHTFLAG_EXTERIOR_ONLY): return LIGHTPASS_FILLER_EXTERIOR_CAUSTIC;
case (LIGHTFLAG_NO_SPECULAR | LIGHTFLAG_TEXTURE_PROJECTION): return LIGHTPASS_FILLER_TEXTURE_CAUSTIC;
case (LIGHTFLAG_NO_SPECULAR | LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_EXTERIOR_ONLY): return LIGHTPASS_FILLER_TEXTURE_EXTERIOR_CAUSTIC;
case (LIGHTFLAG_EXTERIOR_ONLY): return LIGHTPASS_EXTERIOR_CAUSTIC;
case (LIGHTFLAG_TEXTURE_PROJECTION): return LIGHTPASS_TEXTURE_CAUSTIC;
case (LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_EXTERIOR_ONLY): return LIGHTPASS_TEXTURE_EXTERIOR_CAUSTIC;
default:
{
#if __ASSERT
Assertf(false, "Tried to create a caustic light type that we do not support (Pass - %d)", passFlags);
#endif
return LIGHTPASS_STANDARD;
}
}
}
else
{
switch(passFlags)
{
case 0: return LIGHTPASS_STANDARD;
case (LIGHTFLAG_CAST_SHADOWS): return softShadows ? LIGHTPASS_SHADOW_SOFT : LIGHTPASS_SHADOW;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_TEXTURE_PROJECTION): return softShadows ? LIGHTPASS_SHADOW_TEXTURE_SOFT : LIGHTPASS_SHADOW_TEXTURE;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_NO_SPECULAR): return softShadows ? LIGHTPASS_SHADOW_TEXTURE_FILLER_SOFT : LIGHTPASS_SHADOW_TEXTURE_FILLER;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_EXTERIOR_ONLY): return softShadows ? LIGHTPASS_SHADOW_TEXTURE_EXTERIOR_SOFT : LIGHTPASS_SHADOW_TEXTURE_EXTERIOR;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_EXTERIOR_ONLY | LIGHTFLAG_NO_SPECULAR): return softShadows ? LIGHTPASS_SHADOW_TEXTURE_EXTERIOR_FILLER_SOFT : LIGHTPASS_SHADOW_TEXTURE_EXTERIOR_FILLER;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_INTERIOR_ONLY): return softShadows ? LIGHTPASS_SHADOW_TEXTURE_INTERIOR_SOFT : LIGHTPASS_SHADOW_TEXTURE_INTERIOR;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_INTERIOR_ONLY | LIGHTFLAG_NO_SPECULAR): return softShadows ? LIGHTPASS_SHADOW_TEXTURE_INTERIOR_FILLER_SOFT : LIGHTPASS_SHADOW_TEXTURE_INTERIOR_FILLER;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_INTERIOR_ONLY): return softShadows ? LIGHTPASS_SHADOW_INTERIOR_SOFT : LIGHTPASS_SHADOW_INTERIOR;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_EXTERIOR_ONLY): return softShadows ? LIGHTPASS_SHADOW_EXTERIOR_SOFT : LIGHTPASS_SHADOW_EXTERIOR;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_NO_SPECULAR): return softShadows ? LIGHTPASS_SHADOW_FILLER_SOFT : LIGHTPASS_SHADOW_FILLER;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_EXTERIOR_ONLY | LIGHTFLAG_NO_SPECULAR): return softShadows ? LIGHTPASS_SHADOW_EXTERIOR_FILLER_SOFT : LIGHTPASS_SHADOW_EXTERIOR_FILLER;
case (LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_INTERIOR_ONLY | LIGHTFLAG_NO_SPECULAR): return softShadows ? LIGHTPASS_SHADOW_INTERIOR_FILLER_SOFT : LIGHTPASS_SHADOW_INTERIOR_FILLER;
case (LIGHTFLAG_NO_SPECULAR): return LIGHTPASS_FILLER;
case (LIGHTFLAG_NO_SPECULAR | LIGHTFLAG_INTERIOR_ONLY): return LIGHTPASS_FILLER_INTERIOR;
case (LIGHTFLAG_NO_SPECULAR | LIGHTFLAG_EXTERIOR_ONLY): return LIGHTPASS_FILLER_EXTERIOR;
case (LIGHTFLAG_NO_SPECULAR | LIGHTFLAG_TEXTURE_PROJECTION): return LIGHTPASS_FILLER_TEXTURE;
case (LIGHTFLAG_NO_SPECULAR | LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_INTERIOR_ONLY): return LIGHTPASS_FILLER_TEXTURE_INTERIOR;
case (LIGHTFLAG_NO_SPECULAR | LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_EXTERIOR_ONLY): return LIGHTPASS_FILLER_TEXTURE_EXTERIOR;
case (LIGHTFLAG_INTERIOR_ONLY): return LIGHTPASS_INTERIOR;
case (LIGHTFLAG_EXTERIOR_ONLY): return LIGHTPASS_EXTERIOR;
case (LIGHTFLAG_TEXTURE_PROJECTION): return LIGHTPASS_TEXTURE;
case (LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_INTERIOR_ONLY): return LIGHTPASS_TEXTURE_INTERIOR;
case (LIGHTFLAG_TEXTURE_PROJECTION | LIGHTFLAG_EXTERIOR_ONLY): return LIGHTPASS_TEXTURE_EXTERIOR;
case (LIGHTFLAG_USE_VEHICLE_TWIN): return LIGHTPASS_VEHICLE_TWIN_STANDARD;
case (LIGHTFLAG_USE_VEHICLE_TWIN | LIGHTFLAG_CAST_SHADOWS): return softShadows ? LIGHTPASS_VEHICLE_TWIN_SHADOW_SOFT : LIGHTPASS_VEHICLE_TWIN_SHADOW;
case (LIGHTFLAG_USE_VEHICLE_TWIN | LIGHTFLAG_TEXTURE_PROJECTION): return LIGHTPASS_VEHICLE_TWIN_TEXTURE;
case (LIGHTFLAG_USE_VEHICLE_TWIN | LIGHTFLAG_CAST_SHADOWS | LIGHTFLAG_TEXTURE_PROJECTION): return softShadows ? LIGHTPASS_VEHICLE_TWIN_SHADOW_TEXTURE_SOFT : LIGHTPASS_VEHICLE_TWIN_SHADOW_TEXTURE;
default:
{
#if __ASSERT
char buffer[512];
sprintf(buffer, "");
if ((passFlags & (1 << 0 )) != 0) sprintf(buffer, "%s | %s", buffer, "Interior only");
if ((passFlags & (1 << 1 )) != 0) sprintf(buffer, "%s | %s", buffer, "Exterior only");
if ((passFlags & (1 << 5 )) != 0) sprintf(buffer, "%s | %s", buffer, "Texture projection");
if ((passFlags & (1 << 6 )) != 0) sprintf(buffer, "%s | %s", buffer, "Shadow");
if ((passFlags & (1 << 13)) != 0) sprintf(buffer, "%s | %s", buffer, "No specular");
if ((passFlags & (1 << 27)) != 0) sprintf(buffer, "%s | %s", buffer, "Twin vehicle");
Assertf(false, "Light with %s not supported (Pass - %d)", buffer, passFlags);
#endif
return LIGHTPASS_STANDARD;
}
}
}
}
// ----------------------------------------------------------------------------------------------- //
ScalarV LightBoundsPixelCoveragePercent(const spdAABB& lightBounds)
{
// const Vec3V bmin = lightBounds.GetMin();
// const Vec3V bmax = lightBounds.GetMax();
const Vec3V extents = lightBounds.GetExtent();
const ScalarV volume = extents.GetX() * extents.GetY() * extents.GetZ();
const ScalarV radiusSphere = Pow(volume, ScalarV(V_THIRD));
const grcViewport* grcVP = gVpMan.GetCurrentGameGrcViewport();
const Vec3V eye = grcVP->GetCameraPosition();
// const Vec3V eyeDir = grcVP->GetCameraMtx().c();
const Mat44V worldToScreenMtx = grcVP->GetCompositeMtx();
const Vec2V screenResolution = Vec2V(grcVP->GetScreenMtx().GetCol3().GetXY());
// compute roughly how large the light is in screen pixels
return screenResolution.GetX() * radiusSphere / (ScalarVFromF32(grcVP->GetTanHFOV()) *
Abs(Dist(eye, lightBounds.GetCenter())));
}
// ----------------------------------------------------------------------------------------------- //
eLightVolumePass DeferredLighting::CalculateVolumePass(const CLightSource *light, bool useShadows, bool cameraInLight)
{
//Debug tool for switching between shadowed and unshadowed volumes
BANK_ONLY( useShadows = DebugLighting::m_ForceUnshadowedVolumeLightTechnique ? false : useShadows );
eLightVolumePass volumePass;
const s32 flags = light->GetFlags();
bool useBackFaceTechnique = false;
if (light->GetType() == LIGHT_TYPE_SPOT)
{
if(light->GetConeCosOuterAngle() < BANK_SWITCH(DebugLighting::m_MinSpotAngleForBackFaceForce, LIGHT_VOLUME_BACKFACE_TECHNIQUE_MIN_ANGLE))
{
// Disable front face technique for really wide spot lights because it just does not look good
// Triangles in front face becomes really large, and since we perform the attenuation in the vertex
// shader, a lot of lighting info goes missing if the triangle is close to camera.
useBackFaceTechnique = true;
}
else
{
useBackFaceTechnique = cameraInLight;
}
}
else
{
//use back face technique for point lights
useBackFaceTechnique = true;
}
// Using shadow pass only for spot or point lights
if ((light->GetType() == LIGHT_TYPE_SPOT || light->GetType() == LIGHT_TYPE_POINT) && useShadows &&
(flags & (LIGHTFLAG_CAST_STATIC_GEOM_SHADOWS | LIGHTFLAG_CAST_DYNAMIC_GEOM_SHADOWS)) != 0)
{
volumePass = useBackFaceTechnique ? LIGHTVOLUMEPASS_SHADOW : LIGHTVOLUMEPASS_OUTSIDE_SHADOW;
}
else
{
volumePass = useBackFaceTechnique ? LIGHTVOLUMEPASS_STANDARD : LIGHTVOLUMEPASS_OUTSIDE;
}
#if SUPPORT_HQ_VOLUMETRIC_LIGHTS
if ( CSettingsManager::GetInstance().GetSettings().m_graphics.m_ShadowQuality == CSettings::Ultra)
{
volumePass = static_cast<eLightVolumePass>( volumePass + LIGHTVOLUMEPASS_STANDARD_HQ );
}
#endif
return volumePass;
}
void DeferredLighting::SetDirectionalRenderState(eDeferredShaders deferredShader, const MultisampleMode aaMode)
{
// Setup ambient globals
Lights::m_lightingGroup.SetAmbientLightingGlobals();
// Set the light params into the shader.
const CLightSource& dirLight = Lights::GetRenderDirectionalLight();
// Setup the directional light
SetLightShaderParams(deferredShader, &dirLight, NULL, 1.0f, false, false, aaMode);
SetProjectionShaderParams(deferredShader, aaMode);
// Setup shadowing variables
CRenderPhaseCascadeShadowsInterface::SetSharedShaderVars();
}
// ----------------------------------------------------------------------------------------------- //
#if __BANK
// ----------------------------------------------------------------------------------------------- //
const char* GetPassName(const u32 passIndex, const bool noDirLight)
{
if (noDirLight)
{
switch(passIndex)
{
case 0: return "Ambient + Reflections";
case 1: return "Ambient only";
default: return "Unknown";
}
}
else
{
switch(passIndex)
{
case 0: return "Dir | Spec | Refl | Amb";
case 1: return "Refl | Amb";
case 2: return "Amb";
case 3: return "Dir | Amb";
case 4: return "Dir | Spec | Amb";
case 5: return "Dir | Spec | Refl | Penumb | Amb";
case 6: return "Dir | Penumb | Amb";
case 7: return "Dir | Spec | Penumb | Amb";
default: return "Unknown";
}
}
}
// ----------------------------------------------------------------------------------------------- //
#endif
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::RenderTiledDirectionalLight(const bool noDirLight, const MultisampleMode aaMode, const EdgeMode em)
{
#if TILED_LIGHTING_ENABLED
SetDirectionalRenderState(DEFERRED_SHADER_TILED, aaMode);
SetProjectionShaderParams(DEFERRED_SHADER_TILED, aaMode);
DeferredLighting::SetShaderGBufferTargets();
grcStateBlock::SetStates(grcStateBlock::RS_NoBackfaceCull, grcStateBlock::DSS_IgnoreDepth, grcStateBlock::BS_Default);
#if MSAA_EDGE_PASS
grcStateBlock::SetDepthStencilState(
em == EM_IGNORE ? grcStateBlock::DSS_IgnoreDepth : m_directionalEdgeMaskEqualPass_DS,
em == EM_EDGE0 ? EDGE_FLAG : 0);
#else
(void)em;
#endif //MSAA_EDGE_PASS
// Render tiles
GRCDEVICE.SetVertexDeclaration(CTiledLighting::GetTileVertDecl());
GRCDEVICE.SetStreamSource(0, *CTiledLighting::GetTileVertBuffer(), 0, CTiledLighting::GetTileVertBuffer()->GetVertexStride());
#if TILED_LIGHTING_INSTANCED_TILES
GRCDEVICE.SetStreamSource(1, *CTiledLighting::GetTileInstanceBuffer(), 0, CTiledLighting::GetTileInstanceBuffer()->GetVertexStride());
#else
GRCDEVICE.SetStreamSource(1, *CTiledLighting::GetTileInfoVertBuffer(), 0, CTiledLighting::GetTileInfoVertBuffer()->GetVertexStride());
#endif //TILED_LIGHTING_INSTANCED_TILES
u32 passStart = 0;
u32 passEnd = 5;
grcEffectTechnique currentTechnique = m_techniques[aaMode][DEFERRED_TECHNIQUE_TILED_DIRECTIONAL];
if (noDirLight)
{
passStart = 0;
passEnd = 2;
currentTechnique = m_techniques[aaMode][DEFERRED_TECHNIQUE_TILED_AMBIENT];
}
Assert(m_shaderDownsampledDepthSampler != grcevNONE);
m_deferredShaders[aaMode][DEFERRED_SHADER_TILED]->SetVar(m_shaderDownsampledDepthSampler,CTiledLighting::GetClassificationTexture());
SetDeferredVar(DEFERRED_SHADER_TILED, DEFERRED_SHADER_LIGHT_TEXTURE2, SSAO::GetSSAOTexture(), aaMode);
if (m_deferredShaders[aaMode][DEFERRED_SHADER_TILED]->BeginDraw(grmShader::RMC_DRAW, true, currentTechnique))
{
for (u32 i = passStart; i < passEnd; i++)
{
#if __BANK && !__GAMETOOL
const char* passName = GetPassName(i, noDirLight);
PF_PUSH_MARKER(passName);
#endif
GENSHMOO_ONLY(ShmooHandling::BeginShmoo(m_deferredShadersShmoos[DEFERRED_SHADER_TILED], m_deferredShaders[aaMode][DEFERRED_SHADER_TILED], i));
m_deferredShaders[aaMode][DEFERRED_SHADER_TILED]->Bind(i);
#if TILED_LIGHTING_INSTANCED_TILES
GRCDEVICE.DrawInstancedPrimitive(drawTris, 6, CTiledLighting::GetTotalNumTiles(), 0, 0);
#else
GRCDEVICE.DrawPrimitive(drawTris, 0, CTiledLighting::GetTotalNumTiles()*6);
#endif //TILED_LIGHTING_INSTANCED_TILES
m_deferredShaders[aaMode][DEFERRED_SHADER_TILED]->UnBind();
GENSHMOO_ONLY(ShmooHandling::EndShmoo(m_deferredShadersShmoos[DEFERRED_SHADER_TILED]));
#if __BANK && !__GAMETOOL
PF_POP_MARKER();
#endif
}
m_deferredShaders[aaMode][DEFERRED_SHADER_TILED]->EndDraw();
}
GRCDEVICE.ClearStreamSource(1);
GRCDEVICE.ClearStreamSource(0);
#else
(void)noDirLight;
(void)em;
#endif
}
void DeferredLighting::RenderTiledShadow()
{
#if TILED_LIGHTING_ENABLED
SetDirectionalRenderState(DEFERRED_SHADER_TILED);
// Render tiles
// Set world to worldToShadowSpace
const grcViewport& worldToShadowViewport = CRenderPhaseCascadeShadowsInterface::GetCascadeViewport(0);
Mat34V worldToShadowMtx = worldToShadowViewport.GetCameraMtx();
grcWorldMtx( worldToShadowMtx );
GRCDEVICE.SetVertexDeclaration(CTiledLighting::GetTileVertDecl());
GRCDEVICE.SetStreamSource(0, *CTiledLighting::GetTileVertBuffer(), 0, CTiledLighting::GetTileVertBuffer()->GetVertexStride());
#if TILED_LIGHTING_INSTANCED_TILES
GRCDEVICE.SetStreamSource(1, *CTiledLighting::GetTileInstanceBuffer(), 0, CTiledLighting::GetTileInstanceBuffer()->GetVertexStride());
#else
GRCDEVICE.SetStreamSource(1, *CTiledLighting::GetTileInfoVertBuffer(), 0, CTiledLighting::GetTileInfoVertBuffer()->GetVertexStride());
#endif //TILED_LIGHTING_INSTANCED_TILES
grmShader* tiledShader = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_TILED];
Assert(m_shaderDownsampledDepthSampler != grcevNONE);
tiledShader->SetVar(m_shaderDownsampledDepthSampler,CTiledLighting::GetClassificationTexture());
if (tiledShader->BeginDraw(grmShader::RMC_DRAW, true, m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_TILED_SHADOW]))
{
GENSHMOO_ONLY(ShmooHandling::BeginShmoo(m_deferredShadersShmoos[DEFERRED_SHADER_TILED], tiledShader, 0));
tiledShader->Bind(0);
#if TILED_LIGHTING_INSTANCED_TILES
GRCDEVICE.DrawInstancedPrimitive(drawTris, 6, CTiledLighting::GetTotalNumTiles(), 0, 0);
#else
GRCDEVICE.DrawPrimitive(drawTris, 0, CTiledLighting::GetTotalNumTiles()*6);
#endif //TILED_LIGHTING_INSTANCED_TILES
tiledShader->UnBind();
GENSHMOO_ONLY(ShmooHandling::EndShmoo(m_deferredShadersShmoos[DEFERRED_SHADER_TILED]));
tiledShader->EndDraw();
}
#if !(__D3D11 || RSG_ORBIS)
GRCDEVICE.ClearStreamSource(1);
#endif // !(__D3D11 || RSG_ORBIS)
GRCDEVICE.ClearStreamSource(0);
#endif
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::RenderDirectionalLight(s32 pass, const bool setSSAO, const MultisampleMode aaMode)
{
SetDeferredVar(DEFERRED_SHADER_DIRECTIONAL, DEFERRED_SHADER_LIGHT_TEXTURE, Water::GetNoiseTexture(), aaMode);
SetDeferredVar(DEFERRED_SHADER_DIRECTIONAL, DEFERRED_SHADER_LIGHT_TEXTURE1, Water::GetCausticTexture(), aaMode);
SetDeferredVar(DEFERRED_SHADER_DIRECTIONAL, DEFERRED_SHADER_LIGHT_TEXTURE2, (setSSAO) ? SSAO::GetSSAOTexture() : grcTexture::NoneWhite, aaMode);
#if REFLECTION_CUBEMAP_SAMPLING
CRenderPhaseReflection::SetReflectionMap();
#endif
if (ShaderUtil::StartShader("Directional Light", GetShader(DEFERRED_SHADER_DIRECTIONAL, aaMode), GetTechnique(DEFERRED_TECHNIQUE_DIRECTIONAL, aaMode), pass))
{
Render2DDeferredLightingRect(0.0f, 0.0f, 1.0f, 1.0f);
ShaderUtil::EndShader(GetShader(DEFERRED_SHADER_DIRECTIONAL, aaMode));
}
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::Render2DDeferredLightingRect(const float x, const float y, const float w, const float h)
{
float x0 = (x);
float y0 = (y);
float x1 = (x + w);
float y1 = (y + h);
Color32 white(255, 255, 255, 255);
#if RSG_XENON || RSG_ORBIS
grcBegin(drawRects,3);
grcVertex(x0, y0, 0.0f, 0.0f, 0.0f, -1.0f, white, x0, y0);
grcVertex(x1, y0, 0.0f, 0.0f, 0.0f, -1.0f, white, x1, y0);
grcVertex(x0, y1, 0.0f, 0.0f, 0.0f, -1.0f, white, x0, y1);
grcEnd();
#else
grcBegin(drawTriStrip,4);
grcVertex(x0, y0, 0.0f, 0.0f, 0.0f, -1.0f, white, x0, y0);
grcVertex(x1, y0, 0.0f, 0.0f, 0.0f, -1.0f, white, x1, y0);
grcVertex(x0, y1, 0.0f, 0.0f, 0.0f, -1.0f, white, x0, y1);
grcVertex(x1, y1, 0.0f, 0.0f, 0.0f, -1.0f, white, x1, y1);
grcEnd();
#endif
}
void DeferredLighting::Render2DDeferredLightingRect(const float x, const float y, const float w, const float h,
const float u, const float v, const float uW,const float vH)
{
float x0 = (x);
float y0 = (y);
float x1 = (x + w);
float y1 = (y + h);
float u0 = u;
float v0 = v;
float u1 = u + uW;
float v1 = v + vH;
Color32 white(255, 255, 255, 255);
#if RSG_XENON || RSG_ORBIS
grcBegin(drawRects,3);
grcVertex(x0, y0, 0.0f, 0.0f, 0.0f, -1.0f, white, u0, v0);
grcVertex(x1, y0, 0.0f, 0.0f, 0.0f, -1.0f, white, u1, v0);
grcVertex(x0, y1, 0.0f, 0.0f, 0.0f, -1.0f, white, u0, v1);
grcEnd();
#else
grcBegin(drawTriStrip,4);
grcVertex(x0, y0, 0.0f, 0.0f, 0.0f, -1.0f, white, u0, v0);
grcVertex(x1, y0, 0.0f, 0.0f, 0.0f, -1.0f, white, u1, v0);
grcVertex(x0, y1, 0.0f, 0.0f, 0.0f, -1.0f, white, u0, v1);
grcVertex(x1, y1, 0.0f, 0.0f, 0.0f, -1.0f, white, u1, v1);
grcEnd();
#endif
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::PrepareGeometryPass()
{
// Make sure that the render state is set to make any later
// rendering behaviour predictable
grcBindTexture(NULL);
grcStateBlock::SetBlendState(m_geometryPass_B);
grcStateBlock::SetRasterizerState(grcStateBlock::RS_Default);
if (DeferredLighting__m_useGeomPassStencil == false)
{
grcStateBlock::SetDepthStencilState(CShaderLib::DSS_Default_Invert);
}
else
{
grcStateBlock::SetDepthStencilState(m_geometryPass_DS, DEFERRED_MATERIAL_DEFAULT);
}
// Bind and enable vertex & fragment programs.
m_previousGroupId = grmShaderFx::GetForcedTechniqueGroupId();
grmShaderFx::SetForcedTechniqueGroupId(m_deferredTechniqueGroupId);
CShaderLib::SetGlobalEmissiveScale(1.0f);
#if EFFECT_STENCIL_REF_MASK
// limit the in-shader DSS blocks to not affect the edge flag
grcEffect::SetStencilRefMask(static_cast<u8>(~EDGE_FLAG));
#endif //EFFECT_STENCIL_REF_MASK
}// end of PrepareGeometryPass()...
// ----------------------------------------------------------------------------------------------- //
#if __XENON
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::PrepareGeometryPassTiled()
{
//lock all gbuffers
GBuffer::LockTargets();
D3DVECTOR4 ClearColor = { 0.0f, 0.0f, 0.0f, 0.0f };
D3DRECT pTilingRects[NUM_TILES];
GBuffer::CalculateTiles(pTilingRects, NUM_TILES);
u32 flags = D3DTILING_SKIP_FIRST_TILE_CLEAR;
#if __BANK
if (DebugDeferred::m_switchZPass)
flags |= D3DTILING_ONE_PASS_ZPASS|D3DTILING_FIRST_TILE_INHERITS_DEPTH_BUFFER;
if (debugSwitchZPassModeChange != DebugDeferred::m_switchZPass)
{
if (DebugDeferred::m_switchZPass)
GRCDEVICE.GetCurrent()->SetScreenExtentQueryMode(D3DSEQM_CULLED);
else
GRCDEVICE.GetCurrent()->SetScreenExtentQueryMode(D3DSEQM_PRECLIP);
#if __DEV
debugSwitchZPassModeChange = DebugDeferred::m_switchZPass;
#endif
}
#endif
GRCDEVICE.GetCurrent()->BeginTiling( flags, NUM_TILES, pTilingRects, &ClearColor, 0.0f, 0L );
DWORD dwClearFlags = D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL;
if ( PostFX::UseSubSampledAlpha() )
{
dwClearFlags |= D3DCLEAR_TARGET0;
}
GRCDEVICE.GetCurrent()->SetPredication( D3DPRED_TILE(0) );
GRCDEVICE.GetCurrent()->Clear( 0, NULL, dwClearFlags, D3DCOLOR_COLORVALUE(0,0,0,0), 0.0f, 0L );
GRCDEVICE.GetCurrent()->SetPredication( 0 );
#if __BANK
if (DebugDeferred::m_switchZPass)
GRCDEVICE.GetCurrent()->BeginZPass(0);
#endif
// viewport gets trashed by BeginTiling
D3DVIEWPORT9 vp;
CHECK_HRESULT(GRCDEVICE.GetCurrent()->GetViewport(&vp));
vp.MinZ = GRCDEVICE.FixViewportDepth(vp.MinZ);
vp.MaxZ = GRCDEVICE.FixViewportDepth(vp.MaxZ);
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetViewport(&vp));
PrepareGeometryPass();
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::FinishGeometryPassTiled(bool bSkipGBuffer2LastTileResolve /*=false*/)
{
FinishGeometryPass();
#if __BANK
if (DebugDeferred::m_switchZPass)
GRCDEVICE.GetCurrent()->EndZPass();
#endif
// resolve
D3DVECTOR4 ClearColor = { 0.0f, 0.0f, 0.0f, 0.0f };
D3DRECT pTilingRects[NUM_TILES];
GBuffer::CalculateTiles(pTilingRects, NUM_TILES);
grcRenderTarget **targets = GBuffer::GetTargets();
for( int i = 0; i < NUM_TILES; ++i )
{
// Set predication to tile i.
GRCDEVICE.GetCurrent()->SetPredication( D3DPRED_TILE( i ) );
// Destination point is the upper left corner of the tiling rect.
D3DPOINT* pDestPoint = (D3DPOINT*)&pTilingRects[i];
// Resolve render targets 0, 1, 2 and 3, also clear them.
CHECK_HRESULT( GRCDEVICE.GetCurrent()->Resolve( D3DRESOLVE_RENDERTARGET0 | D3DRESOLVE_FRAGMENT0 | D3DRESOLVE_CLEARRENDERTARGET, &pTilingRects[i], static_cast<D3DTexture*>(targets[0]->GetTexturePtr()), pDestPoint, 0, 0, &ClearColor, 0.0f, 0L, NULL ) );
if (bSkipGBuffer2LastTileResolve && i==(NUM_TILES-1))
{
// Skip the last Gbuffer2 tile resolve, we'll get it after cascaded shadow reveal. This remains resident in EDRAM until it is resolved
// during cascaded shadow reveal. We enable basic protection so that we don't accidentally step on this EDRAM region in the mean time.
IDirect3DSurface9 *pSurface2=NULL;
CHECK_HRESULT( GRCDEVICE.GetCurrent()->GetRenderTarget(2,&pSurface2) );
PROTECT_EDRAM_SURFACE( pSurface2 );
SAFE_RELEASE(pSurface2);
}
else
{
CHECK_HRESULT( GRCDEVICE.GetCurrent()->Resolve( D3DRESOLVE_RENDERTARGET2 | D3DRESOLVE_FRAGMENT0 | D3DRESOLVE_CLEARRENDERTARGET, &pTilingRects[i], static_cast<D3DTexture*>(targets[2]->GetTexturePtr()), pDestPoint, 0, 0, &ClearColor, 0.0f, 0L, NULL ) );
}
CHECK_HRESULT( GRCDEVICE.GetCurrent()->Resolve( D3DRESOLVE_RENDERTARGET3 | D3DRESOLVE_FRAGMENT0 | D3DRESOLVE_CLEARRENDERTARGET, &pTilingRects[i], static_cast<D3DTexture*>(targets[3]->GetTexturePtr()), pDestPoint, 0, 0, &ClearColor, 0.0f, 0L, NULL ) );
}
GRCDEVICE.GetCurrent()->SetPredication( 0 );
GRCDEVICE.GetCurrent()->EndTiling( 0, NULL, NULL, &ClearColor, 1.0f, 0L, NULL );
GBuffer::UnlockTargets();
//PostFX::CopyStencil();
}
// ----------------------------------------------------------------------------------------------- //
// Restore depth/stencil on Xbox360 at the start of the lighting phase
void DeferredLighting::RestoreDepthStencil()
{
// Do the fast restore if we'll be rendering scene lights (since they'll have to do the slow restore anyway
// and no one will use stencil before the scene lights).
const bool bUseFastRestore = DeferredLighting__m_useLightsHiStencil && Lights::HasSceneLights();
const bool bRestore3Bits = !bUseFastRestore;
GBuffer::RestoreDepthOptimized(GBuffer::GetDepthTargetAsColor(), bRestore3Bits);
}
// ----------------------------------------------------------------------------------------------- //
#endif //XENON
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::FinishGeometryPass(void)
{
grcStateBlock::SetDepthStencilState(CShaderLib::DSS_Default_Invert);
#if __D3D && __XENON
GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_HISTENCILENABLE, FALSE);
GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_HISTENCILWRITEENABLE, FALSE);
#endif
#if DUMP_GBUFFER_TARGETS
static bool done = false;
if (!g_RenderThreadIndex && !done && grcSetupInstance && GRCDEVICE.GetMSAA())
{
done = true;
grcTextureFactory::CreateParams params;
params.Format = grctfA8R8G8B8;
grcRenderTarget *const resolved = grcTextureFactory::GetInstance().CreateRenderTarget( "GBuffer0_Resolved", grcrtPermanent, GRCDEVICE.GetWidth(), GRCDEVICE.GetHeight(), 32, &params);
# if SUPPORT_RENDERTARGET_DUMP
grcSetupInstance->TakeRenderTargetShotsNow();
//GBuffer::LockTargets();
//GBuffer::UnlockTargets();
static_cast<grcRenderTargetGNM*>( GBuffer::GetTarget(GBUFFER_RT_0) )->Resolve( resolved );
grcSetupInstance->UntakeRenderTargetShots();
# else
GBuffer::GetTarget(GBUFFER_RT_0)->SaveTarget();
resolved->SaveTarget();
# endif //SUPPORT_RENDERTARGET_DUMP
delete resolved;
}
#endif // DUMP_GBUFFER_TARGETS
grmShaderFx::SetForcedTechniqueGroupId(m_previousGroupId);
#if EFFECT_STENCIL_REF_MASK
// revert the ref mask
grcEffect::SetStencilRefMask(0xFF);
#endif
}// end of FinishGeometryPass()...
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::PrepareDecalPass(bool fadePass)
{
PF_PUSH_MARKER(fadePass ? "Decal Fade Pass" : "Decal Pass");
PF_PUSH_TIMEBAR(fadePass ? "Decal Fade Pass" : "Decal Pass");
River::SetDecalPassGlobalVars();
grcStateBlock::SetBlendState(m_decalPass_B);
grcStateBlock::SetDepthStencilState(m_decalPass_DS);
grcStateBlock::SetRasterizerState(grcStateBlock::RS_Default);
#if !RSG_ORBIS && !RSG_DURANGO
if (fadePass && CShaderLib::UsesStippleFades())
{
// On DX11 we can't use the D3DRS_MULTISAMPLEMASK for fade without MSAA (as on 360) so for the fade pass
// it needs to be manually inserted into the shader itself. For DX11, as we don't want to add it to
// all shaders, it's been added to the alphaclip passes and we force the technique here.
m_previousGroupAlphaClipId = grmShaderFx::GetForcedTechniqueGroupId();
grmShaderFx::SetForcedTechniqueGroupId(m_deferredAlphaClipTechniqueGroupId);
}
#else
(void) fadePass;
#endif // DEVICE_MSAA
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::FinishDecalPass()
{
GRC_ALLOC_SCOPE_AUTO_PUSH_POP()
PF_POP_TIMEBAR();
PF_POP_MARKER();
#if !RSG_ORBIS && !RSG_DURANGO
if (CShaderLib::UsesStippleFades())
{
grmShaderFx::SetForcedTechniqueGroupId(m_previousGroupAlphaClipId);
}
#endif // DEVICE_MSAA
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::PrepareFadePass()
{
PF_PUSH_MARKER("Fade Pass");
PF_PUSH_TIMEBAR("Fade Pass");
grcStateBlock::SetBlendState(m_fadePass_B);
grcStateBlock::SetRasterizerState(grcStateBlock::RS_Default);
#if MSAA_EDGE_PROCESS_FADING
if (IsEdgeFadeProcessingActive())
{
CShaderLib::SetForcedEdge(true);
grcStateBlock::SetDepthStencilState(m_fadePassAA_DS, 0);
}else
#endif //MSAA_EDGE_PROCESS_FADING
{
grcStateBlock::SetDepthStencilState(m_fadePass_DS, 0);
}
#if !RSG_ORBIS && !RSG_DURANGO
if (CShaderLib::UsesStippleFades())
{
// On DX11 we can't use the D3DRS_MULTISAMPLEMASK for fade withough MSAA (as on 360) so for the fade pass.
// It needs to be manually inserted into the shader itself. For DX11, as we don't want to add it to
// all shaders, it's been added to the alphaclip passes and we force the technique here.
m_previousGroupAlphaClipId = grmShaderFx::GetForcedTechniqueGroupId();
grmShaderFx::SetForcedTechniqueGroupId(m_deferredAlphaClipTechniqueGroupId);
}
#endif // !RSG_ORBIS
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::FinishFadePass()
{
PF_POP_TIMEBAR();
PF_POP_MARKER();
#if MSAA_EDGE_PROCESS_FADING
CShaderLib::SetForcedEdge(false);
#endif //MSAA_EDGE_PROCESS_FADING
#if !RSG_ORBIS && !RSG_DURANGO
grmShaderFx::SetForcedTechniqueGroupId(m_previousGroupAlphaClipId);
#endif // !RSG_ORBIS
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::PrepareSSAPass( bool PS3_ONLY(useSubSampleAlpha), bool PS3_ONLY(forceClip) )
{
#if __PS3
if (!useSubSampleAlpha && PostFX::UseSubSampledAlpha() && !forceClip)
{
GBuffer::UnlockTargets();
GBuffer::LockSingleTarget(GBUFFER_RT_0, true);
}
#endif // __PS3
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::FinishSSAPass()
{
#if __PS3
if (PostFX::GetMarkingSubSampledAlphaSamples())
{
GBuffer::UnlockSingleTarget(GBUFFER_RT_0);
GBuffer::LockTargets();
}
#endif // _PS3
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::PrepareCutoutPass( bool useSubSampleAlpha, bool forceClip, bool EQAA_ONLY(disableEQAA) )
{
grcStateBlock::SetBlendState(m_cutoutPass_B);
grcStateBlock::SetDepthStencilState(m_cutoutPass_DS);
grcStateBlock::SetRasterizerState(grcStateBlock::RS_Default);
m_previousGroupAlphaClipId = -2;
if ( PostFX::UseSubSampledAlpha() && !forceClip)
{
PostFX::SetMarkingSubSampleAlpha(!useSubSampleAlpha);
m_previousGroupAlphaClipId = grmShaderFx::GetForcedTechniqueGroupId();
if (useSubSampleAlpha)
{
PF_PUSH_TIMEBAR("SSA Diffuse Fragments");
PF_PUSH_MARKER("SSA Diffuse Fragments");
grcStateBlock::SetBlendState( PostFX::UseSinglePassSSA() ? m_SingleSampleSSABlendState : m_SSABlendState );
grmShaderFx::SetForcedTechniqueGroupId(m_deferredSubSampleAlphaTechniqueGroupId);
}
else
{
PF_PUSH_TIMEBAR("SSA Alpha Fragments");
PF_PUSH_MARKER("SSA Alpha Fragments");
grmShaderFx::SetForcedTechniqueGroupId(m_deferredSubSampleWriteAlphaTechniqueGroupId);
}
}
else
{
PostFX::SetMarkingSubSampleAlpha(false);
PF_PUSH_TIMEBAR("Cutout Pass");
PF_PUSH_MARKER("Cutout Pass");
m_previousGroupAlphaClipId = grmShaderFx::GetForcedTechniqueGroupId();
grmShaderFx::SetForcedTechniqueGroupId(m_deferredAlphaClipTechniqueGroupId);
#if MSAA_EDGE_PROCESS_FADING
CShaderLib::SetForcedEdge(IsEdgeFadeProcessingActive());
#endif //MSAA_EDGE_PROCESS_FADING
#if DEVICE_EQAA
if ( BANK_SWITCH(DebugDeferred::m_disableEqaaDuringCutoutPass,true) && disableEQAA &&
GRCDEVICE.GetMSAA() && (GRCDEVICE.GetMSAA().m_uSamples > GRCDEVICE.GetMSAA().m_uFragments) )
{
// Disable EQAA temporarily for the cutout pass, once we're finishes we will re-enable it
m_eqaaDisabledForCutout = true;
GRCDEVICE.SetAACount( 1, 1, 1 );
}
else
{
m_eqaaDisabledForCutout = false;
}
#endif // DEVICE_EQAA
}
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::FinishCutoutPass()
{
PF_POP_MARKER();
PF_POP_TIMEBAR();
if ( m_previousGroupAlphaClipId != -2)
{
grmShaderFx::SetForcedTechniqueGroupId(m_previousGroupAlphaClipId);
}
#if MSAA_EDGE_PROCESS_FADING
CShaderLib::SetForcedEdge(false);
#endif //MSAA_EDGE_PROCESS_FADING
#if DEVICE_EQAA
// EQAA was disabled temporarily for the cutout pass, now that we're done we need to re-enable it
if ( m_eqaaDisabledForCutout )
{
GRCDEVICE.SetAACount( GRCDEVICE.GetMSAA().m_uSamples, GRCDEVICE.GetMSAA().m_uFragments, GRCDEVICE.GetMSAA().m_uFragments );
m_eqaaDisabledForCutout = false;
}
#endif // DEVICE_EQAA
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::PrepareTreePass()
{
#if STENCIL_VEHICLE_INTERIOR
grcStateBlock::SetDepthStencilState(m_treePass_DS);
grcStateBlock::SetRasterizerState(grcStateBlock::RS_Default);
grcStateBlock::SetBlendState(m_defaultPass_B);
#if MSAA_EDGE_PROCESS_FADING
CShaderLib::SetForcedEdge(IsEdgeFadeProcessingActive());
#endif //MSAA_EDGE_PROCESS_FADING
PF_PUSH_MARKER("Default Pass - Tree");
#if __BANK
PF_PUSH_TIMEBAR("Default Pass - Tree");
#endif
#endif // STENCIL_VEHICLE_INTERIOR
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::FinishTreePass()
{
#if STENCIL_VEHICLE_INTERIOR
#if MSAA_EDGE_PROCESS_FADING
CShaderLib::SetForcedEdge(false);
#endif //MSAA_EDGE_PROCESS_FADING
#if __BANK
PF_POP_TIMEBAR();
#endif // __BANK
PF_POP_MARKER();
#endif // STENCIL_VEHICLE_INTERIOR
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::PrepareDefaultPass(fwRenderPassId BANK_ONLY(id))
{
grcStateBlock::SetDepthStencilState(m_defaultPass_DS);
grcStateBlock::SetRasterizerState(grcStateBlock::RS_Default);
grcStateBlock::SetBlendState(m_defaultPass_B);
#if __BANK
static const char* rpassStrTable[] =
{
"Default Pass - Visible",
"Default Pass - Lod",
"Default Pass - Cutout",
"Default Pass - Decal",
"Default Pass - Fading",
"Default Pass - Alpha",
"Default Pass - Water",
"Default Pass - Tree",
};
CompileTimeAssert(NELEM(rpassStrTable) == RPASS_NUM_RENDER_PASSES);
PF_PUSH_MARKER(rpassStrTable[id]);
PF_PUSH_TIMEBAR(rpassStrTable[id]);
#else
PF_PUSH_MARKER("Default Pass");
#endif
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::FinishDefaultPass()
{
#if __BANK
PF_POP_TIMEBAR();
#endif // __BANK
PF_POP_MARKER();
}
// ----------------------------------------------------------------------------------------------- //
#if MSAA_EDGE_PASS
bool DeferredLighting::IsEdgePassEnabled()
{
return GRCDEVICE.GetMSAA()>1
// Cutting off AMD pre-GCN hardware due to an acknowledged bug with stencil compression
&& GRCDEVICE.IsReadOnlyDepthAllowed();
}
bool DeferredLighting::IsEdgePassActive()
{
return IsEdgePassEnabled() BANK_ONLY(&& DebugDeferred::m_EnableEdgePass)
// Portal shadow optimization uses both SPAREOR1 and SPAREOR2 stencil flags
&& !CRenderPhaseCascadeShadowsInterface::ArePortalShadowsActive();
}
bool DeferredLighting::IsEdgePassActiveForSceneLights()
{
return IsEdgePassActive()
// Scene lights use both SPAREOR1 and SPAREOR2 flags for stencil culling
&& !DeferredLighting__m_useLightsHiStencil;
}
bool DeferredLighting::IsEdgePassActiveForPostfx()
{
return IsEdgePassActiveForSceneLights();
}
# if MSAA_EDGE_PROCESS_FADING
bool DeferredLighting::IsEdgeFadeProcessingActive()
{
return IsEdgePassActive() && !CShaderLib::UsesStippleFades() BANK_ONLY(&& DebugDeferred::m_EnableEdgeFadeProcessing);
}
# endif //MSAA_EDGE_PROCESS_FADING
static void DrawQuad()
{
# if FAST_QUAD_SUPPORT
FastQuad::Draw(true);
# else
grcDrawSingleQuadf(0.f,0.f,1.f,1.f, 0.0f, 0.0, 0.0, 0.0f, 0.0f, Color32(0));
# endif
}
enum EdgePass
{
EP_EMPTY,
EP_SHOW,
EP_MARK_DERIVE,
EP_MARK_SAMPLE1,
EP_MARK_SAMPLE2,
EP_MARK_SAMPLE4,
EP_MARK_SAMPLE8,
EP_MARK_SAMPLE16,
EP_MARK_SAMPLE4_OLD,
EP_MARK_SAMPLE8_OLD,
EP_MARK_SAMPLE_HEAVY,
EP_COLLECT2,
EP_COLLECT4,
EP_COLLECT8,
};
void DeferredLighting::ExecuteEdgeMarkPass(bool isInterrior)
{
if (!IsEdgePassActive() BANK_ONLY(|| DebugDeferred::m_IgnoreEdgeDetection))
{
return;
}
GRC_ALLOC_SCOPE_AUTO_PUSH_POP()
grcRenderTarget *stencilTarget = CRenderTargets::GetDepthBuffer();
grmShader *const shader = m_deferredShaders[MM_TEXTURE_READS_ONLY][DEFERRED_SHADER_LIGHTING];
SetShaderGBufferTargets();
EdgePass pass = EP_EMPTY;
#if MSAA_EDGE_PROCESS_FADING
bool bUseEdgeProcessing = !isInterrior && IsEdgeFadeProcessingActive();
switch (GRCDEVICE.GetMSAA())
{
case 2: pass = EP_COLLECT2; break;
case 4: pass = EP_COLLECT4; break;
case 8: pass = EP_COLLECT8; break;
default: bUseEdgeProcessing = false;
}
if (bUseEdgeProcessing)
{
// Collect (with 'OR') all stencil samples into the copy target
grcStateBlock::SetStates(grcStateBlock::RS_NoBackfaceCull, grcStateBlock::DSS_IgnoreDepth, grcStateBlock::BS_Default);
grcTextureFactory::GetInstance().LockRenderTarget(0, m_edgeCopyTarget, NULL);
ShaderUtil::StartShader("Edge - Collect", shader, m_edgeMarkTechniqueIdx, pass);
DrawQuad();
ShaderUtil::EndShader(shader);
grcTextureFactory::GetInstance().UnlockRenderTarget(0);
shader->SetVar(m_edgeCopyTextureVar, m_edgeCopyTarget);
}else
{
shader->SetVar(m_edgeCopyTextureVar, grcTexture::NoneBlack);
}
#else
(void)isInterrior;
#endif //MSAA_EDGE_PROCESS_FADING
#if MSAA_EDGE_USE_DEPTH_COPY
CRenderTargets::CopyDepthBuffer(stencilTarget, m_edgeMarkDepthCopy);
SetShaderGBufferTarget(GBUFFER_DEPTH, m_edgeMarkDepthCopy);
#elif RSG_PC
// avoiding RT conflict
const grcTexture *depthTexture = NULL;
if (GRCDEVICE.IsReadOnlyDepthAllowed())
{
depthTexture = CRenderTargets::GetDepthBuffer();
stencilTarget = CRenderTargets::GetDepthBufferCopy();
}else
{
depthTexture = CRenderTargets::GetDepthBufferCopy(true);
}
SetShaderGBufferTarget(GBUFFER_DEPTH, depthTexture);
//SetShaderGBufferTarget(GBUFFER_STENCIL, depthTexture);
#endif //RSG_PC
grcStateBlock::SetRasterizerState(m_edgePass_R);
grcStateBlock::SetDepthStencilState(m_edgePass_DS, EDGE_FLAG);
grcStateBlock::SetBlendState(m_skinPass_B);
shader->SetVar(m_edgeMarkParamsVar,
BANK_SWITCH(DebugDeferred::m_edgeMarkParams, DEFERRED_LIGHTING_DEFAULT_edgeMarkParams));
pass = EP_MARK_DERIVE;
switch (GRCDEVICE.GetMSAA())
{
case 2: pass = EP_MARK_SAMPLE2; break;
case 4: pass = BANK_ONLY(DebugDeferred::m_OldEdgeDetection ? EP_MARK_SAMPLE4_OLD :) EP_MARK_SAMPLE4; break;
case 8: pass = BANK_ONLY(DebugDeferred::m_OldEdgeDetection ? EP_MARK_SAMPLE8_OLD :) EP_MARK_SAMPLE8; break;
case 16: pass = EP_MARK_SAMPLE16; break;
}
#if __BANK
if (DebugDeferred::m_AlternativeEdgeDetection)
pass = EP_MARK_DERIVE;
if (DebugDeferred::m_AggressiveEdgeDetection)
pass = EP_MARK_SAMPLE_HEAVY;
#endif //__BANK
grcTextureFactory::GetInstance().LockRenderTarget(0, NULL, stencilTarget);
ShaderUtil::StartShader("Edge - Mark", shader, m_edgeMarkTechniqueIdx, pass);
DrawQuad();
ShaderUtil::EndShader(shader);
grcTextureFactory::GetInstance().UnlockRenderTarget(0);
SetShaderGBufferTargets(); //restore GBufferTargets
# if __DEV
if (DebugDeferred::m_DebugEdgePassColor)
{
grcStateBlock::SetStates(grcStateBlock::RS_NoBackfaceCull, grcStateBlock::DSS_IgnoreDepth, grcStateBlock::BS_Default);
grcTextureFactory::GetInstance().LockRenderTarget(0, m_edgeMarkDebugTarget, NULL);
ShaderUtil::StartShader("Edge - Show", shader, m_edgeMarkTechniqueIdx, EP_SHOW);
DrawQuad();
ShaderUtil::EndShader(shader);
grcTextureFactory::GetInstance().UnlockRenderTarget(0);
}
# endif //BANK
}
void DeferredLighting::ExecuteEdgeClearPass()
{
if (!IsEdgePassActive() BANK_ONLY(|| DebugDeferred::m_IgnoreEdgeDetection))
{
return;
}
grcRenderTarget *stencilTarget = CRenderTargets::GetDepthBuffer();
grcStateBlock::SetRasterizerState(m_edgePass_R);
grcStateBlock::SetDepthStencilState(m_edgePass_DS, 0);
grcStateBlock::SetBlendState(m_skinPass_B);
grcTextureFactory::GetInstance().LockRenderTarget(0, NULL, stencilTarget);
ShaderUtil::StartShader("Edge - Clear", m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_LIGHTING], m_edgeMarkTechniqueIdx, EP_EMPTY);
DrawQuad();
ShaderUtil::EndShader(m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_LIGHTING]);
grcTextureFactory::GetInstance().UnlockRenderTarget(0);
}
#endif //MSAA_EDGE_PASS
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::ExecuteSkinLightPass(grcRenderTarget* backBuffer, const bool enablePedLight)
{
GRC_ALLOC_SCOPE_AUTO_PUSH_POP()
#if RSG_PC
if(GRCDEVICE.GetMSAA()>1 || (GRCDEVICE.GetDxFeatureLevel() <= 1000))
{
CRenderTargets::UnlockSceneRenderTargets();
CRenderTargets::LockSceneRenderTargets();
}
#endif
if (enablePedLight)
{
Lights::RenderPedLight();
#if DEVICE_GPU_WAIT
GRCDEVICE.GpuWaitOnPreviousWrites();
#endif
}
#if __BANK
if (!DebugDeferred::m_enableSkinPass)
return;
#endif
#if RSG_PC
if (GRCDEVICE.GetManufacturer() == INTEL && CSettingsManager::GetInstance().GetSettings().m_graphics.m_PostFX < CSettings::High)
return;
#endif
#if DEVICE_MSAA && !ENABLE_PED_PASS_AA_SOURCE
if(GRCDEVICE.GetMSAA()>1)
{
// SSS_SKIN samples from the resolved buffer so resolve after RenderPedLight but before SSS_SKIN
CRenderTargets::ResolveBackBuffer(true);
#if RSG_PC
if (GRCDEVICE.GetDxFeatureLevel() < 1100)
SetShaderGBufferTarget(GBUFFER_DEPTH, CRenderTargets::GetDepthBuffer());
#endif
}
#endif
PF_PUSH_TIMEBAR_DETAIL("Skin");
grmShader* currentShader = GetShader(DEFERRED_SHADER_LIGHTING);
grcStateBlock::SetBlendState(m_skinPass_B);
grcStateBlock::SetRasterizerState(m_skinPass_R);
if (backBuffer == NULL)
{
backBuffer = XENON_SWITCH( CRenderTargets::GetBackBuffer7e3toInt(true), CRenderTargets::GetBackBuffer() );
}
grcRenderTarget* backBufferSrc = backBuffer;
grcRenderTarget* depthRT = NULL;
#if DEVICE_MSAA
if(GRCDEVICE.GetMSAA()>1)
{
#if ENABLE_PED_PASS_AA_SOURCE
currentShader->SetVar( m_shaderLightTextureAA, CRenderTargets::GetBackBufferCopyAA(true) );
#else
backBufferSrc = CRenderTargets::GetBackBufferCopy(false);
#endif
}
#if RSG_PC
else
{
grcRenderTarget* depthCopyRT = CRenderTargets::GetDepthBufferCopy();
if (GRCDEVICE.GetDxFeatureLevel() <= 1000)
{
depthCopyRT = CRenderTargets::GetDepthBuffer();
SetShaderGBufferTarget(GBUFFER_DEPTH, CRenderTargets::GetDepthBufferCopy());
}
// Source/Destination can not be the same so do SSS lighting to Back buffer copy and restore to back buffer afterwards
CRenderTargets::UnlockSceneRenderTargets();
depthRT = (GRCDEVICE.IsReadOnlyDepthAllowed()) ? CRenderTargets::GetDepthBuffer_ReadOnly() : depthCopyRT;
grcTextureFactory::GetInstance().LockRenderTarget(0, CRenderTargets::GetBackBufferCopy(false), depthRT);
GRCDEVICE.Clear(true, Color32(0, 0, 0, 0), false, 0.0f, false, 0);
}
#endif // RSG_PC
#endif // DEVICE_MSAA
// Skin setup
currentShader->SetVar(
m_shaderLightParameterID_skinColourTweak,
BANK_SWITCH(DebugDeferred::m_SubSurfaceColorTweak, DEFERRED_LIGHTING_DEFAULT_subsurfaceColorTweak));
currentShader->SetVar(
m_shaderLightParameterID_skinParams,
BANK_SWITCH(DebugDeferred::m_skinPassParams, DEFERRED_LIGHTING_DEFAULT_skinPassParams));
SetDeferredVar(DEFERRED_SHADER_LIGHTING, DEFERRED_SHADER_LIGHT_TEXTURE, backBufferSrc);
#if __BANK
u32 skinPassPC = (DebugDeferred::m_enableSkinPassNG) ? 4 : 2;
u32 skinPassNG = (DebugDeferred::m_enableSkinPassNG) ? 3 : 0;
#if RSG_PC
skinPassPC += (CSettingsManager::GetInstance().GetSettings().m_graphics.m_PostFX >= CSettings::Ultra && DebugDeferred::m_enableSkinPassNG) ? 1 : 0;
#endif
#else
u32 skinPassPC = 4;
#if RSG_PC
if (CSettingsManager::GetInstance().GetSettings().m_graphics.m_PostFX >= CSettings::Ultra)
skinPassPC = 5;
#endif
u32 skinPassNG = 3;
#endif
if(DeferredLighting__m_useGeomPassStencil)
{
grcStateBlock::SetDepthStencilState(m_skinPass_DS, DEFERRED_MATERIAL_PED);
}
else
{
grcStateBlock::SetDepthStencilState(m_skinNoStencilPass_DS);
}
if (ShaderUtil::StartShader("Ped Pass", currentShader, m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_SSS_SKIN], (depthRT != NULL) ? skinPassPC : skinPassNG))
{
Render2DDeferredLightingRect(0.0f, 0.0f, 1.0, 1.0f);
ShaderUtil::EndShader(currentShader);
}
grcStateBlock::SetDepthStencilState(CShaderLib::DSS_Default_Invert);
#if !__WIN32PC && !RSG_DURANGO && !RSG_ORBIS
CRenderTargets::ClearStencilCull(DEFERRED_MATERIAL_PED);
#endif
#if RSG_PC
if (depthRT != NULL)
{
if (GRCDEVICE.GetDxFeatureLevel() <= 1000)
{
SetShaderGBufferTarget(GBUFFER_DEPTH, CRenderTargets::GetDepthBuffer());
}
// Restore Skin Copy onto back buffer
grcTextureFactory::GetInstance().UnlockRenderTarget(0);
CRenderTargets::CopyTarget(CRenderTargets::GetBackBufferCopy(false), backBuffer, depthRT, DEFERRED_MATERIAL_PED );
CRenderTargets::LockSceneRenderTargets_DepthCopy();
}
#endif // RSG_PC
PF_POP_TIMEBAR_DETAIL();
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::ExecuteUISkinLightPass(grcRenderTarget* backBuffer, grcRenderTarget* backBufferCopy)
{
GRC_ALLOC_SCOPE_AUTO_PUSH_POP()
#if __BANK
if (!DebugDeferred::m_enableSkinPass)
return;
#endif
grmShader* currentShader = DeferredLighting::GetShader(DEFERRED_SHADER_LIGHTING, MM_SINGLE);
grcStateBlock::SetDepthStencilState(m_skinPass_UI_DS, DEFERRED_MATERIAL_CLEAR);
grcStateBlock::SetBlendState(m_skinPass_B);
grcStateBlock::SetRasterizerState(m_skinPass_R);
// Skin setup
currentShader->SetVar(
m_shaderLightParameterID_skinColourTweak,
BANK_SWITCH(DebugDeferred::m_SubSurfaceColorTweak, DEFERRED_LIGHTING_DEFAULT_subsurfaceColorTweak));
currentShader->SetVar(
m_shaderLightParameterID_skinParams,
BANK_SWITCH(DebugDeferred::m_skinPassParams, DEFERRED_LIGHTING_DEFAULT_skinPassParams));
#if __XENON
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_HISTENCILENABLE, TRUE));
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_HISTENCILWRITEENABLE, FALSE));
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_HISTENCILFUNC, D3DHSCMP_NOTEQUAL));
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_HISTENCILREF, 0xFF));
#endif
SetDeferredVar(DEFERRED_SHADER_LIGHTING, DEFERRED_SHADER_LIGHT_TEXTURE, (backBufferCopy ? backBufferCopy : backBuffer), MM_SINGLE);
if (ShaderUtil::StartShader("Ped Pass", currentShader, GetTechnique(DEFERRED_TECHNIQUE_SSS_SKIN, MM_SINGLE), 1))
{
Render2DDeferredLightingRect(0.0f, 0.0f, 1.0, 1.0f);
ShaderUtil::EndShader(currentShader);
}
grcStateBlock::SetDepthStencilState(CShaderLib::DSS_Default_Invert);
}
void DeferredLighting::ExecutePuddlePass()
{
GRC_ALLOC_SCOPE_AUTO_PUSH_POP()
PF_PUSH_TIMEBAR_DETAIL("PuddlePass");
#if RSG_PC
CShaderLib::SetStereoParams(Vector4(0,0,1,0));
#endif
SetProjectionShaderParams(DEFERRED_SHADER_LIGHTING, MM_DEFAULT);
PuddlePassSingleton::InstanceRef().Draw( GetShader(DEFERRED_SHADER_LIGHTING) );
#if RSG_PC
CShaderLib::SetStereoParams(Vector4(0,0,0,0));
#endif
PF_POP_TIMEBAR_DETAIL();
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::ExecuteSkinLightPassForward(grcRenderTarget* pSrcColourTarget, grcRenderTarget* pSrcDepthTarget)
{
#if __BANK
if (!DebugDeferred::m_enableSkinPass)
return;
#endif
PF_PUSH_TIMEBAR_DETAIL("Skin Forward");
grmShader* currentShader = GetShader(DEFERRED_SHADER_LIGHTING);
if(DeferredLighting__m_useGeomPassStencil)
{
grcStateBlock::SetDepthStencilState(m_skinPassForward_DS, DEFERRED_MATERIAL_CLEAR);
}
else
{
grcStateBlock::SetDepthStencilState(m_skinNoStencilPass_DS);
}
grcStateBlock::SetBlendState(m_skinPass_B);
grcStateBlock::SetRasterizerState(m_skinPass_R);
#if DEVICE_MSAA && ENABLE_PED_PASS_AA_SOURCE
currentShader->SetVar( m_shaderLightTextureAA, CRenderTargets::GetBackBufferCopyAA(true) );
#endif
grcRenderTarget* backBuff = NULL;
backBuff = pSrcColourTarget;
SetDeferredGlobalVar(DEFERRED_SHADER_GBUFFER_DEPTH_GLOBAL, pSrcDepthTarget);
// Skin setup
currentShader->SetVar(
m_shaderLightParameterID_skinColourTweak,
BANK_SWITCH(DebugDeferred::m_SubSurfaceColorTweak, DEFERRED_LIGHTING_DEFAULT_subsurfaceColorTweak));
currentShader->SetVar(
m_shaderLightParameterID_skinParams,
BANK_SWITCH(DebugDeferred::m_skinPassParams, DEFERRED_LIGHTING_DEFAULT_skinPassParams));
SetDeferredVar(DEFERRED_SHADER_LIGHTING, DEFERRED_SHADER_LIGHT_TEXTURE, backBuff);
if (ShaderUtil::StartShader("Ped Pass", currentShader, m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_SSS_SKIN], 1))
{
Render2DDeferredLightingRect(0.0f, 0.0f, 1.0, 1.0f);
ShaderUtil::EndShader(currentShader);
}
if(DeferredLighting__m_useGeomPassStencil)
{
grcStateBlock::SetDepthStencilState(CShaderLib::DSS_Default_Invert);
}
PF_POP_TIMEBAR_DETAIL();
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::RenderFoliageHelper(const s32 pass, const MultisampleMode aaMode, const EdgeMode em)
{
#if MSAA_EDGE_PASS
if(DeferredLighting__m_useGeomPassStencil)
{
grcStateBlock::SetDepthStencilState(
em == EM_IGNORE ? m_foliagePass_DS : m_directionalEdgeAllEqualPass_DS,
em == EM_EDGE0 ? DEFERRED_MATERIAL_TREE | EDGE_FLAG : DEFERRED_MATERIAL_TREE);
}
else
{
grcStateBlock::SetDepthStencilState(
em == EM_IGNORE ? m_foliageNoStencilPass_DS : m_directionalEdgeMaskEqualPass_DS,
em == EM_EDGE0 ? EDGE_FLAG : 0);
}
#else //MSAA_EDGE_PASS
(void)em;
if(DeferredLighting__m_useGeomPassStencil)
{
#if __XENON || __PS3
CRenderTargets::RefreshStencilCull(true, DEFERRED_MATERIAL_TREE, 0x07 PS3_ONLY(, false));
#endif
#if RSG_PC
grcStateBlock::SetDepthStencilState(m_foliagePass_DS, DEFERRED_MATERIAL_TREE);
#else
grcStateBlock::SetDepthStencilState(m_foliageMainPass_DS, DEFERRED_MATERIAL_TREE|DEFERRED_MATERIAL_SPECIALBIT);
#endif
}
else
{
grcStateBlock::SetDepthStencilState(m_foliageNoStencilPass_DS);
}
#endif //MSAA_EDGE_PASS
SetDirectionalRenderState(DEFERRED_SHADER_DIRECTIONAL, aaMode);
RenderDirectionalLight(pass, true, aaMode);
}
void DeferredLighting::ExecuteFoliageLightPass()
{
#if __BANK
if (!DebugDeferred::m_enableFoliageLightPass)
return;
#endif // __BANK
PF_PUSH_TIMEBAR_DETAIL("Foliage");
GRC_ALLOC_SCOPE_AUTO_PUSH_POP()
const CLightSource &dirLight = Lights::GetRenderDirectionalLight();
if(dirLight.GetIntensity() > 0.0f)
{
grcStateBlock::SetBlendState(m_foliagePass_B);
grcStateBlock::SetRasterizerState(m_foliagePass_R);
DeferredLighting::SetShaderGBufferTargets();
#if RSG_PC
if (GRCDEVICE.GetDxFeatureLevel() <= 1000)
{
SetShaderGBufferTarget(GBUFFER_DEPTH, CRenderTargets::GetDepthBufferCopy());
SetShaderGBufferTarget(GBUFFER_STENCIL, CRenderTargets::GetDepthBufferCopy_Stencil());
}
#endif
s32 pass = CalculatePass(&dirLight, false, dirLight.IsCastShadows(), true);
#if MSAA_EDGE_PASS
const bool bUseEdgePass = IsEdgePassActive() BANK_ONLY(&& DebugDeferred::m_OptimizeDirectionalFoliage);
if (bUseEdgePass)
{
BANK_ONLY(if (DebugDeferred::m_EnableDirectionalFoliageEdge))
RenderFoliageHelper(pass, MM_SUPER_SAMPLE, EM_EDGE0);
BANK_ONLY(if (DebugDeferred::m_EnableDirectionalFoliageFace))
RenderFoliageHelper(pass, MM_TEXTURE_READS_ONLY, EM_FACE0);
}else
#else
const bool bUseEdgePass = false;
#endif //MSAA_EDGE_PASS
{
RenderFoliageHelper(pass, MM_DEFAULT, EM_IGNORE);
}
if( DeferredLighting__m_useGeomPassStencil || bUseEdgePass)
{
grcStateBlock::SetDepthStencilState(CShaderLib::DSS_Default_Invert);
#if __XENON || __PS3
CRenderTargets::ClearStencilCull(DEFERRED_MATERIAL_TREE);
#endif
}
}
PF_POP_TIMEBAR_DETAIL();
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::ExecuteSnowPass()
{
PF_PUSH_MARKER("Snow");
#if RSG_PC
grcRenderTarget* snowRT = VideoResManager::IsSceneScaled() ? CRenderTargets::GetOffscreenBuffer3() : CRenderTargets::GetOffscreenBuffer2();
grcTextureFactory::GetInstance().LockRenderTarget(0, snowRT, NULL);
#else
grcTextureFactory::GetInstance().LockRenderTarget(0, GBuffer::GetTarget(GBUFFER_RT_0), NULL);
#endif
GRC_ALLOC_SCOPE_AUTO_PUSH_POP()
grcStateBlock::SetStates(grcStateBlock::RS_NoBackfaceCull, grcStateBlock::DSS_IgnoreDepth, grcStateBlock::BS_Default);
DeferredLighting::SetShaderGBufferTargets();
SetDeferredVar(DEFERRED_SHADER_LIGHTING, DEFERRED_SHADER_LIGHT_TEXTURE2, SSAO::GetSSAOTexture());
grmShader* currentShader = GetShader(DEFERRED_SHADER_LIGHTING);
if (ShaderUtil::StartShader("Snow Pass", currentShader, m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_SNOW], 0))
{
Render2DDeferredLightingRect(0.0f, 0.0f, 1.0, 1.0f);
ShaderUtil::EndShader(currentShader);
}
grcResolveFlags flags;
flags.NeedResolve = false;
grcTextureFactory::GetInstance().UnlockRenderTarget(0, &flags);
#if RSG_PC
CRenderTargets::CopyTarget(snowRT, GBuffer::GetTarget(GBUFFER_RT_0));
#endif
#if __XENON
grcTextureFactory::GetInstance().LockRenderTarget(0, GBuffer::GetTarget(GBUFFER_RT_0), NULL);
flags.NeedResolve = true;
flags.ClearColor = true;
grcTextureFactory::GetInstance().UnlockRenderTarget(0, &flags);
#endif
PF_POP_MARKER();
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::SetDepthStencilState(const bool bNoDirLight, const EdgeMode em)
{
#if MSAA_EDGE_PASS
if(DeferredLighting__m_useGeomPassStencil)
{
struct State
{
grcDepthStencilStateHandle *handle;
int refValue;
};
if (BANK_ONLY(DebugDeferred::m_enableFoliageLightPass &&) !bNoDirLight)
{
const State states[] =
{
{&m_directionalFullPass_DS, DEFERRED_MATERIAL_TREE},
{&m_directionalEdgeBit0EqualPass_DS, EDGE_FLAG | 0x0}, //Edge0: xy0
{&m_directionalEdgeAllEqualPass_DS, EDGE_FLAG | 0x1}, //Edge1: 001
{&m_directionalEdgeBit0EqualPass_DS, 0 | 0x0}, //Face0: xy0
{&m_directionalEdgeAllEqualPass_DS, 0 | 0x1}, //Face1: 001
};
CompileTimeAssert(NELEM(states) == EM_TOTAL);
grcStateBlock::SetDepthStencilState(*states[em].handle, states[em].refValue);
}
else
{
const State states[] =
{
{&m_directionalAmbientPass_DS, DEFERRED_MATERIAL_CLEAR},
{&m_directionalEdgeBit2EqualPass_DS, EDGE_FLAG | 0x0}, //Edge0: 0yz
{&m_directionalEdgeAllEqualPass_DS, EDGE_FLAG | 0x4}, //Edge1: 100
{&m_directionalEdgeBit2EqualPass_DS, 0 | 0x0}, //Face0: 0yz
{&m_directionalEdgeAllEqualPass_DS, 0 | 0x4}, //Face1: 100
};
CompileTimeAssert(NELEM(states) == EM_TOTAL);
grcStateBlock::SetDepthStencilState(*states[em].handle, states[em].refValue);
}
}
else
{
grcStateBlock::SetDepthStencilState(
em == EM_IGNORE ? m_directionalNoStencilPass_DS : m_directionalEdgeMaskEqualPass_DS,
em == EM_EDGE0 ? EDGE_FLAG : 0);
}
#else //MSAA_EDGE_PASS
(void)em;
if(DeferredLighting__m_useGeomPassStencil)
{
// use stencil non-zero for sunlight
#if __PPU || __XENON
if (BANK_ONLY(DebugDeferred::m_enableFoliageLightPass &&) !bNoDirLight PS3_ONLY(&& !appliedZCullRefresh))
{
CRenderTargets::RefreshStencilCull(false, DEFERRED_MATERIAL_CLEAR, 0xFB PS3_ONLY(, false));
}
#endif //__PPU || __XENON
if (BANK_ONLY(DebugDeferred::m_enableFoliageLightPass && !(CutSceneManager::GetInstance()->IsPlaying() && CutSceneManager::GetInstance()->IsIsolating()) && ) !bNoDirLight)
{
#if RSG_PC
grcStateBlock::SetDepthStencilState(m_directionalFullPass_DS, DEFERRED_MATERIAL_TREE);
#else
grcStateBlock::SetDepthStencilState(m_directionalFullPass_DS, DEFERRED_MATERIAL_TREE|DEFERRED_MATERIAL_SPECIALBIT);
#endif
}
else
{
grcStateBlock::SetDepthStencilState(m_directionalAmbientPass_DS, DEFERRED_MATERIAL_CLEAR);
}
}
else
{
grcStateBlock::SetDepthStencilState(m_directionalNoStencilPass_DS, 0);
}
#endif //MSAA_EDGE_PASS
}
void DeferredLighting::RenderDirectionalHelper(const bool bNoDirLight, const MultisampleMode aaMode, const EdgeMode em)
{
#if TILED_LIGHTING_ENABLED && (__XENON || __PS3 || __D3D11 || RSG_ORBIS)
if ((BANK_SWITCH(DebugDeferred::m_enableTiledRendering, !(__D3D11 || RSG_ORBIS)) && !Water::IsCameraUnderwater()) BANK_ONLY( || DebugDeferred::m_forceTiledDirectional))
{
RenderTiledDirectionalLight(bNoDirLight, aaMode, em);
}
else
#endif
{
SetDepthStencilState(bNoDirLight, em);
const s32 pass = CalculatePass(&Lights::GetRenderDirectionalLight(), false, !bNoDirLight, false);
CompileTimeAssert(DIRECTIONALPASS_NUM_PASSES < 255); // must fit into u8
SetDirectionalRenderState(DEFERRED_SHADER_DIRECTIONAL, aaMode);
RenderDirectionalLight(pass, true, aaMode);
}
}
void DeferredLighting::ExecuteAmbientAndDirectionalPass(const bool bDrawDefLight, bool PPU_ONLY(appliedZCullRefresh) )
{
PF_PUSH_TIMEBAR_DETAIL("Directional Light");
GRC_ALLOC_SCOPE_AUTO_PUSH_POP()
const CLightSource &dirLight = Lights::GetRenderDirectionalLight();
const bool bNoDirLight = ((dirLight.GetIntensity() == 0.0f) ||
!dirLight.IsCastShadows());
if(bDrawDefLight)
{
#if !RSG_PC
// foliage prepass only for Orbis/Durango - BS#2069821:
grcStateBlock::SetBlendState(grcStateBlock::BS_Default_WriteMaskNone);
grcStateBlock::SetDepthStencilState(m_foliagePrePass_DS, DEFERRED_MATERIAL_TREE|DEFERRED_MATERIAL_SPECIALBIT);
grmShader* currentShader = GetShader(DEFERRED_SHADER_LIGHTING);
if (ShaderUtil::StartShader("Foliage PreProcess", currentShader, m_techniques[MM_DEFAULT][DEFERRED_TECHNIQUE_FOLIAGE_PREPROCESS], 0))
{
Render2DDeferredLightingRect(0.0f, 0.0f, 1.0, 1.0f);
ShaderUtil::EndShader(currentShader);
}
grcStateBlock::SetDepthStencilState(CShaderLib::DSS_Default_Invert);
#endif
grcStateBlock::SetBlendState(grcStateBlock::BS_Default);
#if __XENON
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_HISTENCILENABLE, TRUE));
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_HISTENCILWRITEENABLE, FALSE));
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_HISTENCILFUNC, D3DHSCMP_NOTEQUAL));
if (BANK_ONLY(DebugDeferred::m_enableFoliageLightPass &&) !bNoDirLight)
{
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_HISTENCILREF, 0xFB));
}
else
{
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_HISTENCILREF, 0xFF));
}
CHECK_HRESULT(GRCDEVICE.GetCurrent()->FlushHiZStencil(D3DFHZS_ASYNCHRONOUS));
if(Water::UseHQWaterRendering())//this prevents corruption from being visible in the water depth occluded areas.
GRCDEVICE.Clear(true, Color32(0x0), false, 0.0f, 0);
#endif
grcStateBlock::SetRasterizerState(m_directionalPass_R);
SetShaderGBufferTargets();
#if MSAA_EDGE_PASS
const bool bUseEdgePass = IsEdgePassActive() BANK_ONLY(&& DebugDeferred::m_OptimizeDirectional);
if (bUseEdgePass)
{
// need additional passes to cover tree/non-tree and ambient/non-ambient cases
BANK_ONLY(if (DebugDeferred::m_EnableDirectionalEdge0))
{
RenderDirectionalHelper(bNoDirLight, MM_SUPER_SAMPLE, EM_EDGE0);
}
if (DeferredLighting__m_useGeomPassStencil BANK_ONLY(&& DebugDeferred::m_EnableDirectionalEdge1))
{
RenderDirectionalHelper(bNoDirLight, MM_SUPER_SAMPLE, EM_EDGE1);
}
BANK_ONLY(if (DebugDeferred::m_EnableDirectionalFace0))
{
RenderDirectionalHelper(bNoDirLight, MM_TEXTURE_READS_ONLY, EM_FACE0);
}
if (DeferredLighting__m_useGeomPassStencil BANK_ONLY(&& DebugDeferred::m_EnableDirectionalFace1))
{
RenderDirectionalHelper(bNoDirLight, MM_TEXTURE_READS_ONLY, EM_FACE1);
}
}else
#else
const bool bUseEdgePass = false;
#endif //MSAA_EDGE_PASS
{
RenderDirectionalHelper(bNoDirLight, MM_DEFAULT, EM_IGNORE);
}
if(DeferredLighting__m_useGeomPassStencil || bUseEdgePass)
{
#if __XENON || __PS3
if (BANK_ONLY(DebugDeferred::m_enableFoliageLightPass &&) !bNoDirLight PS3_ONLY(&& !appliedZCullRefresh))
{
CRenderTargets::ClearStencilCull(DEFERRED_MATERIAL_CLEAR);
}
#endif
grcStateBlock::SetDepthStencilState(CShaderLib::DSS_Default_Invert);
}
#if __XENON
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_HISTENCILENABLE, FALSE));
#endif
}
if ( false)
RenderTiledShadow();
PF_POP_TIMEBAR_DETAIL();
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::QualityModeSelect()
{
m_LightingQuality = LQ_INGAME;
if(camInterface::GetCutsceneDirector().IsCutScenePlaying())
{
m_LightingQuality = LQ_CUTSCENE;
}
#if __BANK
if(DebugDeferred::m_bForceHighQualityLighting)
{
m_LightingQuality = LQ_CUTSCENE;
}
#endif // __BANK
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::GetProjectionShaderParams(Vec4V_InOut projParamsOut, Vec3V_InOut shearProj0, Vec3V_InOut shearProj1, Vec3V_InOut shearProj2)
{
const grcViewport *const vp = grcViewport::GetCurrent();
const Vector4 projParams = ShaderUtil::CalculateProjectionParams(vp);
const Vector2 shear = vp->GetPerspectiveShear();
Mat34V_ConstRef invView = vp->GetCameraMtx();
// Pre-combining constants, to avoid constant ops in "GetEyeVec()" in the shaders
// Originally was:
// const float2 projPos = (signedScreenPos + deferredPerspectiveShearParams.xy) * deferredProjectionParams.xy;
// return float4(mul( float4(projPos,-1,0), gViewInverse ).xyz, 1);
//
// After factoring, it is now only a 3x3 transform instead of add + scale + add + scale + 4x4 transform
float sxpx = shear.x * projParams.x;
float sypy = shear.y * projParams.y;
shearProj0 = Vec3V(projParams.x * invView[0][0], projParams.y * invView[1][0], sxpx * invView[0][0] + sypy * invView[1][0] - invView[2][0]);
shearProj1 = Vec3V(projParams.x * invView[0][1], projParams.y * invView[1][1], sxpx * invView[0][1] + sypy * invView[1][1] - invView[2][1]);
shearProj2 = Vec3V(projParams.x * invView[0][2], projParams.y * invView[1][2], sxpx * invView[0][2] + sypy * invView[1][2] - invView[2][2]);
projParamsOut = VECTOR4_TO_VEC4V(projParams);
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::SetProjectionShaderParams(eDeferredShaders deferredShader, const MultisampleMode aaMode)
{
// Set screen size
const float screenWidth = (float)VideoResManager::GetSceneWidth();
const float screenHeight = (float)VideoResManager::GetSceneHeight();
const Vector4 screenSize(screenWidth, screenHeight, 1.0f / screenWidth, 1.0f / screenHeight);
Vec4V projParams;
Vec3V shearProj0, shearProj1, shearProj2;
GetProjectionShaderParams(projParams, shearProj0, shearProj1, shearProj2);
SetDeferredVar(deferredShader, DEFERRED_SHADER_SCREENSIZE, screenSize, aaMode);
SetDeferredVar(deferredShader, DEFERRED_SHADER_PROJECTION_PARAMS, projParams, aaMode);
SetDeferredVar(deferredShader, DEFERRED_SHADER_PERSPECTIVESHEAR_PARAMS0, shearProj0, aaMode);
SetDeferredVar(deferredShader, DEFERRED_SHADER_PERSPECTIVESHEAR_PARAMS1, shearProj1, aaMode);
SetDeferredVar(deferredShader, DEFERRED_SHADER_PERSPECTIVESHEAR_PARAMS2, shearProj2, aaMode);
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::SetLightShaderParams(
eDeferredShaders deferredShader,
const CLightSource* light,
const grcTexture *texture,
float radiusScale,
const bool tangentAlignedToCamDir,
const bool useHighResMesh,
const MultisampleMode aaMode)
{
Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER));
// Light Parameters
Vector4 position;
float radius = 0.0f;
Vector4 direction;
Vector4 tangent;
Vector4 colourAndIntensity;
eLightType type;
// Defaults for all lights
type = light->GetType();
position = Vector4(light->GetPosition());
direction = Vector4(light->GetDirection());
tangent = Vector4(light->GetTangent());
#if __WIN32PC || RSG_DURANGO || RSG_ORBIS
position.w = direction.w = tangent.w = 0.0f; // to prevent NaN in shaders constants asserts
#endif
if (tangentAlignedToCamDir)
{
const Vec3V camDir = -gVpMan.GetRenderGameGrcViewport()->GetCameraMtx().GetCol2();
tangent = VEC3V_TO_VECTOR3(Normalize(Cross(RCC_VEC3V(direction), camDir)));
}
switch (type)
{
case LIGHT_TYPE_POINT:
case LIGHT_TYPE_SPOT:
case LIGHT_TYPE_CAPSULE:
{
position -= direction * light->GetCapsuleExtent() * 0.5f;
radius = light->GetRadius()*radiusScale;
colourAndIntensity = Vector4(light->GetColor().x, light->GetColor().y, light->GetColor().z, light->GetIntensity());
BANK_ONLY(DebugLighting::OverrideDeferredLightParams(&colourAndIntensity, light));
break;
}
case LIGHT_TYPE_DIRECTIONAL:
{
colourAndIntensity.SetVector3ClearW(light->GetColor() * light->GetIntensity());
BANK_ONLY(DebugLighting::OverrideDirectional(&colourAndIntensity));
break;
}
case LIGHT_TYPE_AO_VOLUME:
{
colourAndIntensity = Vector4(light->GetColor().x, light->GetColor().y, light->GetColor().z, light->GetIntensity());
radius = light->GetRadius();
break;
}
default:
{
Assertf(false, "Tried to set shaders parameters for light type %d\n", type);
break;
}
}
Vector4 deferredLightParams[LIGHT_PARAM_COUNT - 5];
Lights::CalculateLightParams(light, deferredLightParams);
Vector4 lightParams[LIGHT_PARAM_COUNT];
lightParams[0] = position;
lightParams[1] = direction;
lightParams[2] = tangent;
lightParams[3] = colourAndIntensity;
lightParams[4] = Lights::CalculateLightConsts(type, radius, useHighResMesh);
lightParams[5] = deferredLightParams[0];
lightParams[6] = deferredLightParams[1];
lightParams[7] = deferredLightParams[2];
lightParams[8] = deferredLightParams[3];
lightParams[9] = deferredLightParams[4];
lightParams[10] = deferredLightParams[5];
lightParams[11] = deferredLightParams[6];
lightParams[12] = deferredLightParams[7];
lightParams[13] = deferredLightParams[8];
SetDeferredVarArray(deferredShader, DEFERRED_SHADER_LIGHT_PARAMS, lightParams, LIGHT_PARAM_COUNT, aaMode);
SetDeferredVar(deferredShader, DEFERRED_SHADER_LIGHT_TEXTURE, (texture == NULL) ? grcTexture::None : texture, aaMode);
// camera below water & light above water
float waterLevel = Water::GetWaterLevel();
if( light->UsesCaustic() && Water::IsCameraUnderwater() && (position.z-2.0f) > waterLevel )
{
SetDeferredVar(deferredShader, DEFERRED_SHADER_LIGHT_TEXTURE1, Water::GetCausticTexture(), aaMode);
}
}
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::SetLightShaftShaderParamsGlobal()
{
Mat44V compositeMtx;
#if __BANK
if (!DebugLighting::m_LightShaftNearClipEnabled)
{
DebugLighting::m_LightShaftNearClipExponent = -logf(grcViewport::GetCurrent()->GetNearClip())/logf(2.0f);
compositeMtx = grcViewport::GetCurrent()->GetCompositeMtx();
}
else
#endif // __BANK
{
grcViewport vp = *grcViewport::GetCurrent();
#if !__BANK || BANK_SWITCH_ASSERT
static float nearClipDefault = powf(0.5f, LIGHTSHAFT_NEAR_CLIP_EXPONENT_DEFAULT);
#endif
vp.SetNearClip(BANK_SWITCH(powf(0.5f, DebugLighting::m_LightShaftNearClipExponent), nearClipDefault));
compositeMtx = vp.GetCompositeMtx();
}
m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_VOLUME]->SetVar(m_shaderVolumeParameterID_deferredVolumeShaftCompositeMtx, compositeMtx);
}
// ----------------------------------------------------------------------------------------------- //
static void AddLightShaftPlane(Vec4V shaftPlanes[3], int& numShaftPlanes, Vec3V_In p0, Vec3V_In p1, Vec3V_In p2, Vec3V_In camPos)
{
const Vec4V plane = BuildPlane(p0, p1, p2);
if (numShaftPlanes < 3 && IsLessThanAll(Dot(plane.GetXYZ(), camPos - p0), ScalarV(V_ZERO)))
{
shaftPlanes[numShaftPlanes++] = plane;
}
}
// ----------------------------------------------------------------------------------------------- //
bool DeferredLighting::SetLightShaftShaderParams(const CLightShaft* shaft)
{
if (shaft->m_intensity <= 0.01f)
{
return false;
}
Vec3V corners[4];
corners[0] = shaft->m_corners[0];
corners[1] = shaft->m_corners[1];
corners[2] = shaft->m_corners[3]; // 2,3 are swapped
corners[3] = shaft->m_corners[2]; // 2,3 are swapped
const Vec3V dirx = corners[1] - corners[0];
const Vec3V diry = corners[2] - corners[0]; // this was corners[3] - corners[0], but that meant diry needed to subtract dirx in the vertex shader
const Vec3V dirz = shaft->m_direction;
const Vec3V norm = Cross(dirx, diry);
if (IsLessThanAll(Dot(norm, dirz), ScalarV(V_ZERO)))
{
return false;
}
const grcViewport& grcVP = *grcViewport::GetCurrent();
const Vec3V camPos = grcVP.GetCameraPosition();
if ((shaft->m_flags & LIGHTSHAFTFLAG_DRAW_IN_FRONT_AND_BEHIND) == 0)
{
if (IsLessThanAll(Dot(norm, camPos - corners[0]), ScalarV(V_ZERO)) BANK_ONLY(&& !DebugLighting::m_drawLightShaftsAlways))
{
return false;
}
}
const ScalarV shaftInvRadius = InvSqrt(Max(MagSquared(dirx), MagSquared(diry))); // normalise intensity so that it is 1 looking perpendicularly through the shaft
const ScalarV shaftIntensity = ScalarV(shaft->m_intensity)*shaftInvRadius;
const ScalarV shaftLength = ScalarV(shaft->m_length);
// TODO -- this could be optimised if we stored light shaft corners as an oriented quad
Vec4V shaftGradient;
Vec4V shaftPlanes[3];
int numShaftPlanes = 0;
const Vec3V offset = dirz*shaftLength;
const Vec3V p000 = corners[0];
const Vec3V p100 = corners[1];
const Vec3V p010 = corners[2];
const Vec3V p110 = corners[3];
const Vec3V p001 = corners[0] + offset;
const Vec3V p101 = corners[1] + offset;
const Vec3V p011 = corners[2] + offset;
const Vec3V p111 = corners[3] + offset;
AddLightShaftPlane(shaftPlanes, numShaftPlanes, p000, p001, p101, camPos);
AddLightShaftPlane(shaftPlanes, numShaftPlanes, p100, p101, p111, camPos);
AddLightShaftPlane(shaftPlanes, numShaftPlanes, p110, p111, p011, camPos);
AddLightShaftPlane(shaftPlanes, numShaftPlanes, p010, p011, p001, camPos);
AddLightShaftPlane(shaftPlanes, numShaftPlanes, p000, p100, p110, camPos);
AddLightShaftPlane(shaftPlanes, numShaftPlanes, p001, p011, p111, camPos);
for (; numShaftPlanes < 3; numShaftPlanes++)
{
shaftPlanes[numShaftPlanes] = BuildPlane(camPos, grcVP.GetCameraMtx().GetCol2());
}
#if __BANK
if (shaft->m_attrExt.m_gradientAlignToQuad) // TODO -- make this work! wtf ..
{
shaftGradient = Vec4V(norm, Dot(norm, corners[0] + offset))/Dot(norm, offset);
}
else
#endif // __BANK
{
const ScalarV zmin = Min(Dot(dirz, p000), Dot(dirz, p100), Dot(dirz, p010), Dot(dirz, p110));
const ScalarV zmax = Max(Dot(dirz, p001), Dot(dirz, p101), Dot(dirz, p011), Dot(dirz, p111));
const ScalarV fall = Invert(zmax - zmin);
shaftGradient = Vec4V(-dirz*fall, ScalarV(V_ONE) + zmin*fall);
}
const Vec4V shaftGradientColourInv = Vec4V(BANK_SWITCH(Invert(Max(shaft->m_attrExt.m_gradientColour, Vec3V(V_FLT_SMALL_3))), Vec3V(V_ONE)), ScalarV(shaft->m_softness));
const Vec4V colourAndIntensity = shaft->m_colour;
const Vec4V colour = colourAndIntensity*colourAndIntensity.GetW()*shaftIntensity;
const Vec3V midPos = (corners[0] + corners[1] + corners[2] + corners[3])*ScalarV(V_QUARTER);
const ScalarV zero(V_ZERO);
grmShader *const volume = m_deferredShaders[MM_DEFAULT][DEFERRED_SHADER_VOLUME];
volume->SetVar(m_shaderVolumeParameterID_deferredVolumePosition, Vec4V(midPos, zero));
volume->SetVar(m_shaderVolumeParameterID_deferredVolumeDirection, Vec4V(dirz, zero));
volume->SetVar(m_shaderVolumeParameterID_deferredVolumeTangentXAndShaftRadius, Vec4V(dirx, Invert(shaftInvRadius)*ScalarV(V_HALF))); // TODO -- shaftInvRadius is actually 1/(2*shaftRadius)
volume->SetVar(m_shaderVolumeParameterID_deferredVolumeTangentYAndShaftLength, Vec4V(diry, shaftLength));
volume->SetVar(m_shaderVolumeParameterID_deferredVolumeColour, colour);
volume->SetVar(m_shaderVolumeParameterID_deferredVolumeShaftPlanes, shaftPlanes, NELEM(shaftPlanes));
volume->SetVar(m_shaderVolumeParameterID_deferredVolumeShaftGradient, shaftGradient);
volume->SetVar(m_shaderVolumeParameterID_deferredVolumeShaftGradientColourInv, shaftGradientColourInv);
SetProjectionShaderParams(DEFERRED_SHADER_VOLUME, MM_DEFAULT);
return true;
}
// ----------------------------------------------------------------------------------------------- //
grcTexture* DeferredLighting::GetVolumeTexture()
{
return m_volumeTexture;
}
// ----------------------------------------------------------------------------------------------- //
#if __XENON
// ----------------------------------------------------------------------------------------------- //
void DeferredLighting::SetExtraRefMapState(bool enable)
{
if (enable)
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_HIGHPRECISIONBLENDENABLE1, TRUE));
else
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_HIGHPRECISIONBLENDENABLE1, FALSE));
}
void DeferredLighting::SetExtraTAAState(float flag)
{
static dev_s32 debugAltMask = 0xD2;
static dev_s32 debugStdMask = 0x87;
if (flag==0.0f)
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_ALPHATOMASKOFFSETS, debugAltMask));
else
CHECK_HRESULT(GRCDEVICE.GetCurrent()->SetRenderState(D3DRS_ALPHATOMASKOFFSETS, debugStdMask));
}
// ----------------------------------------------------------------------------------------------- //
#endif //__XENON
// ----------------------------------------------------------------------------------------------- //
grcDepthStencilStateHandle g_CullEqualStateBlock =grcStateBlock::DSS_Invalid;
void DeferredLighting::InitSetHiStencilCullState()
{
grcDepthStencilStateDesc dssDesc;
dssDesc.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_LESS);
dssDesc.StencilEnable=true;
dssDesc.StencilWriteMask=0x0; // disable writes
dssDesc.FrontFace.StencilFunc = grcRSV::CMP_EQUAL;
dssDesc.BackFace = dssDesc.FrontFace;
g_CullEqualStateBlock = grcStateBlock::CreateDepthStencilState(dssDesc);
}
void DeferredLighting::TerminateHiStencilCullState()
{
grcStateBlock::DestroyDepthStencilState(g_CullEqualStateBlock);
}
// stencil culling works on the PS3
// - set render target
// - set stencil cull control
// - clear stencil only
// - render / update stencil
// - render with stencil test enabled and get early rejection
// Note: always switch off stencil write before early reject
void DeferredLighting::SetHiStencilCullState(HIStencilCullState mode)
{
if (mode == CULL_OFF)
{
grcStateBlock::SetDepthStencilState( CShaderLib::DSS_Default_Invert);
XENON_ONLY( GRCDEVICE.GetCurrent()->SetRenderState( D3DRS_HISTENCILENABLE, FALSE ) );
#if DEPTH_BOUNDS_SUPPORT
BANK_ONLY(if( DebugLighting::m_useLightsDepthBounds ))
{
grcDevice::SetDepthBoundsTestEnable(FALSE);
}
#endif //DEPTH_BOUNDS_SUPPORT
}
else if(mode == CULL_SUBSAMPLEAA_ONLY)
{
grcStateBlock::SetDepthStencilState( g_CullEqualStateBlock, DEFERRED_MATERIAL_SPECIALBIT );
}
}
// ----------------------------------------------------------------------------------------------- //
// Define explicit template instantiations
// ----------------------------------------------------------------------------------------------- //
template void DeferredLighting::SetDeferredVar<const rage::grcTexture*> (eDeferredShaders, eDeferredShaderVars, const rage::grcTexture* const&, MultisampleMode);
template void DeferredLighting::SetDeferredVar<Vector4> (eDeferredShaders, eDeferredShaderVars, const Vector4&, MultisampleMode);
template void DeferredLighting::SetDeferredVar<Vec3V> (eDeferredShaders, eDeferredShaderVars, const Vec3V&, MultisampleMode);
template void DeferredLighting::SetDeferredVar<Vec4V> (eDeferredShaders, eDeferredShaderVars, const Vec4V&, MultisampleMode);
template void DeferredLighting::SetDeferredVar<Mat44V> (eDeferredShaders, eDeferredShaderVars, const Mat44V&, MultisampleMode);
template void DeferredLighting::SetDeferredVarArray<const Vec4V*> (eDeferredShaders, eDeferredShaderVars, const Vec4V*, u32, MultisampleMode);