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

Started by
11 comments, last by theagentd 11 years ago

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?
Advertisement

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.

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...

This topic is closed to new replies.

Advertisement