正常映射给出了奇怪的结果。 (C#XNA)

时间:2013-08-08 16:02:45

标签: c# xna shader

好的,所以这个问题有点大,出于同样的原因,我宁愿发布尽可能少的代码,而是让你想到它可能是什么。我将发布我觉得问题可能出现的代码。如果你想看到更多的问题,我会提供它。

所以,我只是为自己的游戏“偷”了一个着色器。通过偷走我的意思是找到了我以前做过的教程,并且只是复制了最终结果。因此我知道着色器应该可以工作,因为我之前已经使用过它。

我有一个自定义网格类,还有一个自定义顶点结构。我之前从未做过xertex结构,所以最初我认为这就是问题所在。 但我后来发现了一些反驳: 它们的所有变量似乎都是正确的,除了凹凸贴图之外,一切都有效。 改变切线和/或副法线似乎对阴影没什么影响。所以我认为错误不在于它们的计算方式,而在于如何使用它们。

http://imageshack.us/photo/my-images/838/w6kv.png/

这是我得到的输出。请记住,这是一个体素引擎。正如您所看到的,所有方框都具有相同的奇怪的法线贴图阴影。不过这是法线贴图:

http://imageshack.us/photo/my-images/268/r7jt.jpg/

如您所见,它们并不适合。现在,这可能是我认为的三件事之一:

  1. 这可能是我在xna中设置着色器的方式。
  2. 它也可能是顶点结构中的东西
  3. 这也可能是我称之为实际绘图功能的方式。
  4. 所以这里是这三件事的代码(以及着色器):

    着色器设置: ((这里我设置着色器的数据,并绘制网格))

    // Bind the parameters with the shader.
    BBS.Parameters["World"].SetValue(Matrix.Identity);
    BBS.Parameters["View"].SetValue(camera.viewMatrix);
    BBS.Parameters["Projection"].SetValue(camera.projectionMatrix);
    
    BBS.Parameters["AmbientColor"].SetValue(Color.White.ToVector4());
    BBS.Parameters["AmbientIntensity"].SetValue(0.5f);
    
    Vector3 LD = new Vector3(0, 1, -1);
    LD.Normalize();
    
    BBS.Parameters["DiffuseColor"].SetValue(Color.White.ToVector4());
    BBS.Parameters["DiffuseIntensity"].SetValue(0);
    BBS.Parameters["LightDirection"].SetValue(LD);
    
    BBS.Parameters["EyePosition"].SetValue(new Vector3(0.0f, 2.0f, 5.0f));
    BBS.Parameters["SpecularColor"].SetValue(Color.White.ToVector4());
    BBS.Parameters["ColorMap"].SetValue(cubeTexture);
    BBS.Parameters["NormalMap"].SetValue(Content.Load<Texture2D>("images"));
    
    
    BBS.CurrentTechnique = BBS.Techniques["Technique1"];
    
    for (int i = 0; i < BBS.CurrentTechnique.Passes.Count; i++)
    {
        //EffectPass.Apply will update the device to
        //begin using the state information defined in the current pass
        BBS.CurrentTechnique.Passes[i].Apply();
    
        //theMesh contains all of the information required to draw
        //the current mesh
        graphics.DrawUserPrimitives(PrimitiveType.TriangleList, Mesh.Vertices, 0, Mesh.NUM_TRIANGLES);
    }
    

    顶点结构:

    public struct VertexPositionNormalTangentBinormalTexture : IVertexType
    { 
        public Vector3 Position; 
        public Vector3 Normal; 
        public Vector2 TextureCoordinate; 
        public Vector3 Tangent; 
        public Vector3 Binormal;
    
        public static readonly VertexDeclaration VertexElements = new VertexDeclaration
        ( 
            new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0), 
            new VertexElement(12, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0), 
            new VertexElement(24, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0), 
            new VertexElement(32, VertexElementFormat.Vector3, VertexElementUsage.Tangent, 0), 
            new VertexElement(44, VertexElementFormat.Vector3, VertexElementUsage.Binormal, 0)
        );
    
    
        VertexDeclaration IVertexType.VertexDeclaration { get { return VertexElements; } }
    
        public static readonly int SizeInBytes = sizeof(float) * (3 + 3 + 2 + 3 + 3);
    }
    

    Shader:

        // XNA 4.0 Shader Programming #4 - Normal Mapping
    
    // Matrix
    float4x4 World;
    float4x4 View;
    float4x4 Projection;
    
    // Light related
    float4 AmbientColor;
    float AmbientIntensity;
    
    float3 LightDirection;
    float4 DiffuseColor;
    float DiffuseIntensity;
    
    float4 SpecularColor;
    float3 EyePosition;
    
    
    texture2D ColorMap;
    sampler2D ColorMapSampler = sampler_state
    {
        Texture = <ColorMap>;
        MinFilter = linear;
        MagFilter = linear;
        MipFilter = linear;
    };
    
    texture2D NormalMap;
    sampler2D NormalMapSampler = sampler_state
    {
        Texture = <NormalMap>;
        MinFilter = linear;
        MagFilter = linear;
        MipFilter = linear;
    };
    
    // The input for the VertexShader
    struct VertexShaderInput
    {
        float4 Position : POSITION0;
        float2 TexCoord : TEXCOORD0;
        float3 Normal : NORMAL0;
        float3 Binormal : BINORMAL0;
        float3 Tangent : TANGENT0;
    };
    
    // The output from the vertex shader, used for later processing
    struct VertexShaderOutput
    {
        float4 Position : POSITION0;
        float2 TexCoord : TEXCOORD0;
        float3 View : TEXCOORD1;
        float3x3 WorldToTangentSpace : TEXCOORD2;
    };
    
    // The VertexShader.
    VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
    {
        VertexShaderOutput output;
    
        float4 worldPosition = mul(input.Position, World);
        float4 viewPosition = mul(worldPosition, View);
        output.Position = mul(viewPosition, Projection);
        output.TexCoord = input.TexCoord;
    
        output.WorldToTangentSpace[0] = mul(normalize(input.Tangent), World);
        output.WorldToTangentSpace[1] = mul(normalize(input.Binormal), World);
        output.WorldToTangentSpace[2] = mul(normalize(input.Normal), World);
    
        output.View = normalize(float4(EyePosition,1.0) - worldPosition);
    
        return output;
    }
    
    // The Pixel Shader
    float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
    {
        float4 color = tex2D(ColorMapSampler, input.TexCoord);
    
        float3 normalMap = 2.0 *(tex2D(NormalMapSampler, input.TexCoord)) - 1.0;
        normalMap = normalize(mul(normalMap, input.WorldToTangentSpace));
        float4 normal = float4(normalMap,1.0);
    
        float4 diffuse = saturate(dot(-LightDirection,normal));
        float4 reflect = normalize(2*diffuse*normal-float4(LightDirection,1.0));
        float4 specular = pow(saturate(dot(reflect,input.View)),32);
    
        return  color * AmbientColor * AmbientIntensity + 
                color * DiffuseIntensity * DiffuseColor * diffuse + 
                color * SpecularColor * specular;
    }
    
    // Our Techinique
    technique Technique1
    {
        pass Pass1
        {
            VertexShader = compile vs_2_0 VertexShaderFunction();
            PixelShader = compile ps_2_0 PixelShaderFunction();
        }
    }
    

1 个答案:

答案 0 :(得分:0)

这不是以正确的顺序完成的:

output.WorldToTangentSpace[0] = mul(normalize(input.Tangent), World);
output.WorldToTangentSpace[1] = mul(normalize(input.Binormal), World);
output.WorldToTangentSpace[2] = mul(normalize(input.Normal), World);

它应该是这样的:

output.WorldToTangentSpace[0] = normalize(mul(input.Tangent), World);
output.WorldToTangentSpace[1] = normalize(mul(input.Binormal), World);
output.WorldToTangentSpace[2] = normalize(mul(input.Normal), World);

否则,你的法线将从世界空间转换中缩放,并将导致非常明亮和非常暗的补丁(看起来像你的问题)。顺便说一句,看到你对Voxel引擎的法线贴图感兴趣,请查看我做过的以下内容:

http://www.youtube.com/watch?v=roMlOmNgr_w http://www.youtube.com/watch?v=qkfHoGzQ8ZY

希望你得到启发并完成你的项目。