Tangent space is broken
-
- Posts: 322
- Joined: Tue Aug 30, 2005 10:34 am
- Location: slovakia
Tangent space is broken
I don't know wheather this is caused by my shader, but the shader displays normals and texture coordinates properly. but with tangetns or binormals I get very weird results. If this is really a bug, then it will be a very annoing fact about irrlicht making me so sad, I just hope it is the shader
see 4 yourself http://www.medeal.sk/irr/displaynormals.zip
here is what displayed normals looks like
here is what displayed binormals looks like
see 4 yourself http://www.medeal.sk/irr/displaynormals.zip
here is what displayed normals looks like
here is what displayed binormals looks like
what is this thing...
-
- Posts: 322
- Joined: Tue Aug 30, 2005 10:34 am
- Location: slovakia
OK, I just got an serious doubt about createMesheWithTangents() function, since the function doesn't only calculate tangets and bitangents but also changes the normals... see pic, the teapot on the left and room are tangent meshes, the teapot on the right is not tangetmesh,
theese are displayed normals, why has tangent mesh different normals? should it have?
theese are displayed tangents, yes there is a difference
so should normals of a mesh change after it becoms tangent mesh? I doubt that.
theese are displayed normals, why has tangent mesh different normals? should it have?
theese are displayed tangents, yes there is a difference
so should normals of a mesh change after it becoms tangent mesh? I doubt that.
what is this thing...
-
- Posts: 377
- Joined: Fri Oct 28, 2005 10:28 am
- Contact:
-
- Posts: 322
- Joined: Tue Aug 30, 2005 10:34 am
- Location: slovakia
-
- Posts: 377
- Joined: Fri Oct 28, 2005 10:28 am
- Contact:
Well, question is whether they have texture coordinates at all. That you have two teapots, doesn't matter here, as the createMeshWithTangents changes normals, as you said. And it also doesn't matter, that you have no normal map . If you don't have a normal map, then why do you create tangent space bases? They only make sense with some accordingly aligned normal map, or some other effect map, that is in tangent space.
So to properly rephrase my question: Does the teapot have texture coordinates defined? If they are all zero, then the result of createMesheWithTangents is undefined basically, which perfectly explains your results.
So to properly rephrase my question: Does the teapot have texture coordinates defined? If they are all zero, then the result of createMesheWithTangents is undefined basically, which perfectly explains your results.
-
- Posts: 322
- Joined: Tue Aug 30, 2005 10:34 am
- Location: slovakia
the teapots have texture coordinates defined, yes, the teapots were exported with their texture coordinates, you can display them as well in the shader and see how the texture is maped on the mesh... (did you run the program? it makes me ask)... the room has the the normal map aplied but the teapots don't. To be as objective as it could the thing is as follows:
room - a 3ds mesh with 2 texture layer(diffuse and normal) with texture coords, it is made a tangentMesh
teapot - an X mesh with 1 layer texture with texture coords, one of the teapots is made Tanget mesh, the second one is not
but there is no need to have a normal map layer on a mesh if you want to create a tangent space on it, you map the mesh's normals always, not normals in normal map.. thats why you dont need a normal map when you apply createMeshWithTangents() as well, ...
room - a 3ds mesh with 2 texture layer(diffuse and normal) with texture coords, it is made a tangentMesh
teapot - an X mesh with 1 layer texture with texture coords, one of the teapots is made Tanget mesh, the second one is not
but there is no need to have a normal map layer on a mesh if you want to create a tangent space on it, you map the mesh's normals always, not normals in normal map.. thats why you dont need a normal map when you apply createMeshWithTangents() as well, ...
what is this thing...
-
- Posts: 322
- Joined: Tue Aug 30, 2005 10:34 am
- Location: slovakia
-
- Posts: 206
- Joined: Thu Sep 01, 2005 9:26 pm
- Location: France
if you do that, make sure that the resulting TBN matrix still defines an orthagonal coordinate system
What I did in lightfeather was compute averaged (smooth) normals rather than just setting all vertices to the per-tri normal as irrlicht currently does
What I did in lightfeather was compute averaged (smooth) normals rather than just setting all vertices to the per-tri normal as irrlicht currently does
You do a lot of programming? Really? I try to get some in, but the debugging keeps me pretty busy.
Crucible of Stars
Crucible of Stars
-
- Posts: 101
- Joined: Wed Feb 15, 2006 4:22 pm
- Location: RO
Some problems I see, or maybe I am wrong:
1] If you smooth the tangent/bi tangent per vertex you don't lost the orthonormal basis? (no more 90)
2] How do I know what are the correct tangent/bi tangent when I use the NormalMaps generate my NVidia Tool (Melody) or ATI Normal Mapper?
3) I sow somewhere that I must flip the y (green) channel of the NormalMap (NVidai Melody)? Why is that?
So pls can anyone clarify me about this? (Normal mapping in ObjectSpace works OK but I don't need any tangent/bi tangent)
Is anyone who had correct calculated the normal/tangent/bitagent for TangetSpace? (normal-maps generated but ATI NormalMapper or NVIDIA Melody)
Computing tangents on GameDev
1] If you smooth the tangent/bi tangent per vertex you don't lost the orthonormal basis? (no more 90)
2] How do I know what are the correct tangent/bi tangent when I use the NormalMaps generate my NVidia Tool (Melody) or ATI Normal Mapper?
3) I sow somewhere that I must flip the y (green) channel of the NormalMap (NVidai Melody)? Why is that?
So pls can anyone clarify me about this? (Normal mapping in ObjectSpace works OK but I don't need any tangent/bi tangent)
Is anyone who had correct calculated the normal/tangent/bitagent for TangetSpace? (normal-maps generated but ATI NormalMapper or NVIDIA Melody)
Computing tangents on GameDev
blog :] http://redcloud.no-ip.info/
I am NOT an expert on bump/normalmapping or tangent space, but I did struggle through doing the TBN matrix calculations for Lightfeather, so I'll post me code here in the hopes that it may be some help. I drew heavily on niko's code for the texture-gradient calculations, but the main difference in my code is that while I do recompute normals, they should be smooth normals. My grasp on the concepts is a tad tenuous though, so I make no guarantee that the following code is perfect. Also note that since this is Lightfeather code it is not directly compatible with Irrlicht. The concept, however, should transfer easily. Note that while I believe orthonality is maintained, I have not done any detailed analysis to confirm this.
[/code]
Code: Select all
//! computes the tangents for a mesh buffer. If either parameter is false, that tangent will not
//! be computed.
//! to make sure that the TBN matrix will have 3 mutually orthagonal axes,
//! we need to recompute normals. It is possible that a solution could be devised
//! which does not need to recompute normals, but this is easiest
//! \param sTangent: create with s tangents (tangents)
//! \param tTangent: create with t tangents (binormals)
void CMeshBuffer::calculateTangents(bool sTangents, bool tTangents)
{
/* TODO (electron): Clean up this function and figure out what's going on,
what calculations are necessary We assume CW trianglewinding, which is
rather bad form. The CCW winding code is commented out below
but untested*/
//first we zero out all normals and tangents
u32 cnt=vertexBuffer->getVertexCount();
core::vector3df vecZero(0,0,0);
for(u32 i = 0;i < cnt;i++)
{
vertexBuffer->setNormal(i,vecZero);
if(sTangents)
{
vertexBuffer->setTangentS(i,vecZero);
}
if(tTangents)
{
vertexBuffer->setTangentT(i,vecZero);
}
}
//we loop through all triangles and add
//the normals and tangents for each triangle a vertex belongs to
for(u32 i = 0;i < indexBuffer->getIndexCount() - 2;i += 3)
{
u32 idx0 = indexBuffer->getIndex32Safe(i);
u32 idx1 = indexBuffer->getIndex32Safe(i + 1);
u32 idx2 = indexBuffer->getIndex32Safe(i + 2);
calculateTangentsForVertex(idx0,idx1,idx2,sTangents,tTangents);
calculateTangentsForVertex(idx1,idx2,idx0,sTangents,tTangents);
calculateTangentsForVertex(idx2,idx0,idx1,sTangents,tTangents);
//calculateTangentsForVertex(idx2,idx1,idx0,sTangents,tTangents);
//calculateTangentsForVertex(idx1,idx0,idx2,sTangents,tTangents);
//calculateTangentsForVertex(idx0,idx2,idx1,sTangents,tTangents);
}
//normalize all normals and tangents
for(u32 i = 0;i < vertexBuffer->getVertexCount();i++)
{
core::vector3df vec=vertexBuffer->getNormal(i);
vec.normalize();
vertexBuffer->setNormal(i,vec);
vec=vertexBuffer->getNormal(i);
if(sTangents)
{
vec=vertexBuffer->getTangentS(i);
vec.normalize();
vertexBuffer->setTangentS(i,vec);
}
if(tTangents)
{
vec=vertexBuffer->getTangentT(i);
vec.normalize();
vertexBuffer->setTangentT(i,vec);
}
}
}
void CMeshBuffer::calculateTangentsForVertex(u32 idx0,u32 idx1, u32 idx2,bool sTangents, bool tTangents)
{
//i know the vertex and index buffer is slow here
//with different types and data sizes this is the easiest and safest way, but it might
//might be worthwhile to implement this a faster way
//Irrlicht calcualtes matrix seperately for each evertex in a triangle
//but should probably be safe to do it once per triangle. I'm sticking with
//Irrlicht's way for now though
core::vector3df vtx1=vertexBuffer->getPosition(idx0);
core::vector3df vtx2=vertexBuffer->getPosition(idx1);
core::vector3df vtx3=vertexBuffer->getPosition(idx2);
core::position2d<f32> t1=vertexBuffer->getTextureCoord(idx0,0);
core::position2d<f32> t2=vertexBuffer->getTextureCoord(idx1,0);
core::position2d<f32> t3=vertexBuffer->getTextureCoord(idx2,0);
//the following code is adapted from code in the
//Irrlicht engine by Nikolaus Gebhardt
//and from code given at http://www.paulsprojects.net/tutorials/simplebump/simplebump.html
core::vector3df v1 = vtx1 - vtx2;
core::vector3df v2 = vtx3 - vtx1;
core::vector3df normal = v2.crossProduct(v1);
//I believe it would be better (in terms of smoothness) to normalize only at the end of adding in all
//the normals from the different triangles a vertex is part of
//but to retain orthagonality with the tangents
//I believe it is imperative that we normalize here,
//though its something to look into
normal.normalize();
// binormal (t tangent)
f32 deltaX1 = t1.X - t2.X;
f32 deltaX2 = t3.X - t1.X;
core::vector3df tTangent = (v1 * deltaX2) - (v2 * deltaX1);
tTangent.normalize();
// tangent (s tangent)
f32 deltaY1 = t1.Y - t2.Y;
f32 deltaY2 = t3.Y - t1.Y;
core::vector3df sTangent = (v1 * deltaY2) - (v2 * deltaY1);
sTangent.normalize();
// adjust
core::vector3df txb = sTangent.crossProduct(tTangent);
if (txb.dotProduct(normal) < 0.0f)
{
sTangent *= -1.0f;
tTangent *= -1.0f;
}
vertexBuffer->setNormal(idx0,vertexBuffer->getNormal(idx0)+normal);
if(sTangents)
{
vertexBuffer->setTangentS(idx0,vertexBuffer->getTangentS(idx0)+sTangent);
}
if(tTangents)
{
vertexBuffer->setTangentT(idx0,vertexBuffer->getTangentT(idx0)+tTangent);
}
}
You do a lot of programming? Really? I try to get some in, but the debugging keeps me pretty busy.
Crucible of Stars
Crucible of Stars
-
- Posts: 322
- Joined: Tue Aug 30, 2005 10:34 am
- Location: slovakia
bones animatedmeshes doesn't change their UV texure cords during animation! Thanks to this fact, the way how to have correct tangent space on animated meshes is to normalize tangent and bitangent (the "bitangent is a vector orthogonal to normal as well as to tangent so I think the correct name should be bitangentnormal ") against the normal which changes during the animation, done in vertex shader.... I always had a problem of how to get theese UV axis (which get normalized to the normal and thus you get tangentU and bitangentV)for a smooth normal, becouse of faces list leading in the vertex and so. But your code helps a lot.
I am trying to achieve tangent space for animated meshes
I am trying to achieve tangent space for animated meshes
what is this thing...