Revision Difference
CustomPostProcessing#547761
<cat>Code.Shader</cat>⤶
<title>Custom Post-Processing</title>⤶
⤶
# Setting up your material and rendering it⤶
⤶
From the C# side you'll need to do two things. I'll be using a simple color invert shader for this example that you can turn on and off with a ClientCmd.⤶
⤶
1. Setup a class for your PostProcessing based on MaterialPostProcess, where you set up all your shader stuff, including the material.⤶
```cs⤶
public class InvertPostProcess : MaterialPostProcess⤶
{⤶
public InvertPostProcess() : base( "materials/post_invert.vmat" ) { }⤶
⤶
public bool Enabled⤶
{⤶
set => Attributes.SetCombo( "D_ENABLED", value );⤶
}⤶
}⤶
⤶
```⤶
<note>⤶
The DynamicCombo "D_ENABLED" is defined in the example shader below. You can use `Set` to set any attributes. Eg: `float flMyAttribute< Attribute("MyCoolAttribute"); >;` and you'd set it with `Set( "MyCoolAttribute", 1337.0f);`⤶
</note>⤶
⤶
2. Initialize that PostProcessing class in your Game class.⤶
```cs⤶
public CustomGame()⤶
{⤶
if(IsClient)⤶
{⤶
InitPostProcess();⤶
}⤶
}⤶
⤶
⤶
public void InitPostProcess()⤶
{⤶
PostProcess.Add(new InvertPostProcess());⤶
var postInvert = PostProcess.Get<InvertPostProcess>();⤶
postInvert.Enabled = true; // set it to invert colors by default⤶
}⤶
```⤶
<note>You can also directly load a post-processing material if you don't have any attributes you want to set from C#</note>⤶
```⤶
PostProcess.Add( new MaterialPostProcess( "materials/post_invert.vmat" ) );⤶
```⤶
⤶
This is a basic example using the post-processing material `post_invert.vmat`.⤶
That's all we need to do from the C# side to get our post-processing material to draw, now we just need to actually make the shader.⤶
⤶
# Basic Post Processing Shader⤶
⤶
```⤶
HEADER⤶
{⤶
Description = "Example post processing shader";⤶
}⤶
⤶
MODES⤶
{⤶
Default();⤶
VrForward();⤶
}⤶
⤶
FEATURES⤶
{⤶
}⤶
⤶
COMMON⤶
{⤶
#include "postprocess/shared.hlsl"⤶
}⤶
⤶
struct VertexInput⤶
{⤶
float3 vPositionOs : POSITION < Semantic( PosXyz ); >;⤶
float2 vTexCoord : TEXCOORD0 < Semantic( LowPrecisionUv ); >;⤶
};⤶
⤶
struct PixelInput⤶
{⤶
float2 vTexCoord : TEXCOORD0;⤶
⤶
// VS only⤶
#if ( PROGRAM == VFX_PROGRAM_VS )⤶
float4 vPositionPs : SV_Position;⤶
#endif⤶
⤶
// PS only⤶
#if ( ( PROGRAM == VFX_PROGRAM_PS ) )⤶
float4 vPositionSs : SV_ScreenPosition;⤶
#endif⤶
};⤶
⤶
VS⤶
{⤶
PixelInput MainVs( VertexInput i )⤶
{⤶
PixelInput o;⤶
o.vPositionPs = float4(i.vPositionOs.xyz, 1.0f);⤶
o.vTexCoord = i.vTexCoord;⤶
return o;⤶
}⤶
}⤶
⤶
PS⤶
{⤶
#include "postprocess/common.hlsl"⤶
⤶
RenderState( DepthWriteEnable, false );⤶
RenderState( DepthEnable, false );⤶
⤶
CreateTexture2D( g_tColorBuffer ) < Attribute( "ColorBuffer" ); SrgbRead( true ); Filter( MIN_MAG_LINEAR_MIP_POINT ); AddressU( MIRROR ); AddressV( MIRROR ); >;⤶
CreateTexture2D( g_tDepthBuffer ) < Attribute( "DepthBuffer" ); SrgbRead( false ); Filter( MIN_MAG_MIP_POINT ); AddressU( CLAMP ); AddressV( CLAMP ); >;⤶
⤶
DynamicCombo( D_ENABLED, 0..1, Sys( PC ) );⤶
⤶
float4 MainPs( PixelInput i ) : SV_Target0⤶
{⤶
// Get the current screen texture coordinates⤶
float2 vScreenUv = i.vTexCoord.xy - g_vViewportOffset.xy / g_vRenderTargetSize;⤶
⤶
// Get the current color at a given pixel⤶
float3 vFrameBufferColor = Tex2D( g_tColorBuffer, vScreenUv.xy ).rgb;⤶
⤶
#if D_ENABLED⤶
// Invert the color and write it to our output⤶
float4 vColor = float4( 1.0f - vFrameBufferColor, 1.0f );⤶
#else⤶
float4 vColor = float4( vFrameBufferColor, 1.0f );⤶
#endif⤶
return vColor;⤶
}⤶
}⤶
```⤶
⤶
This is a basic post processing shader that inverts the screen color.⤶
⤶
<upload src="3c1ff/8d9a61ea993d2f1.png" size="5219945" name="sbox-dev_oXb7vCc1Z3.png" />