我正在使用 Frank Luna 的书来学习 DirectX 10,但我对我得到的一些照明有点困惑。我有几个对象,一个定向光和一个可以在场景中移动的点光源。我的问题是,当我移动点光源时,光会移动,但距离原点越远,它就会越暗。在原点时,它具有强烈的白光。为什么会这样,我怎样才能让它正常工作?谢谢。
这是点光源的代码:
float3 PointLight(SurfaceInfo v, Light L, float3 eyePos)
{
float3 litColor = float3(0.0f, 0.0f, 0.0f);
// The vector from the surface to the light.
float3 lightVec = L.pos - v.pos;
// The distance from surface to light.
float d = length(lightVec);
if( d > L.range )
return float3(0.0f, 0.0f, 0.0f);
// Normalize the light vector.
lightVec /= d;
// Add the ambient light term.
litColor += v.diffuse * L.ambient;
// Add diffuse and specular term, provided the surface is in
// the line of site of the light.
float diffuseFactor = dot(lightVec, v.normal);
[branch]
if( diffuseFactor > 0.0f )
{
float specPower = max(v.spec.a, 1.0f);
float3 toEye = normalize(eyePos - v.pos);
float3 R = reflect(-lightVec, v.normal);
float specFactor = pow(max(dot(R, toEye), 0.0f), specPower);
// diffuse and specular terms
litColor += diffuseFactor * v.diffuse * L.diffuse;
litColor += specFactor * v.spec * L.spec;
}
// attenuate
return litColor / dot(L.att, float3(1.0f, d, d*d));
}
效果文件:
#include "lighthelper.fx"
#define MaxLights 2
cbuffer cbPerFrame
{
uniform extern Light gLight[MaxLights];
int gLightType;
float3 gEyePosW;
};
bool gSpecularEnabled;
cbuffer cbPerObject
{
float4x4 gWorld;
float4x4 gWVP;
float4x4 gTexMtx;
};
// Nonnumeric values cannot be added to a cbuffer.
Texture2D gDiffuseMap;
Texture2D gSpecMap;
SamplerState gTriLinearSam
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU=Mirror;
AddressV=Mirror;
};
struct VS_IN
{
float3 posL : POSITION;
float3 normalL : NORMAL;
float2 texC : TEXCOORD;
float4 diffuse : DIFFUSE;
float4 spec : SPECULAR;
};
struct VS_OUT
{
float4 posH : SV_POSITION;
float3 posW : POSITION;
float3 normalW : NORMAL;
float2 texC : TEXCOORD;
float4 diffuse : DIFFUSE;
float4 spec : SPECULAR;
};
VS_OUT VS(VS_IN vIn)
{
VS_OUT vOut;
// Transform to world space space.
vOut.posW = mul(float4(vIn.posL, 1.0f), gWorld);
vOut.normalW = mul(float4(vIn.normalL, 0.0f), gWorld);
// Transform to homogeneous clip space.
vOut.posH = mul(float4(vIn.posL, 1.0f), gWVP);
// Output vertex attributes for interpolation across triangle.
vOut.texC = mul(float4(vIn.texC, 0.0f, 1.0f), gTexMtx);
vOut.diffuse = vIn.diffuse;
vOut.spec = vIn.spec;
return vOut;
}
float4 PS(VS_OUT pIn) : SV_Target
{
// Get materials from texture maps.
float4 diffuse = gDiffuseMap.Sample( gTriLinearSam, pIn.texC );
float4 spec = gSpecMap.Sample( gTriLinearSam, pIn.texC );
// Map [0,1] --> [0,256]
spec.a *= 256.0f;
// Interpolating normal can make it not be of unit length so normalize it.
float3 normalW = normalize(pIn.normalW);
// Compute the lit color for this pixel.
SurfaceInfo v = {pIn.posW, normalW, diffuse, spec};
float3 litColor;
for(int i = 0; i < MaxLights; ++i)
{
if( i==0) // Parallel
{
//litColor += ParallelLight(v, gLight[i], gEyePosW);
}
else // Point
{
litColor += PointLight(v, gLight[i], gEyePosW);
}
}
return float4(litColor, diffuse.a);}
technique10 TexTech
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
}
}
光定义:
myLight[1].ambient = D3DXCOLOR(0.4f, 0.8f, 0.4f, 1.0f);
myLight[1].diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
myLight[1].specular = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
myLight[1].att.x = 0.0f;
myLight[1].att.y = 0.1f;
myLight[1].att.z = 0.0f;
myLight[1].range = 50.0f;