6-6.用HLSL定义点光源
问题
直到现在,你已经用定向光照亮你的场景,它对添加阳光到3D世界很有用。常常,你也将需要一个单点光照,例如手电筒或爆炸。这种光源叫点光源。
方案
从你的XNA项目传递点光源的3D位置到你的XNA effect。为每个顶点,你可以计算出从光源到顶点的方向并使用此方向。
运作
在你的.fx文件,用这行代码替换xLightDirection参数,允许你从XNA项目传递光源的3D位置到HLSL effect:
float3 xLightPosition;
接着,你将为每个顶点计算从光到顶点的方向。一直,从A到B的方向通过B减A得到。记住你需要顶点的最终3D位置,意思是用World矩阵变换原3D位置:
float3 final3DPosition = mul(inPos,xWorld);
float3 lightDirection = final3DPosition – xLightPosition;
lightDirection = normalize(lightDirection);
output.LightFactor = dot(rotNormal,-lightDirection);
因为光源到顶点方向将可能比1大许多,你需要确保它的长度被单位化。一旦你知道这个光方向,你就准备去处理了。
当你运行这个代码,在每个顶点你将计算从光源到该顶点的方向,所以这个方向对每个顶点都不同。
衰减距离
要使事情更真实,你可能想要在光源和顶点间距离增大时减少点光源的影响。要这么做,在单位化它之前调用length(lightDirection)得出这个距离。接着,通过这个距离决定LightFactor;这将导致光的强度在光源和顶点间的距离增长时减少:
float3 final3DPosition = mul(inPos,xWorld);
float3 lightDirection = final3DPosition – xLightPosition;
float distance = length(lightDirection);
lightDirection = normalize(lightDirection);
Output.LightFactor = dot(rotNormal,-lightDirection);
Output.LightFactor /= distance;