Problem with Normal Maps and Tangent Space, any advice?

Discussion in 'Public Game Developers Forum' started by Hippieman, Sep 30, 2009.

  1. Hippieman

    Hippieman Well-Known Member

    Nov 6, 2008
    433
    0
    0
    Senior Producer, Designer
    San Francisco
    We've implemented tangent space generation based on the code segment on this page http://www.terathon.com/code/tangent.html, but a good chunk of the polygons are coming out as if the normal map is upside-down. Does this mean the handedness is not being handled properly, or is something else wrong?

    Vertex shader:

    Code:
    attribute vec4 position;
    attribute vec4 color;
    attribute vec2 texcoord;
    attribute vec4 normal;
    attribute vec4 tangent;
    attribute vec4 binormal;
    
    uniform mat4 modelViewMatrix;
    uniform mat4 projectionMatrix;
    uniform mat4 normalMatrix;
    uniform mat4 textureMatrix;
    uniform vec4 lightVector;
    uniform vec4 lightColor;
    
    varying vec4 colorVarying;
    varying vec2 tcVarying;
    varying vec4 tangentLightVector;
    
    void main()
    {
     gl_Position = projectionMatrix * modelViewMatrix * position;
    
     vec4 normalVarying = normalize(normalMatrix * normal);
    
     vec4 tangentEye = normalize(normalMatrix * tangent);
    
     vec4 binormalEye = normalize(normalMatrix * binormal);
    
    //transform eyespace light to tangent space
     tangentLightVector.x = dot(lightVector, tangentEye);
     tangentLightVector.y = dot(lightVector, binormalEye);
     tangentLightVector.z = dot(lightVector, normalVarying);
    
     tangentLightVector.w = 0.0;
     tangentLightVector = normalize(tangentLightVector);
    
     colorVarying = color;
     vec4 fullTexture = textureMatrix*vec4(texcoord.x, texcoord.y, 0, 1);
     tcVarying = vec2(fullTexture.x, fullTexture.y);
    }
    
    The attached screenshot is the result of dot(texture2D(normal map, tcVarying), tangentLightVector) in the fragment shader. Does anything obvious leap out at anyone?
     

    Attached Files:

  2. RPGGuy

    RPGGuy Well-Known Member

    Sep 3, 2008
    827
    0
    0
    Try outputting the normal (x,y,z) as color (r,g,b) and see if there are any visible discontinuities in the source mesh.
     
  3. Hippieman

    Hippieman Well-Known Member

    Nov 6, 2008
    433
    0
    0
    Senior Producer, Designer
    San Francisco
    Sorry I didn't reply so soon. Everything is completely smooth doing that. It's got to be a fault somewhere else in the math.

    We'll get it eventually, there doesn't seem to be many people/anyone working with Normal Maps on the iPhone so far.
     
  4. MikeSz_spokko

    MikeSz_spokko Well-Known Member

    May 27, 2009
    594
    0
    16
    #4 MikeSz_spokko, Oct 7, 2009
    Last edited: Oct 8, 2009
    well, there is a game with normal maps already -> http://forums.toucharcade.com/showthread.php?t=28483

    what might be happening is that when you generate normal maps there is no universal rule as to what is red, green and blue. I had this problem and it looked similar - normal maps generated with some programs produce inverted lighting. so what you can try to do is to flip colors within the shader - use red as blue and so on. will take a few tries, but might solve it

    I did normal maps in DirectX / HLSL some time ago, dont know OpenGL syntax too much. that's the code I used, hope it helps. it was a looooong time ago :D also might contain some debug code, but that shouldn't bother you too much ;)

    texture tex;
    texture normaltexture;
    float4x4 matWorld;
    float4x4 matViewProj;
    float4 eyePos;
    float4 l_LightPos;

    struct VS_INPUT
    {
    float4 Pos : POSITION;
    float3 Normal : NORMAL0;
    float2 Tex0 : TEXCOORD0;
    float3 Tangent : TANGENT;
    float3 Binormal : BINORMAL;
    };

    struct VS_OUTPUT
    {
    float4 Pos : POSITION;
    float2 Tex0 : TEXCOORD0;
    float3 lightDir: TEXCOORD1;
    float3 viewDir: TEXCOORD2;
    float3 exPos : TEXCOORD3;
    };

    VS_OUTPUT VShade(VS_INPUT In)
    {
    VS_OUTPUT Out = (VS_OUTPUT) 0;
    float3 posWorld = mul(In.Pos, matWorld);

    float3 lhtDir = normalize(l_LightPos - posWorld);
    float3 viewDir = normalize(eyePos - posWorld);

    float3 normal = normalize(mul(In.Normal, matWorld));
    float3 tangent= normalize(mul(In.Tangent, matWorld));
    float3 binormal = normalize(mul(In.Binormal, matWorld));

    float3x3 TBNMatrix = float3x3(tangent, binormal , normal);

    Out.lightDir = mul(TBNMatrix,lhtDir).yxz;
    Out.viewDir = mul(TBNMatrix,viewDir);

    Out.Pos = mul(In.Pos,matViewProj);
    Out.exPos = Out.Pos.xyz;
    Out.Tex0 = In.Tex0;

    return Out;
    }

    float4 PShade( VS_OUTPUT In ) : COLOR
    {
    float4 finalcolor;

    float4 texFragment = tex2D( Sampler0, In.Tex0);
    float3 myNormal = 2.0f * tex2D(Sampler1, In.Tex0).rgb - 1.0f;

    float lightStr = saturate(dot(myNormal, normalize(In.lightDir)));

    float3 vectorPointToEye = normalize(float3(eyePos.x, eyePos.y, eyePos.z) - In.exPos);
    float3 vectorReflection = normalize(reflect(In.lightDir, myNormal));
    float angle = acos(dot(vectorReflection, vectorPointToEye));
    float specularLightPower = pow(max(1-angle,0), 4);

    finalcolor = texFragment * (max(lightStr, .15) + specularLightPower);

    return finalcolor;
    }
     
  5. Hippieman

    Hippieman Well-Known Member

    Nov 6, 2008
    433
    0
    0
    Senior Producer, Designer
    San Francisco
    Turns out our Tangent Space math was a bit off. Got it all up and running and it's stunning to look at.

    I don't think Dark Raider does Normal Maps, it looks like Bump Mapping to me. RPGGuy am I close or way off on that? I watched your tech stuff, and got the impression you went with Bump Mapping.
     
  6. MikeSz_spokko

    MikeSz_spokko Well-Known Member

    May 27, 2009
    594
    0
    16
    well, the game description says "The game uses (...) per pixel lighting using normal maps"
     
  7. RPGGuy

    RPGGuy Well-Known Member

    Sep 3, 2008
    827
    0
    0
    The technique I used is more like EMBM. It renders lights to a separate texture than uses the normal maps to perturb the texture.

    It's 2D so it doesn't need all the usual tangent space transformations like you're doing here.

    Glad you got it running anyways. What are you doing with those asteroids? :p
     
  8. Hippieman

    Hippieman Well-Known Member

    Nov 6, 2008
    433
    0
    0
    Senior Producer, Designer
    San Francisco
    Cool. The look you got into Dark Raider with the lights is really cool. I hope to get into multiple light sources eventually. For now just one big light.

    As for the game, I don't want to announce stuff publicly, but I'm happy to drop you an email with info and such. bruce at freeverse dot com
     

Share This Page