In my quest for understanding and using HLSL I have created a few post process shaders that I think are great tools for learning HLSL and doing simple pixel shader work to produce pretty cool post process effects.
All of these effects are self contained, all you need is the shader and your scene thats it!
All of these effects are drawn like:
EffectSurface.BltFromMainBuffer();
Truevision.Immediate.Settings_SetAlphaBlending(true, _BlendingMode);
Truevision.Immediate.Action_Begin2D();
Truevision.Immediate.Draw_FullscreenQuadWithShader(EffectShader, 0f, 0f, 1f, 1f, EffectSurface.GetTexture());
Truevision.Immediate.Action_End2D();
Here are some screen shots and the source code to each shader
Original Image:

Black and White:

// Screen Space Black and White Effect
//
// Cartoon EFfect
// Pat 'Hawthorne' Shearon
// pat.shearon@gmail.com www.theregulators.org
//
// This version is provided under a Creative Commons Attribution 3.0 License
// http://creativecommons.org/licenses/by/3.0/
// View Matrix Projection
sampler2D g_samSrcColor;
// Vertex Shader
struct VS_INPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
struct VS_OUTPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
#define PS_INPUT VS_OUTPUT
VS_OUTPUT vs_main(const VS_INPUT IN)
{
VS_OUTPUT OUT;
OUT.position = IN.position;
OUT.texCoord = IN.texCoord;
return OUT;
}
// Pixel Shader
float4 ps_main( float2 Tex : TEXCOORD0 ) : COLOR0
{
float4 Color;
Color = tex2D( g_samSrcColor, Tex.xy);
Color.rgb = dot(Color.rgb, float3(0.3, 0.59, 0.11));
Color.a = 1.0f;
return Color;
}
technique PostProcess
{
pass Pass_0
{
VertexShader = compile vs_1_1 vs_main();
PixelShader = compile ps_2_0 ps_main();
}
}
Noise:

// Screen Space Noise Effect
//
// Noise EFfect
// Pat 'Hawthorne' Shearon
// pat.shearon@gmail.com www.theregulators.org
//
// This version is provided under a Creative Commons Attribution 3.0 License
// http://creativecommons.org/licenses/by/3.0/
//Global Variables
sampler2D InputTexture;
float Timer : TIME;
// Input and Output Semantics
struct VS_INPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
struct VS_OUTPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
#define PS_INPUT VS_OUTPUT
//Vertex Shader Output
VS_OUTPUT vs_main(const VS_INPUT IN)
{
VS_OUTPUT OUT;
OUT.position = IN.position;
OUT.texCoord = IN.texCoord;
return OUT;
}
// Pixel Shader Output
float4 ps_main( float2 Tex : TEXCOORD0 ) : COLOR0
{
float2 t = Tex;
float x=t.x*t.y*123456 * Timer;
x=fmod(x,13) * fmod(x,123);
float dx = fmod(x,0.01);
float dy = fmod(x,0.012);
float4 c=tex2D(InputTexture, t+float2(dx,dy));
return c;
}
//Technique Calls
technique PostProcess
{
pass Pass_0
{
VertexShader = compile vs_1_1 vs_main();
PixelShader = compile ps_2_0 ps_main();
}
}
Scanlines:

// Screen Space Scanline Effect
//
// Scanline EFfect
// Pat 'Hawthorne' Shearon
// pat.shearon@gmail.com www.theregulators.org
//
// This version is provided under a Creative Commons Attribution 3.0 License
// http://creativecommons.org/licenses/by/3.0/
//Global Variables
sampler2D InputTexture;
float Timer : TIME;
// Input and Output Semantics
struct VS_INPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
struct VS_OUTPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
#define PS_INPUT VS_OUTPUT
//Vertex Shader Output
VS_OUTPUT vs_main(const VS_INPUT IN)
{
VS_OUTPUT OUT;
OUT.position = IN.position;
OUT.texCoord = IN.texCoord;
return OUT;
}
// Pixel Shader Output
float4 ps_main( float2 Tex : TEXCOORD0 ) : COLOR0
{
float4 c;
c = tex2D( InputTexture, Tex.xy);
c.r = c.r*sin(Tex.y*100*Timer)*2;
c.g = c.g*cos(Tex.y*200*Timer)*2;
c.b = c.b*sin(Tex.y*300*Timer)*2;
//c.rgb = (c.r+c.g+c.b)/1.0f;
return c;
}
//Technique Calls
technique PostProcess
{
pass Pass_0
{
VertexShader = compile vs_1_1 vs_main();
PixelShader = compile ps_2_0 ps_main();
}
}
Radial Blur:

