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));
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;
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? )
// 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