Help fixing tangents

Started by
6 comments, last by mmikkelsen 12 years, 3 months ago
I'm working on a DirectX engine that is basically a testbed for some shaders and I've got a problem with my tangents on this model. I decimated it in Zbrush and exported an obj file.

Here's what it looks like with a color and normal map: colorhead2.png

Here's what the tangents look like when drawn to the color channel: tangenthead2.png

And here's what my tangent generation code looks like:


//do the bitangent and tangent crap
VectorType sdir, tdir;
TempVertexType vertex1, vertex2, vertex3;
int counter = 0;
unsigned long i1 = 0, i2 = 0, i3 = 0;

//this is all for the tangents
VectorType* tan1 = new VectorType[m_vertexCount * 2];
VectorType* tan2 = tan1 + m_vertexCount;
ZeroMemory(tan1, m_vertexCount * sizeof(VectorType) * 2);

for(unsigned int i = 0; i < m_indexCount; i++)
{
// get vertex1, vertex2 & vertex3
// Get the three vertices for this face from the model.
i1 = indices;
i++;

i2 = indices;
i++;

i3 = indices;

vertex1.x = m_model[i1].x;
vertex1.y = m_model[i1].y;
vertex1.z = m_model[i1].z;
vertex1.tu = m_model[i1].tu;
vertex1.tv = m_model[i1].tv;
vertex1.nx = m_model[i1].nx;
vertex1.ny = m_model[i1].ny;
vertex1.nz = m_model[i1].nz;

vertex2.x = m_model[i2].x;
vertex2.y = m_model[i2].y;
vertex2.z = m_model[i2].z;
vertex2.tu = m_model[i2].tu;
vertex2.tv = m_model[i2].tv;
vertex2.nx = m_model[i2].nx;
vertex2.ny = m_model[i2].ny;
vertex2.nz = m_model[i2].nz;

vertex3.x = m_model[i3].x;
vertex3.y = m_model[i3].y;
vertex3.z = m_model[i3].z;
vertex3.tu = m_model[i3].tu;
vertex3.tv = m_model[i3].tv;
vertex3.nx = m_model[i3].nx;
vertex3.ny = m_model[i3].ny;
vertex3.nz = m_model[i3].nz;

sdir.x = 0;
sdir.y = 0;
sdir.z = 0;

tdir.x = 0;
tdir.y = 0;
tdir.z = 0;

// Calculate the tangent and bitangent of that face.
CalculateTangentBitangent(vertex1, vertex2, vertex3, sdir, tdir);

tan1[i1].x += sdir.x; tan1[i1].y += sdir.y; tan1[i1].z += sdir.z;
tan1[i2].x += sdir.x; tan1[i2].y += sdir.y; tan1[i2].z += sdir.z;
tan1[i3].x += sdir.x; tan1[i3].y += sdir.y; tan1[i3].z += sdir.z;

tan2[i1].x += tdir.x; tan2[i1].y += tdir.y; tan2[i1].z += tdir.z;
tan2[i2].x += tdir.x; tan2[i2].y += tdir.y; tan2[i2].z += tdir.z;
tan2[i3].x += tdir.x; tan2[i3].y += tdir.y; tan2[i3].z += tdir.z;
}

