S&box Wiki

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" />