利用 OpenGL VBOs 重构

85 阅读1分钟

一名学习 OpenGL 的开发者正在尝试将他的代码重构,以使用 OpenGL VBOs(顶点缓冲对象)来提升性能。他目前有一个简单的 3D 立方体视图,并希望通过使用 VBOs 来提高其运行效率。然而,他在尝试实现过程中遇到了困难,并且没有找到比较好的示例代码来帮助他解决问题。

2、解决方案

提供的代码中有几个问题:

  1. 在绑定 VBO 后,没有使用 glVertexAttribPointer 来指定 VBO 中数据的格式和偏移量。
  2. 在绑定 VBO 后,没有使用 glIndexPointer 来指定索引数据的格式和偏移量。
  3. 在调用 glDrawElements 时,没有指定索引数据类型的字节大小。

以下是修改后的代码,其中修复了上述问题:

import numpy as np

from OpenGL.GL import *
from OpenGL.arrays import vbo
from OpenGL.GLU import *
from OpenGL.GLUT import *

class Cube:
    def __init__(self):
        # Unit cube, centered at the origin.
        self.positions = np.array([(0.5, -0.5, -0.5), (0.5, 0.5, -0.5),
                                   (0.5, 0.5, 0.5), (0.5, -0.5, 0.5),
                                   (-0.5, 0.5, -0.5), (-0.5, -0.5, -0.5),
                                   (-0.5, -0.5, 0.5), (-0.5, 0.5, 0.5),
                                   (-0.5, 0.5, -0.5), (-0.5, 0.5, 0.5),
                                   (0.5, 0.5, 0.5), (0.5, 0.5, -0.5),
                                   (-0.5, -0.5, 0.5), (-0.5, -0.5, -0.5),
                                   (0.5, -0.5, -0.5), (0.5, -0.5, 0.5),
                                   (-0.5, -0.5, 0.5), (0.5, -0.5, 0.5),
                                   (0.5, 0.5, 0.5), (-0.5, 0.5, 0.5),
                                   (0.5, -0.5, -0.5), (-0.5, -0.5, -0.5),
                                   (-0.5, 0.5, -0.5), (0.5, 0.5, -0.5)],
                                  dtype=np.float32)
        self.normals = np.array([(1.0, 0.0, 0.0), (1.0, 0.0, 0.0),
                                  (1.0, 0.0, 0.0), (1.0, 0.0, 0.0),
                                  (-1.0, 0.0, 0.0), (-1.0, 0.0, 0.0),
                                  (-1.0, 0.0, 0.0), (-1.0, 0.0, 0.0),
                                  (0.0, 1.0, 0.0), (0.0, 1.0, 0.0),
                                  (0.0, 1.0, 0.0), (0.0, 1.0, 0.0),
                                  (0.0, -1.0, 0.0), (0.0, -1.0, 0.0),
                                  (0.0, -1.0, 0.0), (0.0, -1.0, 0.0),
                                  (0.0, 0.0, 1.0), (0.0, 0.0, 1.0),
                                  (0.0, 0.0, 1.0), (0.0, 0.0, 1.0),
                                  (0.0, 0.0, -1.0), (0.0, 0.0, -1.0),
                                  (0.0, 0.0, -1.0), (0.0, 0.0, -1.0)],
                                 dtype=np.float32)

        self.faces = np.array(range(24), dtype=np.uint32)

        self.position_vbo = vbo.VBO(self.positions)
        self.normal_vbo = vbo.VBO(self.normals)
        self.faces_vbo = vbo.VBO(self.faces, target=GL_ELEMENT_ARRAY_BUFFER)

    def draw(self):
        # clear color and depth buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_NORMAL_ARRAY)

        self.position_vbo.bind()
        glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, 0)

        self.normal_vbo.bind()
        glVertexAttribPointer(1, 3, GL_FLOAT, False, 0, 0)

        self.faces_vbo.bind()
        glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, 0)

        glDisableClientState(GL_VERTEX_ARRAY)
        glDisableClientState(GL_NORMAL_ARRAY)

if __name__ == "__main__":
    glutInit(sys.argv)
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)
    glutInitWindowSize(500, 500)
    glutInitWindowPosition(100, 100)

    window = glutCreateWindow("Cube")

    cube = Cube()

    def display():
        cube.draw()
        glutSwapBuffers()

    glutDisplayFunc(display)
    glutIdleFunc(display)

    glutMainLoop()

在修改后的代码中,glVertexAttribPointerglVertexAttribPointer 函数被用来指定顶点数据和法线数据的格式和偏移量。此外,glDrawElements 函数中添加了索引数据类型的字节大小,从而解决了之前的问题。

希望这个答案对您有所帮助。