# Tangent Space Mayhem

This topic is 4800 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

reading through tons of tutorials and sample code i tried everything but that stupid Tangent Space Matrix (TBN) does simply not work and i have no clue why. the current thing i have does this: (vertex program)
Quote:
 # compute the 3x3 transform from tangent space to object space ## matObjTan1 = normal % tangent; XPD matObjTan1.xyz, vertex.normal, vertex.texcoord[1]; ## matObjTan2 = normal; (alias) ## matObjTan0 = matObjTan1 % normal; XPD matObjTan0.xyz, matObjTan1, vertex.normal;
both the incoming normal and tangent are |x|=1 . my problem is that still it seems to not work. as trial-and-error gave me no solution i need somebody to give me a hint. thus what is true? 1) my code is correct (hence the error is somewhere else) 2) my code is not correct (hence what is wrong with it?) EDIT: my major problem here is also understanding the matrix. in this tutorial (http://www.blacksmith-studios.dk/projects/downloads/tangent_matrix_derivation.php) they use the 'inverse TBN', which i think i have here too, but they have 'negated' values in the matrix. reproducing those negated values though it looks even worse. i'm all out of ideas on this one, really.

##### Share on other sites
Although I've been using GLSL rather than the ASM shaders, I was having what sounds like a similar problem a while back. You might find it helpful too look through the post I made about it:

http://www.gamedev.net/community/forums/topic.asp?topic_id=347799

(EDIT: Please excuse the broken images. My webhost apparently decided to give me the finger, and I'm not quite sure why... *grumble*)

##### Share on other sites
nice try but that is not my problem. mirrored UVs do not seem to be a problem for me as i wrote a special 'file format' to deal with this in a very easy (for both coder and artist) way.

my problem is that using the shader i get strange lighting problems.

as you can see the tangent seems to be mal-used. the normals and the lighting equations are all ok. if i render only with normals not using normal-mapping and TBN it looks ok (as ok as it can look with gourad shading only). using TBN and company things are broken.

##### Share on other sites
maybe there is problem in ur model's vertices or maybe there is problem in ur calculating the normals ...
try simple modle like sphere .
cya,
ff8

##### Share on other sites
I have to agree with ff8, but your normals look fine, just flat, try smoothing them out.

##### Share on other sites
Actually the toes look like the normals are a little screwed ;)

##### Share on other sites
Hm... First of all I want to compliment you on the image. Looks quite good, even with a few errant normals!

Second, are you orthogonalizing the tangents with the normal? I got similar artifacts when I disabled orthogonalization in my code.

//Orthoganalize the vectorscVect3 tmpTan = curVert.tangent;cVect3 tmpNorm = curVert.normal;cVect3 tmpBitan = curVert.bitangent;cVect3 newT = tmpTan -  ( tmpNorm * tmpNorm.Dot(tmpTan) );cVect3 newB = tmpBitan - ( tmpNorm * tmpNorm.Dot(tmpBitan) ) - ( newT * newT.Dot(tmpBitan) );newT.Normalize();newB.Normalize();curVert.tangent = newT;curVert.bitangent = newB;

##### Share on other sites
@all: nope, the normals are ok. turning on normal/tangent display shows both normals and tangents are perfect. furthermore i said that with normals only things look like they should (with normals only). hence i am 100% sure the normals are not the problem

@Toji: thx for the flowers... but there is more wrong with the graphics than just the tangent-problem (namely, shadow-volumes still create lot of troubles).

what i do is the following.

for my model i calculate on each frame (i don't know if 'skinning' normals/tangents is that much of a good idea speed wise) a face tangent and normals (normals are indexed in the face corners and not the same as positions). those normals and tangents are then normalized. i checked them beeing ok with graphical output not shown on the image and they are perfect.

the face tangent is calculated using (i think the same forumale you use) using a formula from this page with a slight alteration (which deals with the 'mirroring' problem).

now for the corners this yields a normal/tangent pair which is not necessary orthogonal, hence i orthogonalize them in my vertex-shader (to not waste CPU time on this one).

in general the algorithme seems to work as the terrain patches (the wall and ground) do look ok and have the normal-maps working. for those patches i use the same approach for calculating the tangents as for my objects.

now what i don't get is though why the output looks so crappy. if you look closely you see that the foot is outside the light range (ground is only ambient light), but still receives nearly full light strength at some places. so far i have seen this phenomena only if the TBN matrix is not normalized, but this is what i don't get. my input normal and tanget are both normalized and crossing them should yield again vectors of unit length. i also normalized the matrix explecitly afterwards and still have the same effect.

my vertex-program does this (beware, comments are old and off at some places).
!!ARBvp1.0## OpenGL Graphic Module Vertex Program## Copyright (C) 2004, Plüss Roland ( roland@rptd.dnsalias.net )# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later # version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the# GNU General Public License for more details.# # You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.## input data##############ATTRIB inPos = vertex.position;					# position object spaceATTRIB inColor = vertex.color.primary;			# white (+ alpha)ATTRIB inTexPos = vertex.texcoord[0];			# texture coordinatesATTRIB inNormal = vertex.normal;				# face normal object spaceATTRIB inTangent = vertex.texcoord[1];			# face tangent in object space# output data###############OUTPUT outHPos = result.position;				# homogenous positionOUTPUT outColor = result.color.front.primary;	# color * (ambient + emissive)OUTPUT outTexPos = result.texcoord[0];			# texture coordinatesOUTPUT outLightDir = result.texcoord[1];		# light-pos tangent spaceOUTPUT outHalfDir = result.texcoord[2];			# half(lightdir+eye-pos) tangent spaceOUTPUT outAtten = result.texcoord[3];			# attenuation# constants############## eyePARAM pEyePos = program.local[0];	# eye position in object space# lightPARAM pLightPos = program.local[1];	# object spacePARAM pLightDir = program.local[2];	# object spacePARAM pLightColor = program.local[3];PARAM pLightOptions = program.local[4];	# type, power, cutoff, spotexp# opengl states#################PARAM pMatTex1[4] = { state.matrix.texture[0] };PARAM pMatMVP[4] = { state.matrix.mvp };# variables#############TEMP matObjTan0, matObjTan1, lightDir, t1, t2;ATTRIB matObjTan2 = vertex.normal;# calculate texture coordinates## outTexPos = oglMatTex1 * inTexPosDPH outTexPos.x, inTexPos, pMatTex1[0];DPH outTexPos.y, inTexPos, pMatTex1[1];# color is in_color## outColor = inColor;MOV outColor, inColor;# compute the 3x3 transform from tangent space to object space## matObjTan1 = normal % tangent;XPD matObjTan1.xyz, vertex.normal, vertex.texcoord[1];## matObjTan2 = normal; (alias)## matObjTan0 = matObjTan1 % normal;XPD matObjTan0.xyz, matObjTan1, vertex.normal;# calculate light vector## outLightDir.xyz = matObjTan * (lightPos - inPos).xyz;SUB t1, pLightPos, inPos;DP3 lightDir.x, matObjTan0, t1;DP3 lightDir.y, matObjTan1, t1;DP3 lightDir.z, matObjTan2, t1;MOV outLightDir, lightDir;DP3 lightDir.w, lightDir, lightDir;MOV outAtten.x, lightDir.w;RSQ lightDir.w, lightDir.w;MUL lightDir.xyz, lightDir, lightDir.w;# half light-view vector## outHalfDir.xyz = ( outLightDir.xyz + (matObjTan * (eyePos.xyz-inPos.xyz) ) * 0.5;SUB t1, pEyePos, inPos;DP3 t2.x, matObjTan0, t1;DP3 t2.y, matObjTan1, t1;DP3 t2.z, matObjTan2, t1;DP3 t2.w, t2, t2;RSQ t2.w, t2.w;MAD t1.xyz, t2, t2.w, lightDir;MUL outHalfDir.xyz, t1, 0.5;# attenuation## outAtten.x = outLightDir.xyz * outLightDir.xyz;# done above# transform the vertex with the matrix## outHPos = oglMatProj * (oglMatMdl * inPos);DPH outHPos.x, inPos, pMatMVP[0];DPH outHPos.y, inPos, pMatMVP[1];DPH outHPos.z, inPos, pMatMVP[2];DPH outHPos.w, inPos, pMatMVP[3];# end of programEND

##### Share on other sites
Your tangents must be well conditioned across the triangle surface. This means that across any edge of a triangle, your tangent should not change direction very drastically (within a couple of degrees eg. 10-30 is normally fine)

A good way to visually inspect this is to render your tangents at each vertex as lines (as you would do with normals) and inspect the areas that are giving you problems. You will probably find cases where 2 neighbouring verts have wildly varying tangents.

Hope that helps...

##### Share on other sites
i rendered with normal/tangents shown and in the the problem areas outlined the tangents are (after normalizing) less than 1° apart from each other. i don't think that's the problem.

1. 1
2. 2
Rutin
16
3. 3
4. 4
5. 5

• 26
• 11
• 9
• 9
• 11
• ### Forum Statistics

• Total Topics
633702
• Total Posts
3013452
×