XNA Shader编程教程8-光泽贴图(Gloss Map)

这个教程通过实现光泽贴图来更好地控制镜面反射。

程序截图

什么是光泽贴图?

光泽贴图是一张黑白纹理,我们使用这张纹理控制特定顶点的反射程度,黑白纹理让我们可以很容易地做到这点

Shader中颜色的格式如下:r,g,b,每个分量的变化范围是从0.0到1.0。而一个黑白纹理意味着每个分量具有相同的值:

White=(1,1,1)

Light gray=(0.8,0.8,0.8)

Dark gray=(0.2,0.2,0.2)

Black=(0,0,0)

下图是Gloss贴图的例子:

光泽纹理

我们想让白色的部分反光最强,灰色其次,而黑色部分没有反光。

实现Shader

我们需要加载镜面反射纹理并将它传递到shader中。在shader中需要从纹理获取glossmap的颜色并将它储存在一个变量中。

float4 GlossMapColor = tex2D(GlossMapSampler, Tex); 

现在,我们需要使用GlossMapColor以决定图素的镜面反射的颜色:

// R = 2 * (N.L) * N – L 
float3 Reflect = normalize(2 * Diff * Normal - LightDir); 
float Specular = pow(saturate(dot(Reflect, ViewDir)), 20); // R.V^n

请注意,现在我们在“Specular”变量中存储的是最大反光强度,为了减少反光,我们需要以某种方式修改“Specular”,我们如何做到这一点?你猜的对,将镜面反光的颜色乘以GlossMapColor。光泽贴图中只包含黑白两色,即每个RGB分量都相同。所以我们可以只使用一个分量乘以“Specular”:

// R = 2 * (N.L) * N – L 
float3 Reflect = normalize(2 * Diff * Normal - LightDir); 
float Specular = pow(saturate(dot(Reflect, ViewDir)), 20); // R.V^n
Specular = Specular*GlossMapColor.x; 

这里我使用GlossMapColor的x分量乘以 “Specular”。GlossMapColor.x范围从0.0到1.0,相当于镜面反射的比例。如果glossmap是黑色的,则Specular将乘以0.0,使它的值为0.0。如果是白色的,Specular将保持不变,而镜面反射程度取决于GlossMapColor的灰度。

知道了这一点,我们就可以实现光照方程了:

return vAmbient + vDiffuseColor * ColorMapColor * Diff + vSpecularColor * Specular; 

在这个例子中我还增加了一个颜色纹理让效果更明显:)

合成效果

何时使用光泽映射?

只要你想控制反射,就可以使用光泽映射!比如一个生锈的铁杯在某些部位仍会反光,而生锈的部位反光较少。旧汽车,光滑/粗糙的冰面等情况也适用。


发布时间:2009/4/14 下午12:34:45  阅读次数:11383

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

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号