Applying Normal Map To Geometry.Cube?

Oct 1, 2010 at 7:54 AM


I've been trying to apply Normal Map on a cube while practicing the tutorial 14 (Materials and Lights).

CMMIW, but turned out that the vertex declaration used in Geometry.Cube is not applicable for normal map. Is there any way to apply Normal Map to a cube using Geometry.Cube? Or I need to create my own Cube class with the custom Vertex Declaration?

I'm kind of beginner in 3D programming, actually. Sorry if this question seems too newbie :)

Oct 1, 2010 at 10:39 PM

Hi. I've got a nasty cold right now, so this might not be totally coherent:

If you want to use a normal map, then the geometry requires 'tangent normals' and 'binormals'. These are quite difficult to understand from a conceptual point of view, especially if you are a beginner - but needless to say, the basic geometry classes do not generate them. Adding them to the vertex structure is easy - just add a Vector3 Tangent, Binormal; and you are set - the hard bit is calculating them.

The normal is pretty easy to understand, it's the direction orthogonal to the surface, stored per vertex.
Tangents (and binormals) are a bit trickier, these vectors represent the directions texturing is applied to a surface.

Consider the side of a cube - it has 4 vertices with XYZ coordinates for two triangles. The normal per triangle is pretty easy to calculate, take two edges of the triangle and do a cross product. This generates an orthogonal vector to the two edges. Normalize, you are done.

However, tangent/binormal vectors have nothing to do with the XYZ coordinates of those vertices, they related to the UV texture coordinates at each vertex. Specifically, they represent the way these texture coordinates are changing over the surface of the triangle. You could call it the 'texture direction' or the UV derivative. Tangent is the direction/derivative of the U coordinate, binormal is the V coordinate.


Ok. The reason for this is pretty simple: Think of a normal map, it stores a normal per texel in a texture. A normal is an XYZ direction. A flat normal map is entirely (0,0,1). The problem is, this vector is in 'tangent space', so if you use this direction directly in your lighting calculation, it won't make any sense. On one side of the cube, the normal is 0,0,1. On the other side, it's still 0,0,1.

There has to be a mapping from texture tangent space, to world space. This is where the tangent matrix comes in, and it's comprised of the normal, tangent and binormal vectors.

Consider a side of the cube, textured with UVs like so:

0,0 1,0
0,1 1,1

in all 3 vertices, the U's are going from 0->1 left to right, and the Vs are going from 0->1 from top to bottom.
So the tangents are 1,0,0 and the binormals are 0,-1,0 for all 4 verts.

If the UVs were mirroed on the x-axis, then the tangents flip (consider the lighting must also change in such a case).

Unfortunately, it's too late and I'm too tired to explain any further - I suggest you research it. However, the model pipeline can be setup to automatically generate tangents for you, so you could always author a box or find a box model and import that.