Search code examples
pythonopenglpygletopengl-compat

How to work with glDrawArrays and glVertexPointer?


I need to rework my programme from glVertex to glDrawArrays and I am trying to sort out with this functions. Can you explain why this code doesn't work and how to change it, so it draws 2 triangles?

import pyglet
import pyglet.gl as pgl


win = pyglet.window.Window(1300, 1000, resizable=True)



@win.event
def on_draw():

    array = [100, 100, 0,
             500, 300, 0,
             900, 100, 0,
             100, 300, 0,
             500, 500, 0,
             900, 300, 0]


    pgl.glClearColor(0.3, 0.3, 0.3, 0.0)
    pgl.glEnableClientState(pgl.GL_VERTEX_ARRAY)
    pgl.glVertexPointer(3, pgl.GL_FLOAT, 18, (pgl.GLubyte * len(array))(*array))

    pgl.glDrawArrays(pgl.GL_TRIANGLES, 0,18)
    pgl.glDisableClientState(pgl.GL_VERTEX_ARRAY)



pyglet.app.run()

Solution

  • The type of the data in the buffer has to correspond to the type which is specified when the array of vertex data is defined by glVertexPointer.
    Since the set type is GL_FLOAT, the array data has to be of type GLfloat:

    data = (pgl.GLfloat * len(array))(*array)
    

    The 3rd parameter (stride) of glVertexPointer (and similar functions) specifies the byte offset between consecutive attributes.
    Since each vertex consists of 3 components (x, y, z) and the size of one component is the size of GLfloat, the stride has to be 3*4 = 12.
    Since the buffer is tightly packed, stride can be set 0, too. This is special case provided by glVertexPointer (and similar functions). If the stride is set 0, it is automatically calculated by the size and type parameter.

    pgl.glVertexPointer(3, pgl.GL_FLOAT, 0, data)
    

    Final code:

    import pyglet
    import pyglet.gl as pgl
    
    win = pyglet.window.Window(1300, 1000, resizable=True)
    
    @win.event
    def on_draw():
    
        array = [100, 100, 0,
                 500, 300, 0,
                 900, 100, 0,
                 100, 300, 0,
                 500, 500, 0,
                 900, 300, 0]
    
    
        pgl.glClearColor(0.3, 0.3, 0.3, 0.0)
        pgl.glEnableClientState(pgl.GL_VERTEX_ARRAY)
        data = (pgl.GLfloat * len(array))(*array)
        pgl.glVertexPointer(3, pgl.GL_FLOAT, 0, data)
    
        pgl.glDrawArrays(pgl.GL_TRIANGLES, 0, 18)
        pgl.glDisableClientState(pgl.GL_VERTEX_ARRAY)
    
    pyglet.app.run()