2014-10-07 77 views
0

使怪异的图案真希望有人能帮助我在这里 - 我很少无法解决的错误在C#中,因为我有在它经历了相当数量的,但我没有很多去与HLSL。自定义HLSL着色跨越icosphere

链接到下面的图像是相同的模型(上运行程序生成)的两倍,使用我的自定义着色器,下面列出使用BasicEffect和第二时间的第一(白色)的时间。事实上,它与BasicEffect一起使用,我认为这不是为模型或类似的东西生成法线问题。

我已经包括了不同层次的细分,以更好地说明这个问题。值得一提的是,两种效果都使用相同的照明方向。

https://imagizer.imageshack.us/v2/801x721q90/673/qvXyBk.png

这里是我的shader代码(随意挑选它拆开,任何提示都非常欢迎):

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

有几件事情要尝试:1)确保正常化之前,在点产品中使用它。 2)法线和光线方向矢量需要指向点积(从表面出来)的相同方向。如果你的照明意图是+ x方向,那么在做点积之前,你需要将它排除到-x方向。 3)可能不是问题,但要确保'input.Normal'的第四个分量是0或'NormalRotation'矩阵不包含任何翻译。 – megadan 2014-10-08 06:40:30

+0

在点积中使用它之前,还要确保光线方向已标准化 – megadan 2014-10-08 15:14:49

+0

第一句通过标准化法线立即解决了我的问题。可以花几天时间俯瞰!非常感谢您的快速回复。如果您将此作为答案发送,我会标记它。 – 2014-10-08 21:53:13

回答

0

在一般情况下,实现照明方程式时,有几件事情确保:

  1. 法线,光线方向和其他方向矢量在使用点积之前应进行归一化。你的情况,你可以添加类似:

    normal = normalize(normal);

    同样应DiffuseLightDirection做,如果它已经不归。它已经与你的默认值,但如果你的应用程序改变它,它可能不会正常化了。为此,最好在应用程序代码中进行规范化处理,因为只需在其更改时执行一次,而不是每个顶点执行一次。

    还要记住,如果你是乘以包含规模矩阵向量,向量将不再是标准化的,所以它需要被重新归一化。

  2. 的光的方向和在其从表面出来的相同的方向上正常必须指向。您的默认灯光方向是(1,0,0)。如果你希望光线指向+ x方向,那么在用法线执行点积之前,你必须实际上否定矢量,以便它像平常一样从表面指出。如果你已经考虑到了这一点,那么这不是问题。因为它们只是一个方向不是位置

  3. 载体不能被翻译。因此,确保何时用矩阵转换它们非常重要,该矩阵要么是向量的第四个分量(w)是0,要么是转换它的矩阵没有翻译。将w设置为0将在乘法过程中将矩阵的任何转换归零。由于你的矩阵被称为NormalRotation,我假设它只包含一个旋转,所以这可能不是问题。