View Full Version : tangent space with smoothed normals

06-13-2005, 07:13 PM
Sorry if this is old stuff, but I just don't get it.

When calculating the tbn matrix like it is described in the various examples on the internet, the T and B vectors are computed from the vertex coordinates and the tex coords. For the N vector, there are two alternatives:

- use the vertex normal suppiled by the gemoetry: In this case, the N vector is not orthogonal to T and B,
- compute a normal vector that is ortogonal to N and B: In this case, smoothing does no longer take place.

I cannot find any explanation of how to solve this on the internet. So please anyone help ;) .

Thanks and regards,

06-13-2005, 07:42 PM
You have posted two solutions and then request a solution, but you have actually mistaken the problem.

The real problem is tangent and binormals not being orthogonal due to the texture derivatives. If you consider the calculation of tangent and binormals on any surface, their cross product will always match the normal of the polygon because the texture derivatives always lie on the plane of the triangle.

Averaging these correctly will retain consistent results.

The question then becomes one of the correctness of non orthogonal tangent and binormal vectors on a surface relative to the normal map (which has by definition non orthogonal texture derivatives).

It depends to a degree on how the normal map is generated IMHO. If this is detail reduction this can still produce a correct normal although I think the vector transformation to tangent space will be slightly flawed. You could correct by cross product for binormal or tangent against the other two vectors and using this as the basis for the normal map detail model raycast to tangent space and it all just works. I think either is acceptable so long as you shade with the same basis you raycast your normal map with.

IMHO the whole thing is a second order effect and the root cause it poor application of texture coordinates (derivative of s&t non orthogonal). As a precursor to detail reduction you have the application of texture and you can try there to keep derivatives orthogonal at this time.

Mapping arbitrary normal maps and generating the tangent space basis with derivatives of s & t I think you just have to put up with it. The artist has infact applied an orthogonal bump map to a surface with inherent skew, so what's the correct treatment? I think it could be argued that using a slightly non orthogonal tangent space basis is approximately the correct thing to do under those circumstances and it's a content creation issue.

06-13-2005, 08:16 PM
Thanks for answering, I think I will try simply using the vertex normal (first "solution") and see what it looks like.

The fact that suppliyng an normal map to a surface with inherent skew is a problem itself is an interesting fact anyway, I haven't thought of this yet. But you can't do anything about that anyway, I guess. The purpose of normal mapping in my application is not detail reduction but simply use bump mapping to "make it look better" (brick walls etc.).

Another solution I thought of is that maybe it is the right think to calculate an orthogonal N vector for the TBN matrix, but for each vertex with a smoothed (non-orthogonal) normal, rotate the light vector, according to the degree the smoothed normal vector deviates from the orthogonl one. But I guess that would be a little overdone?

06-13-2005, 08:24 PM
There is an inherent rotation during interpolation. The tangent space basis is used to rotate vectors at the vertices, those vectors are then interpolated to produce fragments (not quite a rotation but close). It's all about transformation to a tangent space and interpolation.

Is seems you're still slightly off base. As I said, the geometric normal will equal the tangent space basis normal from the derivatives (cross product of edges will produce a vector the same as the cross products of derivatives (after normalization), assuming sanity with front vs back facing), averaging will then produce a vertex normal. Use the cross product of the polygon edges or the cross product of the tangent and binormal, you'll see that they are identical (after normalization). There is no inconsistency with the normals, only with the binormal and tangent vectors *potentially* being non orthogonal.

If you see other issues your math may be broken (make sure you normalize before averaging for example).

06-14-2005, 06:32 AM
I don't think that I am off base, I exactly understand (and already knew) what you are saying in your last post. I simply wonder what to use for N. When calculating an N vector from the polygon edges (or T and B), T-B-N are orthogonal, but smoothing (like on curved surfaces) gets lost. When using the normal vector which is part of the 3d geometry data, smoothing is there, but N is not orthogonal to T and B. So, what to do? But you already answered that.

