3d graphics, unit vectors and orthogonal matrices
I'm trying to get my head wrapped around tangent space and I'm starting to come up with questions that I can't ask my colleagues be开发者_Go百科cause they're starting to have no idea what I'm talking about. I'm trying to do normal mapping on opengl. My current plan is to calculate the tangent-bitangent-normal matrix in a geometry shader.
- When I have an orthogonal matrix (such as the TBN matrix) and I let opengl interpolate it between vertices, are the three resulting vectors (T, B and N) then still unit length? are they still at a 90 deg angle to each other?
- When I multiply my (unit length) normal map sample with my orthogonal matrix, is the result guaranteed to be unit length too? I think it is but can't reason through it.
- I was thinking about using detail normal maps such that objects up close don't look as bad as they do now. That would mean that there's then two normal maps. How do I combine the two samples?
To reply to my own question, a colleague came over to work on #2 and he came up with an elegant proof. It's a bit much to type out here but suffice to say that it's true.
Since there are still not complete answers, I figured I'd have a go at it:
1) No and no. Imagine three vectors v1
, v2
and v3
that are pair-wise orthogonal and all unit-length. Then of course, -v3
is unit-length and also orthogonal to v1
and v2
. Now imagine the matrices A=(v1|v2|v3)
and B=(v2|v1|-v3)
. If you interpolate between the two, you will get C=((v1+v2)/2|(v1+v2)/2|0)
right in the middle. It's easy to see that this will not maintain length: (0 0 1)^T
will just become the zero-vector. Also, the first and second column will be equal, which means that their angle is 0°. In pratice, however, the two matrices you will be interpolating will usually not be different enough for such a degeneration. that is if your surface is orientable. Surfaces are orientable if you can define a consistent inside and outside on them. The moebius-strip is a common counter-example!
A slightly more correct way would be interpolate rotations (again, the surface needs to be orientable): you can either use spherical interpolation (google!) or normalized interpolation (interpolate the matrices and orthogonalize, but this will also fail with some fringe cases). However, both interpolations can be expensive - and in practice, people just transform the light source into the vertices' TBN coordinates and use linear interpolation (which is equivalent to just use linear interpolation on the TBN matrices).
2.) Definitely yes. In fact, this works for any length, not just one. Orthogonal matrices induce isomorphic mappings, which preserve both lengths and angles between vectors. The two kinds of transformations that you can define using such matrices are rotations and mirrors, both of which intuitively show this.
3.) Personally, I'd just add the two and then renormalize. Mipmapping will typically wash-out normalmaps in the distance because normals become shorter during averaging. Of course, you can renormalize the normals in the mipmapping generation, but I'd leave that out to prevent aliasing and make this effect work. Other than that, it's basically a matter of taste (and looks!) how you combine the two. To be honest, it's probably a better way to not use detail-normalmaps at all and just use higher-resolution textures. Graphics hardware has enough RAM for simple things like that nowadays, and you can always stream stuff if you think RAM is becoming a problem.
1) No and Yes. If you linearly interpolate that matrix the resulting vectors will still be orthogonal. The magnitudes will be less than 1 at points between the starting and ending matrix. You can see this by interpolating vectors from (1,0,0) to (-1,0,0) where at some point the length is actually zero - this is a case you should not encounter with what you're doing, but it shows the length changes.
If the rows and columns are orthogonal unit vectors it's an orthogonal matrix. When interpolating from one orthonormal matrix to another, the intermediate ones will have orthogonal rows and columns, but NOT unit length. I believe the requirement is that the vectors within the matrix all have equal length for this to work, but not necessarily unit length.
2) A unit vector multiplied by an orthonormal matrix will be unit length. You're really just doing a rotation into another reference frame. If the vectors in the matrix are ortho but not normal, your vector will be scaled down by that same fraction.
3) If you want to replace one map with the other, just interpolate between those LODs as well using a function of distance to the viewer. Unfortunately this will result in shortening of the vector (the result will not be unit length).
You should be able to interpolate the normal map, apply the result using the interpolated matrix (without renormalization), and only renormalize the final resultant vector.
精彩评论