Bump / Normal Maps (2)

I’ve been trying to get this code from the ever-wonderful Ozone3D.net working with my normal map.

It’s not working at the moment (in a variety of exciting ways), and I’m pretty sure that’s because my shader is not receiving a value for the attribute vec3 ‘vTangent’. I can turn this attribute into a uniform and set it manually, but I assume I need to calculate this value per-vertex inside the Vertex Shader for it to work properly. Sadly, I have no idea how I might go about doing this :frowning:

Anyone any ideas? All suggestions gratefully accepted.

Here’s the code:

varying vec3 lightVec; 
varying vec3 eyeVec;
varying vec2 texCoord;
attribute vec3 vTangent; 

void main(void)
	gl_Position = ftransform();
	texCoord = gl_MultiTexCoord0.xy;
	vec3 n = normalize(gl_NormalMatrix * gl_Normal);
	vec3 t = normalize(gl_NormalMatrix * vTangent);
	vec3 b = cross(n, t);
	vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
	vec3 tmpVec = gl_LightSource[0].position.xyz - vVertex;

	lightVec.x = dot(tmpVec, t);
	lightVec.y = dot(tmpVec, b);
	lightVec.z = dot(tmpVec, n);

	tmpVec = -vVertex;
	eyeVec.x = dot(tmpVec, t);
	eyeVec.y = dot(tmpVec, b);
	eyeVec.z = dot(tmpVec, n);

varying vec3 lightVec;
varying vec3 eyeVec;
varying vec2 texCoord;
uniform sampler2D colorMap;
uniform sampler2D normalMap;
uniform float invRadius;

void main (void)
	float distSqr = dot(lightVec, lightVec);
	float att = clamp(1.0 - invRadius * sqrt(distSqr), 0.0, 1.0);
	vec3 lVec = lightVec * inversesqrt(distSqr);

	vec3 vVec = normalize(eyeVec);
	vec4 base = texture2D(colorMap, texCoord);
	vec3 bump = normalize( texture2D(normalMap, texCoord).xyz * 2.0 - 1.0);

	vec4 vAmbient = gl_LightSource[0].ambient * gl_FrontMaterial.ambient;

	float diffuse = max( dot(lVec, bump), 0.0 );
	vec4 vDiffuse = gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse * 

	float specular = pow(clamp(dot(reflect(-lVec, bump), vVec), 0.0, 1.0), 
	                 gl_FrontMaterial.shininess );
	vec4 vSpecular = gl_LightSource[0].specular * gl_FrontMaterial.specular * 
	gl_FragColor = ( vAmbient*base + 
					 vDiffuse*base + 
					 vSpecular) * att;

Thanks once again guys,


The tangent should indeed be an attribute. What you need to do is either compute the tangent in your code ( http://www.terathon.com/code/tangent.php ), or export the tangents from a modeling program such as Maya. :slight_smile:

Hi HexCat,

thanks for getting back to me.
Doesn’t look like this bumpmapping method is a goer then. I’m planning to use the normal map to create lighting on a height field, with the height field texture also being used to create the normal map. Any static tangent information will be incorrect after vertex displacement, I guess.


Well, it could still be done. The tangent is the vector tat points in the same direction as the u-direction of your texture space (or maybe it is the bitangent, I always swap them, well, no matter). So if your texture coordinates behave in a regular way, for example, the texture is a planar projection onto the heightfield, then you could compute the bitangent and the tangent in the shader. For example, if the texture space axis correspond to the heightfield X and Z axis (as it is often done) and you know the world space normal vector, you will also know tha the world tangent will arise by transforming the (1, 0, 0) vetor by the same means that would also transform (0, 1, 0) – the normal — to the space normal vector. Hovewer, I don’t have the math right here and it would take me too much time to figure out (my linear algera is really bad), but I am sure it can be solved.

Similarly, you could compute the tangent from the heightfield in your CPU code at the same time when also computing your normal.

Hi Zengar.

Thanks for the explanation. Unfortunately, the development environment I’m using doesn’t give me access to OpenGL instructions, so I’m not able to precompute normals for the mesh. I’m deforming the mesh with the heightfield in the Vertex Shader, so any calculations need to be done in the Vertex or Fragment Shaders.

It’s odd, because I sort-of got the normal map to work without doing any real conversion of the normal vector from tangent space (see my last 2 posts on my blog here ). It was a bit glitchy, but kind of worked. Thinking about it now, I’m not sure why it should work at all…



Just wondering- is there any way to draw the normalmap/bumpmap so the normals are in the correct coordinate space to start with?


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