Python 使用PyOpenGL从索引缓冲区渲染框时出现问题

Python 使用PyOpenGL从索引缓冲区渲染框时出现问题,python,qt,opengl,numpy,Python,Qt,Opengl,Numpy,我正在尝试阅读OpenGL红皮书2.1版的开头部分,并将我学到的内容转换为PyOpenGL绑定,同时将Qt用于窗口框架。但是,由于某种原因,我似乎无法调用gldrawerelements()将任何内容实际绘制到屏幕上。以下是我到目前为止的相关功能 def initializeGL(self): self.qglClearColor(QtGui.QColor(0,0,150)) self.initGeometry() GL.glEnable(GL.GL_DEPTH_TEST

我正在尝试阅读OpenGL红皮书2.1版的开头部分,并将我学到的内容转换为PyOpenGL绑定,同时将Qt用于窗口框架。但是,由于某种原因,我似乎无法调用
gldrawerelements()
将任何内容实际绘制到屏幕上。以下是我到目前为止的相关功能

def initializeGL(self):
    self.qglClearColor(QtGui.QColor(0,0,150))
    self.initGeometry()
    GL.glEnable(GL.GL_DEPTH_TEST)
    self.buffers = GL.glGenBuffers(2)

def paintGL(self):
    GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)

    GL.glLoadIdentity()
    GL.glTranslate(0.0, 0.0, -50.0)
    GL.glScale(20.0, 20.0, 20.0)
    GL.glRotate(self.yRotDeg, 0.2, 1.0, 0.3)
    GL.glTranslate(-0.5, -0.5, -0.5)

    VERTICES = 0
    INDICES = 1
    GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.buffers[VERTICES])
    GL.glBufferData(GL.GL_ARRAY_BUFFER, len(self.cubeVtxArray), self.cubeVtxArray, GL.GL_STATIC_DRAW)
    offset = ctypes.c_void_p(0)
    GL.glVertexPointer(3, GL.GL_FLOAT, 0, offset)
    #GL.glVertexPointerf(self.cubeVtxArray)
    GL.glEnableClientState(GL.GL_VERTEX_ARRAY)
    GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, self.buffers[INDICES])
    GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, len(self.cubeIdxArray), self.cubeIdxArray, GL.GL_STATIC_DRAW)

    GL.glDrawElements(GL.GL_QUADS, 24, GL.GL_UNSIGNED_BYTE, offset)
    #GL.glDrawArrays(GL.GL_QUADS, 0, 24)

def initGeometry(self):
    self.cubeVtxArray = np.array(
            [[0.0, 0.0, 0.0],
             [1.0, 0.0, 0.0],
             [1.0, 1.0, 0.0],
             [0.0, 1.0, 0.0],
             [0.0, 0.0, 1.0],
             [1.0, 0.0, 1.0],
             [1.0, 1.0, 1.0],
             [0.0, 1.0, 1.0]], dtype=np.float32)
    self.cubeIdxArray = np.array([
            0, 1, 2, 3,
            3, 2, 6, 7,
            1, 0, 4, 5,
            2, 1, 5, 6,
            0, 3, 7, 4,
            7, 6, 5, 4], dtype=np.uint8)
当我运行该程序时,它确实会将屏幕清除为正确的颜色,但不会绘制立方体。有趣的是,如果我尝试使用
glDrawArray()
函数进行渲染,它确实会进行渲染(尽管它看起来不像立方体,因为它正在渲染索引)。这里可能出了什么问题

编辑: 以下是两段视频,介绍和的结果

编辑2: 我的问题(正如user1118321所指出的)是,我将数组长度作为第二个参数传递给
glBufferData()
,在这里我应该传递以字节为单位的大小。python的解决方案是:

  • 从OpenGL.arrays.arraydatatype导入arraydatatype
  • 使用
    ArrayDatatype.arrayByteCount(self.cubeVtxArray)
    作为
    glBufferData()
    的第二个参数(对于任何其他缓冲区也是如此)
  • 编辑3:
    实际上,我还想对此进行一次编辑,因为我刚刚在调用glBufferData()时遇到了另一个相关问题。我天真地认为,我也应该能够以与ArrayDatatype.arrayByteCount()相同的方式使用sys.getsizeof()。但如果缓冲区数据是我最后使用的numpy数组,则情况并非如此。sys.getsizeof()返回错误的大小,并且会无意中切掉数组中的一点。再见我生命中的三天….

    我觉得有一件事不对,那就是你将数组大小作为第二个参数发送到
    glBufferData
    。您可能需要发送数据的字节数作为该参数。所以它会是这样的:

     len(self.cubeVtxArray) * numBytesPerElement
    
    其中,
    numbytesperelation
    将是每个浮点4字节乘以每个顶点3个浮点=12字节

    在Python中,可以通过执行以下操作获取数组中的字节数:

  • OpenGL.arrays.arraydatatype导入arraydatatype

  • 使用
    ArrayDatatype.arrayByteCount(self.cubeVtxArray)
    作为
    glBufferData()
    的第二个参数(对于任何其他缓冲区也是如此)

    对于
    self.cubeIdxArray
    ,您需要做同样的事情,尽管在这种情况下
    numbytesRelation
    将为1


  • 我不理解python绑定的细节,但我注意到它将
    np.ubyte
    作为索引数组的类型,而在
    glpaurements()的参数中指定
    GL\u UNSIGNED\u INT
    作为索引类型。这不是错配吗?对不起,开枪。我认为数据类型可能是我的问题,所以在提出这个问题之前,我就在处理这些数据类型。我修复了代码,现在它确实渲染了,但它是不稳定的,而且绝对不像立方体,即使顶点和索引是从工作立方体程序中提取的。我制作了两个视频,记录了我得到的结果,并编辑了这个问题。谢谢。哇,多简单的解决办法啊哈哈。非常感谢。我接受你的回答,但是你介意添加python的细节以防其他人遇到这种麻烦吗?我在问题的末尾添加了修复,但它应该包含在答案中。当然!我现在就添加它。