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

2006 - 2024,推荐分辨率 1024*768 以上,推荐浏览器 Chrome、Edge 等现代浏览器,截止 2021 年 12 月 5 日的访问次数:1872 万 9823 站长邮箱

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号