Lighting errors with normal mapping

I am having some lighting errors trying to implement normal mapping. I am using a spotlight, with its position at the camera, and its direction in the same direction the camera is facing. Everything looks fine if I am using the vertex attribute normals (NormalMatrix*attribVertexNormals).

My normal matrix is the upper 3x3 model view matrix. Here it is with the vertex normals (spotlight aiming on corner of cube):
And here it is when trying to normal map:

My vertex shader:

    void main() 
    	vec3 n = normalize(uNormalMatrix * vec4(VertexNormal,1.0)).xyz; 	//normal
    	vec3 t = normalize(uNormalMatrix * vec4(VertexTangent,1.0)).xyz;	//tangent
    	vec3 b = normalize(cross(n, t));									//bitangent	
    	if (dot(cross(n, t), b) < 0.0f) // check handedness
    		t = t * -1.0f;
    	fTBN = mat3(t.x,b.x,n.x,	// my tbn matrix, pass to fragment shader and multiply lightdir and eyedir for normal mapping	
    	fNormal = n;				// use this in fragment shader if not normal mapping, otherwise use normal map
    	fTexcoord = VertexTexcoord;
    	fPosition = (uViewMatrix*uModelMatrix*vec4(VertexPosition,1.0)).xyz;
    	gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * vec4(VertexPosition, 1);

Fragment shader:

    vec3 spotLight(vec3 diffT, vec3 specT, vec3 ddnT)
    	float spotCutoff = 20;
    	float exponent = 1;
    	vec3 LightDir = normalize(fTBN*(vec3(uLightPosition) - fPosition));	// normal mapping
    	vec3 EyeDir = fTBN*normalize(-fPosition);							// normal mapping
    	//vec3 LightDir = normalize(vec3(uLightPosition) - fPosition); 		// not normal mapping
    	//vec3 EyeDir = normalize(-fPosition);								// not normal mapping
    	vec3 spotLightDir = normalize(fTBN*uLightDir);						// normal mapping
    	//vec3 spotLightDir = normalize(uLightDir);							// not normal mapping	
    	float angle = acos(dot(-LightDir,spotLightDir));
    	float cutOff = radians(clamp(spotCutoff,0.0,90.0));
    	if(angle < cutOff)
    		float spotFactor = pow(dot(-LightDir,spotLightDir),exponent);
    		vec3 h = normalize(EyeDir+LightDir);
    		return uLightIntensity*uKa +
    				uKd*diffT*max(dot(LightDir, ddnT), 0.0) +
    		return uLightIntensity*uKa;
    void main() {
    	vec2 parallaxCoords = fTexcoord;											// parallax occlusion mapping not yet implemented
    	vec3 diffC = texture2D(diff, * uTileAmount.x).rgb;
    	vec3 specC = texture2D(spec, * uTileAmount.y).rgb;
    	vec3 ddnC = 2.0*texture2D(ddn, * uTileAmount.z).rgb - 1.0; // normal mapping
    	//vec3 ddnC = normalize(fNormal); 											 // not normal mapping
    	fragColour = vec4(spotLight(diffC,specC,ddnC),1.0);

I have a flat normal map (0.5,0.5,1.0) for testing purposes when normal maps are on.

is fTBN orthogonal, i.e. are n and t perpendicular?

Also, you should probably be transforming VertexTangent by uViewMatrix*uModelMatrix rather than by uNormalMatrix. The whole point of using a normal matrix which is the inverse-transpose of the model-view matrix is to ensure that normals are perpendicular to tangents even when the model-view matrix isn’t orthogonal. Of course, this won’t actually matter if your model-view matrix is actually orthogonal (comprised from translation, rotation and uniform scaling, with no shear or non-uniform scaling).

Personally, I’d perform the spot cut-off calculation in eye space rather than surface (TBN) space.

When you multiply a normal vector by a matrix, is should have 0 in the 4th component, not 1. If you happen to have something in the last column of your matrix, you are transforming points, not normal.


vec3 n = normalize(uNormalMatrix * vec4(VertexNormal,1.0)).xyz; 	//normal
vec3 t = normalize(uNormalMatrix * vec4(VertexTangent,1.0)).xyz;	//tangent

should be

vec3 n = normalize(uNormalMatrix * vec4(VertexNormal,0.0)).xyz; 	//normal
vec3 t = normalize(uNormalMatrix * vec4(VertexTangent,0.0)).xyz;	//tangent

Also, I agree with what GClements is saying

Thanks guys, it works now. I used the gram schimdt process and made fTBN orthogonal and I fixed my matrix vector multiplication.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.