法线矩阵和TBN矩阵

法线变换矩阵

经过模型变换后,法线也要跟着一起变换。假设物体发生了缩放形变,如果对法线应用相同的变换,可能会得到错误结果:

假设平面上一条切线\(\mathbf{t}\)(比如说,向量\(\text{AB}\)),变换矩阵为\(M\)。经过变换后\(\mathbf{t}'=M\mathbf{t}\)(变换后\(\mathbf{t}'=M\text{B}-M\text{A}=M(\text{B}-\text{A})=M\mathbf{t}\))。变换前后,\(\mathbf{n}\)都应该和切线垂直,可得: \[ \text{dot}(\mathbf{t'}, \mathbf{n}')=\text{dot}(M\mathbf{t},N\mathbf{n})=\mathbf{t}^TM^TN\mathbf{n}=0 \] 很显然,当\(M^TN\)为单位矩阵时上式成立。可得\(N=(M^{T})^{-1}\)。因此对法线应该作用变换矩阵转置的逆,可以保持法线垂直于变换后的平面。可以看出,如果只有平移和旋转,那么\(N=M\)(平移对法线没影响,旋转矩阵的转置即为逆),这也说明了法线变换问题是形变带来的。

TBN矩阵

用途

为物体添加细节的方法除了提高模型的精度,可以使用法线贴图。法线贴图利用图片的三通道存储法线的三个分量。法线贴图可以存储模型空间下法线的值,这样出来的法线贴图看起来就五彩缤纷;也可以存储为在切线空间下的值,在这个空间中,平面的法线为N轴,u、v的方向为T、B轴,如下图所示:

在法线贴图中三个通道RGB分别用于存储T(tangent)、B(bitangent)、N(normal)轴的分量。

模型空间下法线存储贴图是法线变化更加平滑,缺点是一张贴图只能对应一个模型。而切线空间下的法线贴图可以在任何模型之间切换,而且大部分法线都和N靠的比较近(更加靠近\((0,0,1)\),这就是为什么大部分法线贴图都偏蓝),更加便于压缩。

因此,只要能求出在模型空间下T、B、N轴的向量,按照贴图中记录的分量线性组合就可以得到模型空间下的法线。TBN矩阵就是贴图中向量到世界空间的变换矩阵。注意,T、B、N是正交的单位坐标系,因此TBN矩阵也是正交矩阵。

求法

因为U,V方向分别是T,B轴,如上图所示,模型空间下三角面片边\(E_1\)\(E_2\)可以表示成\(T\)\(B\)轴的线性组合: \[ \left[ \begin{matrix} E_1\\ E_2 \end{matrix} \right]=\left[ \begin{matrix} \Delta U_1 & \Delta V_1\\ \Delta U_2 & \Delta V_2 \end{matrix} \right] \left[ \begin{matrix} T\\ B \end{matrix} \right] \] 很显然,我们除了\(T\)\(B\),其它信息都知道,所以可以得到: \[ \left[ \begin{matrix} \Delta U_1 & \Delta V_1\\ \Delta U_2 & \Delta V_2 \end{matrix} \right]^{-1} \left[ \begin{matrix} E_1\\ E_2 \end{matrix} \right]= \frac{1}{\Delta U_1\Delta V_2 - \Delta U_2\Delta V_1} \left[ \begin{matrix} \Delta V_2 & -\Delta V_1\\ -\Delta U_2 & \Delta U_1 \end{matrix} \right] \left[ \begin{matrix} E_1\\ E_2 \end{matrix} \right]= \left[ \begin{matrix} T\\ B \end{matrix} \right] \]

这样就得到T,B轴,加上顶点法线N,就可以构造TBN矩阵了。等等!其实还没完。有以下几点需要注意:

  1. 顶点法线\(\neq\)平面法线:平面法线是垂直于面片的向量;顶点法线可以是任意的,比如艺术家的调整、相邻平面法线的平均(平滑)...
  2. 这样求出的T、B、N不一定正交。这是很正常的,可能物体被拉伸,可能uv映射不是完美对应的,加上N不是平面法线而是顶点法线,大部分情况下这样算出来的T、B、N都不正交。

TBN正交是很重要的,如果不正交,变换后的法线可能被拉伸。而理想情况下(TBN为正交矩阵)应该只是对法线进行旋转而已。

因此还应当进行格拉姆-施密特正交化(\(T'\)代表上面求出的,\(T\)\(B\)是真正的切线和副切线): \[ \begin{aligned} T &= \text{normalize}(T-(N\cdot T')N) \\ B &= N \times T \end{aligned} \] 上式其实就是正交分解的逆过程。

最后,假设从法线贴图中得到的法线是\(n\)(注意贴图中的法线非负做了偏移,真正的法线为\(2n-1\)),那么真正模型空间的法线为: \[ n_xT+n_yB+n_zN=[T,B,N]n \] 这个\([T,B,N]\)就是TBN矩阵。

在加载模型时,就可以对每个面片计算出T和B。因此T,B和N都是作为顶点属性传入着色器。为了保证TBN正交,可以在片元着色器中正交化后构造为TBN矩阵后使用。

Reference

作者

limil

发布于

2024-09-25

更新于

2025-04-05

许可协议