User Tools

Site Tools


tutorials:ffopengl_vbo

Vertex Buffer Objects

Until now, we've been using glBegin and glEnd when drawing our geometry. However, you've probably noticed that this is very slow (especially when rendering lots of vertices). This is largely because you are sending your geometry to the GPU with every frame! Wouldn't it be better if we sent the geometry to the GPU once and just rendered it over and over again without resending the data? Yes, yes, it would… We can do this using vertex buffer objects (or VBO for short). This is a complicated way of saying that you're putting an array of vertices in memory on the GPU. Nothing fancy. Let's render some simple geometry, say a circle. Below is some code to generate a vertex list for a circle.

def generateCircle(radius):
    ptlist=[]
 
    for theta in range(0, 360):
        x=np.cos(np.radians(theta))*radius
        y=np.sin(np.radians(theta))*radius
        ptlist.append([x, y, 0.0])
 
    return ptlist

To get started, you will need to include several new imports at the top of your program.

from OpenGLContext.arrays import *
from OpenGL.arrays import vbo

In the example below, we make two VBOs for two circles, one with a radius of four and another with a radius of two. I recommend keeping a list of your VBOs (such as the self.vbos shown below), so you can loop through them when doing your rendering. Once you've gotten your vertex list for your geometry, you can copy it into a VBO and then add that VBO to your list.

        self.vbos=[]
 
        self.vertices=generateCircle(4)
        cvbo=vbo.VBO(array(np.float32(self.vertices)))
        self.vbos.append(cvbo)
 
        self.vertices=generateCircle(2)
        cvbo=vbo.VBO(array(np.float32(self.vertices)))
        self.vbos.append(cvbo)

The following code would go inside your display function. We activate the VBO that we want to work with by calling the bind function. We also have to specify that we are working with an array of vertices using glEnableClientState by passing it GL_VERTEX_ARRAY. Next, we pass our current VBO to the glVertexPointerf function. This tells the GPU where in memory to look for your VBO. We then can call the glDrawArrays function to direct the GPU to render the geometry stored in the VBO. This function takes three parameters. This first is the type of geometry you want to render. In the case of this example, we are drawing a GL_LINE_LOOP so that we will have a solid circle. The second parameter is the byte offset of your first vertex. This is almost always going to be 0 (the first byte in the array). The third parameter is the number of elements in the VBO. Once you've finished calling the draw function, you will need to deactivate your VBO by calling unbind and disabling your client state using glDisableClientState.

        glPushMatrix()
        glTranslatef(0.0, 0.0, -5.0)
 
        for cvbo in self.vbos:
            cvbo.bind()
            glEnableClientState(GL_VERTEX_ARRAY)
            glVertexPointerf(cvbo)
 
            glDrawArrays(GL_LINE_LOOP, 0, len(cvbo))
 
            cvbo.unbind()
            glDisableClientState(GL_VERTEX_ARRAY)
 
        glPopMatrix()
tutorials/ffopengl_vbo.txt · Last modified: 2021/08/01 00:53 by jones