XNA Shader Programming – Tutorial 23, Blur post process

XNA Shader Programming
Tutorial 23 – Blur post process shader
Welcome to the XNA Shader Programming Tutorial 23. Today, we are going to implement a simple version of blur. The shader will be a post process shader, an will blur any given texture.
 
Implementing the Shader
To blur a scene, we will need to implement a new post process shader that will take the average of a number of the pixels neighbor pixels, and return that color as the color we want the player to see. The blur shader will have a distance variable that will be used to modify the texture coordinate we will use as a lookup texture containing our normal scene, so it takes the top-left, top-right, bottom-left and bottom-right pixel, adds them together and divides it by 4 so we get the average.
 
 
On the image, you can see the blur shader in effect. The shader takes the average of the surrounding pixels with a given distance (in this case 0.002) set in the shader or in the application.

Fig 23.2 – This shows how the blur shader works( From tutorial 19 )

The following piece of code looks up the pixels surrounding the current pixel that is being processed.
Color  = tex2D( ColorMapSampler, float2(Tex.x+BlurDistance, Tex.y+BlurDistance));
Color += tex2D( ColorMapSampler, float2(Tex.x-BlurDistance, Tex.y-BlurDistance));
Color += tex2D( ColorMapSampler, float2(Tex.x+BlurDistance, Tex.y-BlurDistance));
Color += tex2D( ColorMapSampler, float2(Tex.x-BlurDistance, Tex.y+BlurDistance));

We simply just modify the pixel to grab the surrounding pixels and add it to our color. Next, we need to divide color by 4 so we get the average color.
Color = Color / 4;
 
Listing 23.1 – Blur post process shader
// The blur amount( how far away from our texel will we look up neighbour texels? )
float BlurDistance = 0.002f;
 
// This will use the texture bound to the object( like from the sprite batch ).
sampler ColorMapSampler : register(s0);
 
float4 PixelShader(float2 Tex: TEXCOORD0) : COLOR
{
float4 Color;
 
// Get the texel from ColorMapSampler using a modified texture coordinate. This
// gets the texels at the neighbour texels and adds it to Color.
       Color  = tex2D( ColorMapSampler, float2(Tex.x+BlurDistance, Tex.y+BlurDistance));
       Color += tex2D( ColorMapSampler, float2(Tex.x-BlurDistance, Tex.y-BlurDistance));
       Color += tex2D( ColorMapSampler, float2(Tex.x+BlurDistance, Tex.y-BlurDistance));
Color += tex2D( ColorMapSampler, float2(Tex.x-BlurDistance, Tex.y+BlurDistance));
// We need to devide the color with the amount of times we added
// a color to it, in this case 4, to get the avg. color
Color = Color / 4;
 
// returned the blurred color
return Color;
}
 
technique PostProcess
{
       pass P0
       {
             // A post process shader only needs a pixel shader.
             PixelShader = compile ps_2_0 PixelShader();
       }
}

This was a pretty simple blur effect. You can also create blur effects by rendering to a downscaled texture. You can downscale multiple times to create a nice blur. You could also use this shader and blur a texture multiple times to create a better looking blur.
 
I have added a line crossing the scene, where the left side of the line is the blurred scene, and the right side of the screen is the original scene.
 
I will wite a tutorial on Gaussian Blur later, as this blur effect is not very nice. But to get better results with this shader, you can blur a scene multiple times using this shader.
 
 
Source and Executable: Tutorial 23 – Blur

This entry was posted in XNA Shader Tutorial. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.