Then I thought that maybe it's The Right Way to use an orthogonal N vector, but shift the light vector a little bit for the smoothing effect to have influence. Maybe I will draw an image to explain what I mean, if it is not clear. But as I said, I guess this approach might be a little exaggerated.

06-14-2005, 06:45 AM
N from edges matches N from derivatives (after normalization and assuming sane back-front). The plane defined by T and B is by definition coplanar with the polygon.

The calculation of N in either case comes before smoothing. You smooth all vectors, T B and N together. You should probably normalize first. When you average several entire orthogonal coordinate frames across a shared vertex the result should remain orthogonal.

It is very important for smooth bump mapping on a curved surface that all three basis vectors are averaged, this is central to vector interpolation accross polygons. Of course this introduces a new set of issues for derivative continuity accross polygons (again this depends on content and how the normal map was generated).

I guess this is where you keep throwing me because you keep implying there's a difference between different versions of N, and in either case the normal should be smoothed with T & B.

06-14-2005, 07:18 AM
OK I see.. have an orthogonal N vector, but smooth T, B and N together. But how is this calculated?

I do not compute smoothed vectors myself, the gemoetry data is loaded from a .obj file (rather, several), and this contains vertex coordinates, texture coordinates and normal vectors (which might already be smoothed). I have no idea what to do to get this working.

06-14-2005, 08:42 AM
dorbie, is the following approach correct ?


PARAM mvp[4] = { state.matrix.mvp };

PARAM light_pos =program.local[0];
PARAM view_pos =program.local[1];

TEMP light_vec, view_vec, half_angle;
TEMP norm_light_vec, norm_view_vec, norm_half_angle;
TEMP tmp, B;

OUTPUT oTBN_light_vec =result.texcoord[1];
OUTPUT oTBN_half_angle_vec =result.texcoord[2];

# transform vertex to clip
DP4 result.position.x, mvp[0], vertex.position;
DP4 result.position.y, mvp[1], vertex.position;
DP4 result.position.z, mvp[2], vertex.position;
DP4 result.position.w, mvp[3], vertex.position;

# pass the decal texcoord out - to the fragment prog
MOV result.texcoord[0], vertex.texcoord[0];

# create TBN: use the Tangent and Normal to calculate the Binormal
XPD tmp, vertex.texcoord[1], vertex.normal; # B = T x N

# normalize B
DP3 B.w, tmp, tmp;
RSQ B.w, B.w;
MUL B.xyz, B.w, tmp;

SUB light_vec, light_pos, vertex.position;
DP3 norm_light_vec.w, light_vec, light_vec;
RSQ norm_light_vec.w, norm_light_vec.w;
MUL norm_light_vec.xyz, norm_light_vec.w, light_vec;

DP3 oTBN_light_vec.x, norm_light_vec, vertex.texcoord[1]; #T
DP3 oTBN_light_vec.y, norm_light_vec, B; #B
DP3 oTBN_light_vec.z, norm_light_vec, vertex.normal; #N

# ... ?

06-14-2005, 09:03 AM
@JanHH, just use the vectors, if you have TBN the chances are they are consistent. You can shade them as color triplets to check for mismatching discontinuities.

@glBug, from a casual glance that code seems to compute the binormal as the cross product of the normal and tangent vectors. This keeps things orthogonal in the coordinate frame because as I said before by definition the face normal is orthogonal to both derivatives, it also saves data bandwidth at the expense of shader instructions.

This goes back the my earlier observation that the real problem is the orthogonality of tangent and binormal vectors due to non orthogonal texture derivatives. It's a point of contention what the best approach is if applying non orthogonal coords to a non orthogonal frame vs orthogonal frame unless it's consistent with how the normal map was created (by raycasting in the same orthogonal frame), then your coords can be arbitrary with an orthogonal frame. With an aligned image and non orthogonal coords you have bad behavior and you have to pick the lesser of two evils, but this is probably a bit esoteric for this discussion.