XNA Shader编程教程11-Post process灰度图
此教程是建立在教程9.1基础上的。如果你还没理解教程9.1,请先弄懂它。
要制作一张黑白图片或场景,我们需要将场景纹理转换成它的反相颜色,这可以在一个post process pixel shader中实现。一张黑白图片只由一些灰度的像素组成,所以我们的shader必须将一个颜色变成灰度。有几个方法可以使用,我将介绍这些方法中的两个。
1.平均颜色
一种方法是将颜色的三个通道相加并除以3,这可以获得颜色平均值,并将各个颜色通道设置为这个平均值:
Color.rgb = (Color.r + Color.g + Color.b)/3;
这将把一个像素的所有颜色通道都设置为同一个值,结果不错,但如果你仔细观察,它是不正确的!让我们看一下另一种方法。
2.灰度强度
人的眼睛对绿色比红色和蓝色更加敏感,将图片转换为灰度的一种常用方法是使用一个设置好的值,这个值表示三个颜色通道的灰度强度/权重:
g = 0.3 R + 0.59 G + 0.11 B
译者注:按照《GPU精粹1》中文版第253页的说法,推荐数值是(0.222,0.707,0.071),因为这个数值遵循一个被称为ITU Rec 709的国际工业标准,而不是这个教程中的(0.3, 0.59, 0.11)。
这样可以正确地转换图片,在shader中可以这样实现:
Color.rgb = dot(Color.rgb, float3(0.3, 0.59, 0.11));
下图是这两种不同方法的区别,在更鲜艳的场景或包含更多绿色的图片中区别更大。
实现shader
我在shader中两种方法都使用了。
1.平均颜色
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. 灰度强度
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(); } }
发布时间:2009/5/3 上午11:23:12 阅读次数:10298