1
votes

I am trying to calculate a normal map from subdivisions of a mesh, there are 2 meshes a UV unwrapped base mesh which contains quads and triangles and a subdivision mesh that contains only quads.

Suppose a I have a quad with all the coordinates of the vertices both in object space and UV space (quad is not flat), the quad's face normal and a pixel with it's position in UV space.

Can I calculate the TBN matrix for the given quad and write colors to the pixel, if so then is it different for quads?

I ask this because I couldn't find any examples for calculating a TBN matrix for quads, only triangles ?

1
I'm not sure if it is possible to calculate a consistent tangent space for a general quad. In the blender source code and the documentation there is a little bit of explanation, but they are splitting quads into triangles for the calculation. The problem is, that a consistent tangent frame would have to be interpolated over the whole quad which means that it has to be continuous. But from what I understand, that's not the case.BDL
Just for completeness: Modern OpenGL does not support quads anymore. If you are not absolutely bound to an ancient version, use triangle meshes.BDL
i think it's the same the tbn is computed by resolving an equation using the deltaUV and deltaPos between 2 points. In the case of your quad you have 3 points availables. I would suggest to avoid picking the point in the opposite corner for non planar quads like blender seems to do.Paltoquet
In openGL, quads must be coplanar: The four vertices are expected to be coplanar; failure to do so can lead to undefined results. A quad is typically rasterized as a pair of triangles. This is not defined by the GL spec, but it is allowed by it. This can lead to some artifacts due to how vertex/geometry shader outputs are interpolated over the 2 generated triangles. (khronos.org/opengl/wiki/Primitive)Amadeus
I will use another 3'rd mesh that is the triangulated version of the subdivision mesh, to compute good normals rather that doing imprecise calculations.Macelaru Tiberiu

1 Answers

4
votes

Before answering your question, let me start by explaining what the tangents and bitangents that you need actually are.

Let's forget about triangles, quads, or polygons for a minute. We just have a surface (given in whatever representation) and a parameterization in form of texture coordinates that are defined at every point on the surface. We could then define the surface as: xyz = s(uv). uv are some 2D texture coordinates and the function s turns these texture coordinates into 3D world positions xyz. Now, the tangent is the direction in which the u-coordinate increases. I.e., it is the derivative of the 3D position with respect to the u-coordinate: T = d s(uv) / du. Similarly, the bitangent is the derivative with respect to the v-coordinate. The normal is a vector that is perpendicular to both of them and usually points outwards. Remember that the three vectors are usually different at every point on the surface.

Now let's go over to discrete computer graphics where we approximate our continuous surface s with a polygon mesh. The problem is that there is no way to get the exact tangents and bitangents anymore. We just lost to much information in our discrete approximation. So, there are three common ways how we can approximate the tangents anyway:

  1. Store the vectors with the model (this is usually not done).
  2. Estimate the vectors at the vertices and interpolate them in the faces.
  3. Calculate the vectors for each face separately. This will give you a discontinuous tangent space, which produces artifacts when the dihedral angle between two neighboring faces is too big. Still, this is apparently what most people are doing. And it is apparently also what you want to do.

Let's focus on the third method. For triangles, this is especially simple because the texture coordinates are interpolated linearly (barycentric interpolation) across the triangle. Hence, the derivatives are all constant (it's just a linear function). This is why you can calculate tangents/bitangents per triangle.

For quads, this is not so simple. First, you must agree on a way to interpolate positions and texture coordinates from the vertices of the quad to its inside. Oftentimes, bilinear interpolation is used. However, this is not a linear interpolation, i.e. the tangents and bitangents will not be constant anymore. This will only happen in special cases (if the quad is planar and the quad in uv space is a parallelogram). In general, these assumptions do not hold and you end up with different tangents/bitangents/normals for every point on the quad.

One way to calculate the required derivatives is by introducing an auxiliary coordinate system. Let's define a coordinate system st, where the first corner of the quad has coordinates (0, 0) and the diagonally opposite corner has (1, 1) (the other corners have (0, 1) and (1, 0)). These are actually our interpolation coordinates. Therefore, given an arbitrary interpolation scheme, it is relatively simple to calculate the derivatives d xyz / d st and d uv / d st. The first one will be a 3x2 matrix and the second one will be a 2x2 matrix (these matrices are called Jacobians of the interpolation). Then, given these matrices, you can calculate:

d xyz / d uv = (d xyz / d st) * (d st / d uv) = (d xyz / d st) * (d uv / d st)^-1

This will give you a 3x2 matrix where the first column is the tangent and the second column is the bitangent.