Monday 8 April 2013

Normal Mapping

This blog will cover the graphics topic of normal mapping, also known as bump mapping. No, there is no difference between normal mapping and bump mapping other than the word normal, and bump. If there is one thing I will walk away from this class with and never forget it is that. Thanks for the good laugh Dr. Hogue and students who pretend to pay attention. Anyways, I will cover more detail about normal mapping and how it is done in both object space and tangent space along with the differences between them.

Here is a quick image to show you what an improvement bump mapping can do to graphics. This is a huge improvement on how much more realistic the image looks on the right. The process is a very simple one as well. What needs to be done if one would like to generate a model or surface that has this effect on it would require the process to begin in a modeling software such as Mudbox. Here we will create what we want, say a cube, and we will paint it so it has a texture. Then what we want to do after we have that saved is we want to create a high poly version of this same model. Once we have something that is now in the hundreds of thousands of faces, we can start to add a bump to the model. The way how we would do this is by getting a sculpting tool with a low magnitude and we will pull at the faces to make the model bumpy. We don't want to make it too dramatic because it will perform a poor illusion in the end of the process so nice and little bumps will work great for this. Bump the model in the desired way you would like the model to look then we are going to create a normal map which can be done in either object or tangent space. Here are a couple of examples I made for both:
 The one on the left is normal mapping of my cube in object space and the one on the right is in tangent space. These were generated from the texture map generator in Mudbox after I selected both types of normal mapping. Now these examples are very dramatic because I sculpted with a high magnitude brush as you can tell. Now the reason why these two look different is easy to explain. But first let me explain why they look so colorful.
So, a normal map is simply the normals of every fragment on the texture map. More specifically, it is the xyz normals being displayed as rgb values. Mind blown, I know. Here we have the x part of the normal vector being represented as red and the y as green and finally z as blue. Now, looking at these two different textures and knowing what I just explain you can say a few different things about them.

Let's look at the left one first, our object space normal map. Now it's called the object space normal map because all of the normals are relative to the object itself. Remember how I said green is equal to the y portion of the normal? well if you look at the bottom square of the normal map it is entirely green, so I know that this green square is the top face of the cube because relative to the object's space, the normals are all pointing in the y axis. Likewise, the top left square is almost all red, that must mean that square is on the right face of that cube.

Now we look at the tangent space normal map. All the squares look relatively the same in color, this happens because with tangent space, we no longer static to the object itself. The normals are now dynamic to the mesh of the texture. By that I mean if we were to deform the mesh with tangent space normal mapping the bump map will hold true in any deformation the mesh skinning throws at it. The reason why it is mostly all in the z axis or blue value is because the bump map is now done in world space. Here is a quick snippet from a great source on tangent space normal mapping:

If we now calculate U and V in the object local space (as well as U cross V which is the normal to the texture) we can generate a transformation matrix to move the normals from the map into the object local space. From there they can be transformed to world space as usual and take part in lighting calculation. The common practice is to call the U vector in the object local space the Tangent and the V vector in the object local space theBitangent. The transformation matrix that we need to generate is called a TBN matrix (Tangent-Bitangent-Normal). These Tangent-Bitangent-Normal vectors define a coordinate system known as Tangent (or texture ) space. Therefore, the normals in the map are stored in tangent/texture space.

The link is provided at the end if you are interested in more normal mapping. There is all sorts of math and code examples as well in this link plus some background of it. Anyways, the snippet explains it well in regards to how we need to use the tangent, bitangent, normal matrix to generate what we need to put the normals in tangent space.

The question now is, which one do I use? Why wouldn't we always use tangent space normal mapping? Well, you could always use tangent space normal mapping if one desires, you will get the same result for some objects. The only ones you won't have them work for is object space won't work for dynamic meshes that transform. What will happen if you do is called a candy wrapper effect where the normals are being deformed relative to the object and not the world and the skin starts to deform in glitchy ways you don't want. So a good time to use object space normal mapping is when the object or surface is static such as a wall or statue. This is good because it is faster to compute than tangent space and you get the same effect.

Here are the fragment shaders I used to demonstrate both object and tangent space normal mapping:

Object Space fragment shader

Tangent Space fragment shader


Now at the end of the day, after all of this has been rendered through the pipeline, the models and textures are being loaded correctly and the shaders don't complain about random typos, there is magic called normal mapping.
That cube from the beginning of the blog.


http://ogldev.atspace.co.uk/www/tutorial26/tutorial26.html

No comments:

Post a Comment