Shader 点光源和自阴影

 

原文地址: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

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

view source
print ?
1 float LightRange;

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

view source
print ?
1 // calculate distance to light in world space 
2 float3 L = vecLightPos - PosWorld; 
3   
4 // Transform light to tangent space 
5 Out.Light.xyz = normalize(mul(worldToTangentSpace, L));// L, light 
6   
7 // Add range to the light, attenuation 
8 Out.Light.w = saturate( 1 - dot(L / LightRange, L / LightRange));

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

view source
print ?
1 float Shadow = saturate(4.0 * LightDir.z);
2 ....
3 ....
4 return 0.2 * Color + Shadow*((Color * D * LightColor + S*LightColor) * (L.w));

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

使用shader

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

view source
print ?
1 effect.Parameters["vecLightPos"].SetValue(vLightPosition); 
2 effect.Parameters["LightRange"].SetValue(100.0f); 
3 effect.Parameters["LightColor"].SetValue(vLightColor);
文件下载,已下载197次

你可能感兴趣的:(算法,优化,工具,float,shader,distance)