OpenGL ES 2.0 Android:normalMatrix 应该有哪些维度?

OpenGL ES 2.0 an Android: What dimensions should the normalMatrix have?

我正在学习 OpenGL ES 2.0,但从未学习过 OpenGL 或 OpenGL ES 1.x。

我正在对 modelViewMatrix 应用非均匀缩放,因此教程告诉我需要采取特殊步骤来计算 normalMatrix。在我的应用程序中,modelViewMatrix 的尺寸为 4x4。

  1. 一些教程说对于 normalMatrix 我需要简单地计算 transpose(inverse(modelViewMatrix)).

  2. 其他说明说我需要先取 modelViewMatrix 的左上角 3x3 子矩阵,然后计算转置(inverse(submatrix))。

有什么不同吗?它们会导致相同的结果吗?

现在我正在使用方法 1,然后在顶点着色器中我在应用转换后提取一个 vec3:

vec3 vNormalEyespace = vec3(normalMatrix * vec4(vertexNormal, 1.0));

我对此表示怀疑,因为 I see strange effects in my diffuse lighting。我正在考虑尝试方法 2,但是 android.opengl.Matrix class 不提供反转或转置 3x3 矩阵的方法...

我在renderFrame()中的实际代码如下:

  final float[] normalMatrix=new float[16];
  final float[] unscaledModelViewMatrix=modelViewMatrix_Vuforia.getData();
  Matrix.invertM(normalMatrix, 0, unscaledModelViewMatrix, 0);
  Matrix.transposeM(normalMatrix, 0, normalMatrix, 0);
  // pass the normalMatrix to the shader
  GLES20.glUniformMatrix4fv(normalMatrixHandleBottle, 1, false, normalMatrix, 0);

一个 3x3 矩阵足以变换法线。

使用对位置的齐次坐标进行运算的 4x4 矩阵的主要目的是它们可以表示平移。应用于 3 元向量的 3x3 矩阵可以 表达翻译。你可以很容易地确认这一点,因为它总是将原点映射回原点。

由于法线是向量,而不是位置,我们特别不是想要将模型视图矩阵的平移部分应用于它们。它们描述方向,并且在应用翻译时方向不会改变。

所以最干净的方法是对法线使用 3x3 矩阵,并将其设置为模型视图矩阵左上角 3x3 元素的逆变换。

在模型视图矩阵中只有旋转和均匀缩放的情况下(不适用于您的特定情况),人们有时会使用他们也用于位置的相同模型视图矩阵。这是正确的,只要不应用翻译部分。这可以通过将向量的 w 分量设置为零以进行乘法来完成:

vec3 transformedNormal = (modelViewMatrix * vec4(originalNormal, 0.0)).xyz

由于 w 分量为零,编码翻译的矩阵元素对结果没有影响,这对应于仅使用矩阵的左上角 3x3 部分。只要这与矩阵的逆转置相同,即旋转和均匀缩放的情况,这就是有效的捷径。