• Create Account

# What to do with old per-vertex normals when doing normal mapping?

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

12 replies to this topic

### #1theagentd  Members   -  Reputation: 912

Like
0Likes
Like

Posted 20 April 2013 - 07:32 AM

Hello. I have a really small question regarding how to implement normal mapping. All the model files I have already have per-vertex normals stored in them. All the tutorials/articles I've found computes all three of the normals, tangents and bitangents per vertex by averaging the triangles the vertex is part of and then orthogonalizing them. However, I can't find any information on what I should do with the already existing per-vertex normals. What are 3D programs that generate normal maps etc expecting me to do? Should I ignore the per vertex normals, can I assume that they're already what I need (calculated the same way the tutorials/articles tell me to) or do I need to take them into consideration in some special way?

### #2L. Spiro  Crossbones+   -  Reputation: 24752

Like
0Likes
Like

Posted 20 April 2013 - 07:54 AM

Normal mapping adds 2 more normal types: Tangent and Binormal.
The normal map tells you how much to shift the normal in these directions.

Which means you use the existing normal exactly the same way as you did but adjust it in the direction of the binormal and tangent based off the values read from the normal map.

L. Spiro

Edited by L. Spiro, 21 April 2013 - 03:29 AM.

### #3theagentd  Members   -  Reputation: 912

Like
0Likes
Like

Posted 20 April 2013 - 08:37 AM

Thanks for the response. However, what I'm asking about is a bit simpler than that. I'm asking about generating the normals, tangents and bitangents. There are already normals in my 3D models, but the articles are telling me to calculate a normals, tangents and bitangents by averaging triangles. If I use the normals in the 3D models I may not get orthogonal vectors, but if I calculate a new one I'm ignoring the one that came with the model.

### #4eppo  Crossbones+   -  Reputation: 4494

Like
1Likes
Like

Posted 20 April 2013 - 09:20 AM

It simply depends on whether you find the pre-computed normals usable or not. If they differ much from your own calculations or give poor lighting results you might feel like throwing them out. Tangent vectors can always be orthonormalized in respect to a normal vector.

### #5theagentd  Members   -  Reputation: 912

Like
0Likes
Like

Posted 20 April 2013 - 10:10 AM

I see. I'll just experiment and see which one looks best then. Thanks!

### #6tanzanite7  Members   -  Reputation: 1410

Like
0Likes
Like

Posted 20 April 2013 - 04:44 PM

Normal mapping added 2 more normal types: Tangent and Binormal.

biTANGENT. Binormal is nonsensical in this context.

### #7phil_t  Crossbones+   -  Reputation: 7602

Like
0Likes
Like

Posted 20 April 2013 - 05:12 PM

biTANGENT. Binormal is nonsensical in this context.

Why is that? The semantics in HLSL at least, are TANGENT and BINORMAL.

### #8Hodgman  Moderators   -  Reputation: 49122

Like
1Likes
Like

Posted 20 April 2013 - 05:50 PM

If you're using 'baked' normal maps, (which are authored by copying the details from a high poly model onto texutres for a low poly object) then your engine and modeling tools both need to use the exact same t/b/n vectors. So in some cases you need to be able import these as well as the normals from your art tools.

In other cases, you can import just the normals, and then generate the t/b, or you can generate all three.

biTANGENT. Binormal is nonsensical in this context.

Why is that? The semantics in HLSL at least, are TANGENT and BINORMAL.
Depending on which branch of mathematics you're using, one of either one of them is the properly defined term (and the other is nonsense).
In computer graphics though, we use them interchangeably.

### #9L. Spiro  Crossbones+   -  Reputation: 24752

Like
1Likes
Like

Posted 20 April 2013 - 10:15 PM

Normal mapping added 2 more normal types: Tangent and Binormal.

biTANGENT. Binormal is nonsensical in this context.

Read reply by Hodgman. I typed “Bitangent”, erased it, and specifically typed “Binormal” in order not to confuse the original poster who is likely used to seeing HLSL semantics or tutorials commonly referring to it as such.

L. Spiro

### #10theagentd  Members   -  Reputation: 912

Like
0Likes
Like

Posted 21 April 2013 - 05:59 AM

ead reply by Hodgman. I typed “Bitangent”, erased it, and specifically typed “Binormal” in order not to confuse the original poster who is likely used to seeing HLSL semantics or tutorials commonly referring to it as such.

L. Spiro

That's fine, I'm aware of the confusion around it so everyone should just use whatever they're used to. I'm using GLSL by the way, but that's not really relevant.

