GLSL bump mapping using a normal map

Started by
7 comments, last by Wilhelm van Huyssteen 13 years, 7 months ago
Hey.

Please help me unserstand the process.

My game engine allready uses GLSL and per pixel lighitng so im asuming adding bump mapping would be trivial.

In my fragment shader i calculate the normal of the current pixel and then i compare it with my light source to get the intensity. Now im also passing in the "normal map texture" and im retrieving the "bump map normal" from it for the current pixel.

So now i have 2 normals.

A) The one i always had that i needed for my per pixel lighting and
B) The one i retrieved from my normal map.

Im guessing i need to "combine" them somehow into 1 normal which i can then use to calculate the light intensity.

Am i understanding the process correctly and if i do how do i "combine" the 2 normals?

Thnx in Advance!
Advertisement
If you use a tangent space normal map, which is probably the case, you need to transform the normal from the normal map to the space where you wish to perform your lighting calculations. To do this, you need to generate tangent vectors for your model. A good explanation can be found here:
http://www.terathon.com/code/tangent.html

So, you don't combine the two normals, you actually use the one from the map for your lighting calculations but to transform it to the correct space you still need to use the other normal and a tangent vector.
The normal map contains a normal in 'tangent space' - i.e. relative to the surface orientation.
The surface orientation is defined by the vertex normals, but that's only one axis. We need 3 axis (x/y/z) to properly describe a 3D space. The other two are called the tangent and the bi-normal/bi-tangent.

The normal, tangent and bi-normal (or bi-tangent, same deal) are all perpendicular to each other -- they define the x, y and z axis relative to the surface of the model.

So, you need to modify your mesh so that each vertex contains not just a normal, but also a bi-normal and a tangent. Hopefully someone will post more details on how to do this :P


In your shader you sample the normal map like any other texture, but we need to convert the "0 to 1" values into "-1 to +1" values:
vec3 texNormal = texture2D(normalMap, uv).rgb * 2.0 - 1.0;

Then, we need to transform this normal from tangent space into world-space or view-space (whatever space your lighting is done in). We do this by constructing a 3x3 "tangent space basis" matrix from the vertex data, and multiplying it with the normal from the normal map:
mat3 tsb = mat3( vertTangent, vertBitangent, vertNormal )
vec3 finalNormal = tsb * texNormal;

Another way to think of this is, the red channel of the normal-map is relative to vertTangent, the green channel is relative to vertBitangent and the blue channel is relative to vertNormal. If you multiply each channel with it's associated vector, and add the results together, that's the same thing as the above matrix-multiply.
Thnx that makes it alot clearer for me.

Now about the tangent and bi-tangent. Am i suposed to calculate that client side and store it in my VBO's? or do i do it in my vertex shader?

does the rest all happen in the fragment shader? except mat3 tsb = mat3( vertTangent, vertBitangent, vertNormal ) which i asume can be a varying variable in the vertex shader
Yeah the tangent/bi-tanget belong in the VBO (along with the normal). You can generate these in your program when you load a model, but usually they're created when you export from your modelling program.

Yep, I've got 'mat3 tsb' set up as a varying - the vertex shader creates it, and then the normal-map sampling and the multiplication is done in the fragment shader.
OK awesome.

i export my models from blender into my engines native format using a custom export script. Im asuming blender will allready have the tangent and bi-tangent information available for me to use so il take a look at the blender api. If not il just calculate it in my export script :D

just one more thing. Im stil using the old method of VBO's that involve using glNormalPointer, glVertexPointer, glColorPointer etc. I dont see any glTangentPointer?

I supose i should just rewrite that part of my engine so it defnines everything itself but for now and for the sake of focusing on my game instead of the engine is there a way i can get the tangent and bitangent data into GLSL without "upgrading" my engine?

maybe i can use some of the other ones that im not using. for example packing tangent data using glSecondaryColorPointer and bi-normal data using glSomethingElsePointer? or maybe im just way too lazy?
Since the bitangent is the cross product of the normal and the tangent, you can calculate it in the vertex shader. The cost of the cross product is negligible.
Quote:Original post by EternityZA
just one more thing. Im stil using the old method of VBO's that involve using glNormalPointer, glVertexPointer, glColorPointer etc. I dont see any glTangentPointer?
You can put the data in a texture-coordinate slot, or use a generic vertex attribute via glVertexAttribPointer.
Thnx a lot! I think i have everything i need to get this working.

This topic is closed to new replies.

Advertisement