【发布时间】:2013-08-09 08:27:48
【问题描述】:
在顶点着色器中我们通常会创建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矩阵传递给片段着色器,然后通过该方法转换从法线贴图中读取的每个法线。这样我们就可以将这样的法线转换为视图空间。- 这样我们在眼睛/相机空间中进行光照计算
选项 1 似乎更快:我们在顶点着色器中进行了大部分转换,只有一个从法线贴图读取。
选项2需要将法线贴图中的每个法线通过TBN矩阵进行变换。不过好像简单了一点。
问题:
哪个选项更好?
是否有任何性能损失? (也许纹理读取将“覆盖”进行矩阵转换的成本)
哪个选项更常用?
【问题讨论】:
-
无法按要求回答此问题。答案将取决于许多因素,例如被插值的每个顶点参数的数量、相对于每个片段处理的每个顶点处理量等等。
-
好吧,尤其是性能不能轻易衡量...但是视觉差异呢?我认为这些解决方案应该是平等的?
标签: opengl glsl shader normals