Jump to content
3DCoat Forums

Local space (TBN) normalization? What is it?


ajz3d
 Share

Recommended Posts

d069d.png

http://wiki.polycoun...#Re-normalizing

Re-normalizing

Re-normalizing means resetting the length of each normal in the map to 1.

A normal mapping shader takes the three color channels of a normal map and combines them to create the direction and length of each pixel's normal. These normals are then used to apply the scene lighting to the mesh. However if you edit normal maps by hand or if you blend multiple normal maps together this can cause those lengths to change. Most shaders expect the length of the normals to always be 1 (normalized), but some are written to re-normalize the normal map dynamically (for example, 3ds Max's Hardware Shaders do re-normalize).

If the normals in your normal map are not normalized, and your shader doesn't re-normalize them either, then you may see artifacts on the shaded surface... the specular highlight may speckle like crazy, the surface may get patches of odd shadowing, etc

Link to comment
Share on other sites

  • 2 months later...

Technically, each vertex of a mesh is the origin of the tangent space of each vertex.

You provide a tangent basis to your shader by setting up one normal and one texture coordinate (uv) that's the normalized binormal, and one texture coordinate (uvset) that's the normalized tangent. These, together, make up your tangent basis, which is the vector that you take the light vector through to get it in the space of the normal map. You can re-construct tangent from normal+binormal using a cross product if you have lots of fragment shader instructions available.

For each triangle on a face the tangents for each vertex of the triangle are computed. If the triangle is mapped (that is, has uv's) and those uvs are non-degenerate then the computation in Per triangle tangent computation) is performed.

Degenerate uv's means having a 0 length vector in uv space along any edge of the triangle. If the triangle is either not mapped or degenerate, the geometric edges are used to compute the tangent.

When normalized, a vector keeps the same direction but its length is 1.0

The typical code looks something like:

tangentLight.x = dot3( light, in.normal );

tangentLight.y = dot3( light, in.texcoord[1] );

tangentLight.z = dot3( light, in.texcoord[2] );

normal = tex2D( myNormalMap, in.texcoord[0] );

diffuse = clamp( dot3( light, normal ) ) * lightColor;

However, if you also want reflection mapping, you're probably better off bringing the normal map normal out to object space by using the inverse of that 3x3 tangent basis; either by changing the dot3 to a bunch of muls, or by inverting the matrix before stuffing it into the per-vertex attributes.

source

http://www.opengl.or...o-Tangent-Space

  • Like 1
Link to comment
Share on other sites

  • Contributor

Hey Carlosa, thank you for digging this out and for remembering this thread. I didn't have time to study this technical talk yet, but once I get a free day (or week :rofl: ), I promised to myself that I will sit in my worn chair, read the info from the page you linked, doodle some sketches on the paper, then read the thing again until I fully understand it dammit. :)

There's something wrong with the link, by the way.

What are "muls"?

Tony, "muls" (I think Carlosa ate a letter here) are hard to come by, but if you choose a proper option to display them, they will appear. I'm not sure how to enable them in 3D Coat though.

Here. On the screenshot below (Silo) I managed to change dot3 to a bunch of them.

post-12523-0-52400100-1363399307_thumb.j

Link to comment
Share on other sites

  • Contributor

"Tony, "muls" (I think Carlosa ate a letter here) are hard to come by, but if you choose a proper option to display them, they will appear. I'm not sure how to enable them in 3D Coat though.

Here. On the screenshot below (Silo) I managed to change dot3 to a bunch of them."

Thanks for clarifying that. It's a cute feature but I have to come down on the side of bug squashing on this one. Andrew has enough on his hands. Anyway, why couldn't you just load them as objects/presets?

Link to comment
Share on other sites

  • Contributor

Bad jokes aside, those "muls" or rather "mul" seems to be some kind of multiply function probably found in C++ or openGL (or maybe its body needs to be implemented by a coder). I assume it's for multiplying matrices or vectors. So "replacing dot3 (it's per-pixel lighting I think) with a bunch of muls" might simply mean to replace dot3(...) with mul(...) in the code.

Link to comment
Share on other sites

  • Contributor

I didn't think the jokes were so bad. Your speculation sounds plausible (I quit with Visual Basic). Your question, "Like some real World examples on when to use B by T, T by B or not normalize at all?" would make a useful addendum to the documentation similar to Andrew's recent "Happy Baking" which gave meaning to the properties involved.

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...