XNA Shader编程教程17-点光源和自阴影

原文地址:http://digierr.spaces.live.com/blog/cns!2B7007E9EC2AE37B!612.entry。

程序截图

本教程基于教程4-法线映射。在实现一个点光源前你无需知道法线映射,所以如果你只想知道如何实现一个点光源,可以暂时无需理解教程4的知识。

这个教程只解释什么是点光源以及如何实现它,你可以在本教程使用的算法之后添加法线映射或其他你需要的shader。

只要你理解了教程1,2,3,这个教程不是很难。

点光源

点光源(Point lights,在某些渲染工具中也叫做Omni light)的光线是从3D空间中的一个点向四周发出的。

点光源

不像前面教程中的单向光,点光源有一个作用范围,光线传播一段距离后会衰减为零,这叫做衰减因子(attenuation factor):

attenuation=1-((x/r )2+(y/r )2+(z/r )2

公式中的r为衰减距离,公式也可表达为:

attenuation=1-(L/r )•(L/r )

如果用1减去V1=L/r和V2=L/r的点乘,就能获得衰减因子。

在点光源光照范围之外的物体只有环境光颜色,所以最后的光照方程如下:

I = A + Diffuse*Specular*attenuation

自阴影

使用上述光照方程会遇到的一个问题是:在漫反射和镜面高光计算时会有一些显示错误,当光线向量和视线向量方向相反时像素也会被照亮,而且,如果光源距物体表面过近,也会有显示错误。

解决上述问题的一个方法是使用自阴影(Self-Shadowing),它可以避免不应该被照亮的像素获得光照。

当物体被遮挡或不应该获得光照时,自阴影因子为零或接近于零,如果像素被照亮,则这个因子大于零。

那么如何实现呢?只需计算表面法线和光照方向的点乘即可:

S = saturate( N.L );

但是这里的临界值过低,所以将它乘以4才可以获得正确的临界值。

现在我们可以用S乘以漫反射和镜面高光反射的颜色,这样当S为零时颜色也为零!我们的新光照方程如下:

I = A + S*(Diffuse*Specular*attenuation)

这个方程可以进行优化,方法是只有当S大于零时才计算漫反射和镜面高光反射,否则颜色就为零:if( S > 0) { calculate.. }.

当使用法线映射时,我们是在切线空间中进行计算的。这个算法让我们可以使用光线向量的Z分量,因为切线空间中的这个Z分量就等于N•L. 所以有以下方程:

S = 4 * LightDirection.z;

实现shader

首先我们需要声明光照范围:

float LightRange;

然后在顶点着色器中计算光照,将衰减值放在光源w分量,光线方向放在L向量中:

// calculate distance to light in world space 
float3 L = vecLightPos - PosWorld; 

// Transform light to tangent space 
Out.Light.xyz = normalize(mul(worldToTangentSpace, L)); // L, light 

// Add range to the light, attenuation 
Out.Light.w = saturate( 1 - dot(L / LightRange, L / LightRange));

剩下的事情就是在光照方程中使用衰减值和施加自阴影,这是在像素着色器中进行处理的:

float Shadow = saturate(4.0 * LightDir.z);
....
....
return 0.2 * Color + Shadow*((Color * D * LightColor + S*LightColor) * (L.w));

如你所见,点光源与前面我们使用的单向光源区别不大,当使用光照时,自阴影值也可以用于前面的示例。

使用shader

除了需要设置光照范围和光源位置代替前面教程中的光线方向,XNA代码没有其他变化:

effect.Parameters["vecLightPos"].SetValue(vLightPosition); 
effect.Parameters["LightRange"].SetValue(100.0f); 
effect.Parameters["LightColor"].SetValue(vLightColor);
文件下载(已下载 1570 次)

发布时间:2010/6/21 下午4:31:00  阅读次数:9241

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

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号