// Screen Space Radial Blur
//
// Radial Blur
// Pat 'Hawthorne' Shearon
// pat.shearon@gmail.com www.theregulators.org
//
// This version is provided under a Creative Commons Attribution 3.0 License
// http://creativecommons.org/licenses/by/3.0/
sampler2D screenSampler : register(s0);
struct VS_OUTPUT
{
float4 Pos : POSITION;
float2 TexCoord : TEXCOORD0;
};
VS_OUTPUT vs_main(in float4 pos : POSITION,
in float2 texCoord : TEXCOORD)
{
VS_OUTPUT Out;
Out.Pos = pos;
Out.TexCoord = texCoord;
return Out;
}
float4 ps_main(float2 TexCoord : TEXCOORD0) : COLOR0
{
float2 Center = {0.5, 0.5};
float BlurStart = 1.0;
float BlurWidth = -0.14;
float samples = 16;
float4 Color = 0;
for(int i = 0; i < samples; i++)
{
float scale = BlurStart + BlurWidth * (i / (samples - 1));
Color += tex2D(screenSampler, (TexCoord - 0.5) * scale + Center );
}
Color /= samples;
return Color;
}
//Technique Calls
technique PostProcess
{
pass Pass_0
{
VertexShader = compile vs_1_1 vs_main();
PixelShader = compile ps_2_0 ps_main();
}
}
Cartoon / Edging Effect:

// Screen Space Cartoon Effect
//
// Cartoon EFfect
// Pat 'Hawthorne' Shearon
// pat.shearon@gmail.com www.theregulators.org
//
// This version is provided under a Creative Commons Attribution 3.0 License
// http://creativecommons.org/licenses/by/3.0/
//Global Variables
sampler2D smpSource;
float4 ColorBlend = float4(4,4,4,0.11f);
// Input and Output Semantics
struct VS_INPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
struct VS_OUTPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
#define PS_INPUT VS_OUTPUT
//Vertex Shader Output
VS_OUTPUT vs_main(const VS_INPUT IN)
{
VS_OUTPUT OUT;
OUT.position = IN.position;
OUT.texCoord = IN.texCoord;
return OUT;
}
// Pixel Shader Output
float4 ps_main( float2 Tex : TEXCOORD0 ) : COLOR0
{
half4 color = tex2D(smpSource,Tex.xy);
color.r = round(color.r*ColorBlend.r)/ColorBlend.r;
color.g = round(color.g*ColorBlend.g)/ColorBlend.g;
color.b = round(color.b*ColorBlend.b)/ColorBlend.b;
const float threshold = ColorBlend.w;
const int NUM = 9;
const float2 c[NUM] =
{
float2(-0.0078125, 0.0078125),
float2( 0.00 , 0.0078125),
float2( 0.0078125, 0.0078125),
float2(-0.0078125, 0.00 ),
float2( 0.0, 0.0),
float2( 0.0078125, 0.007 ),
float2(-0.0078125,-0.0078125),
float2( 0.00 , -0.0078125),
float2( 0.0078125,-0.0078125),
};
int i;
float3 col[NUM];
for (i=0; i < NUM; i++)
{
col[i] = tex2D(smpSource, Tex.xy + 0.2*c[i]);
}
float3 rgb2lum = float3(0.30, 0.59, 0.11);
float lum[NUM];
for (i = 0; i < NUM; i++)
{
lum[i] = dot(col[i].xyz, rgb2lum);
}
float x = lum[2]+ lum[8]+2*lum[5]-lum[0]-2*lum[3]-lum[6];
float y = lum[6]+2*lum[7]+ lum[8]-lum[0]-2*lum[1]-lum[2];
float edge =(x*x + y*y < threshold)? 1.0:0.0;
color.rgb *= edge;
return color;
}
//Technique Calls
technique PostProcess
{
pass Pass_0
{
VertexShader = compile vs_1_1 vs_main();
PixelShader = compile ps_2_0 ps_main();
}
}
Colorization 256:

