title: Refactoring to use OpenGL VBOs
body: <p>I'm learning OpenGL from the <a href="http://www.glprogramming.com/red/" rel="nofollow noreferrer">OpenGL Programming Guide</a>, and have a simple 3d view of a cube working.  The I know that using VBOs should help performance and would like to modify my code to use them.  I'm having trouble getting this to work, and haven't really found good clean examples online.</p>
  
  <p>Here's what I have working.</p>
  
  <p>My imports are:</p>
  
  <pre><code>import numpy as np
  
  from OpenGL.GL import *
  from OpenGL.arrays import vbo
  from OpenGL.GLU import *
  from OpenGL.GLUT import *
  </code></pre>
  
  <p>In my initialization I have:</p>
  
  <pre><code>    # 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)
  </code></pre>
  
  <p>In my draw code:</p>
  
  <pre><code>    # 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()
      glVertexPointer(3, GL_FLOAT, 0, self.positions)
  
      # self.normal_vbo.bind()
      glNormalPointer(GL_FLOAT, 0, self.normals)
  
      glColor3f(0., 1., 0.)
      glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, self.faces)
  
      glDisableClientState(GL_VERTEX_ARRAY)
      glDisableClientState(GL_NORMAL_ARRAY)
  </code></pre>
  
  <p>To refactor this to use VBOs, I've added this to the init:</p>
  
  <pre><code>    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)
  </code></pre>
  
  <p>And changed the draw to bind the VBOs:</p>
  
  <pre><code>    # 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()
      glVertexPointer(3, GL_FLOAT, 0, 0)
  
      self.normal_vbo.bind()
      glNormalPointer(GL_FLOAT, 0, 0)
  
      self.faces_vbo.bind()
      glIndexPointer(GL_UNSIGNED_INT, 0, 0)
  
      glColor3f(0., 1., 0.)
      glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, None)
  
      glDisableClientState(GL_VERTEX_ARRAY)
      glDisableClientState(GL_NORMAL_ARRAY)
  </code></pre>
  
  <p>I've also tried putting only the positions and normals in VBOs, and leaving the <code>faces</code> alone.  I've also tried using 0 instead of <code>None</code> in the glDrawElements.</p>
  
  <p>There is a similar question <a href="https://stackoverflow.com/questions/10075653/opengl-vbo-setup">here</a>, except that it doesn't use the<code>vbo.VBO</code> wrappers available in PyOpenGL.</p>