我需要能够根据变换矩阵修改顶点坐标,但我有每顶点光照,所以我不确定,我的方法对于法线是正确的:
#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行执行所有转换。 你能否评论一下是否正确?
答案 0 :(得分:3)
如果你想创建一个普通矩阵,那么你必须使用4 * 4矩阵左上角3 * 3的inverse
transpose
。
见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,这意味着X,Y和Z轴是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)和
vec3 v;
mat3 m1, m2;
(m1 * v) * m2
不等于
m1 * (v * m2);
答案 1 :(得分:1)
正常转换看起来不正确。
由于v * transpose(M)与M * v完全相同,因此您根本没有对非均匀缩放进行任何特殊处理。
您正在寻找的最有可能是使用反转置矩阵:
normal = gl_NormalMatrix * transpose(inverse(mat3(transformationMatrix))) * gl_Normal;
有关此背后数学的更多详细信息,请查看this。