• 13
• 16
• 27
• 9
• 9

# Anisotropic BRDFs and normal mapping

This topic is 3683 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I am currently experimenting with different BRDFs, and I've been wondering how to integrate anisotropic BRDFs with normal mapping. Anisotropic BRDFs generally require an orthonormal TBN basis, which would need to be modified according to the mapped normal vector. The only article I found on that topic was this one: http://ati.amd.com/developer/shaderx/ShaderX_PerPixelAniso.pdf which suggest subtracting the part of the tangent pointing in the direction of the normal (and renormalizing). Now, this works for most cases, but if the mapped normal is parallel to the original tangent (n.x = +-1) this obviously won't work. And if it is very close it could cause numerical precision problems. Does anyone have a suggestion for a solution which works in the general case? If anyone cares, the BRDF I want to apply this to the anisotropic phong brdf by Ashikhmin and Shirley.

##### Share on other sites
hi,

I've never done this before, so this is just an idea. given is the normal N of the BRDF's local TBN. Then compute the transformation that rotates N into the normal N' of the normal map (or vice-versa). Quaternions are the best and easiest choice here!

After this step you have a transformation that rotates one normal into another. If applied to Bitangent and Tangent Vector as well, you should have your local "normal-map-deferred" TBN (in fact, the rotation only has to be applied to either tangent or bitangent, since the third basisvector is obtained by the crossproduct).

Greets,
Nick

##### Share on other sites
How exactly would quaternions help?

The problem with creating a rotation matrix (and i presume a quaternion as well) is that there are infinitely many (non-equivalent) rotations which would cause the mapped normal to point in the real normals direction (or vice-versa). For example if the mapped normal is already pointing in the same direction, we can rotate around the mapped normal without changing anything, except that we'd like to have the original tangent not to be changed in this case...

##### Share on other sites
ok, I accidently ignored this problem. So what you need is the transformation that rotates one basis into another, don't you? just a stupid idea, but what about rotating the identity of one basis into the identity of the other? (with idendity I mean like the vector ||(1,1,1)|| in euclidean space or ||(T+B+N)|| in general). this vector should'nt be invariant regarding rotation IMO!?

##### Share on other sites
I think I found a workable solution: I create an axis angle representation using the cross product of the original normal and the mapped normal as axis of rotation. Converting this to a matrix does require a division by the length of the cross product which is 0 when the normals coincide, but that part is multiplied by the 1-cos (of the angle between the normals) which is zero, so I added a 1e-6 "fudge factor" to prevent the division by zero and this seems to work just fine.

The GLSL code looks like this (simplified, because I assume an original normal of (0,0,1), since it's cheaper to transform the light and view vectors to tangent space in the vertex shader):

mat3 rotationFromNormal(vec3 N){   mat3 A;   A[0] = vec3( N.z, 0.0,N.x);   A[1] = vec3( 0.0, N.z,N.y);   A[2] = vec3(-N.x,-N.x,N.z);      float x2 = N.x * N.x;   float y2 = N.y * N.y;   float xy = N.x * N.y;      mat3 B;   B[0] = vec3( y2,-xy,0.0);   B[1] = vec3(-xy, x2,0.0);   B[2] = vec3(0.0,0.0,0.0);      return A + (1.0-N.z) / (1e-6+x2+y2) * B;}