2

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

#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 行执行所有转换。您能否评论它是否正确?

4

2 回答 2

3

如果要创建普通矩阵,则必须使用左上角 3*3 的 4*4 矩阵。inverse transpose

请参阅为什么使用模型视图矩阵的逆转置来转换法线?
为什么要使用模型视图矩阵的转置逆来转换法线向量?

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

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


但是,如果将向量从左侧乘以矩阵,则结果对应于将列向量从右侧乘以转置矩阵。

请参阅GLSL 编程/向量和矩阵运算

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

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


如果 4*4 矩阵transformationMatrixOrthogonal matrix,这意味着 X、Y 和 Z 轴是正交的(单位向量并且彼此正交),那么使用左上角的 3*3 就足够了。在这种情况下,逆矩阵等于转置矩阵。

请参阅在哪些情况下逆矩阵等于转置?

这将简化您的代码:

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);
于 2018-02-10T08:22:59.410 回答
1

正常的转换看起来不正确。

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

您正在寻找的很可能是使用反转置矩阵:

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

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

于 2018-02-10T08:22:14.523 回答