vector<int> handedness;
for (unsigned long a = 0; a < m_vertexCount; a++)
{
VectorType n;
n.x = vertexList[a].nx; n.y = vertexList[a].ny; n.z = vertexList[a].nz;

const VectorType& t = tan1[a];

// Gram-Schmidt orthogonalize
tempTangents.push_back(normalize((t - n * dot(n, t))));

// Calculate handedness
handedness.push_back( (dot(cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F );
}

//calculate bitangents
for (unsigned long a = 0; a < m_vertexCount; a++)
{
//B' = m(N × T')
VectorType tempN;
tempN.x = vertexList[a].nx; tempN.y = vertexList[a].ny; tempN.z = vertexList[a].nz;
tempBitangent.push_back(cross(tempN,tempTangents[a]) * handedness[a]);
}


Here's the CalculateTangentBitangent function:

void ModelClass::CalculateTangentBitangent(TempVertexType vertex1, TempVertexType vertex2, TempVertexType vertex3,
VectorType& sdir, VectorType& tdir)
{
float x1 = vertex2.x - vertex1.x;
float y1 = vertex2.y - vertex1.y;
float z1 = vertex2.z - vertex1.z;

float x2 = vertex3.x - vertex1.x;
float y2 = vertex3.y - vertex1.y;
float z2 = vertex3.z - vertex1.z;

float s1 = vertex2.tu - vertex1.tu;
float t1 = vertex2.tv - vertex1.tv;

float s2 = vertex3.tu - vertex1.tu;
float t2 = vertex3.tv - vertex1.tv;

float r = 1.0f / (s1 * t2 - s2 * t1);

sdir.x = (t2 * x1 - t1 * x2) * r;
sdir.y = (t2 * y1 - t1 * y2) * r;
sdir.z = (t2 * z1 - t1 * z2) * r;

tdir.x = (s1 * x2 - s2 * x1) * r;
tdir.y = (s1 * y2 - s2 * y1) * r;
tdir.z = (s1 * z2 - s2 * z1) * r;
}


Any ideas on how I can fix this?

Edit: The tangents looked a lot worse before, but I deleted some internal geometry in the model that didn't need to be there and for some reason this fixed a lot of the problems with the tangents. They still aren't that smooth though, and there are some artifacts I'd like to get rid of if possible.
Show me a sane man and I will cure him for you.
Advertisement

I'm working on a DirectX engine that is basically a testbed for some shaders and I've got a problem with my tangents on a model I exported from Zbrush.


You just exported that from zbrush? amazing how much it looks like the one that was donated here --> http://www.ir-ltd.net/infinite-3d-head-scan-released
:)

Anyway, you could try out using an existing tangent space generator such as the one that is used in xNormal? The code is in the examples folder of the sdk
but also available and described here --> http://wiki.blender.org/index.php/Dev:Shading/Tangent_Space_Normal_Maps
It's very easy to integrate one .h and one .c file. No dependencies.



[quote name='Icetigris' timestamp='1322005660' post='4886714']
I'm working on a DirectX engine that is basically a testbed for some shaders and I've got a problem with my tangents on a model I exported from Zbrush.


You just exported that from zbrush? amazing how much it looks like the one that was donated here --> http://www.ir-ltd.ne...d-scan-released
:)

Anyway, you could try out using an existing tangent space generator such as the one that is used in xNormal? The code is in the examples folder of the sdk
but also available and described here --> http://wiki.blender....ace_Normal_Maps
It's very easy to integrate one .h and one .c file. No dependencies.



[/quote]

Yeah, I used that model, I needed to decimate it though, so I used their Zbrush file and exported an obj file. I'm not trying to claim it as my own work. I edited my original post to make that more clear.

I will try using xNormal, though I would really like to know what I'm doing wrong.
Show me a sane man and I will cure him for you.

Yeah, I used that model, I needed to decimate it though, so I used their Zbrush file and exported an obj file. I'm not trying to claim it as my own work. I edited my original post to make that more clear.

I will try using xNormal, though I would really like to know what I'm doing wrong.




I know you weren't saying the model was proprietary work. I was just pulling your chain :)

Perhaps you could show the unwrap? I'd like to see the texture coordinates to that model (visually).
One thing you are doing wrong is you are assuming that triangles with different winding
in UV-space never share texture coordinates (since you don't generate any splits).
But this is clearly not the only issue.





I know you weren't saying the model was proprietary work. I was just pulling your chain :)

Perhaps you could show the unwrap? I'd like to see the texture coordinates to that model (visually).
One thing you are doing wrong is you are assuming that triangles with different winding
in UV-space never share texture coordinates (since you don't generate any splits).
But this is clearly not the only issue.



Here's the texture that came with the model: zheadcolor.png

When you talk about the winding issue, is that part of the facet problem, or the texture seam problem? I'm not especially worried about the texture seams blending nicely at the moment, I just want to get rid of the random facets.
Show me a sane man and I will cure him for you.

When you talk about the winding issue, is that part of the facet problem, or the texture seam problem? I'm not especially worried about the texture seams blending nicely at the moment, I just want to get rid of the random facets.


Perhaps you could just make the version of the mesh you are using to calculate tangent spaces for available online? I realize I can get the model online obviously but I mean the version you are currently doing these experiments with.
This is assuming of course it's in a format I'd be able to read and not something proprietary.

Cheers,

Morten.
Here's the link to the model, color map, and normal map I'm using:
http://www.mediafire.com/?pjb9x2zig4qimnm,n2aiqqnuluuzx8u,u5rykzra1x8tsxz

As an interesting sidenote, I tried loading this model in 3ds Max and using their implementation of a tangent-space normal map shader and it too had the same faceting issue.
Show me a sane man and I will cure him for you.
In that case you probably just need to weld the vertices. This is one of the issues discussed here --> http://wiki.blender.org/index.php/Dev:Shading/Tangent_Space_Normal_Maps

This topic is closed to new replies.

Advertisement