Search Home Members Contacts
About Us
Products
Downloads
Community
Support
Pages: [1]
  Print  
Author Topic: HLSL Post Process Shaders for Newbies  (Read 18473 times)
Hawthorne
Customers
Community Member
*****
Posts: 275


« on: January 22, 2009, 10:39:05 AM »

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:
Code:
                    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:

Code:
// 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:

Code:
// 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:

Code:
// 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:

Code:
// 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:

Code:
// 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:

Code:
// 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:

Code:
// 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:

Code:
// 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:

Code:
// 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
« Last Edit: January 24, 2009, 12:38:12 PM by Hawthorne » Logged
nadjibus
Community Member
*
Posts: 250

Heavy Dev Process


« Reply #1 on: January 22, 2009, 10:56:24 AM »

Great Hawthorne!!:D Thank you very much it's really useful!
Logged

rootsage
Customers
Community Member
*****
Posts: 444

Gamer Enthusiast


WWW
« Reply #2 on: January 22, 2009, 03:07:24 PM »

Very cool! Thank you for these Cheesy
Logged

while( !( succeed = try_again()) );
------
10 print "Is this recursive?"
20 goto 10
sybixsus
Customers
Community Member
*****
Posts: 1339


WWW
« Reply #3 on: January 22, 2009, 03:53:20 PM »

Very interesting, and hopefully it will spark some of us into doing our own. It certainly makes me want to have a go. I'm intrigued by the way you get the pixel color. You just declare a sampler and use it, without any semantic. It is automatic that the sampler gets the screen color? Can you use any other kind of sampler with a semantic or is the screen color all that's available at this point in the pipeline?
Logged
Hawthorne
Customers
Community Member
*****
Posts: 275


« Reply #4 on: January 23, 2009, 12:55:07 AM »

Very interesting, and hopefully it will spark some of us into doing our own. It certainly makes me want to have a go. I'm intrigued by the way you get the pixel color. You just declare a sampler and use it, without any semantic. It is automatic that the sampler gets the screen color? Can you use any other kind of sampler with a semantic or is the screen color all that's available at this point in the pipeline?

I am pretty sure the routine DrawFullScreenWithQuad handles the Texture setup (Default = backbuffer, or you supply a surface/texture).

I tried to make the shaders as simple and with the least amount of instructions as possible so that they would be pretty easy to grasp.

I am glad you guys like them.

-Pat
Logged
tom_namibia
Customers
Community Member
*****
Posts: 177


WWW
« Reply #5 on: January 23, 2009, 07:32:14 AM »

Very nice!
But can I also add this between tv3d.Clear() and tv3d.RenderToScreen()?
I would like to add one of these effect to the whole scene.

Code:

tv3d.SetViewport(VP)
tv3d.Clear()

'... render my stuff ...

' apply effect to the whole scene
tv2d.Action_Begin2D()
tv2d.Draw_FullscreenQuadWithShader(mShader, 0, 0, 1, 1)
tv2d.Action_End2D()

tv3d.RenderToScreen()


But I only got a black screen.
According to the debugfile, the shader was loaded ok.

Tom
Logged
Hawthorne
Customers
Community Member
*****
Posts: 275


« Reply #6 on: January 23, 2009, 10:15:35 AM »

Very nice!
But can I also add this between tv3d.Clear() and tv3d.RenderToScreen()?
I would like to add one of these effect to the whole scene.

But I only got a black screen.
According to the debugfile, the shader was loaded ok.

Tom

You may need to make a rendersurface and BltFromMainBuffer before calling it, I think there is a call you can make to do that during the fullscreenquadwithshader call but I simply cant recall what it is or if it does exist. I know that using this method with a surface to get the main texture on does work.

Code:
                    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();
« Last Edit: January 23, 2009, 10:36:23 AM by Hawthorne » Logged
tom_namibia
Customers
Community Member
*****
Posts: 177


WWW
« Reply #7 on: January 23, 2009, 11:32:41 AM »

Thanks Pat,

BltFromMainBuffer is the trick, works good now.
Your posting is very helpful to start with shaders  Smiley

This might add as an additional help:
http://msdn.microsoft.com/en-us/library/ms810449.aspx

Tom
Logged
aksoysoft
Community Member
*
Posts: 46


WWW
« Reply #8 on: January 24, 2009, 02:05:24 AM »

Very nice! Thanks Hawthorne.

Really useful.
Logged

Hawthorne
Customers
Community Member
*****
Posts: 275


« Reply #9 on: January 24, 2009, 12:40:36 PM »

Very nice! Thanks Hawthorne.

Really useful.

I have just updated the post with a Ripple Effect. I will be updating this thread from time to time with new effects.

-Pat
Logged
Gamecode
Customers
Community Member
*****
Posts: 467


WWW
« Reply #10 on: January 29, 2009, 08:50:18 AM »

amazing ! thanks !
Logged

aiR Captains - RC aircraft project TV65
Omnicrash
Community Member
*
Posts: 66


WWW
« Reply #11 on: February 12, 2009, 01:40:23 PM »

Nice! This will really help me in picking up HLSL again & expanding my knowledge of it.
25 internets for you, dear sir!
Logged

Pages: [1]
  Print  
 
Jump to:  

Powered by SMF 1.1.3 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks