S&box Wiki

Revision Difference

CustomPostProcessing#546108

<cat>Code.Shader</cat> <title>Custom Post-Processing</title> # Setting up your material and rendering it From the C# side you'll need to load a material with your custom shader and render it in the PostProcess event. ``` 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 BasePostProcess, where you setup all your shader stuff, including the material. ``` public class PostInvert : BasePostProcess { private Material PostProcessMaterial; private static PostInvert Current; public bool Invert { set => Set("invert", value); } public PostInvert() { PostProcessMaterial = Material.Load("materials/post_invert.vmat"); Current = this; } public override void Render() { if(PostProcessMaterial is null) return; Sandbox.Render.Material = PostProcessMaterial; RenderScreenQuad(); } [ClientCmd("post_invert")] public static void SetValue(bool state) { Host.AssertClient(); Current.Invert = state; } } ``` <note> The attribute "invert" in this case is a Dynamic expression I set in the material editor. </note> 2. Initialize that PostProcessing class in your Game class. ``` public CustomGame() { if(IsClient) { InitPostProcess(); } } private Material _postProcessMaterial; public void InitPostProcess() { _postProcessMaterial = Material.Load("materials/post_process_example.vmat"); } [Event("render.postprocess")] public void PostProcess() public void InitPostProcess() { if(_postProcessMaterial != null) { Render.CopyFrameBuffer(false); PostProcess.Add(new PostInvert()); var postInvert = PostProcess.Get<PostInvert>(); postInvert.Invert = true; // set it to invert colors by default Render.Material = _postProcessMaterial; Render.DrawScreenQuad(); } } ``` <note>You can also directly load a post processing material if you don't have any attributes you want to set from C#</note> ``` This is a basic example using the post processing material `post_process_example.vmat`. We're loading the material on the client in the game's constructor. 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 { CompileTargets = ( IS_SM_50 && ( PC || VULKAN ) ); Description = "Post Processing Shader"; Description = "Base Post Processing Shader"; } //========================================================================================================================= FEATURES { #include "common/features.hlsl" } //========================================================================================================================= MODES { VrForward(); Default(); } //========================================================================================================================= COMMON { #include "system.fxc" #include "common.fxc" } //========================================================================================================================= struct VertexInput { float3 vPositionOs : POSITION < Semantic( PosXyz ); >; float2 vTexCoord : TEXCOORD0 < Semantic( LowPrecisionUv ); >; }; //========================================================================================================================= struct PixelInput { float4 vPositionPs : SV_Position; float2 vTexCoord : TEXCOORD0; }; //========================================================================================================================= VS { PixelInput MainVs( VertexInput i ) { PixelInput o; o.vPositionPs = float4(i.vPositionOs.xyz, 1.0f); o.vTexCoord = i.vTexCoord; return o; } } //========================================================================================================================= PS { struct PixelOutput { float4 vColor : SV_Target0; }; // grab the frame buffer texture CreateTexture2D( g_FrameBuffer )< Attribute("FrameBufferCopyTexture"); SrgbRead( false ); >; CreateTexture2D( g_FrameBuffer ) < Attribute( "ColorBuffer" ); SrgbRead( true ); Filter( MIN_MAG_LINEAR_MIP_POINT ); AddressU( MIRROR ); AddressV( MIRROR ); >; bool g_vInvert < UiGroup("Invert"); UiType(CheckBox); Default(0); >; PixelOutput MainPs( PixelInput i ) { PixelOutput o; float2 uv = i.vTexCoord.xy; // uv from 0,0 in the top left to 1,1 in the bottom right float2 uv = i.vTexCoord.xy - g_vViewportOffset.xy / g_vRenderTargetSize; // uv from 0,0 in the top left to 1,1 in the bottom right float4 color = Tex2D(g_FrameBuffer, uv.xy).rgba; // grab color from frame texture color = 1 - color; // invert color if(g_vInvert) color = 1 - color; // invert color o.vColor = color; return o; } } ``` This is a basic example post processing shader that inverts the screen color. This is a basic post processing shader that inverts the screen color. <upload src="3c1ff/8d9a61ea993d2f1.png" size="5219945" name="sbox-dev_oXb7vCc1Z3.png" />