Jump to content
3DCoat Forums
ajz3d

Local space (TBN) normalization? What is it?

Recommended Posts

It has three possible states:

- Normalize B by T,

- Normalize T by B,

- Don't normalize.

What does it do? What is it used for? :ph34r:

Share this post


Link to post
Share on other sites

Thanks, but how about some explanation in English? :rofl:

Like some real World examples on when to use B by T, T by B or not normalize at all?

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×