【问题标题】:Trouble rendering box from index buffer with PyOpenGL使用 PyOpenGL 从索引缓冲区渲染框时出现问题
【发布时间】:2015-04-09 17:39:10
【问题描述】:

我正在尝试完成 2.1 版 OpenGL 红皮书的开头部分,并将我学到的知识转化为 PyOpenGL 绑定,同时将 Qt 用于窗口框架。但出于某种原因,我似乎无法拨打glDrawElements() 的电话来实际在屏幕上绘制任何内容。以下是我目前拥有的相关功能。

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() 函数进行渲染,它会渲染(尽管它看起来不像立方体,因为它正在渲染索引)。这里可能出了什么问题?

编辑: 以下是glDrawElements()glDrawArrays() 的结果的几个视频。

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

  1. from OpenGL.arrays.arraydatatype import ArrayDatatype
  2. 使用ArrayDatatype.arrayByteCount(self.cubeVtxArray) 作为glBufferData() 的第二个参数(对于任何其他缓冲区也是如此)。

编辑 3: 实际上,我想对此再做一次编辑,因为我刚刚在调用 glBufferData() 时遇到了另一个相关问题。我天真地认为我也应该能够以与 ArrayDatatype.arrayByteCount() 相同的方式使用 sys.getsizeof()。但是,如果您的缓冲区数据是我最终使用的 numpy 数组,则情况并非如此。 sys.getsizeof() 返回错误的大小,并且会无意中将您的数组切碎一点。再见了我生命中的三天......

【问题讨论】:

  • 我不明白python绑定的细节,但我注意到它说np.ubyte作为索引数组的类型,而你在参数中指定GL_UNSIGNED_INT作为索引类型为glDrawElements()。这不是错配吗?
  • 开枪,对不起。我认为数据类型可能是我的问题,所以我在摆出这个之前就在玩这些。我修复了代码,它现在可以渲染,但它很不稳定,而且绝对不像一个立方体,即使顶点和索引是从一个工作的立方体程序中提取的。我制作了一些关于我得到的结果的视频并编辑了问题。谢谢。

标签: python qt opengl numpy


【解决方案1】:

在我看来有一个问题是您将数组大小作为第二个参数发送给glBufferData。您可能需要将数据的字节数作为该参数发送。所以它会是这样的:

 len(self.cubeVtxArray) * numBytesPerElement

其中numBytesPerElement 将是每个浮点数 4 个字节乘以每个顶点 3 个浮点数 = 12 个字节。

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

  1. 来自OpenGL.arrays.arraydatatype import ArrayDatatype

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

    您需要为self.cubeIdxArray 做同样的事情,尽管在这种情况下numBytesPerElement 将是1。

【讨论】:

  • 哇,多么简单的修复哈哈。谢谢你。我接受你的回答,但你介意添加 python 细节以防其他人遇到这个麻烦吗?我在问题的末尾包含了修复程序,但它确实应该包含在答案中。
  • 没问题!我现在添加它。
猜你喜欢
  • 1970-01-01
  • 2012-04-08
  • 2014-06-14
  • 1970-01-01
  • 2020-04-05
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多