★ TouchArcade needs your help. Click here to support us on Patreon.

Problem with Normal Maps and Tangent Space, any advice?

09-29-2009, 08:43 PM
#1
Joined: Nov 2008
Location: San Francisco
Posts: 430
Problem with Normal Maps and Tangent Space, any advice?

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 Images
 

I've made a lot of games. You've played them.
09-29-2009, 09:18 PM
#2
Joined: Sep 2008
Posts: 826
Try outputting the normal (x,y,z) as color (r,g,b) and see if there are any visible discontinuities in the source mesh.

Apps: Mech Pilot, Zombies HD, Zombies The Last Stand, iFishing (and all spinoffs), Puppet Jump, Pocket Farm, Dark Raider, Blue Skies, and more! (www.RockingPocketGames.com)

10-07-2009, 10:51 AM
#3
Joined: Nov 2008
Location: San Francisco
Posts: 430
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.

I've made a lot of games. You've played them.
10-07-2009, 05:59 PM
#4
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 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;
}

Last edited by MikeSz_spokko; 10-07-2009 at 06:01 PM.
10-07-2009, 10:54 PM
#5
Joined: Nov 2008
Location: San Francisco
Posts: 430
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.

I've made a lot of games. You've played them.
10-08-2009, 04:28 AM
#6
Quote:
Originally Posted by Hippieman View Post
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.
well, the game description says "The game uses (...) per pixel lighting using normal maps"
10-08-2009, 06:59 AM
#7
Joined: Sep 2008
Posts: 826
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?

Apps: Mech Pilot, Zombies HD, Zombies The Last Stand, iFishing (and all spinoffs), Puppet Jump, Pocket Farm, Dark Raider, Blue Skies, and more! (www.RockingPocketGames.com)
10-08-2009, 09:44 AM
#8
Joined: Nov 2008
Location: San Francisco
Posts: 430
Quote:
Originally Posted by RPGGuy View Post
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?
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

I've made a lot of games. You've played them.