1
0
mirror of https://github.com/LearnOpenGL-CN/LearnOpenGL-CN.git synced 2025-08-23 04:35:28 +08:00
This commit is contained in:
Krasjet
2019-02-03 15:07:44 -05:00
parent 798e32585e
commit 9fef24af66

View File

@@ -98,7 +98,7 @@ void main()
![](../img/05/04/normal_mapping_surface_edges.png)
上图中我们可以看到边\(E_2\)纹理坐标的不同,\(E_2\)是一个三角形的边,这个三角形的另外两条边是\(\Delta U_2\)\(\Delta V_2\),它们与切线向量\(T\)和副切线向量\(B\)方向相同。这样我们可以把边\(E_1\)\(E_2\)切线向量\(T\)和副切线向量\(B\)的线性组合表示出来(译注:注意\(T\)和\(B\)都是单位长度,在\(TB\)平面中所有点的\(T\)、\(B\)坐标都在0到1之间因此可以进行这样的组合
注意上图中边\(E_2\)纹理坐标的差\(\Delta U_2\)、\(\Delta V_2\)构成一个三角形。\(\Delta U_2\)与切线向量\(T\)方向相同,而\(\Delta V_2\)与副切线向量\(B\)方向相同。这也就是说,所以我们可以将三角形的边\(E_1\)\(E_2\)写成切线向量\(\T\)和副切线向量\(B\)的线性组合:
$$
E_1 = \Delta U_1T + \Delta V_1B
@@ -107,6 +107,7 @@ $$
$$
E_2 = \Delta U_2T + \Delta V_2B
$$
我们也可以写成这样:
$$
@@ -117,7 +118,7 @@ $$
(E_{2x}, E_{2y}, E_{2z}) = \Delta U_2(T_x, T_y, T_z) + \Delta V_2(B_x, B_y, B_z)
$$
\(E\)是两个向量位置的差,\(\Delta U\)和\(\Delta V\)是纹理坐标的差。然后我们得到两个未知数(切线*T*和副切线*B*)和两个等式。你可能想起你的代数课了,这是让我们去\(T\)和\(B\)。
\(E\)是两个向量位置的差,\(\Delta U\)和\(\Delta V\)是纹理坐标的差。然后我们得到两个未知数(切线\(T\)和副切线\(B\))和两个等式。你可能想起你的代数课了,这是让我们去\(T\)和\(B\)。
上面的方程允许我们把它们写成另一种格式:矩阵乘法
@@ -131,7 +132,7 @@ $$
\begin{bmatrix} \Delta U_1 & \Delta V_1 \\ \Delta U_2 & \Delta V_2 \end{bmatrix}^{-1} \begin{bmatrix} E_{1x} & E_{1y} & E_{1z} \\ E_{2x} & E_{2y} & E_{2z} \end{bmatrix} = \begin{bmatrix} T_x & T_y & T_z \\ B_x & B_y & B_z \end{bmatrix}
$$
这样我们就可以解出\(T\)和\(B\)了。这需要我们计算出delta纹理坐标矩阵的阵。我不打算讲解计算逆矩阵的细节但大致是把它变化为1除以矩阵的行列式再乘以它的伴随矩阵(Adjugate Matrix)。
这样我们就可以解出\(T\)和\(B\)了。这需要我们计算出delta纹理坐标矩阵的逆矩阵。我不打算讲解计算逆矩阵的细节但大致是把它变化为1除以矩阵的行列式再乘以它的伴随矩阵(Adjugate Matrix)。
$$
\begin{bmatrix} T_x & T_y & T_z \\ B_x & B_y & B_z \end{bmatrix} = \frac{1}{\Delta U_1 \Delta V_2 - \Delta U_2 \Delta V_1} \begin{bmatrix} \Delta V_2 & -\Delta V_1 \\ -\Delta U_2 & \Delta U_1 \end{bmatrix} \begin{bmatrix} E_{1x} & E_{1y} & E_{1z} \\ E_{2x} & E_{2y} & E_{2z} \end{bmatrix}
@@ -226,11 +227,11 @@ void main()
}
```
我们先将所有TBN向量变换到我们所操作的坐标系中现在是世界空间我们可以乘以model矩阵。然后我们创建实际的TBN矩阵直接把相应的向量应用到mat3构造器就行。注意如果我们希望更精确的话就不要TBN向量乘以model矩阵而是使用法线矩阵但我们只关心向量的方向不会平移也和缩放这个变换。
我们先将所有TBN向量变换到我们所操作的坐标系中现在是世界空间我们可以乘以model矩阵。然后我们创建实际的TBN矩阵直接把相应的向量应用到mat3构造器就行。注意如果我们希望更精确的话就不要TBN向量乘以model矩阵而是使用法线矩阵但我们只关心向量的方向不会平移也和缩放这个变换。
!!! Important
从技术上讲顶点着色器中无需副切线。所有的这三个TBN向量都是相互垂直的所以我们可以在顶点着色器中使用T和N向量的叉乘自己计算出副切线vec3 B = cross(T, N);
从技术上讲顶点着色器中无需副切线。所有的这三个TBN向量都是相互垂直的所以我们可以在顶点着色器中用T和N向量的叉乘自己计算出副切线vec3 B = cross(T, N);
现在我们有了TBN矩阵如果来使用它呢通常来说有两种方式使用它我们会把这两种方式都说明一下
@@ -396,7 +397,7 @@ vector<Texture> specularMaps = this->loadMaterialTextures(
关于法线贴图还有最后一个技巧要讨论,它可以在不必花费太多性能开销的情况下稍稍提升画质表现。
当在更大的网格上计算切线向量的时候,它们往往有很大数量的共享顶点,当发下贴图应用到这些表面时将切线向量平均化通常能获得更好更平滑的结果。这样做有个问题就是TBN向量可能会不能互相垂直这意味着TBN矩阵不再是正交矩阵了。法线贴图可能会稍稍偏移但这仍然可以改进。
当在更大的网格上计算切线向量的时候,它们往往有很大数量的共享顶点,当法向贴图应用到这些表面时将切线向量平均化通常能获得更好更平滑的结果。这样做有个问题就是TBN向量可能会不能互相垂直这意味着TBN矩阵不再是正交矩阵了。法线贴图可能会稍稍偏移但这仍然可以改进。
使用叫做*格拉姆-施密特*正交化过程Gram-Schmidt process的数学技巧我们可以对TBN向量进行重正交化这样每个向量就又会重新垂直了。在顶点着色器中我们这样做