[翻译]XNA 3.0 Game Programming Recipes之forty-two

PS:自己翻译的,转载请著明出处格
                                                  6-6 使用HLSL定义一个发光的点
问题
                      直到现在,你已经使用了方向的光亮去点亮你的屏幕,它非常有用去添加光照到你的3D世界。通常情况下,你同样需要一个来自单一个点的光照,如来自一个手电筒或者一个爆炸。这样一个光源被称为:point Light。
解决方案
                      传递光照点的3D位置从你的XNA工程到你的XNA效果。每一个顶点,你可以计算方向从光源朝着顶点,使用这个光照方向。一旦你知道光照方向,你继续象以前一样使用。
它是如何工作的
                      在你的.fx文件中,取代这xLightDirection参数用这一行,允许你传递光源的3D位置从你的XNA工程到你的HLSL效果:
1 float3 xLightPosition;
                      其次,每一个顶点,你计算这个方向从光照朝着顶点。一如往常,从A到B的方向是通过由B减A得到的。这意味着你需要顶点的最终3D位置,这意味着原来的3D位置转换成世界矩阵:
1 float3 final3DPosition=mul(inPos,xWorld);
2 float3 lightDirection=final3DPosition-xLightPosition;
3 lightDirection=normalize(lightDirection);
4 Output.LightFactor=dot(rotNormal,-lightDirection);
                      由于光源和顶点之间的方向可能大于1,你需要确保它的长度成为统一单位通过规格化它。一旦你知道这个光照方向,你已经准备去处理如果前面章节介绍的。
                      当您运行此代码时,在每个顶点你会计算从光源到那个顶点的方向,这样这个方向每个顶点都会不同。
Distance Attenuation
                      为了让事情更现实一点,你可以减少一个光照点的影响,正如光源和顶点之间的距离变的很大。要做到这一点,找到这个距离通过调用length值在lightDirection之前规格化它。接下来,用这个距离划分LightFactor;这将导致光照的强度减少,正如在光源和增长顶点之间的距离:
1 float3 final3DPosition=mul(inPos,xWorld);
2 float3 lightDirection=final3DPosition-xLightPosition;
3 float distance=length(lightDirection);
4 lightDirection=normalize(lightDirection);
5 Output.LightFactor=dot(rotNormal,-lightDirection);
6 Output.LightFactor/=distance;
代码
                       在你的XNA工程中,你可以在任何位置布置你的光源:
1 effect.CurrentTechnique=effect.Technique["VertexShadin"];
2 effect.Parameters["xView"].SetValue(fpsCam.ViewMatrix);
3 effect.Parameters["xProjection"].SetValue(fpsCam.ProjectionMatrix);
4 effect.Parameters["xLightDirection"].SetValue(new Vector3(1,5,0));
5 effect.Parameters["xAmbient"].SetValue(0.0f);
                       这是你的完整的顶点着色器:
 1 VSVertexToPixel VSVertexShader(float4 inPos:POSITION0,float3 inNormal:NORMAL0)
 2 {
 3       VSVertexToPixel Output=(VSVertexToPixel)0;
 4       float4*4 preViewProjection=mul(xView,xProjection);
 5       float4*4 preWorldViewProjection=mul(xWorld,preViewProjection);
 6       Output.Position=mul(inPos,preWorldViewProjection);
 7       float3 normal=normalize(inNormal);
 8       float3*3 rotMatrix=(float3*3)xWorld;
 9       float3 rotNormal=mul(normal,rotMatrix);
10       float3 final3DPosition=mul(inPos,xWorld);
11       float3 lightDirection=final3DPosition-xLightPosition;
12       lightDiection=normalize(lightDirection);
13       Output.LightFactor=dot(rotNormal,-lightDirection);
14       return Output;
15 }  

posted on 2009-08-12 15:13  一盘散沙  阅读(213)  评论(0编辑  收藏  举报

导航