验证顶点着色器中变换矩阵的使用。正确性或法线转换

Verification of transformation matrix usage in vertex shader. Correctness or normals transformation

我需要能够根据变换矩阵修改顶点坐标,但我有逐顶点照明,所以我不确定我的方法是否适用于法线:

#version 120
uniform mat4 transformationMatrix;
void main() {
    vec3 normal, lightDir;
    vec4 diffuse, ambient, globalAmbient;
    float NdotL;
    // Transformation part
    normal = gl_NormalMatrix * gl_Normal * transpose(mat3(transformationMatrix));
    gl_Position = gl_ModelViewProjectionMatrix * transformationMatrix * gl_Vertex;
    // Calculate color
    lightDir = normalize(vec3(gl_LightSource[0].position));
    NdotL = max(abs(dot(normal, lightDir)), 0.0);
    diffuse = gl_Color * gl_LightSource[0].diffuse;
    ambient = gl_Color * gl_LightSource[0].ambient;
    globalAmbient = gl_LightModel.ambient * gl_Color;
    gl_FrontColor =  NdotL * diffuse + globalAmbient + ambient;
 } 

我在第 8-9 行执行所有转换。 你能评论一下这种方法是否正确吗?

正常转换看起来不正确。

由于 v * transpose(M) 与 M * v 完全相同,您根本没有对非均匀缩放进行任何特殊情况处理。

你要找的最有可能是使用反转置矩阵:

normal = gl_NormalMatrix * transpose(inverse(mat3(transformationMatrix))) * gl_Normal;

有关这背后数学的更多详细信息,请查看 this

如果要创建普通矩阵,那么就得用左上3*3的inverse transpose,4*4的矩阵

Why transforming normals with the transpose of the inverse of the modelview matrix?
Why is the transposed inverse of the model view matrix used to transform the normal vectors?

这意味着您必须像这样编写代码:

normal = gl_NormalMatrix * transpose(inverse(mat3(transformationMatrix))) * gl_Normal;


但是,如果一个向量从左边乘以一个矩阵,结果对应于从右边乘一个列向量到转置矩阵。

GLSL Programming/Vector and Matrix Operations

这意味着您可以像这样编写代码并避免 transpose 操作:

normal = gl_NormalMatrix * (gl_Normal * inverse(mat3(transformationMatrix)));


如果4*4的矩阵transformationMatrix是一个Orthogonal matrix, this means the X, Y, and Z axis are Orthonormal(单位向量且相互垂直),那么用左上角的3*3就够了。在这种情况下,逆矩阵等于转置矩阵。

In which cases is the inverse matrix equal to the transpose?

这将简化您的代码:

normal = gl_NormalMatrix * mat3(transformationMatrix) * gl_Normal;

当然也可以这样表达:

normal = gl_NormalMatrix * (gl_Normal * transpose(mat3(transformationMatrix)));

请注意,这与您在代码中所做的不同,因为 * 操作是从左到右处理的(参见 GLSL - The OpenGL Shading Language 4.6, 5.1 Operators, page 97),而 [=28] 的结果=]

vec3 v;
mat3 m1, m2;

(m1 * v) * m2

不等于

m1 * (v * m2);