If you're using 'baked' normal maps, (which are authored by copying the details from a high poly model onto texutres for a low poly object) then your engine and modeling tools both need to use the exact same t/b/n vectors. So in some cases you need to be able import these as well as the normals from your art tools.

In other cases, you can import just the normals, and then generate the t/b, or you can generate all three.

I see. That's what I was a bit worried about, but I'm using .smd files which only contain normals. I'm already "compiling" my .smd files to an internal format in my engine in which I store the (generated) tangents, and using the normal and tangent I can generate the bitangent/binormal using a cross product between them. Assuming I can get my hands on tangents and/or bitangents I can store them in my compiled format.

I'm not done implementing normal mapping yet, but I've taken the approach where

1. generate a tangent

2. orthogonalizes it to the normal

3. generate the bitangent using a cross product between the normal and the tangent

Since I'm at least respecting the normal information in the model, shouldn't this have a close to or maybe even identical result to what the modelling program was using?

### #11Hodgman  Moderators   -  Reputation: 49122

Like
0Likes
Like

Posted 21 April 2013 - 06:16 AM

Since I'm at least respecting the normal information in the model, shouldn't this have a close to or maybe even identical result to what the modelling program was using?

No, there are many methods to generate the t/b vectors, given a normal. Any t/b/n basis per vertex is valid, provided they're all perpendicular. This means if you rotate the basis around the normal axis, you've still got valid data. You can even flip one axis in the reverse direction (e.g. Do Binormal = -Binormal), and you've still got a valid t/b/n basis.

Also, art tools generally try to take the UV/texture coordinates into account when generating the t/b vectors, so that the Tangent points in the same direction the U (x texture coord) is increasing, and the Binormal/Bitangent point in the direction the V (y) is increasing. This makes the normal map texture make a but more sense to look at and edit by hand ;) This also means that if the UVs are flipped at one point (e.g. The artist only textured half a face, but then used he same UV layout on both sides of the face, causing a mirroring in the tex-coords down he centre) then your binormals might also flip direction arbitrarily. If you're using artist-generated data, you often can't throw out the Binormal and just recreate it with a cross product -- you need to at least store a single bit encoding whether the cross product should be multiplied with 1 or -1.

This means that unless you know the algorithm being used by your art tools, it's very likely that your engine will produce different results...
Putting a normal map onto a brick wall is fairly simple, but handling all the little problems that come up when modeling a character is a lot more complex ;(

That model format is from the Source engine, right? Maybe there's source code for a loader/importer/compiler/viewer in the Source SDK, and you can copy their TBN generation algorithm?

### #12theagentd  Members   -  Reputation: 912

Like
0Likes
Like

Posted 21 April 2013 - 10:42 AM

I currently only calculate the tangent using vertex positions and UV coordinates. I see now that I've made a few assumptions that may not always hold.

I decided on smd-files because it was the only format that supports skinning AND actually makes sense to me, so I'd prefer it if I could keep on using them. I'm pretty sure that the normal maps will be generated from a high-poly model, which I assume is done by a separate program. Skinning and animating is done in yet another program and is completely unrelated to the normal maps, so in theory it should be possible to in some way export the normals, tangents and bitangents into a separate file from the low-poly generating program (together with the normal map) and use them together with the .smd file to compile it all into my own format. Although it's far from optimal, it's the easiest solution I can think of right now.

Although the format is used by the Source engine, the models are custom made from scratch. After some quick googling I found this thread: http://www.polycount.com/forum/showthread.php?t=107420. It seems to suggest that the Source engine follows certain standards, but I'm a bit unsure what programs our modelers use (it's a hobby project so we're not terribly organized ^^'). I will try to speak with them as soon as possible to figure out the details.

Thanks a lot for your input, everyone! I had no idea that this would be so difficult to implement.

### #13theagentd  Members   -  Reputation: 912

Like
0Likes
Like

Posted 22 April 2013 - 05:20 PM

I thought I'd just add a small post to wrap up this thread.

I spoke to one of our modelers and got my hands on a few test models. After a few tests and a some bug squashing we finally got some code that actually looked decent. The solution isn't perfect; some surfaces look rounded when they should be flat, but the problems are very minor so unless I encounter a model that has any visible quirks I'll probably stick with my current code. It's a bit disappointing though. I implemented my shaders exactly like I the example for MikkTspace (don't normalize tangent/bitangent/normal in the pixel shader, but normalize the calculated normal), but the result is still not perfect, so it has to be how I calculate the tangents...

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

PARTNERS