Implementing Deferred lighting into Source 2013: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
 
(18 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{langsp}}__NOTOC__
{{LanguageBar}}
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
{{warning|This guide aims to provide a quick and simple way of implementing this feature, but the implementation itself needs further work to make it stable, robust, and usable.}}
which is something that Source's regular dynamic light entities would be incapable of (aka projected textures).
{{draft}}
__NOTOC__


==Implementing into your Source 2013SP mod==
Having [[Deferred lighting|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). However, keep in mind that all publicly available implementations are still unstable and can cause visual glitches and slowdowns.
Now we are going to use {{lw|1}}'s implementation for it as its an enhanced/upgraded version of {{asd|1}}'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==
==Background and resources used==
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".
This implementation was originally [https://github.com/jonathonracz/swarm-deferred-src made by Kristjan Skutta aka Biohazard90], based on [https://github.com/NicolasDe/AlienSwarm Alien Swarm's deferred shading approach], then it was [https://github.com/Sandern/lambdawars expended by the Lambda Wars team], and finally it was [https://github.com/SCell555/sdk-2013-deferred ported to Source 2013 by SCell555]. This implementation has been since ported into various Source SDK forks, but for the purpose of simplicity, this tutorial will focus on adding deferred lighting to the [https://github.com/Source-SDK-Resources/source-sdk-vs2022 source-sdk-vs2022] repo, as it is an almost unchanged {{Src13|4}} SDK repo with added compatibility for modern editions of Visual Studio.
<source lang=cpp>
The end result should be identical, or at least very similar, to [https://github.com/54ac/source-sdk-vs2022-deferred source-sdk-vs2022-deferred], which is an implementation of deferred lighting for the source-sdk-vs2022 repo (both MP and SP).
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
#include "deferred/deferred_shared_common.h"
#endif
</source>
Now aound lines 1816 in void CHLClient::ResetStringTablePointers() place the following code.
<source lang=cpp>
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
g_pStringTable_LightCookies = NULL;
#endif
</source>
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'''.
<source lang=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
</source>
Now open '''viewrender.h''' and around lines 19 paste the following code.
<source lang=cpp>
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
#include "../../materialsystem/stdshaders/deferred_global_common.h"
#endif
</source>
And around lines 39 paste this too.
<source lang=cpp>
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
struct def_light_t;
#endif
</source>
Now around lines 96, but the following code into enum view_id_t.
<source lang=cpp>
        // @Deferred - Biohazard
VIEW_DEFERRED_GBUFFER = 8,
VIEW_DEFERRED_SHADOW = 9,
</source>
And around lines 263, but the following code into class CRendering3dView : public CBase3dView.
<source lang=cpp>
#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
</source>
 
And around lines 505, paste the following code, and we should be done with viewrender.h.
<source lang=cpp>
 
#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
</source>
Now open viewrender.cpp and around lines 81 paste the following code.
<source lang=cpp>
#ifdef DEFERRED_ENABLED
#include "deferred/deferred_shared_common.h"
#include "tier1/callqueue.h"
#endif // DEFERRED_ENABLED
</source>
And now around lines 98 replace static convar with a regular convar like so.
<source lang=cpp>
ConVar r_visocclusion( "r_visocclusion", "0", FCVAR_CHEAT );
</source>
Now around lines 155 replace static convars with a regular convars like so.
<source lang=cpp>
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" );
</source>
And again aorund lines 175 turn the static convar into a regular one.
<source lang=cpp>
ConVar r_eyewaterepsilon( "r_eyewaterepsilon", "7.0f", FCVAR_CHEAT );
</source>
And around lines 199 replace static int with regular int like so.
<source lang=cpp>
int g_CurrentViewID = VIEW_NONE;
</source>
And around lines 383 put the following code.
<source lang=cpp>
#ifdef DEFERRED_ENABLED // @Deferred - Biohazard
void FlushWorldLists()
{
g_WorldListCache.Flush();
}
#endif
</source>
And around lines 397 replace Setup with the fallowing code.
<source lang=cpp>
bool Setup( const CViewSetup &view, int *pClearFlags, SkyboxVisibility_t *pSkyboxVisible, bool bGBuffer = false );
</source>
And around lines 399 add the following code inside class CSkyboxView : public CRendering3dView.
<source lang=cpp>
#if DEFERRED_ENABLED // @Deferred - Biohazard
bool m_bGBufferPass;
#endif
</source>
And around lines 694 paste the following code.
<source lang=cpp>
// 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 );
==Preparation==
void DrawExecute( float waterHeight, view_id_t viewID, float waterZAdjust, bool bShadowDepth = false );
Using the right tools will make copying code from one repo to another a relatively quick and painless process.
# Download [https://winmerge.org WinMerge] or a similar diff/merge tool.
# Use git to clone the two repos used in this tutorial (or download them as ZIP files): [https://github.com/Source-SDK-Resources/source-sdk-vs2022 source-sdk-vs2022] and [https://github.com/54ac/source-sdk-vs2022-deferred source-sdk-vs2022-deferred].
# Make sure the source-sdk-vs2022 repo compiles successfully in your installation of Visual Studio 2022 before you modify it.


// BUGBUG this causes all sorts of problems
The repo also includes diff files which should allow you to easily apply all of the necessary changes per branch as long as you know how to use them. This tutorial will focus on the slightly more user-friendly WinMerge approach.
virtual bool ShouldCacheLists(){ return false; };


protected:
==Implementation using WinMerge==
void DrawOpaqueRenderablesDeferred( bool bNoDecals );
You can copy all the necessary files and apply changes to the code by comparing both folders in WinMerge. The source-sdk-vs2022-deferred aims to modify as few files as possible, so the process should be relatively quick.
};


class CGBufferBlendView : public CBaseWorldBlendViewDeferred
The process is very similar for both the MP and SP branches. In both cases, the new files that need to be transferred are contained in separate deferred folders in the client, server, and shared folders in /game, as well as in /materialsystem/stdshaders and /public. The files that need to be modified are contained in the same folders as well as in /tier1 and the root folder (creategameprojects.bat).
{
DECLARE_CLASS( CGBufferBlendView, CBaseWorldBlendViewDeferred );
public:
CGBufferBlendView(CViewRender *pMainView) : CBaseWorldBlendViewDeferred( pMainView )
{
}


void Setup( const CViewSetup &view, bool bDrewSkybox );
===File modifications===
void Draw();
Apply the modifications as shown by WinMerge. Consult the manual if you're unsure how to do this, though you could probably do this solely with the Ctrl and arrow keys if you wanted to. The majority of the modifications will involve files in /game/client and /materialsystem/stdshaders. All new entries for files related to deferred lighting are added in *_base.vpc files, and the creategameprojects.bat file is changed to generate the Visual Studio solution for the shader DLL as well.


virtual void PushView( float waterHeight );
Once you've applied all the changes shown by WinMerge, run the creategameprojects.bat file to recreate the Visual Studio solutions. At this stage, you should be able to compile the client and server DLLs.
virtual void PopView();


private:  
==Compiling shaders with ShaderCompile==
VisibleFogVolumeInfo_t m_fogInfo;
In order to compile the shader DLL, you will need to generate the .inc shader include files. This tutorial uses [https://github.com/SCell555/ShaderCompile SCell555's ShaderCompile tool] to simplify the process.
bool m_bDrewSkybox;
};


abstract_class CBaseShadowBlendView : public CBaseWorldBlendViewDeferred
# Download the ShaderCompile 7z file from the latest release on the GitHub releases page.
{
# Follow the "getting started" section in the readme of the repo (replace cshader.h and buildshaders.bat, modify game_shader_dx9_base.vpc and buildsdkshaders.bat, copy over ShaderCompile.exe and process_shaders.ps1).
DECLARE_CLASS( CBaseShadowBlendView, CBaseWorldBlendViewDeferred );
# Run e.g. buildhl2mpshaders.bat in materialsystem\stdshaders to build the shaders.
public:
CBaseShadowBlendView(CViewRender *pMainView) : CBaseWorldBlendViewDeferred( pMainView )
{
m_bOutputRadiosity = false;
};


void Setup( const CViewSetup &view,
If the batch file refuses to run, open it in a text editor and encase the paths for GAMEDIR and SOURCEDIR in quotation marks, i.e. so that it looks similar to this (SDKBINDIR is irrelevant here):
ITexture *pDepthTexture,
<source>
ITexture *pDummyTexture );
@echo off
void SetupRadiosityTargets(
setlocal
ITexture *pAlbedoTexture,
ITexture *pNormalTexture );


void SetRadiosityOutputEnabled( bool bEnabled );
rem ================================
rem ==== MOD PATH CONFIGURATIONS ===


void Draw();
rem == Set the absolute path to your mod's game directory here ==
virtual bool AdjustView( float waterHeight );
set GAMEDIR="%cd%\..\..\..\game\mod_hl2mp"
virtual void PushView( float waterHeight );
virtual void PopView();


virtual void CalcShadowView() = 0;
rem == Set the relative or absolute path to Source SDK Base 2013 Singleplayer\bin ==
virtual void CommitData(){};
set SDKBINDIR=


virtual int GetShadowMode() = 0;
rem ==  Set the Path to your mod's root source code ==
rem This should already be correct, accepts relative paths only!
set SOURCEDIR="..\.."


private:
rem ==== MOD PATH CONFIGURATIONS END ===
rem ====================================


ITexture *m_pDepthTexture;
ITexture *m_pDummyTexture;
ITexture *m_pRadAlbedoTexture;
ITexture *m_pRadNormalTexture;
ViewCustomVisibility_t shadowVis;


bool m_bOutputRadiosity;
call buildsdkshaders.bat
};
 
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
</source>
</source>


==Serverside==
Once you've compiled all the shaders, launch the creategameprojects.bat file again. You should now be able to compile the shader DLL.


==Shaders==
==Notes==
{{cleanup|Actually properly research what is needed for this implementation. Until someone actually decides to the hard work this section should be dedicated to the stuff that is most definietly needed for this implementation to work. And when thats done this notice should be deleted.
* At this point, deferred lighting should be implemented. If not, either go through the steps again or simply use the source-sdk-vs2022-deferred repo as your starting point. Make sure to read through the notes in the readme.
[https://github.com/Sandern/lambdawars Lamba War's source code]
* Don't be discouraged by how janky it is - use it as motivation to become the first person to create a robust, stable deferred lighting implementation without making it closed source.
Reference project : [https://github.com/SCell555/sdk-2013-deferred 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===
== External links ==
*Client
* [https://github.com/NicolasDe/AlienSwarm Alien Swarm SDK (deferred shading)]
**cdll_client_int.cpp ,modification needed
* [https://github.com/jonathonracz/swarm-deferred-src Biohazard90's deferred lighting implementation for Alien Swarm]
**viewrender.h ,modification needed
* [https://github.com/Sandern/lambdawars Lambda Wars source code]
**viewrender.cpp ,modification needed
* [https://github.com/SCell555/sdk-2013-deferred SCell555's port of deferred lighting to Source SDK 2013]
**flashlighteffect.h ,modification needed
* [https://github.com/Source-SDK-Resources/source-sdk-vs2022 Source SDK 2013 with Visual Studio 2022 support]
**flashlighteffect.cpp ,modification needed
* [https://github.com/54ac/source-sdk-vs2022-deferred Implementation of deferred lighting for the VS2022 fork]
**c_entityflame.cpp ,modification needed although it's not necessary it's still a quality of life feature
* [https://github.com/SCell555/ShaderCompile SCell555's ShaderCompile tool]
**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
*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
}}


== External links ==
[[Category:Programming]]
*[https://github.com/Sandern/lambdawars Lambda war's source code]
[[Category:Shaders|*]]

Latest revision as of 12:38, 27 September 2025

English (en)Translate (Translate)
Warning.pngWarning:This guide aims to provide a quick and simple way of implementing this feature, but the implementation itself needs further work to make it stable, robust, and usable.
Icon-under construction-blue.png
This is a draft page. It is a work in progress open to editing by anyone.
Remember to check for any notes left by the tagger at this article's talk page.


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). However, keep in mind that all publicly available implementations are still unstable and can cause visual glitches and slowdowns.

Background and resources used

This implementation was originally made by Kristjan Skutta aka Biohazard90, based on Alien Swarm's deferred shading approach, then it was expended by the Lambda Wars team, and finally it was ported to Source 2013 by SCell555. This implementation has been since ported into various Source SDK forks, but for the purpose of simplicity, this tutorial will focus on adding deferred lighting to the source-sdk-vs2022 repo, as it is an almost unchanged Source 2013 Source 2013 SDK repo with added compatibility for modern editions of Visual Studio. The end result should be identical, or at least very similar, to source-sdk-vs2022-deferred, which is an implementation of deferred lighting for the source-sdk-vs2022 repo (both MP and SP).

Preparation

Using the right tools will make copying code from one repo to another a relatively quick and painless process.

  1. Download WinMerge or a similar diff/merge tool.
  2. Use git to clone the two repos used in this tutorial (or download them as ZIP files): source-sdk-vs2022 and source-sdk-vs2022-deferred.
  3. Make sure the source-sdk-vs2022 repo compiles successfully in your installation of Visual Studio 2022 before you modify it.

The repo also includes diff files which should allow you to easily apply all of the necessary changes per branch as long as you know how to use them. This tutorial will focus on the slightly more user-friendly WinMerge approach.

Implementation using WinMerge

You can copy all the necessary files and apply changes to the code by comparing both folders in WinMerge. The source-sdk-vs2022-deferred aims to modify as few files as possible, so the process should be relatively quick.

The process is very similar for both the MP and SP branches. In both cases, the new files that need to be transferred are contained in separate deferred folders in the client, server, and shared folders in /game, as well as in /materialsystem/stdshaders and /public. The files that need to be modified are contained in the same folders as well as in /tier1 and the root folder (creategameprojects.bat).

File modifications

Apply the modifications as shown by WinMerge. Consult the manual if you're unsure how to do this, though you could probably do this solely with the Ctrl and arrow keys if you wanted to. The majority of the modifications will involve files in /game/client and /materialsystem/stdshaders. All new entries for files related to deferred lighting are added in *_base.vpc files, and the creategameprojects.bat file is changed to generate the Visual Studio solution for the shader DLL as well.

Once you've applied all the changes shown by WinMerge, run the creategameprojects.bat file to recreate the Visual Studio solutions. At this stage, you should be able to compile the client and server DLLs.

Compiling shaders with ShaderCompile

In order to compile the shader DLL, you will need to generate the .inc shader include files. This tutorial uses SCell555's ShaderCompile tool to simplify the process.

  1. Download the ShaderCompile 7z file from the latest release on the GitHub releases page.
  2. Follow the "getting started" section in the readme of the repo (replace cshader.h and buildshaders.bat, modify game_shader_dx9_base.vpc and buildsdkshaders.bat, copy over ShaderCompile.exe and process_shaders.ps1).
  3. Run e.g. buildhl2mpshaders.bat in materialsystem\stdshaders to build the shaders.

If the batch file refuses to run, open it in a text editor and encase the paths for GAMEDIR and SOURCEDIR in quotation marks, i.e. so that it looks similar to this (SDKBINDIR is irrelevant here):

@echo off
setlocal

rem ================================
rem ==== MOD PATH CONFIGURATIONS ===

rem == Set the absolute path to your mod's game directory here ==
set GAMEDIR="%cd%\..\..\..\game\mod_hl2mp"

rem == Set the relative or absolute path to Source SDK Base 2013 Singleplayer\bin ==
set SDKBINDIR=

rem ==  Set the Path to your mod's root source code ==
rem This should already be correct, accepts relative paths only!
set SOURCEDIR="..\.."

rem ==== MOD PATH CONFIGURATIONS END ===
rem ====================================


call buildsdkshaders.bat

Once you've compiled all the shaders, launch the creategameprojects.bat file again. You should now be able to compile the shader DLL.

Notes

  • At this point, deferred lighting should be implemented. If not, either go through the steps again or simply use the source-sdk-vs2022-deferred repo as your starting point. Make sure to read through the notes in the readme.
  • Don't be discouraged by how janky it is - use it as motivation to become the first person to create a robust, stable deferred lighting implementation without making it closed source.

External links