Search Home Members Contacts
About Us
Products
Downloads
Community
Support
Pages: [1]
  Print  
Author Topic: Static/Noise Color/Black&White Scanline Shaders  (Read 8400 times)
Hawthorne
Customers
Community Member
*****
Posts: 275


« on: January 11, 2009, 08:46:08 AM »

http://www.zepastudios.com/sales/static.wmv

I was goofing off this weekend playing left4dead and I really wanted to recreate that film grain shader they have in place but every solution I was reading about required a 3D textured cube map and then some Tex3D calls etc. That seemed like a lot to do just to get some random noise to bounce around in a post process filter.

I took a 2 shader approach to this, both of them being post process so you can apply them to the same rendersurface or directly to your finish product. Below are the two shaders, the first one does "Scanlines" like an old TV or some other old Analog receiving display.

ScanLines.fx
Code:
//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*1024);
c.g = c.g*cos(Tex.y*1024);
c.b = c.b*sin(Tex.y*1024);
//Remove comment tag for black and white scanlines
//c.rgb = (c.r+c.g+c.b)/3.0f;
return c;

}

//Technique Calls
technique PostProcess
{
   pass Pass_0
   {
      VertexShader = compile vs_1_1 vs_main();
      PixelShader = compile ps_2_0 ps_main();
   }
}

Next is noise routine that will pull pixels from the sampled source and dislocate them around the image to finish off the effect.


Noise.fx
Code:
//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();
   }
}





Enjoy!
Pat Shearon
« Last Edit: January 12, 2009, 08:43:19 AM by Hawthorne » Logged
Hawthorne
Customers
Community Member
*****
Posts: 275


« Reply #1 on: January 12, 2009, 11:47:10 AM »

Me and a pal made a few adjustments so I just wanted to post the unified shader here that does both jobs in one shader. The result can be tweaked and looks like it works well!

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 = (cResult.r * 0.3f + cResult.g * 0.59f + cResult.b * 0.11f);
#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();
   }
}



-Pat
« Last Edit: January 12, 2009, 12:29:27 PM by Hawthorne » Logged
Zaknafein
Customers
Community Member
*****
Posts: 2940


WWW
« Reply #2 on: January 12, 2009, 02:17:35 PM »

Nice stuff, and tidy too! One question though...

Quote
pull pixels from the sampled source and dislocate them

What kind of sampled source? Any 2D noise texture?
Logged

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


« Reply #3 on: January 12, 2009, 02:20:38 PM »

Nice stuff, and tidy too! One question though...

What kind of sampled source? Any 2D noise texture?

No, from the scanlined source. Since the first iteration was 2 post process shaders, I would scanline the backbuffer, then use that texture as the input source and just produce noise based on the freshly rendered scanline output.

The third shader is the culmination of all of this into 1 shader, ps2.0 with no texture needed at all that does scanlines and or noise like film grain or static and even in black and white if you define it. Both versions use the backbuffer as the source and noise routine. I think its pretty cool because it produces a very real effect without the extra noise texture needed.

For this shader to work all you need is the shader and a fullscreen quad, the rest is made directly from the backbuffer.

-Pat
« Last Edit: January 12, 2009, 02:27:37 PM by Hawthorne » Logged
Pages: [1]
  Print  
 
Jump to:  

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