5

This is related to a problem described in another question (images there):

Opengl shader problems - weird light reflection artifacts

I have a .obj importer that creates a data structure and calculates the tangents and bitangents. Here is the data for the first triangle in my object:

Data Structure

My understanding of tangent space is that the normal points outward from the vertex, the tangent is perpendicular (orthogonal?) to the normal vector and points in the direction of positive S in the texture, and the bitangent is perpendicular to both. I'm not sure what you call it but I thought that these 3 vectors formed what would look like a rotated or transformed x,y,z axis. They wouldn't be 3 randomly oriented vectors, right?

Also my understanding: The normals in a normal map provide a new normal vector. But in tangent space texture maps there is no built in orientation between the rgb encoded normal and the per vertex normal. So you use a TBN matrix to bridge the gap and get them in the same space (or get the lighting in the right space).

But then I saw the object data... My structure has 270 vertices and all of them have a 0 for the Tangent Y. Is that correct for tangent data? Are these tangents in like a vertex normal space or something? Or do they just look completely wrong? Or am I confused about how this works and my data is right?

To get closer to solving my problem in the other question I need to make sure my data is right and my understanding on how tangent space lighting math works.

Community
  • 1
  • 1
badweasel
  • 2,349
  • 1
  • 19
  • 31
  • By definition, the 3 vectors are perpendicular. Of course they _can_ be non-perpendicular for a variety of reasons, but that will result in a sheared/distorted texture space. – Damon Mar 15 '13 at 13:59
  • So your vote is that my tangent data is wrong? – badweasel Mar 15 '13 at 14:16
  • 1
    Bitangent and normal being identical looks like something is wrong (at least it's very uncommon). It basically means that any texture samples you get back are on a line defined by the tangent vector. This will look really weird. – Damon Mar 15 '13 at 14:22
  • The Y's being all zero makes them all really 2 dimensional vectors. So what space is the tangent vector typically in? "tangent space" but what does that mean? Texture Image space? They shouldn't be in the plane that the triangle represents that the texture is being mapped to? I guess I have to recalculate them all myself and see how they compare. – badweasel Mar 16 '13 at 05:12

1 Answers1

10

The tangent and bitangent vectors point in the direction of the S and T components of the texture coordinate (U and V for people not used to OpenGL terms). So the tangent vector points along S and the bitangent points along T.

So yes, these do not have to be orthogonal to either the normal or each other. They follow the direction of the texture mapping. Indeed, that's their purpose: to allow you to transform normals from model space into the texture's space. They define a mapping from model space into the space of the texture.

The tangent and bitangent will only be orthogonal to each other if the S and T components at that vertex are orthogonal. That is, if the texture mapping has no sheering. And while most texture mapping algorithms will try to minimize sheering, they can't eliminate it. So if you want an accurate matrix, you need a non-orthogonal tangent and bitangent.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • But what about the data excerpt shown there. The bitangent on vertex 2 is the same as the normal. Does that seem correct? And.. all the tangent y's are zero? That doesn't seem right either does it? – badweasel Mar 15 '13 at 14:15
  • @badweasel: I can't control what this program generates; I can only tell you what the correct answer ought to be. You'll have to look through your data to see if that fits what you're getting. – Nicol Bolas Mar 16 '13 at 00:18
  • I'm waiting to accept it as an answer since I'm getting conflicting info. See my comment on my question. In your experience to tangents typically have a zero Y when they're mapped to a sphere? Ignoring my data for a minute to assume it's wrong.. is the tangent in the space/coordinate system of the 2d texture, or of the plane that is created by the triangle? – badweasel Mar 16 '13 at 05:15
  • Also, your answer is that they DO NOT have to be orthogonal to each other but most tutorials on writing bump map shaders calculate the bitangent = cross (normal, tangent). So does ever tutorial on how to do this assume that your texture won't have any shearing, cause that seems like it would be a wildly inaccurate assumption in most real applications. – badweasel Mar 16 '13 at 05:17
  • @badweasel: Most tutorials don't really care. As long as the result is "good enough", they're willing to leave it at that. Also, you shouldn't feel pressure to accept an answer that you don't feel answers your question well enough. – Nicol Bolas Mar 16 '13 at 07:07
  • @badweasel: "*is the tangent in the space/coordinate system of the 2d texture, or of the plane that is created by the triangle?*" It is neither. The tangent is in the same space as the normal, which is usually model space. The tangent points in the direction that the S texture coordinate component is moving in. – Nicol Bolas Mar 16 '13 at 07:08
  • 2
    In other words, when working out the tangent vectors at a vertex, you typically use vectors representing the adjacent edges in both texture-space, and model-space, in order to map one to the other. There is a good write-up here: http://www.terathon.com/code/tangent.html – JasonD Mar 16 '13 at 07:21
  • @JasonD but even that code just takes the cross product of norm and tan to get bitan. it doesn't calculate bitan on its own from the texture s and t. The answer (not written by you I know) says that tan and bitan will only be orthogonal if s and t are. Then why not calculate bitan based on the direction of t and s? No one does that and most shaders recreate bitan using cross(). – badweasel Mar 17 '13 at 12:22
  • @badweasel: "*Then why not calculate bitan based on the direction of t and s?*" The given site does exactly that; it's in the math part at the top of the page. It later says, "It is not necessarily true that the tangent vectors are perpendicular to each other or to the normal vector [...] It is safe to assume, however, that the three vectors will at least be close to orthogonal". The accuracy of the last part is for you to decide, and rather depends on your mesh. – Nicol Bolas Mar 17 '13 at 12:27
  • @badweasel: "*No one does that*" ***I*** do that. The fact that others try to avoid it doesn't mean that it is *right* for them to do so. If you want your bump mapping to be *correct*, you use 3 vectors. If you want your bump mapping to be "maybe good enough, maybe not," you use a cross-product. People online generally don't care about correctness. – Nicol Bolas Mar 17 '13 at 12:30
  • Ok thanks. I'm not as good at reading math formulas as I am reading code. So I had skimmed the text and skipped to the code and ported it to objective c and my data structure. Can you clarify in your answer that they're generally close to orthogonal: " It is safe to assume, however, that the three vectors will at least be close to orthogonal, so using the Gram-Schmidt algorithm to orthogonalize them should not cause any unacceptable distortions." And then I'll accept your answer. Cause I had read it that they could be any 3 vectors and that wouldn't make a good transformation matrix. Thanks! – badweasel Mar 17 '13 at 12:39
  • @badweasel: No. *I don't agree with that*. I consider that kind of thinking dangerous. I don't care how many people online use the cross-product hack; the mathematically correct thing to do is pass 3 vectors. Period. – Nicol Bolas Mar 17 '13 at 12:41
  • Interesting. Ok. I'm going to try it again in my code with taking out the gram-Schmidt and just normalizing the vector. And see how that looks. I'll have to figure out how to add code to calc the bitan though. – badweasel Mar 17 '13 at 12:44
  • @NicolBolas: Part of your comments here ought to be included in your answer, as it may be helpful to many people. Another thing you should put in your answer: How does someone calculate the "correct" bitangent, if not the cross product? Is it as simple as swapping S and T in [this page](http://www.terathon.com/code/tangent.html) and treating the recalculated "tangent" as the bitangent? – Peter O. Jun 13 '15 at 12:49