本篇为3D基础的第3部分,主要讲述顶点切向量的计算原理,相信很多人都对Shader里的Tangent分量没有深入了解,希望我的这篇文章能对各位理解切空间有所帮助。我们以凹凸映射为例子来解释今天的原理。
实际上凹凸贴图中存储的发现扰动值实际上是以图中X Y为基的(对凹凸映射不太熟悉的请先参考其他相关文章)。所以需要一个转换将纹理坐标系转换到世界坐标系中,这个转换其实是一个基变换过程(参见3D基础2),说白了就是要找到纹理在世界空间中是如何摆的,纹理在方向的变化率如何。而要得到这点,需要计算得到U V轴分别对应到世界坐标系中的向量。如果纹理映射到三角形不时均匀的,Tangent向量和Binormal向量肯定不是正交的。已知:空间三角形3个顶点坐标分别为(Xa, Ya, Za)(Xb, Yb, Zb)(Xc, Yc, Zc),纹理坐标分别为(Sa, Ta)(Sb, Tb)(Sc, Tc),因此得:
条件:
纹理向量 ( (Sb - Sa), (Tb - Ta) ) => 世界向量 ( (Xb - Xa), (Yb - Ya), (Zb - Za) )
纹理向量 ( (Sc - Sa), (Tc - Ta) ) => 世界向量 ( (Xc - Xa), (Yc - Ya), (Zc - Za) )
需要求:
( 1, 0 ) => Tangent
( 0, 1 ) => Binormal
D表示三角形内任意一点: D - A = ( S - Sa ) * T + ( T - Ta ) * B,设
P = B - A
Q = C - A
( S1, T1 ) = ( (Sb - Sa), (Tb - Ta) )
( S2, T2 ) = ( (Sc - Sa), (Tc - Ta) )
| Px Py Pz | | S1 T1 | | Tx Ty Tz |
= *
| Qx Qy Qz | | S2 T2 | | Bx By Bz |
最后我们计算得到的T B N之间很有可能并不正交,这样严格意义上他们并不能直接用来进行基转换,但只要T B N之间夹角接近垂直就OK,在最终视觉上不会有太多影响,特别是在 T B 与N垂直的情况,毕竟只相当于将扰动NORMAL绕N小转个角度,一般先用Gram-Schmidt算法让TBN正交后再作处理:
T' = T - (N*T)N
B' = B - (N*B)N - (T'*B)T'
N' = N
提示:当基轴互相不正交的时候,Vx*x + Vy*y + Vz*z是不正确的切空间到世界空间表示,当为夹角为锐角时结果模会偏大,而且方向也是错误的,钝角结果模会偏小,方向也不对。