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。
一些教程说对于 normalMatrix 我需要简单地计算 transpose(inverse(modelViewMatrix)).
其他说明说我需要先取 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 部分。只要这与矩阵的逆转置相同,即旋转和均匀缩放的情况,这就是有效的捷径。
我正在学习 OpenGL ES 2.0,但从未学习过 OpenGL 或 OpenGL ES 1.x。
我正在对 modelViewMatrix 应用非均匀缩放,因此教程告诉我需要采取特殊步骤来计算 normalMatrix。在我的应用程序中,modelViewMatrix 的尺寸为 4x4。
一些教程说对于 normalMatrix 我需要简单地计算 transpose(inverse(modelViewMatrix)).
其他说明说我需要先取 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 部分。只要这与矩阵的逆转置相同,即旋转和均匀缩放的情况,这就是有效的捷径。