# OpenGL Tangent computation problem

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

## Recommended Posts

I've followed Eric Lengyel's method exposed OpenGL thread and it works under certain texture coordinates. I observed that sometimes tangent vectors are not being computed correctly, as you can see in this image. The key is: normals(blue), tangents(red) and bitangents (green). Lighting in object is not from tangent space, is object space per-pixel lighting (the one i want to improve with tangent space when it works). I don't know what's up with tangents, so if you can give some light on it, let me know. Thanks.

##### Share on other sites
Oh, man...
You know, Eric's method computes TS only per-triangle - all the real problems begin just after that. Converting per-triangle information to per-vertex one is the real killer for all TS computators. Just averaging don't work in a fraction of cases, and it matters - where you have mirrored and not-mirrored triangles meeting in adjacent vertex and so on.
Try NVMeshMender library - it gives somewhat correct result, if your meshes aren't completely crazy of course...
Or one method, is to collect all triangle TS-s in a vertex, then invert mirrored ones, then average and then split the vertex in two - for normal and for mirrored triangles. Then just copy the averaged TS in the normal vertex, then in averaged one and invert it back.

##### Share on other sites
Here's my implementation (rather the same as Eric's):

void Mesh::ComputeTangentSpaceMatrices ( ){	Vector3 *pkSTangents;	pkSTangents = new Vector3[m_uiNumVertices*2];	memset( pkSTangents, 0, sizeof(Vector3)*m_uiNumVertices*2);	Vector3 *pkTTangents = &pkSTangents[m_uiNumVertices];	m_pkTangents = new Vector3[m_uiNumVertices];	m_pkBitangents = new Vector3[m_uiNumVertices];	// sustituir el 0 por el canal que corresponda al normalmap	Vector2 *pkTexCoords = (Vector2 *)m_apkTexCoords[0];	if ( !pkTexCoords )		return;		for ( unsigned int uiT=0; uiT<m_uiNumFaces; uiT++ )	{		unsigned int uiI1 = m_pusIndices[uiT + 0];		unsigned int uiI2 = m_pusIndices[uiT + 1];		unsigned int uiI3 = m_pusIndices[uiT + 2];		Vector3 &rkV1 = m_pkVertices[uiI1];		Vector3 &rkV2 = m_pkVertices[uiI2];		Vector3 &rkV3 = m_pkVertices[uiI3];		Vector2 &rkT1 = pkTexCoords[uiI1];		Vector2 &rkT2 = pkTexCoords[uiI2];		Vector2 &rkT3 = pkTexCoords[uiI3];		Vector3 kEdge1 = rkV2 - rkV1;		Vector3 kEdge2 = rkV3 - rkV1;		Vector2 kTex1  = rkT2 - rkT1;		Vector2 kTex2  = rkT3 - rkT1;				float   fInvDet = 1.0f/(kTex1.x * kTex2.y - kTex1.y * kTex2.x );		Vector3 kSDir( (kTex2.y * kEdge1.x - kTex1.y * kEdge2.x) * fInvDet, 									 (kTex2.y * kEdge1.y - kTex1.y * kEdge2.y) * fInvDet, 									 (kTex2.y * kEdge1.z - kTex1.y * kEdge2.z) * fInvDet ); 		Vector3 kTDir( (kTex1.x * kEdge2.x - kTex2.x * kEdge1.x) * fInvDet, 									 (kTex1.x * kEdge2.y - kTex2.x * kEdge1.y) * fInvDet, 									 (kTex1.x * kEdge2.z - kTex2.x * kEdge1.z) * fInvDet ); 		pkSTangents[uiI1] += kSDir;		pkSTangents[uiI2] += kSDir;		pkSTangents[uiI3] += kSDir;		pkTTangents[uiI1] += kTDir;		pkTTangents[uiI2] += kTDir;		pkTTangents[uiI3] += kTDir;	}	for ( unsigned int uiV=0; uiV<m_uiNumVertices; uiV++ )	{		Vector3 &rkNormal			= m_pkNormals[uiV];		Vector3 &rkAuxTangent = pkSTangents[uiV];		float		 fHandedness  = ((rkNormal ^ rkAuxTangent)*pkTTangents[uiV] < 0 ? -1.0f : 1.0f);				Vector3 kTangent = rkAuxTangent - rkNormal * (rkNormal*rkAuxTangent);		kTangent.Normalize();		Vector3 kBitangent = (rkNormal ^ kTangent) * fHandedness;		m_pkTangents[uiV]		= kTangent;		m_pkBitangents[uiV] = kBitangent;	}	delete [] pkSTangents;}

I think it's correct because it works if UV's are good enough, but there are meshes that cannot get that UV (unfolding, many parts, ...). I can see Eric's method computes the tangents per triangle, but then it adds up to that temporary S and T tangents array to get the average later. After that, it computes tangent/bitangent having into account handedness.

I debugged the code with a simple cube with smoothed faces (averaged normals) and noticed that for 3 of 12 triangles the inverse determinant is huge (determinant near zero).

##### Share on other sites
Quote:
 Original post by YengaMatiCHere's my implementation (rather the same as Eric's):

It don't handle the case when mirrored and non-mirrored triangles meet at a vertex.

1. 1
Rutin
33
2. 2
3. 3
4. 4
5. 5

• 12
• 14
• 9
• 9
• 9
• ### Forum Statistics

• Total Topics
633338
• Total Posts
3011416
• ### Who's Online (See full list)

There are no registered users currently online

×