// Screen Space Colorization 256 Effect
//
// Colorization 256 EFfect
// Pat 'Hawthorne' Shearon
// pat.shearon@gmail.com www.theregulators.org
//
// This version is provided under a Creative Commons Attribution 3.0 License
// http://creativecommons.org/licenses/by/3.0/
//Global Variables
sampler2D InputTexture;
float Timer : TIME;
// Input and Output Semantics
struct VS_INPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
struct VS_OUTPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
#define PS_INPUT VS_OUTPUT
//Vertex Shader Output
VS_OUTPUT vs_main(const VS_INPUT IN)
{
VS_OUTPUT OUT;
OUT.position = IN.position;
OUT.texCoord = IN.texCoord;
return OUT;
}
// Pixel Shader Output
float4 ps_main( float2 Tex : TEXCOORD0 ) : COLOR0
{
float4 c=tex2D(InputTexture, Tex.xy);
c=round(c*10)/10;
c.a=1;
return c;
}
//Technique Calls
technique PostProcess
{
pass Pass_0
{
VertexShader = compile vs_1_1 vs_main();
PixelShader = compile ps_2_0 ps_main();
}
}
Static Effect:

// Screen Space Static Postprocessor
//
// Produces an analogue noise overlay similar to a film grain / TV static
//
// Original implementation and noise algorithm
// Pat 'Hawthorne' Shearon
//
// Optimized scanlines + noise version with intensity scaling
// Georg 'Leviathan' Steinröhder
//
// This version is provided under a Creative Commons Attribution 3.0 License
// http://creativecommons.org/licenses/by/3.0/
//
//Global Variables
float Timer : TIME;
//noise effect intensity value (0 = no effect, 1 = full effect)
float fNintensity = 0.5;
//scanlines effect intensity value (0 = no effect, 1 = full effect)
float fSintensity = 0.1;
//scanlines effect count value (0 = no effect, 4096 = full effect)
float fScount = 2048;
#define RGB
//#define MONOCHROME
texture texScreen;
sampler2D sampScreen = sampler_state
{
Texture = <texScreen>;
MinFilter = Point;
MagFilter = Point;
AddressU = Wrap;
AddressV = Wrap;
};
// Input and Output Semantics
struct VS_INPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
struct VS_OUTPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
#define PS_INPUT VS_OUTPUT
//Vertex Shader Output
VS_OUTPUT vs_main(const VS_INPUT IN)
{
VS_OUTPUT OUT;
OUT.position = IN.position;
OUT.texCoord = IN.texCoord;
return OUT;
}
// Pixel Shader Output
float4 ps_main( float2 Tex : TEXCOORD0 ) : COLOR0
{
// sample the source
float4 cTextureScreen = tex2D( sampScreen, Tex.xy);
// make some noise
float x = Tex.x * Tex.y * Timer * 1000;
x = fmod(x, 13) * fmod(x, 123);
float dx = fmod(x, 0.01);
// add noise
float3 cResult = cTextureScreen.rgb + cTextureScreen.rgb * saturate(0.1f + dx.xxx * 100);
// get us a sine and cosine
float2 sc; sincos(Tex.y * fScount, sc.x, sc.y);
// add scanlines
cResult += cTextureScreen.rgb * float3(sc.x, sc.y, sc.x) * fSintensity;
// interpolate between source and result by intensity
cResult = lerp(cTextureScreen, cResult, saturate(fNintensity));
// convert to grayscale if desired
#ifdef MONOCHROME
cResult.rgb = dot(cResult.rgb, float3(0.3, 0.59, 0.11));
#endif
// return with source alpha
return float4(cResult, cTextureScreen.a);
}
//Technique Calls
technique PostProcess
{
pass Pass_0
{
VertexShader = compile vs_1_1 vs_main();
PixelShader = compile ps_2_0 ps_main();
}
}
Caustics:

