我的场景中的照明问题仍未解决。尽管模型中的法线是正确的,并且其他程序(3D 编辑器和 Unity 中)中的光照看起来很完美,但我自己的着色器会产生不可预测的结果。
我尝试了很多方法,但都没有达到预期的效果。该模型表现出光照的突然变化,光线突然聚焦在一侧,而另一侧仍处于阴影中。当模型旋转并且光线突然“跳”到新的一侧时,这一点尤其明显。此外,模型的正面和背面几乎没有光线,使其外观完全黑色。
我无法弄清楚是什么导致了这个问题。也许这是在着色器中错误设置法线的问题,或者可能是我在照明计算中遗漏了一些重要方面。对于解决这个问题的任何帮助,我将不胜感激。
cbuffer ConstantBuffer : register(b0)
{
matrix World;
matrix View;
matrix Projection;
float4 lightDirection;
float4 lightColor;
float4 ambientColor;
}
struct VS_INPUT
{
float4 Pos : POSITION;
float2 Tex : TEXCOORD0;
float3 Normal : NORMAL;
};
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float2 Tex : TEXCOORD0;
float3 Normal : TEXCOORD1;
};
PS_INPUT VS(VS_INPUT input)
{
PS_INPUT output;
output.Pos = mul(input.Pos, World);
output.Pos = mul(output.Pos, View);
output.Pos = mul(output.Pos, Projection);
output.Tex = float2(input.Tex.x, -input.Tex.y);
output.Normal = mul(float4(input.Normal, 1), World).xyz;
return output;
}
Texture2D txDiffuse : register(t0);
SamplerState samLinear : register(s0);
float4 PS(PS_INPUT input) : SV_Target
{
float4 finalColor = 0;
finalColor += saturate(dot((float3) -lightDirection, input.Normal) * lightColor);
finalColor.a = 1;
return finalColor;
}

当从顶点着色器传递到像素着色器时,属性值被插值。插值期间,不会保留矢量长度,因此应在像素着色器中再次对法线进行标准化:
此外,如果顶点着色器中的世界矩阵具有平移(即第 4 行具有非零 xyz 分量),则法线将不仅仅是旋转,而是移位和旋转,这将破坏它们。您需要将法线乘以零位移矩阵,或者创建一个新矩阵:
这比简单地将另一个世界变换矩阵传递给一个常量而不进行移位要慢,但它可以用于测试。
问题出在完全不同的地方。将传入元素的顺序发送到着色器非常重要:
现在是顶点、法线和纹理坐标。首先是顶点、纹理坐标和法线。我交换了它们,一切正常。灯光正确显示阴影和模型。