Implementing Deferred lighting into Source 2013: Difference between revisions
Line 288: | Line 288: | ||
int m_iIndex; | int m_iIndex; | ||
}; | }; | ||
#endif | |||
</source> | |||
And now around lines 963 paste the following code. | |||
<source lang=cpp> | |||
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard | |||
static CViewRender g_ViewRender; | |||
IViewRender *GetViewRenderInstance() | |||
{ | |||
return &g_ViewRender; | |||
} | |||
#endif | |||
</source> | |||
And now around lines 973 put the fallowing code inside CViewRender::CViewRender(). | |||
<source lang=cpp> | |||
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard | |||
m_pMesh_RadiosityScreenGrid[0] = NULL; | |||
m_pMesh_RadiosityScreenGrid[1] = NULL; | |||
#endif // DEFERRED_ENABLED | |||
</source> | |||
Now around lines 1465 paste the following code into void CViewRender::ViewDrawScene( bool bDrew3dSkybox, SkyboxVisibility_t nSkyboxVisible, const CViewSetup &view, | |||
int nClearFlags, view_id_t viewID, bool bDrawViewModel, int baseDrawFlags, ViewCustomVisibility_t *pCustomVisibility ). | |||
<source lang=cpp> | |||
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard | |||
const bool bDeferredActive = GetDeferredManager()->IsDeferredRenderingEnabled(); | |||
if( bDeferredActive ) | |||
{ | |||
ViewDrawGBuffer( view, bDrew3dSkybox, nSkyboxVisible, bDrawViewModel ); | |||
PerformLighting( view ); | |||
} | |||
#endif | |||
</source> | |||
And around lines 1502 put the following code. | |||
<source lang=cpp> | |||
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard | |||
if( bDeferredActive ) | |||
{ | |||
GetLightingManager()->RenderVolumetrics( view ); | |||
} | |||
#endif | |||
</source> | |||
And around lines 1950 add the fallowing lines of code. | |||
<source lang=cpp> | |||
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard | |||
static lightData_Global_t GetActiveGlobalLightState() | |||
{ | |||
lightData_Global_t data; | |||
CLightingEditor *pEditor = GetLightingEditor(); | |||
if ( pEditor->IsEditorLightingActive() && pEditor->GetKVGlobalLight() != NULL ) | |||
{ | |||
data = pEditor->GetGlobalState(); | |||
} | |||
else if ( GetGlobalLight() != NULL ) | |||
{ | |||
data = GetGlobalLight()->GetState(); | |||
} | |||
return data; | |||
} | |||
struct defData_setGlobals | |||
{ | |||
public: | |||
Vector orig, fwd; | |||
float zDists[2]; | |||
VMatrix frustumDeltas; | |||
#if DEFCFG_BILATERAL_DEPTH_TEST | |||
VMatrix worldCameraDepthTex; | |||
#endif | |||
static void Fire( defData_setGlobals d ) | |||
{ | |||
IDeferredExtension *pDef = GetDeferredExt(); | |||
pDef->CommitOrigin( d.orig ); | |||
pDef->CommitViewForward( d.fwd ); | |||
pDef->CommitZDists( d.zDists[0], d.zDists[1] ); | |||
pDef->CommitFrustumDeltas( d.frustumDeltas ); | |||
#if DEFCFG_BILATERAL_DEPTH_TEST | |||
pDef->CommitWorldToCameraDepthTex( d.worldCameraDepthTex ); | |||
#endif | |||
}; | |||
}; | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CViewRender::ProcessDeferredGlobals( const CViewSetup &view ) | |||
{ | |||
VMatrix matPerspective, matView, matViewProj, screen2world; | |||
matView.Identity(); | |||
matView.SetupMatrixOrgAngles( vec3_origin, view.angles ); | |||
MatrixSourceToDeviceSpace( matView ); | |||
matView = matView.Transpose3x3(); | |||
Vector viewPosition; | |||
Vector3DMultiply( matView, view.origin, viewPosition ); | |||
matView.SetTranslation( -viewPosition ); | |||
MatrixBuildPerspectiveX( matPerspective, view.fov, view.m_flAspectRatio, | |||
view.zNear, view.zFar ); | |||
MatrixMultiply( matPerspective, matView, matViewProj ); | |||
MatrixInverseGeneral( matViewProj, screen2world ); | |||
GetLightingManager()->SetRenderConstants( screen2world, view ); | |||
Vector frustum_c0, frustum_cc, frustum_1c; | |||
float projDistance = 1.0f; | |||
Vector3DMultiplyPositionProjective( screen2world, Vector(0,projDistance,projDistance), frustum_c0 ); | |||
Vector3DMultiplyPositionProjective( screen2world, Vector(0,0,projDistance), frustum_cc ); | |||
Vector3DMultiplyPositionProjective( screen2world, Vector(projDistance,0,projDistance), frustum_1c ); | |||
frustum_c0 -= view.origin; | |||
frustum_cc -= view.origin; | |||
frustum_1c -= view.origin; | |||
Vector frustum_up = frustum_c0 - frustum_cc; | |||
Vector frustum_right = frustum_1c - frustum_cc; | |||
frustum_cc /= view.zFar; | |||
frustum_right /= view.zFar; | |||
frustum_up /= view.zFar; | |||
defData_setGlobals data; | |||
data.orig = view.origin; | |||
AngleVectors( view.angles, &data.fwd ); | |||
data.zDists[0] = view.zNear; | |||
data.zDists[1] = view.zFar; | |||
data.frustumDeltas.Identity(); | |||
data.frustumDeltas.SetBasisVectors( frustum_cc, frustum_right, frustum_up ); | |||
data.frustumDeltas = data.frustumDeltas.Transpose3x3(); | |||
#if DEFCFG_BILATERAL_DEPTH_TEST | |||
VMatrix matWorldToCameraDepthTex; | |||
MatrixBuildScale( matWorldToCameraDepthTex, 0.5f, -0.5f, 1.0f ); | |||
matWorldToCameraDepthTex[0][3] = matWorldToCameraDepthTex[1][3] = 0.5f; | |||
MatrixMultiply( matWorldToCameraDepthTex, matViewProj, matWorldToCameraDepthTex ); | |||
data.worldCameraDepthTex = matWorldToCameraDepthTex.Transpose(); | |||
#endif | |||
QUEUE_FIRE( defData_setGlobals, Fire, data ); | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CViewRender::ViewDrawGBuffer( const CViewSetup &view, bool &bDrew3dSkybox, SkyboxVisibility_t &nSkyboxVisible, | |||
bool bDrawViewModel ) | |||
{ | |||
MDLCACHE_CRITICAL_SECTION(); | |||
int oldViewID = g_CurrentViewID; | |||
g_CurrentViewID = VIEW_DEFERRED_GBUFFER; | |||
int nClearFlags = VIEW_CLEAR_DEPTH; | |||
CSkyboxView *pSkyView = new CSkyboxView( this ); | |||
if ( ( bDrew3dSkybox = pSkyView->Setup( view, &nClearFlags, &nSkyboxVisible, true ) ) != false ) | |||
AddViewToScene( pSkyView ); | |||
SafeRelease( pSkyView ); | |||
// Start view | |||
unsigned int visFlags; | |||
SetupVis( view, visFlags, NULL ); | |||
CRefPtr<CGBufferBlendView> pGBufferView = new CGBufferBlendView( this ); | |||
pGBufferView->Setup( view, bDrew3dSkybox ); | |||
AddViewToScene( pGBufferView ); | |||
DrawViewModels( view, bDrawViewModel/*, true*/ ); | |||
g_CurrentViewID = oldViewID; | |||
} | |||
static int GetSourceRadBufferIndex( const int index ) | |||
{ | |||
Assert( index == 0 || index == 1 ); | |||
const bool bFar = index == 1; | |||
const int iNumSteps = bFar ? deferred_radiosity_propagate_count_far.GetInt() : deferred_radiosity_propagate_count.GetInt() | |||
+ bFar ? deferred_radiosity_blur_count_far.GetInt() : deferred_radiosity_blur_count.GetInt(); | |||
return ( iNumSteps % 2 == 0 ) ? 0 : 1; | |||
} | |||
void CViewRender::BeginRadiosity( const CViewSetup &view ) | |||
{ | |||
Vector fwd; | |||
AngleVectors( view.angles, &fwd ); | |||
float flAmtVertical = abs( DotProduct( fwd, Vector( 0, 0, 1 ) ) ); | |||
flAmtVertical = RemapValClamped( flAmtVertical, 0, 1, 1, 0.5f ); | |||
for ( int iCascade = 0; iCascade < 2; iCascade++ ) | |||
{ | |||
const bool bFar = iCascade == 1; | |||
const Vector gridSize( RADIOSITY_BUFFER_SAMPLES_XY, RADIOSITY_BUFFER_SAMPLES_XY, | |||
RADIOSITY_BUFFER_SAMPLES_Z ); | |||
const Vector gridSizeHalf = gridSize / 2; | |||
const float gridStepSize = bFar ? RADIOSITY_BUFFER_GRID_STEP_SIZE_FAR | |||
: RADIOSITY_BUFFER_GRID_STEP_SIZE_CLOSE; | |||
const float flGridDistance = bFar ? RADIOSITY_BUFFER_GRID_STEP_DISTANCEMULT_FAR | |||
: RADIOSITY_BUFFER_GRID_STEP_DISTANCEMULT_CLOSE; | |||
Vector vecFwd; | |||
AngleVectors( view.angles, &vecFwd ); | |||
m_vecRadiosityOrigin[iCascade] = view.origin | |||
+ vecFwd * gridStepSize * RADIOSITY_BUFFER_SAMPLES_XY * flGridDistance * flAmtVertical; | |||
for ( int i = 0; i < 3; i++ ) | |||
m_vecRadiosityOrigin[iCascade][i] -= fmod( m_vecRadiosityOrigin[iCascade][i], gridStepSize ); | |||
m_vecRadiosityOrigin[iCascade] -= gridSizeHalf * gridStepSize; | |||
const int iSourceBuffer = GetSourceRadBufferIndex( iCascade ); | |||
static int iLastSourceBuffer[2] = { iSourceBuffer, GetSourceRadBufferIndex( 1 ) }; | |||
const int clearSizeY = RADIOSITY_BUFFER_RES_Y / 2; | |||
const int clearOffset = (iCascade == 1) ? clearSizeY : 0; | |||
CMatRenderContextPtr pRenderContext( materials ); | |||
pRenderContext->PushRenderTargetAndViewport( GetDefRT_RadiosityBuffer( iSourceBuffer ), NULL, | |||
0, clearOffset, RADIOSITY_BUFFER_RES_X, clearSizeY ); | |||
pRenderContext->ClearColor3ub( 0, 0, 0 ); | |||
pRenderContext->ClearBuffers( true, false ); | |||
pRenderContext->PopRenderTargetAndViewport(); | |||
if ( iLastSourceBuffer[iCascade] != iSourceBuffer ) | |||
{ | |||
iLastSourceBuffer[iCascade] = iSourceBuffer; | |||
pRenderContext->PushRenderTargetAndViewport( GetDefRT_RadiosityBuffer( 1 - iSourceBuffer ), NULL, | |||
0, clearOffset, RADIOSITY_BUFFER_RES_X, clearSizeY ); | |||
pRenderContext->ClearColor3ub( 0, 0, 0 ); | |||
pRenderContext->ClearBuffers( true, false ); | |||
pRenderContext->PopRenderTargetAndViewport(); | |||
pRenderContext->PushRenderTargetAndViewport( GetDefRT_RadiosityNormal( 1 - iSourceBuffer ), NULL, | |||
0, clearOffset, RADIOSITY_BUFFER_RES_X, clearSizeY ); | |||
pRenderContext->ClearColor3ub( 127, 127, 127 ); | |||
pRenderContext->ClearBuffers( true, false ); | |||
pRenderContext->PopRenderTargetAndViewport(); | |||
} | |||
pRenderContext->PushRenderTargetAndViewport( GetDefRT_RadiosityNormal( iSourceBuffer ), NULL, | |||
0, clearOffset, RADIOSITY_BUFFER_RES_X, clearSizeY ); | |||
pRenderContext->ClearColor3ub( 127, 127, 127 ); | |||
pRenderContext->ClearBuffers( true, false ); | |||
pRenderContext->PopRenderTargetAndViewport(); | |||
} | |||
UpdateRadiosityPosition(); | |||
} | |||
void CViewRender::UpdateRadiosityPosition() | |||
{ | |||
struct defData_setupRadiosity | |||
{ | |||
public: | |||
radiosityData_t data; | |||
static void Fire( defData_setupRadiosity d ) | |||
{ | |||
GetDeferredExt()->CommitRadiosityData( d.data ); | |||
}; | |||
}; | |||
defData_setupRadiosity radSetup; | |||
radSetup.data.vecOrigin[0] = m_vecRadiosityOrigin[0]; | |||
radSetup.data.vecOrigin[1] = m_vecRadiosityOrigin[1]; | |||
QUEUE_FIRE( defData_setupRadiosity, Fire, radSetup ); | |||
} | |||
void CViewRender::PerformRadiosityGlobal( const int iRadiosityCascade, const CViewSetup &view ) | |||
{ | |||
const int iSourceBuffer = GetSourceRadBufferIndex( iRadiosityCascade ); | |||
const int iOffsetY = (iRadiosityCascade == 1) ? RADIOSITY_BUFFER_RES_Y/2 : 0; | |||
CMatRenderContextPtr pRenderContext( materials ); | |||
pRenderContext->SetIntRenderingParameter( INT_RENDERPARM_DEFERRED_RADIOSITY_CASCADE, iRadiosityCascade ); | |||
pRenderContext->PushRenderTargetAndViewport( GetDefRT_RadiosityBuffer( iSourceBuffer ), NULL, | |||
0, iOffsetY, RADIOSITY_BUFFER_VIEWPORT_SX, RADIOSITY_BUFFER_VIEWPORT_SY ); | |||
pRenderContext->SetRenderTargetEx( 1, GetDefRT_RadiosityNormal( iSourceBuffer ) ); | |||
pRenderContext->Bind( GetDeferredManager()->GetDeferredMaterial( DEF_MAT_LIGHT_RADIOSITY_GLOBAL ) ); | |||
GetRadiosityScreenGrid( iRadiosityCascade )->Draw(); | |||
pRenderContext->PopRenderTargetAndViewport(); | |||
} | |||
void CViewRender::EndRadiosity( const CViewSetup &view ) | |||
{ | |||
const int iNumPropagateSteps[2] = { deferred_radiosity_propagate_count.GetInt(), | |||
deferred_radiosity_propagate_count_far.GetInt() }; | |||
const int iNumBlurSteps[2] = { deferred_radiosity_blur_count.GetInt(), | |||
deferred_radiosity_blur_count_far.GetInt() }; | |||
IMaterial *pPropagateMat[2] = { | |||
GetDeferredManager()->GetDeferredMaterial( DEF_MAT_LIGHT_RADIOSITY_PROPAGATE_0 ), | |||
GetDeferredManager()->GetDeferredMaterial( DEF_MAT_LIGHT_RADIOSITY_PROPAGATE_1 ), | |||
}; | |||
IMaterial *pBlurMat[2] = { | |||
GetDeferredManager()->GetDeferredMaterial( DEF_MAT_LIGHT_RADIOSITY_BLUR_0 ), | |||
GetDeferredManager()->GetDeferredMaterial( DEF_MAT_LIGHT_RADIOSITY_BLUR_1 ), | |||
}; | |||
for ( int iCascade = 0; iCascade < 2; iCascade++ ) | |||
{ | |||
bool bSecondDestBuffer = GetSourceRadBufferIndex( iCascade ) == 0; | |||
const int iOffsetY = (iCascade==1) ? RADIOSITY_BUFFER_RES_Y / 2 : 0; | |||
for ( int i = 0; i < iNumPropagateSteps[iCascade]; i++ ) | |||
{ | |||
const int index = bSecondDestBuffer ? 1 : 0; | |||
CMatRenderContextPtr pRenderContext( materials ); | |||
pRenderContext->PushRenderTargetAndViewport( GetDefRT_RadiosityBuffer( index ), NULL, | |||
0, iOffsetY, RADIOSITY_BUFFER_VIEWPORT_SX, RADIOSITY_BUFFER_VIEWPORT_SY ); | |||
pRenderContext->SetRenderTargetEx( 1, GetDefRT_RadiosityNormal( index ) ); | |||
pRenderContext->Bind( pPropagateMat[ 1 - index ] ); | |||
GetRadiosityScreenGrid( iCascade )->Draw(); | |||
pRenderContext->PopRenderTargetAndViewport(); | |||
bSecondDestBuffer = !bSecondDestBuffer; | |||
} | |||
for ( int i = 0; i < iNumBlurSteps[iCascade]; i++ ) | |||
{ | |||
const int index = bSecondDestBuffer ? 1 : 0; | |||
CMatRenderContextPtr pRenderContext( materials ); | |||
pRenderContext->PushRenderTargetAndViewport( GetDefRT_RadiosityBuffer( index ), NULL, | |||
0, iOffsetY, RADIOSITY_BUFFER_VIEWPORT_SX, RADIOSITY_BUFFER_VIEWPORT_SY ); | |||
pRenderContext->SetRenderTargetEx( 1, GetDefRT_RadiosityNormal( index ) ); | |||
pRenderContext->Bind( pBlurMat[ 1 - index ] ); | |||
GetRadiosityScreenGrid( iCascade )->Draw(); | |||
pRenderContext->PopRenderTargetAndViewport(); | |||
bSecondDestBuffer = !bSecondDestBuffer; | |||
} | |||
} | |||
#if ( DEFCFG_DEFERRED_SHADING == 0 ) | |||
DrawLightPassFullscreen( GetDeferredManager()->GetDeferredMaterial( DEF_MAT_LIGHT_RADIOSITY_BLEND ), | |||
view.width, view.height ); | |||
#endif | |||
} | |||
IMesh *CViewRender::GetRadiosityScreenGrid( const int iCascade ) | |||
{ | |||
if ( m_pMesh_RadiosityScreenGrid[iCascade] == NULL ) | |||
{ | |||
Assert( m_pMesh_RadiosityScreenGrid[iCascade] == NULL ); | |||
const bool bFar = iCascade == 1; | |||
m_pMesh_RadiosityScreenGrid[iCascade] = CreateRadiosityScreenGrid( | |||
Vector2D( 0, (bFar?0.5f:0) ), | |||
bFar ? RADIOSITY_BUFFER_GRID_STEP_SIZE_FAR : RADIOSITY_BUFFER_GRID_STEP_SIZE_CLOSE ); | |||
} | |||
Assert( m_pMesh_RadiosityScreenGrid[iCascade] != NULL ); | |||
return m_pMesh_RadiosityScreenGrid[iCascade]; | |||
} | |||
IMesh *CViewRender::CreateRadiosityScreenGrid( const Vector2D &vecViewportBase, | |||
const float flWorldStepSize ) | |||
{ | |||
VertexFormat_t format = VERTEX_POSITION | |||
| VERTEX_TEXCOORD_SIZE( 0, 4 ) | |||
| VERTEX_TEXCOORD_SIZE( 1, 4 ) | |||
| VERTEX_TANGENT_S; | |||
const float flTexelGridMargin = 1.5f / RADIOSITY_BUFFER_SAMPLES_XY; | |||
const float flTexelHalf[2] = { 0.5f / RADIOSITY_BUFFER_VIEWPORT_SX, | |||
0.5f / RADIOSITY_BUFFER_VIEWPORT_SY }; | |||
const float flLocalCoordSingle = 1.0f / RADIOSITY_BUFFER_GRIDS_PER_AXIS; | |||
const float flLocalCoords[4][2] = { | |||
0, 0, | |||
flLocalCoordSingle, 0, | |||
flLocalCoordSingle, flLocalCoordSingle, | |||
0, flLocalCoordSingle, | |||
}; | |||
CMatRenderContextPtr pRenderContext( materials ); | |||
IMesh *pRet = pRenderContext->CreateStaticMesh( | |||
format, TEXTURE_GROUP_OTHER ); | |||
CMeshBuilder meshBuilder; | |||
meshBuilder.Begin( pRet, MATERIAL_QUADS, | |||
RADIOSITY_BUFFER_GRIDS_PER_AXIS * RADIOSITY_BUFFER_GRIDS_PER_AXIS ); | |||
float flGridOrigins[RADIOSITY_BUFFER_SAMPLES_Z][2]; | |||
for ( int i = 0; i < RADIOSITY_BUFFER_SAMPLES_Z; i++ ) | |||
{ | |||
int x = i % RADIOSITY_BUFFER_GRIDS_PER_AXIS; | |||
int y = i / RADIOSITY_BUFFER_GRIDS_PER_AXIS; | |||
flGridOrigins[i][0] = x * flLocalCoordSingle + flTexelHalf[0]; | |||
flGridOrigins[i][1] = y * flLocalCoordSingle + flTexelHalf[1]; | |||
} | |||
const float flGridSize = flWorldStepSize * RADIOSITY_BUFFER_SAMPLES_XY; | |||
const float flLocalGridSize[4][2] = { | |||
0, 0, | |||
flGridSize, 0, | |||
flGridSize, flGridSize, | |||
0, flGridSize, | |||
}; | |||
const float flLocalGridLimits[4][2] = { | |||
-flTexelGridMargin, -flTexelGridMargin, | |||
1 + flTexelGridMargin, -flTexelGridMargin, | |||
1 + flTexelGridMargin, 1 + flTexelGridMargin, | |||
-flTexelGridMargin, 1 + flTexelGridMargin, | |||
}; | |||
for ( int x = 0; x < RADIOSITY_BUFFER_GRIDS_PER_AXIS; x++ ) | |||
{ | |||
for ( int y = 0; y < RADIOSITY_BUFFER_GRIDS_PER_AXIS; y++ ) | |||
{ | |||
const int iIndexLocal = x + y * RADIOSITY_BUFFER_GRIDS_PER_AXIS; | |||
const int iIndicesOne[2] = { MIN( RADIOSITY_BUFFER_SAMPLES_Z - 1, iIndexLocal + 1 ), MAX( 0, iIndexLocal - 1 ) }; | |||
for ( int q = 0; q < 4; q++ ) | |||
{ | |||
meshBuilder.Position3f( | |||
(x * flLocalCoordSingle + flLocalCoords[q][0]) * 2 - flLocalCoordSingle * RADIOSITY_BUFFER_GRIDS_PER_AXIS, | |||
flLocalCoordSingle * RADIOSITY_BUFFER_GRIDS_PER_AXIS - (y * flLocalCoordSingle + flLocalCoords[q][1]) * 2, | |||
0 ); | |||
meshBuilder.TexCoord4f( 0, | |||
(flGridOrigins[iIndexLocal][0] + flLocalCoords[q][0]) * RADIOSITY_UVRATIO_X + vecViewportBase.x, | |||
(flGridOrigins[iIndexLocal][1] + flLocalCoords[q][1]) * RADIOSITY_UVRATIO_Y + vecViewportBase.y, | |||
flLocalGridLimits[q][0], | |||
flLocalGridLimits[q][1] ); | |||
meshBuilder.TexCoord4f( 1, | |||
(flGridOrigins[iIndicesOne[0]][0] + flLocalCoords[q][0]) * RADIOSITY_UVRATIO_X + vecViewportBase.x, | |||
(flGridOrigins[iIndicesOne[0]][1] + flLocalCoords[q][1]) * RADIOSITY_UVRATIO_Y + vecViewportBase.y, | |||
(flGridOrigins[iIndicesOne[1]][0] + flLocalCoords[q][0]) * RADIOSITY_UVRATIO_X + vecViewportBase.x, | |||
(flGridOrigins[iIndicesOne[1]][1] + flLocalCoords[q][1]) * RADIOSITY_UVRATIO_Y + vecViewportBase.y ); | |||
meshBuilder.TangentS3f( flLocalGridSize[q][0], | |||
flLocalGridSize[q][1], | |||
iIndexLocal * flWorldStepSize ); | |||
meshBuilder.AdvanceVertex(); | |||
} | |||
} | |||
} | |||
meshBuilder.End(); | |||
return pRet; | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CViewRender::PerformLighting( const CViewSetup &view ) | |||
{ | |||
bool bResetLightAccum = false; | |||
const bool bRadiosityEnabled = DEFCFG_ENABLE_RADIOSITY != 0 && deferred_radiosity_enable.GetBool(); | |||
if ( bRadiosityEnabled ) | |||
BeginRadiosity( view ); | |||
if ( GetGlobalLight() != NULL ) | |||
{ | |||
struct defData_setGlobalLightState | |||
{ | |||
public: | |||
lightData_Global_t state; | |||
static void Fire( defData_setGlobalLightState d ) | |||
{ | |||
GetDeferredExt()->CommitLightData_Global( d.state ); | |||
}; | |||
}; | |||
defData_setGlobalLightState lightDataState; | |||
lightDataState.state = GetActiveGlobalLightState(); | |||
if ( !GetLightingEditor()->IsEditorLightingActive() && | |||
deferred_override_globalLight_enable.GetBool() ) | |||
{ | |||
lightDataState.state.bShadow = deferred_override_globalLight_shadow_enable.GetBool(); | |||
UTIL_StringToVector( lightDataState.state.diff.AsVector3D().Base(), deferred_override_globalLight_diffuse.GetString() ); | |||
UTIL_StringToVector( lightDataState.state.ambh.AsVector3D().Base(), deferred_override_globalLight_ambient_high.GetString() ); | |||
UTIL_StringToVector( lightDataState.state.ambl.AsVector3D().Base(), deferred_override_globalLight_ambient_low.GetString() ); | |||
lightDataState.state.bEnabled = ( lightDataState.state.diff.LengthSqr() > 0.01f || | |||
lightDataState.state.ambh.LengthSqr() > 0.01f || | |||
lightDataState.state.ambl.LengthSqr() > 0.01f ); | |||
} | |||
QUEUE_FIRE( defData_setGlobalLightState, Fire, lightDataState ); | |||
if ( lightDataState.state.bEnabled ) | |||
{ | |||
bool bShadowedGlobal = lightDataState.state.bShadow; | |||
if ( bShadowedGlobal ) | |||
{ | |||
Vector origins[2] = { view.origin, view.origin + lightDataState.state.vecLight.AsVector3D() * 1024 }; | |||
render->ViewSetupVis( false, 2, origins ); | |||
RenderCascadedShadows( view, bRadiosityEnabled ); | |||
} | |||
} | |||
else | |||
bResetLightAccum = true; | |||
} | |||
else | |||
bResetLightAccum = true; | |||
CViewSetup lightingView = view; | |||
if ( building_cubemaps.GetBool() ) | |||
engine->GetScreenSize( lightingView.width, lightingView.height ); | |||
CMatRenderContextPtr pRenderContext( materials ); | |||
pRenderContext->PushRenderTargetAndViewport( GetDefRT_Lightaccum() ); | |||
if ( bResetLightAccum ) | |||
{ | |||
pRenderContext->ClearColor4ub( 0, 0, 0, 0 ); | |||
pRenderContext->ClearBuffers( true, false ); | |||
} | |||
else | |||
DrawLightPassFullscreen( GetDeferredManager()->GetDeferredMaterial( DEF_MAT_LIGHT_GLOBAL ), lightingView.width, lightingView.height ); | |||
pRenderContext->PopRenderTargetAndViewport(); | |||
pRenderContext->PushRenderTargetAndViewport( GetDefRT_Lightaccum2() ); | |||
pRenderContext->ClearColor4ub( 0, 0, 0, 0 ); | |||
pRenderContext->ClearBuffers( true, false ); | |||
pRenderContext.SafeRelease(); | |||
GetLightingManager()->RenderLights( lightingView, this ); | |||
if ( bRadiosityEnabled ) | |||
EndRadiosity( view ); | |||
pRenderContext.GetFrom( materials ); | |||
pRenderContext->PopRenderTargetAndViewport(); | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CViewRender::ResetCascadeDelay() | |||
{ | |||
for ( int i = 0; i < SHADOW_NUM_CASCADES; i++ ) | |||
m_flRenderDelay[i] = 0; | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CViewRender::RenderCascadedShadows( const CViewSetup &view, const bool bEnableRadiosity ) | |||
{ | |||
for ( int i = 0; i < SHADOW_NUM_CASCADES; i++ ) | |||
{ | |||
const cascade_t &cascade = GetCascadeInfo(i); | |||
const bool bDoRadiosity = bEnableRadiosity && cascade.bOutputRadiosityData; | |||
const int iRadTarget = cascade.iRadiosityCascadeTarget; | |||
float delta = m_flRenderDelay[i] - gpGlobals->curtime; | |||
if ( delta > 0.0f && delta < 1.0f ) | |||
{ | |||
if ( bDoRadiosity ) | |||
PerformRadiosityGlobal( iRadTarget, view ); | |||
continue; | |||
} | |||
m_flRenderDelay[i] = gpGlobals->curtime + cascade.flUpdateDelay; | |||
#if CSM_USE_COMPOSITED_TARGET == 0 | |||
int textureIndex = i; | |||
#else | |||
int textureIndex = 0; | |||
#endif | |||
CRefPtr<COrthoShadowBlendView> pOrthoDepth = new COrthoShadowBlendView( this, i ); | |||
pOrthoDepth->Setup( view, GetShadowDepthRT_Ortho( textureIndex ), GetShadowColorRT_Ortho( textureIndex ) ); | |||
if ( bDoRadiosity ) | |||
{ | |||
pOrthoDepth->SetRadiosityOutputEnabled( true ); | |||
pOrthoDepth->SetupRadiosityTargets( GetRadiosityAlbedoRT_Ortho( textureIndex ), | |||
GetRadiosityNormalRT_Ortho( textureIndex ) ); | |||
} | |||
AddViewToScene( pOrthoDepth ); | |||
if ( bDoRadiosity ) | |||
PerformRadiosityGlobal( iRadTarget, view ); | |||
} | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CViewRender::DrawLightShadowView( const CViewSetup &view, int iDesiredShadowmap, def_light_t *l ) | |||
{ | |||
CViewSetup setup; | |||
setup.origin = l->pos; | |||
setup.angles = l->ang; | |||
setup.m_bOrtho = false; | |||
setup.m_flAspectRatio = 1; | |||
setup.x = setup.y = 0; | |||
Vector origins[2] = { view.origin, l->pos }; | |||
render->ViewSetupVis( false, 2, origins ); | |||
switch ( l->iLighttype ) | |||
{ | |||
default: | |||
Assert( 0 ); | |||
break; | |||
case DEFLIGHTTYPE_POINT: | |||
{ | |||
CRefPtr<CDualParaboloidShadowBlendView> pDPView0 = new CDualParaboloidShadowBlendView( this, l, false ); | |||
pDPView0->Setup( setup, GetShadowDepthRT_DP( iDesiredShadowmap ), GetShadowColorRT_DP( iDesiredShadowmap ) ); | |||
AddViewToScene( pDPView0 ); | |||
CRefPtr<CDualParaboloidShadowBlendView> pDPView1 = new CDualParaboloidShadowBlendView( this, l, true ); | |||
pDPView1->Setup( setup, GetShadowDepthRT_DP( iDesiredShadowmap ), GetShadowColorRT_DP( iDesiredShadowmap ) ); | |||
AddViewToScene( pDPView1 ); | |||
} | |||
break; | |||
case DEFLIGHTTYPE_SPOT: | |||
{ | |||
CRefPtr<CSpotLightShadowBlendView> pProjView = new CSpotLightShadowBlendView( this, l, iDesiredShadowmap ); | |||
pProjView->Setup( setup, GetShadowDepthRT_Proj( iDesiredShadowmap ), GetShadowColorRT_Proj( iDesiredShadowmap ) ); | |||
AddViewToScene( pProjView ); | |||
} | |||
break; | |||
} | |||
} | |||
#endif | #endif | ||
</source> | </source> |
Revision as of 04:59, 13 April 2024


Having deferred lighting in your mod comes with quite a lot of upsides as with it, you can have volumetric lighting, realtime shadows and lighting from the sun and from other light sources, while still keeping the performance steady which is something that Source's regular dynamic light entities would be incapable of (aka projected textures).
Implementing into your Source 2013SP mod
Now we are going to use Lambda Wars's implementation for it as its an enhanced/upgraded version of Alien Swarm Deferred's, but beware implementing deferred lighting in your mod is extremely complex requiring you to modify client and server side code, and even add new shaders to your game. Among other things source's default shaders are also needed to be modified.
Clientside
Firstly we are going to modify cdll_client_int.cpp. Now put the following code at the top of the file around lines 175 but it must be before #include "tier0/memdbgon.h".
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
#include "deferred/deferred_shared_common.h"
#endif
Now aound lines 1816 in void CHLClient::ResetStringTablePointers() place the following code.
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
g_pStringTable_LightCookies = NULL;
#endif
Now around lines 2058 put the following code inside void CHLClient::InstallStringTableCallback( const char *tableName ). And after that we should be done with cdll_client_int.cpp.
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
else if ( !Q_strcasecmp( tableName, COOKIE_STRINGTBL_NAME ) )
{
g_pStringTable_LightCookies = networkstringtable->FindTable( tableName );
g_pStringTable_LightCookies->SetStringChangedCallback( NULL, OnCookieTableChanged );
}
#endif // DEFERRED_ENABLED
Now open viewrender.h and around lines 19 paste the following code.
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
#include "../../materialsystem/stdshaders/deferred_global_common.h"
#endif
And around lines 39 paste this too.
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
struct def_light_t;
#endif
Now around lines 96, but the following code into enum view_id_t.
// @Deferred - Biohazard
VIEW_DEFERRED_GBUFFER = 8,
VIEW_DEFERRED_SHADOW = 9,
And around lines 263, but the following code into class CRendering3dView : public CBase3dView.
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
void PushComposite();
void PopComposite();
static void PushGBuffer( bool bInitial, float zScale = 1.0f, bool bClearDepth = true );
static void PopGBuffer();
#endif
And around lines 505, paste the following code, and we should be done with viewrender.h.
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
void ProcessDeferredGlobals( const CViewSetup &view );
void ViewDrawGBuffer( const CViewSetup &view, bool &bDrew3dSkybox, SkyboxVisibility_t &nSkyboxVisible,
bool bDrawViewModel );
void BeginRadiosity( const CViewSetup &view );
void UpdateRadiosityPosition();
void PerformRadiosityGlobal( const int iRadiosityCascade, const CViewSetup &view );
void EndRadiosity( const CViewSetup &view );
void DebugRadiosity( const CViewSetup &view );
IMesh *GetRadiosityScreenGrid( const int iCascade );
IMesh *CreateRadiosityScreenGrid( const Vector2D &vecViewportBase, const float flWorldStepSize );
void PerformLighting( const CViewSetup &view );
void ResetCascadeDelay();
void RenderCascadedShadows( const CViewSetup &view, const bool bEnableRadiosity );
public:
virtual void DrawLightShadowView( const CViewSetup &view, int iDesiredShadowmap, def_light_t *l );
protected:
float m_flRenderDelay[SHADOW_NUM_CASCADES];
Vector m_vecRadiosityOrigin[2];
IMesh *m_pMesh_RadiosityScreenGrid[2];
CUtlVector< IMesh* > m_hRadiosityDebugMeshList[2];
#endif
Now open viewrender.cpp and around lines 81 paste the following code.
#ifdef DEFERRED_ENABLED
#include "deferred/deferred_shared_common.h"
#include "tier1/callqueue.h"
#endif // DEFERRED_ENABLED
And now around lines 98 replace static convar with a regular convar like so.
ConVar r_visocclusion( "r_visocclusion", "0", FCVAR_CHEAT );
Now around lines 155 replace static convars with a regular convars like so.
ConVar r_ForceWaterLeaf( "r_ForceWaterLeaf", "1", 0, "Enable for optimization to water - considers view in leaf under water for purposes of culling" );
static ConVar mat_drawwater( "mat_drawwater", "1", FCVAR_CHEAT );
ConVar mat_clipz( "mat_clipz", "1" );
And again aorund lines 175 turn the static convar into a regular one.
ConVar r_eyewaterepsilon( "r_eyewaterepsilon", "7.0f", FCVAR_CHEAT );
And around lines 199 replace static int with regular int like so.
int g_CurrentViewID = VIEW_NONE;
And around lines 383 put the following code.
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
void FlushWorldLists()
{
g_WorldListCache.Flush();
}
#endif
And around lines 397 replace Setup with the fallowing code.
bool Setup( const CViewSetup &view, int *pClearFlags, SkyboxVisibility_t *pSkyboxVisible, bool bGBuffer = false );
And around lines 399 add the following code inside class CSkyboxView : public CRendering3dView.
#if DEFERRED_ENABLED // @Deferred - Biohazard
bool m_bGBufferPass;
#endif
And around lines 694 paste the following code.
// Deferred views
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
class CBaseWorldBlendViewDeferred : public CBaseWorldView
{
DECLARE_CLASS( CBaseWorldBlendViewDeferred, CBaseWorldView );
public:
CBaseWorldBlendViewDeferred(CViewRender *pMainView) : CBaseWorldView( pMainView )
{
}
void DrawSetup( float waterHeight, int flags, float waterZAdjust, int iForceViewLeaf = -1, bool bShadowDepth = false );
void DrawExecute( float waterHeight, view_id_t viewID, float waterZAdjust, bool bShadowDepth = false );
// BUGBUG this causes all sorts of problems
virtual bool ShouldCacheLists(){ return false; };
protected:
void DrawOpaqueRenderablesDeferred( bool bNoDecals );
};
class CGBufferBlendView : public CBaseWorldBlendViewDeferred
{
DECLARE_CLASS( CGBufferBlendView, CBaseWorldBlendViewDeferred );
public:
CGBufferBlendView(CViewRender *pMainView) : CBaseWorldBlendViewDeferred( pMainView )
{
}
void Setup( const CViewSetup &view, bool bDrewSkybox );
void Draw();
virtual void PushView( float waterHeight );
virtual void PopView();
private:
VisibleFogVolumeInfo_t m_fogInfo;
bool m_bDrewSkybox;
};
abstract_class CBaseShadowBlendView : public CBaseWorldBlendViewDeferred
{
DECLARE_CLASS( CBaseShadowBlendView, CBaseWorldBlendViewDeferred );
public:
CBaseShadowBlendView(CViewRender *pMainView) : CBaseWorldBlendViewDeferred( pMainView )
{
m_bOutputRadiosity = false;
};
void Setup( const CViewSetup &view,
ITexture *pDepthTexture,
ITexture *pDummyTexture );
void SetupRadiosityTargets(
ITexture *pAlbedoTexture,
ITexture *pNormalTexture );
void SetRadiosityOutputEnabled( bool bEnabled );
void Draw();
virtual bool AdjustView( float waterHeight );
virtual void PushView( float waterHeight );
virtual void PopView();
virtual void CalcShadowView() = 0;
virtual void CommitData(){};
virtual int GetShadowMode() = 0;
private:
ITexture *m_pDepthTexture;
ITexture *m_pDummyTexture;
ITexture *m_pRadAlbedoTexture;
ITexture *m_pRadNormalTexture;
ViewCustomVisibility_t shadowVis;
bool m_bOutputRadiosity;
};
class COrthoShadowBlendView : public CBaseShadowBlendView
{
DECLARE_CLASS( COrthoShadowBlendView, CBaseShadowBlendView );
public:
COrthoShadowBlendView(CViewRender *pMainView, const int &index)
: CBaseShadowBlendView( pMainView )
{
iCascadeIndex = index;
}
virtual void CalcShadowView();
virtual void CommitData();
virtual int GetShadowMode(){
return DEFERRED_SHADOW_MODE_ORTHO;
};
private:
int iCascadeIndex;
};
class CDualParaboloidShadowBlendView : public CBaseShadowBlendView
{
DECLARE_CLASS( CDualParaboloidShadowBlendView, CBaseShadowBlendView );
public:
CDualParaboloidShadowBlendView(CViewRender *pMainView,
def_light_t *pLight,
const bool &bSecondary)
: CBaseShadowBlendView( pMainView )
{
m_pLight = pLight;
m_bSecondary = bSecondary;
}
virtual bool AdjustView( float waterHeight );
virtual void PushView( float waterHeight );
virtual void PopView();
virtual void CalcShadowView();
virtual int GetShadowMode(){
return DEFERRED_SHADOW_MODE_DPSM;
};
private:
bool m_bSecondary;
def_light_t *m_pLight;
};
class CSpotLightShadowBlendView : public CBaseShadowBlendView
{
DECLARE_CLASS( CSpotLightShadowBlendView, CBaseShadowBlendView );
public:
CSpotLightShadowBlendView(CViewRender *pMainView,
def_light_t *pLight, int index )
: CBaseShadowBlendView( pMainView )
{
m_pLight = pLight;
m_iIndex = index;
}
virtual void CalcShadowView();
virtual void CommitData();
virtual int GetShadowMode(){
return DEFERRED_SHADOW_MODE_PROJECTED;
};
private:
def_light_t *m_pLight;
int m_iIndex;
};
#endif
And now around lines 963 paste the following code.
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
static CViewRender g_ViewRender;
IViewRender *GetViewRenderInstance()
{
return &g_ViewRender;
}
#endif
And now around lines 973 put the fallowing code inside CViewRender::CViewRender().
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
m_pMesh_RadiosityScreenGrid[0] = NULL;
m_pMesh_RadiosityScreenGrid[1] = NULL;
#endif // DEFERRED_ENABLED
Now around lines 1465 paste the following code into void CViewRender::ViewDrawScene( bool bDrew3dSkybox, SkyboxVisibility_t nSkyboxVisible, const CViewSetup &view, int nClearFlags, view_id_t viewID, bool bDrawViewModel, int baseDrawFlags, ViewCustomVisibility_t *pCustomVisibility ).
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
const bool bDeferredActive = GetDeferredManager()->IsDeferredRenderingEnabled();
if( bDeferredActive )
{
ViewDrawGBuffer( view, bDrew3dSkybox, nSkyboxVisible, bDrawViewModel );
PerformLighting( view );
}
#endif
And around lines 1502 put the following code.
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
if( bDeferredActive )
{
GetLightingManager()->RenderVolumetrics( view );
}
#endif
And around lines 1950 add the fallowing lines of code.
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
static lightData_Global_t GetActiveGlobalLightState()
{
lightData_Global_t data;
CLightingEditor *pEditor = GetLightingEditor();
if ( pEditor->IsEditorLightingActive() && pEditor->GetKVGlobalLight() != NULL )
{
data = pEditor->GetGlobalState();
}
else if ( GetGlobalLight() != NULL )
{
data = GetGlobalLight()->GetState();
}
return data;
}
struct defData_setGlobals
{
public:
Vector orig, fwd;
float zDists[2];
VMatrix frustumDeltas;
#if DEFCFG_BILATERAL_DEPTH_TEST
VMatrix worldCameraDepthTex;
#endif
static void Fire( defData_setGlobals d )
{
IDeferredExtension *pDef = GetDeferredExt();
pDef->CommitOrigin( d.orig );
pDef->CommitViewForward( d.fwd );
pDef->CommitZDists( d.zDists[0], d.zDists[1] );
pDef->CommitFrustumDeltas( d.frustumDeltas );
#if DEFCFG_BILATERAL_DEPTH_TEST
pDef->CommitWorldToCameraDepthTex( d.worldCameraDepthTex );
#endif
};
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CViewRender::ProcessDeferredGlobals( const CViewSetup &view )
{
VMatrix matPerspective, matView, matViewProj, screen2world;
matView.Identity();
matView.SetupMatrixOrgAngles( vec3_origin, view.angles );
MatrixSourceToDeviceSpace( matView );
matView = matView.Transpose3x3();
Vector viewPosition;
Vector3DMultiply( matView, view.origin, viewPosition );
matView.SetTranslation( -viewPosition );
MatrixBuildPerspectiveX( matPerspective, view.fov, view.m_flAspectRatio,
view.zNear, view.zFar );
MatrixMultiply( matPerspective, matView, matViewProj );
MatrixInverseGeneral( matViewProj, screen2world );
GetLightingManager()->SetRenderConstants( screen2world, view );
Vector frustum_c0, frustum_cc, frustum_1c;
float projDistance = 1.0f;
Vector3DMultiplyPositionProjective( screen2world, Vector(0,projDistance,projDistance), frustum_c0 );
Vector3DMultiplyPositionProjective( screen2world, Vector(0,0,projDistance), frustum_cc );
Vector3DMultiplyPositionProjective( screen2world, Vector(projDistance,0,projDistance), frustum_1c );
frustum_c0 -= view.origin;
frustum_cc -= view.origin;
frustum_1c -= view.origin;
Vector frustum_up = frustum_c0 - frustum_cc;
Vector frustum_right = frustum_1c - frustum_cc;
frustum_cc /= view.zFar;
frustum_right /= view.zFar;
frustum_up /= view.zFar;
defData_setGlobals data;
data.orig = view.origin;
AngleVectors( view.angles, &data.fwd );
data.zDists[0] = view.zNear;
data.zDists[1] = view.zFar;
data.frustumDeltas.Identity();
data.frustumDeltas.SetBasisVectors( frustum_cc, frustum_right, frustum_up );
data.frustumDeltas = data.frustumDeltas.Transpose3x3();
#if DEFCFG_BILATERAL_DEPTH_TEST
VMatrix matWorldToCameraDepthTex;
MatrixBuildScale( matWorldToCameraDepthTex, 0.5f, -0.5f, 1.0f );
matWorldToCameraDepthTex[0][3] = matWorldToCameraDepthTex[1][3] = 0.5f;
MatrixMultiply( matWorldToCameraDepthTex, matViewProj, matWorldToCameraDepthTex );
data.worldCameraDepthTex = matWorldToCameraDepthTex.Transpose();
#endif
QUEUE_FIRE( defData_setGlobals, Fire, data );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CViewRender::ViewDrawGBuffer( const CViewSetup &view, bool &bDrew3dSkybox, SkyboxVisibility_t &nSkyboxVisible,
bool bDrawViewModel )
{
MDLCACHE_CRITICAL_SECTION();
int oldViewID = g_CurrentViewID;
g_CurrentViewID = VIEW_DEFERRED_GBUFFER;
int nClearFlags = VIEW_CLEAR_DEPTH;
CSkyboxView *pSkyView = new CSkyboxView( this );
if ( ( bDrew3dSkybox = pSkyView->Setup( view, &nClearFlags, &nSkyboxVisible, true ) ) != false )
AddViewToScene( pSkyView );
SafeRelease( pSkyView );
// Start view
unsigned int visFlags;
SetupVis( view, visFlags, NULL );
CRefPtr<CGBufferBlendView> pGBufferView = new CGBufferBlendView( this );
pGBufferView->Setup( view, bDrew3dSkybox );
AddViewToScene( pGBufferView );
DrawViewModels( view, bDrawViewModel/*, true*/ );
g_CurrentViewID = oldViewID;
}
static int GetSourceRadBufferIndex( const int index )
{
Assert( index == 0 || index == 1 );
const bool bFar = index == 1;
const int iNumSteps = bFar ? deferred_radiosity_propagate_count_far.GetInt() : deferred_radiosity_propagate_count.GetInt()
+ bFar ? deferred_radiosity_blur_count_far.GetInt() : deferred_radiosity_blur_count.GetInt();
return ( iNumSteps % 2 == 0 ) ? 0 : 1;
}
void CViewRender::BeginRadiosity( const CViewSetup &view )
{
Vector fwd;
AngleVectors( view.angles, &fwd );
float flAmtVertical = abs( DotProduct( fwd, Vector( 0, 0, 1 ) ) );
flAmtVertical = RemapValClamped( flAmtVertical, 0, 1, 1, 0.5f );
for ( int iCascade = 0; iCascade < 2; iCascade++ )
{
const bool bFar = iCascade == 1;
const Vector gridSize( RADIOSITY_BUFFER_SAMPLES_XY, RADIOSITY_BUFFER_SAMPLES_XY,
RADIOSITY_BUFFER_SAMPLES_Z );
const Vector gridSizeHalf = gridSize / 2;
const float gridStepSize = bFar ? RADIOSITY_BUFFER_GRID_STEP_SIZE_FAR
: RADIOSITY_BUFFER_GRID_STEP_SIZE_CLOSE;
const float flGridDistance = bFar ? RADIOSITY_BUFFER_GRID_STEP_DISTANCEMULT_FAR
: RADIOSITY_BUFFER_GRID_STEP_DISTANCEMULT_CLOSE;
Vector vecFwd;
AngleVectors( view.angles, &vecFwd );
m_vecRadiosityOrigin[iCascade] = view.origin
+ vecFwd * gridStepSize * RADIOSITY_BUFFER_SAMPLES_XY * flGridDistance * flAmtVertical;
for ( int i = 0; i < 3; i++ )
m_vecRadiosityOrigin[iCascade][i] -= fmod( m_vecRadiosityOrigin[iCascade][i], gridStepSize );
m_vecRadiosityOrigin[iCascade] -= gridSizeHalf * gridStepSize;
const int iSourceBuffer = GetSourceRadBufferIndex( iCascade );
static int iLastSourceBuffer[2] = { iSourceBuffer, GetSourceRadBufferIndex( 1 ) };
const int clearSizeY = RADIOSITY_BUFFER_RES_Y / 2;
const int clearOffset = (iCascade == 1) ? clearSizeY : 0;
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->PushRenderTargetAndViewport( GetDefRT_RadiosityBuffer( iSourceBuffer ), NULL,
0, clearOffset, RADIOSITY_BUFFER_RES_X, clearSizeY );
pRenderContext->ClearColor3ub( 0, 0, 0 );
pRenderContext->ClearBuffers( true, false );
pRenderContext->PopRenderTargetAndViewport();
if ( iLastSourceBuffer[iCascade] != iSourceBuffer )
{
iLastSourceBuffer[iCascade] = iSourceBuffer;
pRenderContext->PushRenderTargetAndViewport( GetDefRT_RadiosityBuffer( 1 - iSourceBuffer ), NULL,
0, clearOffset, RADIOSITY_BUFFER_RES_X, clearSizeY );
pRenderContext->ClearColor3ub( 0, 0, 0 );
pRenderContext->ClearBuffers( true, false );
pRenderContext->PopRenderTargetAndViewport();
pRenderContext->PushRenderTargetAndViewport( GetDefRT_RadiosityNormal( 1 - iSourceBuffer ), NULL,
0, clearOffset, RADIOSITY_BUFFER_RES_X, clearSizeY );
pRenderContext->ClearColor3ub( 127, 127, 127 );
pRenderContext->ClearBuffers( true, false );
pRenderContext->PopRenderTargetAndViewport();
}
pRenderContext->PushRenderTargetAndViewport( GetDefRT_RadiosityNormal( iSourceBuffer ), NULL,
0, clearOffset, RADIOSITY_BUFFER_RES_X, clearSizeY );
pRenderContext->ClearColor3ub( 127, 127, 127 );
pRenderContext->ClearBuffers( true, false );
pRenderContext->PopRenderTargetAndViewport();
}
UpdateRadiosityPosition();
}
void CViewRender::UpdateRadiosityPosition()
{
struct defData_setupRadiosity
{
public:
radiosityData_t data;
static void Fire( defData_setupRadiosity d )
{
GetDeferredExt()->CommitRadiosityData( d.data );
};
};
defData_setupRadiosity radSetup;
radSetup.data.vecOrigin[0] = m_vecRadiosityOrigin[0];
radSetup.data.vecOrigin[1] = m_vecRadiosityOrigin[1];
QUEUE_FIRE( defData_setupRadiosity, Fire, radSetup );
}
void CViewRender::PerformRadiosityGlobal( const int iRadiosityCascade, const CViewSetup &view )
{
const int iSourceBuffer = GetSourceRadBufferIndex( iRadiosityCascade );
const int iOffsetY = (iRadiosityCascade == 1) ? RADIOSITY_BUFFER_RES_Y/2 : 0;
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->SetIntRenderingParameter( INT_RENDERPARM_DEFERRED_RADIOSITY_CASCADE, iRadiosityCascade );
pRenderContext->PushRenderTargetAndViewport( GetDefRT_RadiosityBuffer( iSourceBuffer ), NULL,
0, iOffsetY, RADIOSITY_BUFFER_VIEWPORT_SX, RADIOSITY_BUFFER_VIEWPORT_SY );
pRenderContext->SetRenderTargetEx( 1, GetDefRT_RadiosityNormal( iSourceBuffer ) );
pRenderContext->Bind( GetDeferredManager()->GetDeferredMaterial( DEF_MAT_LIGHT_RADIOSITY_GLOBAL ) );
GetRadiosityScreenGrid( iRadiosityCascade )->Draw();
pRenderContext->PopRenderTargetAndViewport();
}
void CViewRender::EndRadiosity( const CViewSetup &view )
{
const int iNumPropagateSteps[2] = { deferred_radiosity_propagate_count.GetInt(),
deferred_radiosity_propagate_count_far.GetInt() };
const int iNumBlurSteps[2] = { deferred_radiosity_blur_count.GetInt(),
deferred_radiosity_blur_count_far.GetInt() };
IMaterial *pPropagateMat[2] = {
GetDeferredManager()->GetDeferredMaterial( DEF_MAT_LIGHT_RADIOSITY_PROPAGATE_0 ),
GetDeferredManager()->GetDeferredMaterial( DEF_MAT_LIGHT_RADIOSITY_PROPAGATE_1 ),
};
IMaterial *pBlurMat[2] = {
GetDeferredManager()->GetDeferredMaterial( DEF_MAT_LIGHT_RADIOSITY_BLUR_0 ),
GetDeferredManager()->GetDeferredMaterial( DEF_MAT_LIGHT_RADIOSITY_BLUR_1 ),
};
for ( int iCascade = 0; iCascade < 2; iCascade++ )
{
bool bSecondDestBuffer = GetSourceRadBufferIndex( iCascade ) == 0;
const int iOffsetY = (iCascade==1) ? RADIOSITY_BUFFER_RES_Y / 2 : 0;
for ( int i = 0; i < iNumPropagateSteps[iCascade]; i++ )
{
const int index = bSecondDestBuffer ? 1 : 0;
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->PushRenderTargetAndViewport( GetDefRT_RadiosityBuffer( index ), NULL,
0, iOffsetY, RADIOSITY_BUFFER_VIEWPORT_SX, RADIOSITY_BUFFER_VIEWPORT_SY );
pRenderContext->SetRenderTargetEx( 1, GetDefRT_RadiosityNormal( index ) );
pRenderContext->Bind( pPropagateMat[ 1 - index ] );
GetRadiosityScreenGrid( iCascade )->Draw();
pRenderContext->PopRenderTargetAndViewport();
bSecondDestBuffer = !bSecondDestBuffer;
}
for ( int i = 0; i < iNumBlurSteps[iCascade]; i++ )
{
const int index = bSecondDestBuffer ? 1 : 0;
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->PushRenderTargetAndViewport( GetDefRT_RadiosityBuffer( index ), NULL,
0, iOffsetY, RADIOSITY_BUFFER_VIEWPORT_SX, RADIOSITY_BUFFER_VIEWPORT_SY );
pRenderContext->SetRenderTargetEx( 1, GetDefRT_RadiosityNormal( index ) );
pRenderContext->Bind( pBlurMat[ 1 - index ] );
GetRadiosityScreenGrid( iCascade )->Draw();
pRenderContext->PopRenderTargetAndViewport();
bSecondDestBuffer = !bSecondDestBuffer;
}
}
#if ( DEFCFG_DEFERRED_SHADING == 0 )
DrawLightPassFullscreen( GetDeferredManager()->GetDeferredMaterial( DEF_MAT_LIGHT_RADIOSITY_BLEND ),
view.width, view.height );
#endif
}
IMesh *CViewRender::GetRadiosityScreenGrid( const int iCascade )
{
if ( m_pMesh_RadiosityScreenGrid[iCascade] == NULL )
{
Assert( m_pMesh_RadiosityScreenGrid[iCascade] == NULL );
const bool bFar = iCascade == 1;
m_pMesh_RadiosityScreenGrid[iCascade] = CreateRadiosityScreenGrid(
Vector2D( 0, (bFar?0.5f:0) ),
bFar ? RADIOSITY_BUFFER_GRID_STEP_SIZE_FAR : RADIOSITY_BUFFER_GRID_STEP_SIZE_CLOSE );
}
Assert( m_pMesh_RadiosityScreenGrid[iCascade] != NULL );
return m_pMesh_RadiosityScreenGrid[iCascade];
}
IMesh *CViewRender::CreateRadiosityScreenGrid( const Vector2D &vecViewportBase,
const float flWorldStepSize )
{
VertexFormat_t format = VERTEX_POSITION
| VERTEX_TEXCOORD_SIZE( 0, 4 )
| VERTEX_TEXCOORD_SIZE( 1, 4 )
| VERTEX_TANGENT_S;
const float flTexelGridMargin = 1.5f / RADIOSITY_BUFFER_SAMPLES_XY;
const float flTexelHalf[2] = { 0.5f / RADIOSITY_BUFFER_VIEWPORT_SX,
0.5f / RADIOSITY_BUFFER_VIEWPORT_SY };
const float flLocalCoordSingle = 1.0f / RADIOSITY_BUFFER_GRIDS_PER_AXIS;
const float flLocalCoords[4][2] = {
0, 0,
flLocalCoordSingle, 0,
flLocalCoordSingle, flLocalCoordSingle,
0, flLocalCoordSingle,
};
CMatRenderContextPtr pRenderContext( materials );
IMesh *pRet = pRenderContext->CreateStaticMesh(
format, TEXTURE_GROUP_OTHER );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pRet, MATERIAL_QUADS,
RADIOSITY_BUFFER_GRIDS_PER_AXIS * RADIOSITY_BUFFER_GRIDS_PER_AXIS );
float flGridOrigins[RADIOSITY_BUFFER_SAMPLES_Z][2];
for ( int i = 0; i < RADIOSITY_BUFFER_SAMPLES_Z; i++ )
{
int x = i % RADIOSITY_BUFFER_GRIDS_PER_AXIS;
int y = i / RADIOSITY_BUFFER_GRIDS_PER_AXIS;
flGridOrigins[i][0] = x * flLocalCoordSingle + flTexelHalf[0];
flGridOrigins[i][1] = y * flLocalCoordSingle + flTexelHalf[1];
}
const float flGridSize = flWorldStepSize * RADIOSITY_BUFFER_SAMPLES_XY;
const float flLocalGridSize[4][2] = {
0, 0,
flGridSize, 0,
flGridSize, flGridSize,
0, flGridSize,
};
const float flLocalGridLimits[4][2] = {
-flTexelGridMargin, -flTexelGridMargin,
1 + flTexelGridMargin, -flTexelGridMargin,
1 + flTexelGridMargin, 1 + flTexelGridMargin,
-flTexelGridMargin, 1 + flTexelGridMargin,
};
for ( int x = 0; x < RADIOSITY_BUFFER_GRIDS_PER_AXIS; x++ )
{
for ( int y = 0; y < RADIOSITY_BUFFER_GRIDS_PER_AXIS; y++ )
{
const int iIndexLocal = x + y * RADIOSITY_BUFFER_GRIDS_PER_AXIS;
const int iIndicesOne[2] = { MIN( RADIOSITY_BUFFER_SAMPLES_Z - 1, iIndexLocal + 1 ), MAX( 0, iIndexLocal - 1 ) };
for ( int q = 0; q < 4; q++ )
{
meshBuilder.Position3f(
(x * flLocalCoordSingle + flLocalCoords[q][0]) * 2 - flLocalCoordSingle * RADIOSITY_BUFFER_GRIDS_PER_AXIS,
flLocalCoordSingle * RADIOSITY_BUFFER_GRIDS_PER_AXIS - (y * flLocalCoordSingle + flLocalCoords[q][1]) * 2,
0 );
meshBuilder.TexCoord4f( 0,
(flGridOrigins[iIndexLocal][0] + flLocalCoords[q][0]) * RADIOSITY_UVRATIO_X + vecViewportBase.x,
(flGridOrigins[iIndexLocal][1] + flLocalCoords[q][1]) * RADIOSITY_UVRATIO_Y + vecViewportBase.y,
flLocalGridLimits[q][0],
flLocalGridLimits[q][1] );
meshBuilder.TexCoord4f( 1,
(flGridOrigins[iIndicesOne[0]][0] + flLocalCoords[q][0]) * RADIOSITY_UVRATIO_X + vecViewportBase.x,
(flGridOrigins[iIndicesOne[0]][1] + flLocalCoords[q][1]) * RADIOSITY_UVRATIO_Y + vecViewportBase.y,
(flGridOrigins[iIndicesOne[1]][0] + flLocalCoords[q][0]) * RADIOSITY_UVRATIO_X + vecViewportBase.x,
(flGridOrigins[iIndicesOne[1]][1] + flLocalCoords[q][1]) * RADIOSITY_UVRATIO_Y + vecViewportBase.y );
meshBuilder.TangentS3f( flLocalGridSize[q][0],
flLocalGridSize[q][1],
iIndexLocal * flWorldStepSize );
meshBuilder.AdvanceVertex();
}
}
}
meshBuilder.End();
return pRet;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CViewRender::PerformLighting( const CViewSetup &view )
{
bool bResetLightAccum = false;
const bool bRadiosityEnabled = DEFCFG_ENABLE_RADIOSITY != 0 && deferred_radiosity_enable.GetBool();
if ( bRadiosityEnabled )
BeginRadiosity( view );
if ( GetGlobalLight() != NULL )
{
struct defData_setGlobalLightState
{
public:
lightData_Global_t state;
static void Fire( defData_setGlobalLightState d )
{
GetDeferredExt()->CommitLightData_Global( d.state );
};
};
defData_setGlobalLightState lightDataState;
lightDataState.state = GetActiveGlobalLightState();
if ( !GetLightingEditor()->IsEditorLightingActive() &&
deferred_override_globalLight_enable.GetBool() )
{
lightDataState.state.bShadow = deferred_override_globalLight_shadow_enable.GetBool();
UTIL_StringToVector( lightDataState.state.diff.AsVector3D().Base(), deferred_override_globalLight_diffuse.GetString() );
UTIL_StringToVector( lightDataState.state.ambh.AsVector3D().Base(), deferred_override_globalLight_ambient_high.GetString() );
UTIL_StringToVector( lightDataState.state.ambl.AsVector3D().Base(), deferred_override_globalLight_ambient_low.GetString() );
lightDataState.state.bEnabled = ( lightDataState.state.diff.LengthSqr() > 0.01f ||
lightDataState.state.ambh.LengthSqr() > 0.01f ||
lightDataState.state.ambl.LengthSqr() > 0.01f );
}
QUEUE_FIRE( defData_setGlobalLightState, Fire, lightDataState );
if ( lightDataState.state.bEnabled )
{
bool bShadowedGlobal = lightDataState.state.bShadow;
if ( bShadowedGlobal )
{
Vector origins[2] = { view.origin, view.origin + lightDataState.state.vecLight.AsVector3D() * 1024 };
render->ViewSetupVis( false, 2, origins );
RenderCascadedShadows( view, bRadiosityEnabled );
}
}
else
bResetLightAccum = true;
}
else
bResetLightAccum = true;
CViewSetup lightingView = view;
if ( building_cubemaps.GetBool() )
engine->GetScreenSize( lightingView.width, lightingView.height );
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->PushRenderTargetAndViewport( GetDefRT_Lightaccum() );
if ( bResetLightAccum )
{
pRenderContext->ClearColor4ub( 0, 0, 0, 0 );
pRenderContext->ClearBuffers( true, false );
}
else
DrawLightPassFullscreen( GetDeferredManager()->GetDeferredMaterial( DEF_MAT_LIGHT_GLOBAL ), lightingView.width, lightingView.height );
pRenderContext->PopRenderTargetAndViewport();
pRenderContext->PushRenderTargetAndViewport( GetDefRT_Lightaccum2() );
pRenderContext->ClearColor4ub( 0, 0, 0, 0 );
pRenderContext->ClearBuffers( true, false );
pRenderContext.SafeRelease();
GetLightingManager()->RenderLights( lightingView, this );
if ( bRadiosityEnabled )
EndRadiosity( view );
pRenderContext.GetFrom( materials );
pRenderContext->PopRenderTargetAndViewport();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CViewRender::ResetCascadeDelay()
{
for ( int i = 0; i < SHADOW_NUM_CASCADES; i++ )
m_flRenderDelay[i] = 0;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CViewRender::RenderCascadedShadows( const CViewSetup &view, const bool bEnableRadiosity )
{
for ( int i = 0; i < SHADOW_NUM_CASCADES; i++ )
{
const cascade_t &cascade = GetCascadeInfo(i);
const bool bDoRadiosity = bEnableRadiosity && cascade.bOutputRadiosityData;
const int iRadTarget = cascade.iRadiosityCascadeTarget;
float delta = m_flRenderDelay[i] - gpGlobals->curtime;
if ( delta > 0.0f && delta < 1.0f )
{
if ( bDoRadiosity )
PerformRadiosityGlobal( iRadTarget, view );
continue;
}
m_flRenderDelay[i] = gpGlobals->curtime + cascade.flUpdateDelay;
#if CSM_USE_COMPOSITED_TARGET == 0
int textureIndex = i;
#else
int textureIndex = 0;
#endif
CRefPtr<COrthoShadowBlendView> pOrthoDepth = new COrthoShadowBlendView( this, i );
pOrthoDepth->Setup( view, GetShadowDepthRT_Ortho( textureIndex ), GetShadowColorRT_Ortho( textureIndex ) );
if ( bDoRadiosity )
{
pOrthoDepth->SetRadiosityOutputEnabled( true );
pOrthoDepth->SetupRadiosityTargets( GetRadiosityAlbedoRT_Ortho( textureIndex ),
GetRadiosityNormalRT_Ortho( textureIndex ) );
}
AddViewToScene( pOrthoDepth );
if ( bDoRadiosity )
PerformRadiosityGlobal( iRadTarget, view );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CViewRender::DrawLightShadowView( const CViewSetup &view, int iDesiredShadowmap, def_light_t *l )
{
CViewSetup setup;
setup.origin = l->pos;
setup.angles = l->ang;
setup.m_bOrtho = false;
setup.m_flAspectRatio = 1;
setup.x = setup.y = 0;
Vector origins[2] = { view.origin, l->pos };
render->ViewSetupVis( false, 2, origins );
switch ( l->iLighttype )
{
default:
Assert( 0 );
break;
case DEFLIGHTTYPE_POINT:
{
CRefPtr<CDualParaboloidShadowBlendView> pDPView0 = new CDualParaboloidShadowBlendView( this, l, false );
pDPView0->Setup( setup, GetShadowDepthRT_DP( iDesiredShadowmap ), GetShadowColorRT_DP( iDesiredShadowmap ) );
AddViewToScene( pDPView0 );
CRefPtr<CDualParaboloidShadowBlendView> pDPView1 = new CDualParaboloidShadowBlendView( this, l, true );
pDPView1->Setup( setup, GetShadowDepthRT_DP( iDesiredShadowmap ), GetShadowColorRT_DP( iDesiredShadowmap ) );
AddViewToScene( pDPView1 );
}
break;
case DEFLIGHTTYPE_SPOT:
{
CRefPtr<CSpotLightShadowBlendView> pProjView = new CSpotLightShadowBlendView( this, l, iDesiredShadowmap );
pProjView->Setup( setup, GetShadowDepthRT_Proj( iDesiredShadowmap ), GetShadowColorRT_Proj( iDesiredShadowmap ) );
AddViewToScene( pProjView );
}
break;
}
}
#endif
Serverside
Shaders

Lamba War's source code Reference project : Source 2013MP deferred this project uses the older Alien swarm deferred's version but it still should give us some idea what needs to be changed.
Cpp files and header files needed to be modified or added
- Client
- cdll_client_int.cpp ,modification needed
- viewrender.h ,modification needed
- viewrender.cpp ,modification needed
- flashlighteffect.h ,modification needed
- flashlighteffect.cpp ,modification needed
- c_entityflame.cpp ,modification needed although it's not necessary it's still a quality of life feature
- deferred ,This folder contents are needed which are:
- cascade_t.cpp
- cascade_t.h
- DefCookieProjectable.cpp
- DefCookieProjectable.h
- DefCookieTexture.cpp
- DefCookieTexture.h
- IDefCookie.h
- IDeferredExtClient.cpp
- cdeferred_manager_client.cpp
- cdeferred_manager_client.h
- clight_editor.cpp
- clight_editor.h
- clight_manager.cpp
- clight_manager.h
- def_light_t.cpp
- def_light_t.h
- deferred_client_common.cpp
- deferred_client_common.h
- deferred_rt.cpp
- deferred_rt.h
- flashlighteffect_deferred.cpp
- flashlighteffect_deferred.h
- viewrender_deferred.cpp
- viewrender_deferred.h
- vgui ,This folder is also needed
- projectable_factory.cpp
- projectable_factory.h
- vgui_deferred.h
- vgui_editor_controls.cpp
- vgui_editor_controls.h
- vgui_editor_props.cpp
- vgui_editor_props.h
- vgui_editor_root.cpp
- vgui_marquee.cpp
- vgui_marquee.h
- vgui_particles.cpp
- vgui_particles.h
- vgui_particles.cpp
- vgui_projectable.cpp
- vgui_projectable.h
- Server
- gameinterface.cpp ,modification needed
- lights.cpp ,modification needed
- EntityFlame.h ,modification needed although it's not necessary it's still a quality of life feature
- deferred ,This folder contents are needed which are:
- cdeferred_manager_server.cpp
- deferred_server_common.h
- cdeferred_manager_server.h
- Shared
- deferred ,This folder contents are needed which are:
- CDefLight.cpp
- CDefLight.h
- CDefLightContainer.cpp
- CDefLightContainer.h
- CDefLightGlobal.cpp
- CDefLightGlobal.h
- deferred_shared_common.cpp
- deferred_shared_common.h
- ssemath_ext.h
- deferred ,This folder contents are needed which are:
- Public
- renderparm.h ,modification needed
Shaders
- common_deferred_fxc.h
- deferred_context.h
- deferred_global_common.h
- deferred_includes.h
- deferred_utility.h
- defpass_composite.h
- defpass_gbuffer.h
- defpass_shadow.h
- IDeferredExt.h
- lighting_helper.h
- lighting_pass_basic.h
- lighting_pass_volum.h
- lightshafts_helper.h
- vertexlitgeneric_dx9_helper.h
- lightmappedgeneric_deferred_ps30.h
- lightmappedgeneric_dx9_helper.h
- debug_lightingctrl.cpp
- debug_radiosity_grid.cpp
- deferred_decalModulate.cpp
- deferred_model.cpp
- deferred_brush.cpp
- defpass_composite.cpp
- deferred_utility.cpp
- defpass_gbuffer.cpp
- defpass_shadow.cpp
- GlobalLitGeneric.cpp
- IDeferredExt.cpp
- lighting_global.cpp
- lighting_pass_basic.cpp
- lighting_pass_volum.cpp
- lighting_volume.cpp
- lighting_world.cpp
- radiosity_blend.cpp
- radiosity_global.cpp
- radiosity_propagate.cpp
- volume_prepass.cpp
- volume_blend.cpp
- unlitgeneric_dx9.cpp
- vertexlitgeneric_dx9.cpp
- vertexlitgeneric_dx9_helper.cpp
- lightmappedgeneric_dx9.cpp
- lightmappedgeneric_dx9_helper.cpp
- lightmappedgeneric_dx9_deferred_helper.cpp
- phong_dx9_helper.cpp
- gbuffer_vs30.fxc
- gbuffer_ps30.fxc
- gbuffer_defshading_ps30.fxc
- shadowpass_vs30.fxc
- shadowpass_ps30.fxc
- composite_vs30.fxc
- composite_ps30.fxc
- defconstruct_vs30.fxc
- decalmodulate_vs20.fxc
- decalmodulate_ps2x.fxc
- lightingpass_global_ps30.fxc
- lightingpass_point_ps30.fxc
- lightingpass_spot_ps30.fxc
- screenspace_shading_ps30.fxc
- screenspace_combine_ps30.fxc
- volume_blend_ps30.fxc
- volume_prepass_vs30.fxc
- volume_prepass_ps30.fxc
- volumpass_point_ps30.fxc
- volumpass_spot_ps30.fxc
- radiosity_gen_global_ps30.fxc
- radiosity_gen_vs30.fxc
- radiosity_propagate_ps30.fxc
- radiosity_propagate_vs30.fxc
- radiosity_blend_ps30.fxc
- screenspace_vs20.fxc
- gaussianblur_6_ps30.fxc
- debug_shadow_ortho_ps30.fxc
- debug_lighting_ctrl_ps30.fxc
- debug_radiosity_grid_ps30.fxc
- debug_radiosity_grid_vs30.fxc
- globallitgeneric_ps30.fxc
- globallitgeneric_vs30.fxc
- phong_deferred_ps30.fxc
- lightmappedgeneric_deferred_vs30.fxc
- lightmappedgeneric_deferred_ps30.fxc
- vertexlit_and_unlit_generic_bump_deferred_ps30.fxc