< / >

This is a blog by about coding and web development.

Vertex buffer objects in PyOpenGL

Posted on in

Decided to move some of my vertex array code over to ARB_vertex_buffer_object, to see if I could get a bit of a speed boost out of PyOpenGL. Much to my dismay, these functions don’t have the sexy extension wrappers I talked about before, so it was a bit of a chore to get it all working.

Here’s a little wrapper class I wrote to make things easier:

from OpenGL.GL import *
from OpenGL.raw import GL
from OpenGL.arrays import ArrayDatatype as ADT

class VertexBuffer(object):

    def __init__(self, data, usage):
        self.buffer = GL.GLuint(0)
        glGenBuffers(1, self.buffer)
        self.buffer = self.buffer.value
        glBindBuffer(GL_ARRAY_BUFFER_ARB, self.buffer)
        glBufferData(GL_ARRAY_BUFFER_ARB, ADT.arrayByteCount(data),
                     ADT.voidDataPointer(data), usage)

    def __del__(self):
        glDeleteBuffers(1, GL.GLuint(self.buffer))

    def bind(self):
        glBindBuffer(GL_ARRAY_BUFFER_ARB, self.buffer)

    def bind_vertexes(self, size, type, stride=0):
        self.bind()
        glVertexPointer(size, type, stride, None)

    ... snipped for length ...

Download buffers.py.

So, how to use it? Let’s say you have a Python list with a bunch of vertexes with float x, y, and z components:

verts = [[x, y, z], [x, y, z], [x, y, z], ...]

You’ll have to use NumPy or an equivalent to convert it to a PyOpenGL compatible array:

import numpy
numpy_verts = numpy.array(verts, dtype=numpy.float32)

Create the VertexBuffer object with it:

buffer = VertexBuffer(numpy_verts, GL_STATIC_DRAW)

Use it in your day to day rendering:

glEnableClientState(GL_VERTEX_ARRAY)
buffer.bind_vertexes(3, GL_FLOAT)
glDrawElementsui(GL_TRIANGLES, indexes)

They’re not shown in the snippet, but I’ve also defined bind_colors, bind_edgeflags, bind_indexes, bind_normals, and bind_texcoords, as shortcuts for the rest of the GL array functions.