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);⤶
Render.Material = _postProcessMaterial;⤶
Render.DrawScreenQuad();⤶
}⤶
PostProcess.Add(new PostInvert());
var postInvert = PostProcess.Get<PostInvert>();
postInvert.Invert = 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>⤶
```
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" />