Three.js 在顶点着色器与片段着色器中计算TBN矩阵?

Three.js 在顶点着色器与片段着色器中计算TBN矩阵?,three.js,webgl,shader,Three.js,Webgl,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

我认为我们可以在顶点着色器和片段着色器中计算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矩阵

// 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中,法线、切线和双切线作为变量传递,在基本体的面上插值,重新规范化,并在片段着色器中构造TBN矩阵。这样,矩阵列(1)为单位长度,(2)可能接近正交

您可以在片段着色器中计算双切线,强制其与插值法线和切线正交,但这样做可能不会产生太大差异,因为插值法线和切线无论如何都不能保证正交


three.js r.102

要使TBN矩阵正交,我们可以使用Gram-Schmidt过程,对吗?我认为它可以在顶点着色器和片段着色器中处理…正如我所说的,TBN矩阵的列必须具有单位长度。这意味着需要在片段着色器中重新规范化列。