OpenGL着色器中矩阵乘法致立方体消失问题求助
问题描述
使用ModernGL学习OpenGL时,原本能通过顶点数据和基础着色器正常渲染红色立方体,但在着色器中引入单位矩阵并将顶点与矩阵相乘后,立方体消失。尝试投影矩阵、平移矩阵等其他矩阵也无法正常工作。
原始可运行代码
顶点数据生成代码
def get_vertex_data(self): vertices = [(-1, -1, 1), (1, -1, 1), (1, 1, 1), (-1, 1, 1), (-1, 1, -1), (-1, -1, -1), (1, -1, -1), (1, 1, -1),] indices = [(0, 2, 3),(0, 1, 2), (1, 7, 2),(1, 6, 7), (6, 5, 4),(4, 7, 6), (3, 4, 5),(3, 5, 0), (3, 7, 4),(3, 2, 7), (0, 6, 1),(0, 5, 6),] vertex_data = self.get_data(vertices, indices) print(f'Vertex data = \n {vertex_data}') return vertex_data @staticmethod def get_data(vertices, indices): data = [vertices[ind] for triangle in indices for ind in triangle] return np.array(data, dtype='f4')
原始顶点着色器
#version 330 layout(location = 0) in vec3 ini_position; void main() { gl_Position = vec4(ini_position.xy, ini_position.z, 1.0); }
修改后出现问题的代码
单位矩阵定义
@staticmethod def mIdentity(): return np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1],]).astype('float32')
矩阵传入方式
self.shaderProgram['identityMatrix'].write(self.camera.m_identity)
更新后的顶点着色器
#version 330 layout(location = 0) in vec3 ini_position; uniform mat4 identityMatrix; void main() { gl_Position = identityMatrix * vec4(ini_position.xy, ini_position.z, 1.0); }
运行输出信息
shaderProgram["ini_position"] = <Attribute: 0> shaderProgram["identityMatrix"] = <Uniform: 0> identity matrix value = [[1. 0. 0. 0.] [0. 1. 0. 0.] [0. 0. 1. 0.] [0. 0. 0. 1.]] shaderProgram["ini_position"] = <Attribute: 0> Vertex data = [[-1. -1. 1.] [ 1. 1. 1.] [-1. 1. 1.] [-1. -1. 1.] [ 1. -1. 1.] [ 1. 1. 1.] [ 1. -1. 1.] [ 1. 1. -1.] [ 1. 1. 1.] [ 1. -1. 1.] [ 1. -1. -1.] [ 1. 1. -1.] [ 1. -1. -1.] [-1. -1. -1.] [-1. 1. -1.] [-1. 1. -1.] [ 1. 1. -1.] [ 1. -1. -1.] [-1. 1. 1.] [-1. 1. -1.] [-1. -1. -1.] [-1. 1. 1.] [-1. -1. -1.] [-1. -1. 1.] [-1. 1. 1.] [ 1. 1. -1.] [-1. 1. -1.] [-1. 1. 1.] [ 1. 1. 1.] [ 1. 1. -1.] [-1. -1. 1.] [ 1. -1. -1.] [ 1. -1. 1.] [-1. -1. 1.] [-1. -1. -1.] [ 1. -1. -1.]] vao created: <moderngl.VertexArray object at 0x000001FB688C5880> VAO, VBO AND SHADER PROGRAM RELEASED
解决方案
问题根源在于矩阵存储顺序不匹配:OpenGL(包括ModernGL)使用列主序存储矩阵,而NumPy默认创建的是行主序数组。直接将NumPy的行主序矩阵传入着色器,会导致矩阵被错误解析,即使是单位矩阵,后续使用其他矩阵(如投影、平移)时也会出现坐标变换错误,导致物体不可见。
解决方法1:转置矩阵后传入
在调用write()方法时,对NumPy矩阵进行转置:
self.shaderProgram['identityMatrix'].write(self.camera.m_identity.T)
解决方法2:创建列主序矩阵
修改矩阵生成方法,指定NumPy使用Fortran顺序(列主序)创建数组:
@staticmethod def mIdentity(): return np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1],], dtype='float32', order='F')
额外验证点
- 确认着色器中矩阵乘法顺序正确:
identityMatrix * vec4(...)是正确的,因为OpenGL中顶点向量是列向量,矩阵需要左乘。 - 从输出信息看,uniform和attribute都已正确绑定,无需修改这部分逻辑。
应用上述任一方法后,单位矩阵的变换会和原始逻辑一致,立方体将正常显示,其他矩阵(投影、平移等)也能正确工作。
内容的提问来源于stack exchange,提问作者Gabriel Ribeiro
相关产品推荐
相关产品推荐

