You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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')

额外验证点

  1. 确认着色器中矩阵乘法顺序正确:identityMatrix * vec4(...)是正确的,因为OpenGL中顶点向量是列向量,矩阵需要左乘。
  2. 从输出信息看,uniform和attribute都已正确绑定,无需修改这部分逻辑。

应用上述任一方法后,单位矩阵的变换会和原始逻辑一致,立方体将正常显示,其他矩阵(投影、平移等)也能正确工作。

内容的提问来源于stack exchange,提问作者Gabriel Ribeiro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 01:52:34