Post Process GreyScale
Adapted to XNA 4.0 by A. Nadif. To see the original article for XNA 3.1, follow this link.
This tutorial builds on Tutorial 9, post process wiggling. If you haven't read that yet, you should in order to fully understand what's going on here.
The source-code and binaries can be found in the end of the chapter.
The source-code and binaries can be found in the end of the chapter.
GreyScale Image
In order to make a black and white image/scene, we will need to convert our colored SceneTexture to a negative one. This is done in a post process pixel shader.
A black and white image consist of only pixels with a shade of gray, so our shader must somehow take a color, and make it to a shade of gray. There is a few ways of doing this, and Im going to show you two of them.
1. Average color
One way of doing this is to take the three color channels, add them together and devide the result on 3. This gives us the average color, and we set all components of our color to this average color:
A black and white image consist of only pixels with a shade of gray, so our shader must somehow take a color, and make it to a shade of gray. There is a few ways of doing this, and Im going to show you two of them.
1. Average color
One way of doing this is to take the three color channels, add them together and devide the result on 3. This gives us the average color, and we set all components of our color to this average color:
Color.rgb = (Color.r + Color.g + Color.b)/3; |
This will result in a pixel with all components set to the same value. It gives a pretty good result, but if you look closely, it's incorrect! Let's take a look on an other method of doing this.
2. Grayscale intensity
The eye is more sensitive to one color component, green, than towards the others and so on. One of the most common ways of converting an image to grayscale is to use a set of values that describe the grayscales intensity/weight for each of the three color components:
g = 0.3 R + 0.59 G + 0.11 B
This will convert our grayscale image correctly, and can be implemented in the shader like this:
The eye is more sensitive to one color component, green, than towards the others and so on. One of the most common ways of converting an image to grayscale is to use a set of values that describe the grayscales intensity/weight for each of the three color components:
g = 0.3 R + 0.59 G + 0.11 B
This will convert our grayscale image correctly, and can be implemented in the shader like this:
Color.rgb = dot(Color.rgb, float3(0.3, 0.59, 0.11)); |
I have added this figure as a comparison on the two different grayscale methods. It's a little hard to see in this example but it can be seen in a more colorful scene, or one that contains more green.
Implementing the shader
We have seen how to convert a color to grayscale. I've also added the shaders for both methods, so you can see the whole picture without having to download the example.
1. Average color
1. Average color
sampler ColorMapSampler : register(s0); float4 PixelShaderGo(float2 Tex: TEXCOORD0) : COLOR { float4 Color = tex2D(ColorMapSampler, Tex); Color.rgb = (Color.r + Color.g + Color.b)/3; // Keep our alphachannel at 1. Color.a = 1.0f; return Color; } technique PostProcess { pass P0 { PixelShader = compile ps_2_0 PixelShaderGo(); } } |
2. Grayscale intensity
sampler ColorMapSampler : register(s0); float4 PixelShaderGo(float2 Tex: TEXCOORD0) : COLOR { float4 Color = tex2D(ColorMapSampler, Tex); Color.rgb = dot(Color.rgb, float3(0.3, 0.59, 0.11)); // Keep our alphachannel at 1. Color.a = 1.0f; return Color; } technique PostProcess { pass P0 { PixelShader = compile ps_2_0 PixelShaderGo(); } } |
Thats about it, if you have any inputs on this one, please leave a comment, or send me an e-mail on petriw(at)gmail(dot)com
Download Sample
Download Sample