验证顶点着色器中变换矩阵的使用。正确性或法线转换
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);
我需要能够根据变换矩阵修改顶点坐标,但我有逐顶点照明,所以我不确定我的方法是否适用于法线:
#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);