在顶点着色器和片段着色器中计算 TBN 矩阵?
Calculate TBN matrix in vertex shader vs fragment shader?
我想我们可以在顶点着色器和片段着色器中计算 TBN 矩阵。
// calculate in vs
varying mat3 vTbnMatrix;
void main() {
vec3 n = normalMatrix * aNormal;
vec3 t = normalMatrix * vec3(aTangent.xyz);
vec3 b = cross(n, t) * aTangent.w;
vTbnMatrix = mat3(t, b, n);
}
// calculate in fs
varying vec3 vNormal; // transformed by normalMatrix
varying vec3 vTangent; // transformed by normalMatrix
varying vec3 vBitantent;
void main() {
mat3 tbnMatrix = mat3(vTangent, vBitangent, vNormal);
}
有什么区别?我认为我们可以在顶点着色器中计算 TBN 矩阵,因为它可以加快程序速度。
但是当我深入研究 THREE.js 和 PlayCanvas 引擎的源代码时,它们都在片段着色器中计算 TBN 矩阵。
在片段着色器中计算有什么好处?
理论上,TBN 矩阵应该是正交的。
在three.js中,法线、切线和双切线作为变量传递,在图元的表面进行插值,重新归一化,然后在片段着色器中构建 TBN 矩阵。这样,矩阵列是 (1) 单位长度,并且 (2) 可能接近正交。
您可以在片段着色器中计算双切线,以强制它与插值法线和切线正交,但这样做可能不会产生太大差异,因为插值法线和切线不是保证无论如何都是正交的。
three.js r.102
我想我们可以在顶点着色器和片段着色器中计算 TBN 矩阵。
// calculate in vs
varying mat3 vTbnMatrix;
void main() {
vec3 n = normalMatrix * aNormal;
vec3 t = normalMatrix * vec3(aTangent.xyz);
vec3 b = cross(n, t) * aTangent.w;
vTbnMatrix = mat3(t, b, n);
}
// calculate in fs
varying vec3 vNormal; // transformed by normalMatrix
varying vec3 vTangent; // transformed by normalMatrix
varying vec3 vBitantent;
void main() {
mat3 tbnMatrix = mat3(vTangent, vBitangent, vNormal);
}
有什么区别?我认为我们可以在顶点着色器中计算 TBN 矩阵,因为它可以加快程序速度。
但是当我深入研究 THREE.js 和 PlayCanvas 引擎的源代码时,它们都在片段着色器中计算 TBN 矩阵。
在片段着色器中计算有什么好处?
理论上,TBN 矩阵应该是正交的。
在three.js中,法线、切线和双切线作为变量传递,在图元的表面进行插值,重新归一化,然后在片段着色器中构建 TBN 矩阵。这样,矩阵列是 (1) 单位长度,并且 (2) 可能接近正交。
您可以在片段着色器中计算双切线,以强制它与插值法线和切线正交,但这样做可能不会产生太大差异,因为插值法线和切线不是保证无论如何都是正交的。
three.js r.102