// Screen Space Caustic Effect
//
// Caustic EFfect
// Pat 'Hawthorne' Shearon
// pat.shearon@gmail.com www.theregulators.org
//
// This version is provided under a Creative Commons Attribution 3.0 License
// http://creativecommons.org/licenses/by/3.0/
// View Matrix Projection
sampler2D g_samSrcColor;
float Timer : TIME;
float RedOffset = 0.0f;
float GreenOffset = 0.0f;
float BlueOffset = 0.0f;
// Vertex Shader
struct VS_INPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
struct VS_OUTPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
#define PS_INPUT VS_OUTPUT
VS_OUTPUT vs_main(const VS_INPUT IN)
{
VS_OUTPUT OUT;
OUT.position = IN.position;
OUT.texCoord = IN.texCoord;
return OUT;
}
// Pixel Shader
float4 ps_main( float2 Tex : TEXCOORD0 ) : COLOR0
{
float2 wave;
wave.y = Tex.y + (sin((Tex.x*15)+Timer)*0.01);
wave.x = Tex.x + (sin((Tex.y*5)+Timer)*0.01);
float4 c=tex2D(g_samSrcColor,wave);
c.r+=RedOffset;
c.g+=GreenOffset;
c.b+=BlueOffset;
c.a=1;
return c;
}
technique PostProcess
{
pass Pass_0
{
VertexShader = compile vs_1_1 vs_main();
PixelShader = compile ps_2_0 ps_main();
}
}
Ripple:

// Screen Space Ripple Effect
//
// Rippl EFfect
// Pat 'Hawthorne' Shearon
// pat.shearon@gmail.com www.theregulators.org
//
// This version is provided under a Creative Commons Attribution 3.0 License
// http://creativecommons.org/licenses/by/3.0/
float wave = 3.14159f / 0.75f; // pi/.75 is a good default
float distortion = 1; // 1 is a good default
float2 centerCoord = (0.5f,0.5f); // 0.5,0.5 is the screen center
// View Matrix Projection
sampler2D g_samSrcColor;
// Vertex Shader
struct VS_INPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
struct VS_OUTPUT
{
float4 position : POSITION;
float2 texCoord : TEXCOORD;
};
#define PS_INPUT VS_OUTPUT
VS_OUTPUT vs_main(const VS_INPUT IN)
{
VS_OUTPUT OUT;
OUT.position = IN.position;
OUT.texCoord = IN.texCoord;
return OUT;
}
float4 ps_main(float2 texCoord: TEXCOORD0) : COLOR0
{
float2 distance = abs(texCoord - centerCoord);
float scalar = length(distance);
// invert the scale so 1 is centerpoint
scalar = abs(1 - scalar);
// calculate how far to distort for this pixel
float sinoffset = sin(wave / scalar);
sinoffset = clamp(sinoffset, 0, 1);
// calculate which direction to distort
float sinsign = cos(wave / scalar);
// reduce the distortion effect
sinoffset = sinoffset * distortion/32;
// pick a pixel on the screen for this pixel, based on
// the calculated offset and direction
float4 color = tex2D(g_samSrcColor, texCoord+(sinoffset*sinsign));
return color;
}
technique PostProcess
{
pass Pass_0
{
VertexShader = compile vs_1_1 vs_main();
PixelShader = compile ps_2_0 ps_main();
}
}
I hope that some of you find these techniques useful and if you have anything to add please append to the post!!
-Pat