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.
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’v also added the shaders for both methods, so you can see the whole picture without having to download the example.
1. Average color
sampler ColorMapSampler : register(s0);
float4 PixelShader(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 PixelShader();
}
}
2. Grayscale intensity
sampler ColorMapSampler : register(s0);
float4 PixelShader(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 PixelShader();
}
}
NOTE:
You might have noticed that I have not used effect.commitChanges(); in this code. If you are rendering many objects using this shader, you should add this code in the pass.Begin() part so the changed will get affected in the current pass, and not in the next pass. This should be done if you set any shader paramteres inside the pass.
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
YouTube – XNA Shader programming, Tutorial 11 – Grayscale postprocess