GLSL/GLM与Python/numpy的4x4矩阵乘法是否存在差异?
问题:预计算PVM矩阵传入着色器后模型消失
可正常运行的实现
Python端代码
glUniformMatrix4fv(glGetUniformLocation(self.shader.program, "projection"), 1, GL_FALSE, self.P) glUniformMatrix4fv(glGetUniformLocation(self.shader.program, "view"), 1, GL_FALSE, self.V) glUniformMatrix4fv(glGetUniformLocation(self.shader.program, "model"), 1, GL_FALSE, self.M)
顶点着色器代码
#version 330 core layout (location=0) in vec3 vertexPos; layout (location=1) in vec2 vertexTexCoord; layout (location=2) in vec3 vertexNormal; uniform mat4 model; uniform mat4 view; uniform mat4 projection; out vec2 fragmentTexCoord; void main(){ gl_Position = projection * view * model * vec4(vertexPos, 1.0); fragmentTexCoord = vertexTexCoord; }
无法正常运行的实现
Python端代码
self.PVM = np.matmul(self.P, np.matmul(self.V, self.M)) glUniformMatrix4fv(glGetUniformLocation(self.shader.program, "PVM"), 1, GL_FALSE, self.PVM)
顶点着色器代码
#version 330 core layout (location=0) in vec3 vertexPos; layout (location=1) in vec2 vertexTexCoord; layout (location=2) in vec3 vertexNormal; uniform mat4 PVM; out vec2 fragmentTexCoord; void main(){ gl_Position = PVM * vec4(vertexPos, 1.0); fragmentTexCoord = vertexTexCoord; }
问题原因
核心是NumPy与GLSL的矩阵逻辑不匹配,两个关键点:
- 乘法顺序:GLSL采用列主序逻辑,
projection * view * model * 顶点的顺序是先给顶点套model变换,再view,最后projection。但NumPy默认是行主序逻辑,直接按P * V * M计算的话,变换顺序完全颠倒,顶点会被移出视锥体,导致模型消失。 - 存储顺序:GLSL的
mat4是列主序存储,而NumPy数组默认是行主序。直接传递会导致矩阵元素排列错乱,变换结果完全错误。
解决办法
两种可行的修正方式:
方式一:调整乘法顺序,保持列主序传入
把NumPy中的乘法顺序反过来,对齐GLSL的变换逻辑:
# 先乘model,再view,最后projection,和GLSL逻辑一致 self.PVM = np.matmul(np.matmul(self.M, self.V), self.P) glUniformMatrix4fv(glGetUniformLocation(self.shader.program, "PVM"), 1, GL_FALSE, self.PVM)
方式二:保持原乘法顺序,让OpenGL自动转置矩阵
调用glUniformMatrix4fv时,把第四个参数从GL_FALSE改成GL_TRUE,告诉OpenGL传入的是行主序矩阵,它会自动转成列主序适配GLSL:
self.PVM = np.matmul(self.P, np.matmul(self.V, self.M)) # GL_TRUE表示让OpenGL转置矩阵,匹配GLSL的列主序 glUniformMatrix4fv(glGetUniformLocation(self.shader.program, "PVM"), 1, GL_TRUE, self.PVM)
内容的提问来源于stack exchange,提问作者geo9
相关产品推荐
相关产品推荐

