Normal map question

Started by
9 comments, last by rwang 15 years, 3 months ago
Hi all, I have a quick question of normal map. As I know, normal map (not bump map) uses 3 channels. red and green channel are for binormal and tangent. what is blue channl for? Normal could be calculated from the binormal and tangent, right?
Advertisement
Quick answer:
A normal map stores normal vectors. RGB channels are for the compressed X,Y,Z components of the normal vector. You need tangent space vectors for correct lighting, that is to transfom the light vector to the texture space.
Quote:Original post by zhugel_007
Hi all,

I have a quick question of normal map. As I know, normal map (not bump map) uses 3 channels. red and green channel are for binormal and tangent. what is blue channl for? Normal could be calculated from the binormal and tangent, right?


You're correct in saying it should be possible to calculate the third component of the vector from the other two - and while I believe there are some DX image formats that do this, by and large, you don't want to be paying this hit at runtime (don't forget there's a sqrt in there!) - so the normal map usually stores all three normal components.

If you do compress the normal down to two channels, I think most engines usually choose to store the normal and tangent (and calculate the binormal).

There's no rule which forces you to use particular colours for particular channels - but usually, if the normal map is storing world or object space values, RGB is usually XYZ. Tangent space normal maps are a little different. Blue is "up" (i.e. off the surface) and R and G are the tangent and binormal. But you'll need to be aware of which coordinate system (left/right handed) to use.
That make sense.
Thanks for all your answers!
:)
if you have the x and y values in the texture, to make the z channel you can just use Normalize() in the pixel shader, like normalize(float3(normr, normg, 0.08f).

That gives you the z channel. So one could pack 2 normal maps into a single rgba texture.
If understand correctly, world/object space normal map are using three channels and tangent space normal map is using 2 channels? If there is not much performance penalty by using 2 channels as Matt said, what is the benefit by using world/object space normal map?
The advantage of using world space normal maps means you don't have to do the matrix math to transform world space light vectors into tangent space.. this saves vertex or pixel processing time. However, it also means you can't transform the positions of your geometry, or use tiling in your normal map; this means world space normal maps are almost never used in applications like games.

Just to clarify some things in case there is confusion: "tangent", "binormal"(or bitangent), and "normal" are each 3-component vectors. The normal map defines a single 3-vector which is a normal in world or tangent space. It does require 3 components, x,y,z. You can generate the 3rd component, z, in a shader using the normalize function, but I don't know if this works in a world space normal. Most applications use rgb tangent space normal maps.
Generating the z component of a normal vector works in tangent space because in tangent space, z is always positive. If it was world/object space, you would need to know the sign of the z component.
Quote:Original post by Matt Aufderheide
if you have the x and y values in the texture, to make the z channel you can just use Normalize() in the pixel shader, like normalize(float3(normr, normg, 0.08f).

That gives you the z channel. So one could pack 2 normal maps into a single rgba texture.


Ummm, is that really correct? I don't think I've ever seen that done. We re-construct Z in our tangent-space normal maps, but we do the much more common sqrt(1-dot(xy,xy)).

Using normalize like you're suggesting would involve scaling all of the values you put into the normal map so that you get the correct results out. And that constant that you pick as Z affects the amount of precision you can encode. For very skewed normals, it won't work at all, because the X and Y encoded in the normal map would need to have magnitude greater than one.
To skip another instruction you can use partial derivative normal maps. The idea is to store the paritial derivate of the normal in two channels of the map like this

dx = (-nx/nz);
dy = (-ny/nz);

Then you can reconstruct the normal like this:

nx = -dx;
ny = -dy;
nz = 1;
normalize(n);

The advantage is that you do not have to scale (*2)and bias (-1), so you can skip one instruction in each pixel shader that uses normal maps.
This is especially cool on the PS3 while on the XBOX 360 you can also create a custom texture format to let the texture fetch unit do the scale and bias.
More details can be found at

http://www.insomniacgames.com/tech/articles/1108/files/Ratchet_and_Clank_WWS_Debrief_Feb_08.pdf

Look for Partial Derivative Normal Maps.

This topic is closed to new replies.

Advertisement