真的希望有人可以在这里帮助我 - 我很少能解决C#中的错误,因为我有相当多的经验,但我没有太多可以继续使用HLSL。
链接到下面的图片是相同的模型(在运行时以编程方式生成)两次,第一次(白色)时间使用BasicEffect,第二次使用我的自定义着色器,如下所示。它与BasicEffect一起工作的事实使我认为生成模型的法线或类似的东西不是问题。
我已经包含了不同级别的细分以更好地说明问题。值得一提的是,两种效果都使用相同的照明方向。
https://imagizer.imageshack.us/v2/801x721q90/673/qvXyBk.png
这是我的着色器代码(随意挑选它,任何提示都非常受欢迎):
float4x4 WorldViewProj;
float4x4 NormalRotation = float4x4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);
float4 ModelColor = float4(1, 1, 1, 1);
bool TextureEnabled = false;
Texture ModelTexture;
sampler ColoredTextureSampler = sampler_state
{
texture = <ModelTexture>;
magfilter = LINEAR; minfilter = LINEAR; mipfilter = LINEAR;
AddressU = mirror; AddressV = mirror;
};
float4 AmbientColor = float4(1, 1, 1, 1);
float AmbientIntensity = 0.1;
float3 DiffuseLightDirection = float3(1, 0, 0);
float4 DiffuseColor = float4(1, 1, 1, 1);
float DiffuseIntensity = 1.0;
struct VertexShaderInput
{
float4 Position : POSITION0;
float4 Normal : NORMAL0;
float2 TextureCoordinates : TEXCOORD0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float4 Color : COLOR0;
float2 TextureCoordinates : TEXCOORD0;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output = (VertexShaderOutput)0;
output.Position = mul(input.Position, WorldViewProj);
float4 normal = mul(input.Normal, NormalRotation);
float lightIntensity = dot(normal, DiffuseLightDirection);
output.Color = saturate(DiffuseColor * DiffuseIntensity * lightIntensity);
output.TextureCoordinates = input.TextureCoordinates;
return output;
}
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
float4 pixBaseColor = ModelColor;
if (TextureEnabled == true)
{
pixBaseColor = tex2D(ColoredTextureSampler, input.TextureCoordinates);
}
float4 lighting = saturate((input.Color + AmbientColor * AmbientIntensity) * pixBaseColor);
return lighting;
}
technique BestCurrent
{
pass Pass1
{
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
答案 0 :(得分:0)
通常,在实施照明方程式时,需要确保一些事项:
在点积中使用法线,光线方向和其他方向矢量之前,应将其标准化。在您的情况下,您可以添加如下内容:
normal = normalize(normal);
如果DiffuseLightDirection
已经未正常化,则应该这样做。它已经使用了您的默认值,但如果您的应用更改了它,则可能不再进行规范化。为此,最好在应用程序代码中进行规范化,因为它只需要在更改时执行一次,而不是每个顶点执行一次。
还要记住,如果您将向量乘以包含比例的矩阵,则向量将不再被标准化,因此需要重新标准化。
光线方向和法线必须指向与表面相同的方向。您的默认指示灯是(1,0,0)
。如果你想让光线指向+ x方向,那么你必须在使用法线执行点积之前实际否定向量,这样它就像法线一样指向表面。如果你已经考虑到这一点,那么这不是问题。
矢量无法翻译,因为它们只是一个方向而不是一个位置。因此,重要的是要确保何时使用矩阵转换它们,该矩阵要么向量的第四个分量(w)为0,要么转换它的矩阵没有转换。将w设置为0将在乘法期间将矩阵的任何平移归零。由于你的矩阵被称为NormalRotation
,我假设它只包含一个轮换,所以这可能不是问题。