我一直试图在HLSL中创建一个简单的指示灯几天,我一直在关注本指南: D3DBook:(Lighting) Direct Light Sources
特别是点光源的衰减功能和部分。这是我的代码:
//------------------------------------------------------------------------------------------------------
// Global params provided by the app
//------------------------------------------------------------------------------------------------------
uniform extern float4x4 gWVP;
uniform extern float4x4 gWorldViewIT; //for normals
uniform extern float4x4 gWorldView;//work out view vector from all vertices
uniform extern float4x4 gLightMatrix;//light in view space
uniform extern float4x4 gWorld;
uniform extern float4 gDiffuseMtrl;
uniform extern float4 gAmbMtrl;
uniform extern float4 gSpecMtrl;
//lights
uniform extern float4 gLightCol = {1, 1, 1, 1}; //set to white
//uniform extern float4 gLightPos[4];
uniform extern float4 gLightPos[4] = {{0,0,3,0},{0,0,-1,0},{0,100,1,0},{0,-100,0,0}};
uniform extern float gLightPow[4] = {25,25,0.1,0.1};//range of light
uniform extern float roughness;//roughness per object
uniform extern float ref;//reflectance at normal//used in fresnel calculation
//pi
const shared float pi= 3.14159f;
//attenuation constants
const float a_a = 0.0f;
const float a_b = 0.1f;
const float a_c = 1.0f;
//calculate light attenuation
float atten( float distance, float range, float a, float b, float c)
{
float atten = 1.0f / ((a * distance * distance) + (b * distance) + c );
//step clamps to 0 if out of range
return step(distance, range) * saturate( atten );
}
//---------------------------------------------------------------------------------------------------------------------------
// Input channel (vertex shader)
//---------------------------------------------------------------------------------------------------------------------------
struct InputVS
{
float3 posL : POSITION0;
float3 Norm : NORMAL;
};
//---------------------------------------------------------------------------------------------------------------------------
// Output channel (vertex shader)
//---------------------------------------------------------------------------------------------------------------------------
struct OutputVS
{
float4 posH : POSITION0;
float4 col : COLOR0;
};
//vertex shader//passthrough
OutputVS gourardVS(InputVS input)
{
float n = 1/roughness;
//Zero out our output
OutputVS outVS = (OutputVS)0;
//Transform to homogeneous clipspace
outVS.posH = mul(float4(input.posL, 1.0f), gWVP);
float4 col_amb = gAmbMtrl*gLightCol;
float4 col_diff = gDiffuseMtrl*gLightCol;
float4 col_spec = gSpecMtrl*gLightCol;
//ambient term
float4 ambient={0.2, 0.2, 0.2, 1.00f};
float4 finalColour=0;
float diff = 0;
float3 pWorld = mul( float4( input.posL, 1.0f ), gWorld).xyz;
//normal
float3 N =normalize(mul(float4(input.Norm, 1.0f),gWorldViewIT));
//point lights
float attenu = atten(distance(pWorld, gLightPos[1]), gLightPow[1], a_a, a_b, a_c);
float3 l_dir= normalize(gLightPos[1] - pWorld);
//n dot l
float dotNL = max(0, dot(N, l_dir));
finalColour = float4( attenu * dotNL * col_diff);
//}
outVS.col = finalColour;// + (ambient * col_amb);
outVS.col.a = 1;
//return
return outVS;
}
//---------------------------------------------------------------------------------------------------------------------------
// Input channel pixel shader
//---------------------------------------------------------------------------------------------------------------------------
struct InputPS{
float4 posH : POSITION0;
float4 col : COLOR0;
};
float4 noPS(InputPS input): COLOR
{
return input.col;
}
technique Phong{
pass P0
{
Lighting = TRUE;
SpecularEnable = TRUE;
vertexShader = compile vs_3_0 gourardVS();
pixelShader = compile ps_3_0 noPS();
//specify render device states associated with the pass
//FillMode = WireFrame;
//ShadeMode = Gouraud;
}
}
我很确定传入的矩阵是正确的,因为我已经从定向光示例重新调整了它,所以这只留下HLSL代码作为问题的根源。这会输出正确的顶点,但无论我在灯光位置和功率阵列上使用什么值,它们几乎都不会点亮。
答案 0 :(得分:2)
我终于找到了问题,光线方向在世界空间而法线在View空间中,我忘了通过视图矩阵(gLightMatrix)转换光线方向这里是修改后的代码:
...
float3 l_dir= normalize(gLightPos[1] - pWorld);
float3 L=normalize(mul(l_dir, gLightMatrix));
//n dot l
float dotNL = max(0, dot(N, L));
finalColour = float4( attenu * dotNL * col_diff);
...
无论如何,谢谢大家,看看。