Sign in to follow this  

GLSL bump mapping using a normal map

This topic is 2665 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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!

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

This topic is 2665 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this