XNA Creators Club Online
Page 1 of 1 (10 items)
Sort Posts: Previous Next

normal map & custom vertex problem

Last post 11/11/2009 6:23 PM by Shawn Hargreaves. 9 replies.
  • 11/7/2009 9:09 PM

    normal map & custom vertex problem

    Hi.

    I tried to use a custom vertex (because the normal map looked very strange all ATI card, but with this, it looks well) :

    public struct VertexPositionNormalTextureTangent 
        { 
            public Vector3 Position; 
            public Vector3 Normal; 
            public Vector2 TextureCoordinate; 
            public Vector3 Tangent; 
     
            public static readonly VertexElement[] VertexElements = new VertexElement[] 
            { 
                new VertexElement(0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0), 
                new VertexElement(0, sizeof(float) * 3, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Normal, 0), 
                new VertexElement(0, sizeof(float) * 6, VertexElementFormat.Vector2, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 0), 
                new VertexElement(0, sizeof(float) * 8, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Tangent, 0) 
            }; 
             
            public VertexPositionNormalTextureTangent(Vector3 position, Vector3 normal, Vector2 textureCoordinate, Vector3 tangent, Vector3 binormal) 
            { 
                Position = position; 
                Normal = normal; 
                TextureCoordinate = textureCoordinate; 
                Tangent = tangent; 
            } 
            public static int SizeInBytes { get { return sizeof(float) * 14; } } 
        } 

    In my entity class:
    protected VertexDeclaration vertexDeclaration; 
     
    //LoadContent 
    vertexDeclaration = new VertexDeclaration(game.GraphicsDevice, VertexPositionNormalTextureTangent.VertexElements); 
        game.GraphicsDevice.VertexDeclaration = vertexDeclaration; 
     
     
    //Draw 
    for (int i = 0; i < mesh.Meshes.Count; i++) 
        game.GraphicsDevice.Indices = mesh.Meshes[i].IndexBuffer; 
        game.GraphicsDevice.VertexDeclaration = vertexDeclaration; 
     
        SetEffectParameters(i); 
     
        Effect.Begin(); 
        Effect.CurrentTechnique.Passes[0].Begin(); 
        Effect.CommitChanges(); 
     
        foreach (ModelMeshPart part in mesh.Meshes[i].MeshParts) 
        { 
            game.GraphicsDevice.Vertices[0].SetSource(mesh.Meshes[i].VertexBuffer, part.StreamOffset, part.VertexStride); 
            game.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, part.BaseVertex, 0, 
                part.NumVertices, part.StartIndex, part.PrimitiveCount); 
        } 
     
        Effect.CurrentTechnique.Passes[0].End(); 
        Effect.End(); 

    The HLSL code:
    float4x4 world;
    float4x4 worldViewProj;

    float3 lightPosition;
    float4 lightDiffuse;
    float4 lightAmbient  = float4(0.3f, 0.3f, 0.3f, 1.0f);

    texture diffuseTexture;
    sampler diffuseSampler = sampler_state
    {
        Texture   = <diffuseTexture>;
        MinFilter = LINEAR;
        MagFilter = LINEAR;
        MipFilter = LINEAR;
        //AddressU  = CLAMP;
        //AddressV  = CLAMP;
    };

    texture normalTexture;
    sampler normalSampler = sampler_state
    {
        Texture   = <normalTexture>;
        MinFilter = LINEAR;
        MagFilter = LINEAR;
        MipFilter = LINEAR;
        //AddressU  = CLAMP;
        //AddressV  = CLAMP;
    };

    // --------------------------
    // ----- Normal mapping -----
    // --------------------------
    struct VSOUT
    {
        float4 Position       : POSITION;
        float2 TexCoord       : TEXCOORD0;
        float3 Light          : TEXCOORD1;
    };

    VSOUT VS(float4 pos : POSITION, float3 n : Normal, float2 texcoord : TEXCOORD0, float3 t : TANGENT)
    {
        VSOUT Out = (VSOUT)0;
        
        Out.Position = mul(pos, worldViewProj);
        
        float3x3 wtt;
        wtt[0] = mul(normalize(t), world);
        wtt[1] = mul(normalize(cross(t, n)), world);
        wtt[2] = mul(normalize(n), world);
        
        Out.TexCoord = texcoord;
        Out.Light = normalize(mul(wtt, lightPosition));
        
        return Out;
    }

    float4 PS(VSOUT In) : COLOR0
    {
        float4 outColor = tex2D(diffuseSampler, In.TexCoord);
        float3 normal = (2.0 * (tex2D(normalSampler, In.TexCoord))) - 1.0;    
        float diffuse = saturate(dot(normal, In.Light));
        return outColor * (lightAmbient + (diffuse * lightDiffuse));
    }

    technique NormalMap
    {
        pass p0
        {
            //FillMode = Solid;
            CullMode = CCW;
            ZEnable = true;
            ZWriteEnable = true;
            AlphaBlendEnable = false;
            AlphaTestEnable = false;

            VertexShader = compile vs_2_0 VS();
            PixelShader  = compile ps_2_0 PS();
        }
    }

    And here is an image what represent my problem: (In real-time the white "leak" is black)
    http://ilab.hu/jf/datas/users/1403-screenshot1.png

    Any idea?

    Thanks,
    screat

    P.S.:
    If I use the "mesh.Meshes[i].Draw()" method, it's working...
    And sorry for my bad english :)
  • 11/8/2009 5:14 AM In reply to

    Re: normal map & custom vertex problem

    Are you using SizeInBytes anywhere? Because it's wrong (it should be sizeof(float) * 11, not 14).
    Matt Pettineo | DirectX/XNA MVP


    Ride into The Danger Zone | PIX With XNA Tutorial
  • 11/8/2009 11:41 AM In reply to

    Re: normal map & custom vertex problem

    MJP:
    Are you using SizeInBytes anywhere? Because it's wrong (it should be sizeof(float) * 11, not 14).

    Yeah, I forgot write back to 11 from 14. (I used Binormal too)
    But I don't use SizeInBytes (maybe later to compute bounding box).
    new VertexElement(0, sizeof(float) * 8, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Tangent, 0)
    If here, I write 4 instead of 8, it's working... But why?
  • 11/9/2009 5:48 PM In reply to

    Re: normal map & custom vertex problem

    I would guess that maybe you aren't setting something correctly onto the device, or your buffers don't contain the data you think they should, or maybe your shader isn't doing the right computation with this data?

    The easiest way to debug such things is using PIX (part of the DirectX SDK) in single frame capture mode. That will let you debug your vertex and pixel shaders, so you can see exactly what data is coming into them, what computations they are doing, what their outputs are, etc.
    XNA Framework Developer - blog - homepage
  • 11/9/2009 7:05 PM In reply to

    Re: normal map & custom vertex problem

    Shawn Hargreaves:
    I would guess that maybe you aren't setting something correctly onto the device, or your buffers don't contain the data you think they should, or maybe your shader isn't doing the right computation with this data?

    The easiest way to debug such things is using PIX (part of the DirectX SDK) in single frame capture mode. That will let you debug your vertex and pixel shaders, so you can see exactly what data is coming into them, what computations they are doing, what their outputs are, etc.

    Thanks, I'm going to try it.

    EDIT:
    But if I use the basic mesh.Meshes[i].Draw(), the program works correctly.
  • 11/9/2009 7:22 PM In reply to

    Re: normal map & custom vertex problem

    Screat:
    But if I use the basic mesh.Meshes[i].Draw(), the program works correctly.


    If that works correctly, why not just use that?  :-)
    XNA Framework Developer - blog - homepage
  • 11/10/2009 3:10 PM In reply to

    Re: normal map & custom vertex problem

    Shawn Hargreaves:
    Screat:
    But if I use the basic mesh.Meshes[i].Draw(), the program works correctly.


    If that works correctly, why not just use that?  :-)

    Well... I dont know :D
    I think, my code is faster than the basic mesh.Draw(); (or not... :))
    Ok i'm going to use the basic draw. Thanks
  • 11/10/2009 5:31 PM In reply to

    Re: normal map & custom vertex problem

    Screat:
    I think, my code is faster than the basic mesh.Draw(); (or not... :))


    Not really. It's basically just doing the same thing that ModelMesh.Draw does internally, only not quite so robust since you don't handle things like models with non identity bone transforms, and you are forcing the vertex declaration to a fixed setting rather than using the one specified by the model data.

    If ModelMesh.Draw works but your code does not, PIX would be a perfect way to find out why. Take two captures and compare the device states (vertex declaration, shaders, shader parameters, etc) for this draw call. What is different between the two?
    XNA Framework Developer - blog - homepage
  • 11/11/2009 5:03 PM In reply to

    Re: normal map & custom vertex problem

    Hmm. I've never useed the PIX. What should I see? :)
  • 11/11/2009 6:23 PM In reply to

    Re: normal map & custom vertex problem

    There's a good tutorial here.
    XNA Framework Developer - blog - homepage
Page 1 of 1 (10 items) Previous Next