From e87f76ec53ce282fa30c10d52246f66ea04dbfdb Mon Sep 17 00:00:00 2001 From: kenlee Date: Wed, 26 Apr 2017 15:27:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86Normal=20Mapping?= =?UTF-8?q?=E7=AB=A0=E8=8A=82=E7=9A=84=E6=8E=92=E7=89=88=E5=92=8C=E7=BF=BB?= =?UTF-8?q?=E8=AF=91=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/05 Advanced Lighting/04 Normal Mapping.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/05 Advanced Lighting/04 Normal Mapping.md b/docs/05 Advanced Lighting/04 Normal Mapping.md index c8e0963..63049e2 100644 --- a/docs/05 Advanced Lighting/04 Normal Mapping.md +++ b/docs/05 Advanced Lighting/04 Normal Mapping.md @@ -224,12 +224,17 @@ void main() 我们先将所有TBN向量变换到我们所操作的坐标系中,现在是世界空间,我们可以乘以model矩阵。然后我们创建实际的TBN矩阵,直接把相应的向量应用到mat3构造器就行。注意,如果我们希望更精确的话就不要讲TBN向量乘以model矩阵,而是使用法线矩阵,但我们只关心向量的方向,不会平移也和缩放这个变换。 -从技术上讲,顶点着色器中无需副切线。所有的这三个TBN向量都是相互垂直的所以我们可以在顶点着色器中庸T和N向量的叉乘,自己计算出副切线:vec3 B = cross(T, N); -现在我们有了TBN矩阵,如果来使用它呢?基本有两种方式可以使用,我们会把这两种方式都说明一下: +!!! Important -我们可以用TBN矩阵把所有向量从切线空间转到世界空间,传给像素着色器,然后把采样得到的法线用TBN矩阵从切线空间变换到世界空间;法线就处于和其他光照变量一样的空间中了。 -我们用TBN的逆矩阵把所有世界空间的向量转换到切线空间,使用这个矩阵将除法线以外的所有相关光照变量转换到切线空间中;这样法线也能和其他光照变量处于同一空间之中。 -我们来看看第一种情况。我们从法线贴图重采样得来的法线向量,是以切线空间表达的,尽管其他光照向量是以世界空间表达的。把TBN传给像素着色器,我们就能将采样得来的切线空间的法线乘以这个TBN矩阵,将法线向量变换到和其他光照向量一样的参考空间中。这种方式随后所有光照计算都可以简单的理解。 + 从技术上讲,顶点着色器中无需副切线。所有的这三个TBN向量都是相互垂直的所以我们可以在顶点着色器中使用T和N向量的叉乘,自己计算出副切线:vec3 B = cross(T, N); + +现在我们有了TBN矩阵,如果来使用它呢?通常来说有两种方式使用它,我们会把这两种方式都说明一下: + +1. 我们直接使用TBN矩阵,这个矩阵可以把切线坐标空间的向量转换到世界坐标空间。因此我们把它传给片段着色器中,把通过采样得到的法线坐标左乘上TBN矩阵,转换到世界坐标空间中,这样所有法线和其他光照变量就在同一个坐标系中了。 +2. 我们也可以使用TBN矩阵的逆矩阵,这个矩阵可以把世界坐标空间的向量转换到切线坐标空间。因此我们使用这个矩阵左乘其他光照变量,把他们转换到切线空间,这样法线和其他光照变量再一次在一个坐标系中了。 + + +**我们来看看第一种情况。**我们从法线贴图重采样得来的法线向量,是以切线空间表达的,尽管其他光照向量是以世界空间表达的。把TBN传给像素着色器,我们就能将采样得来的切线空间的法线乘以这个TBN矩阵,将法线向量变换到和其他光照向量一样的参考空间中。这种方式随后所有光照计算都可以简单的理解。 把TBN矩阵发给像素着色器很简单: @@ -268,7 +273,7 @@ normal = normalize(fs_in.TBN * normal); 因为最后的normal现在在世界空间中了,就不用改变其他像素着色器的代码了,因为光照代码就是假设法线向量在世界空间中。 -我们同样看看第二种情况,我们用TBN矩阵的逆矩阵将所有相关的世界空间向量转变到采样所得法线向量的空间:切线空间。TBN的建构还是一样,但我们在将其发送给像素着色器之前先要求逆矩阵: +**我们同样看看第二种情况。**我们用TBN矩阵的逆矩阵将所有相关的世界空间向量转变到采样所得法线向量的空间:切线空间。TBN的建构还是一样,但我们在将其发送给像素着色器之前先要求逆矩阵: ```c++ vs_out.TBN = transpose(mat3(T, B, N));