在顶点着色器中,我们通常创建 TBN 矩阵:
vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 t = normalize(gl_NormalMatrix * Tangent.xyz);
vec3 b = normalize(gl_NormalMatrix * Bitangent.xyz);
mat3 tbn = mat3(t, b, n);
该矩阵将顶点从切线空间转换到眼睛/相机空间。
现在对于法线贴图(在前向渲染中完成),我们有两个选项:
- 逆 tbn 矩阵和变换
light_vector
并将view_direction
这些向量发送到片段着色器。之后,这些向量位于切线空间中。- 这样在片段着色器中我们只需要从法线贴图中读取法线。由于这些法线在切线空间中(通过“定义”),因此它们与变换后的
light_vector
和相匹配view_direction
。 - 这样我们就可以在切线空间中进行光照计算。
- 这样在片段着色器中我们只需要从法线贴图中读取法线。由于这些法线在切线空间中(通过“定义”),因此它们与变换后的
- 将
tbn
矩阵传递给片段着色器,然后通过它转换从法线贴图中读取的每个法线。这样我们就可以将这样的法线转换为视图空间。- 这样我们在 Eye/Camera 空间中进行光照计算
选项1似乎更快:我们在顶点着色器中进行了大部分转换,只有一个从法线贴图读取。
选项2需要通过 TBN 矩阵从法线贴图转换每个法线。但它似乎有点简单。
问题:
哪个选项更好?
有没有性能损失?(也许纹理读取将“覆盖”进行矩阵转换的成本)
哪个选项更常用?