pythonopenglpygamepyopenglopengl-compat

Rendering a 2D quad from a VBO with PyOpenGL?


How Can You Render A Quad From A VBO using PyOpenGL and Pygame?

I am trying to get an image to render on my screen using PyOoenGL and pygame, while not using any VBO's I managed to get it to display using this draw function:

def draw(texture: Texture):
    texture.Bind()
    glBegin(GL_QUADS)
    glTexCoord2f(0, 0)
    glVertex2f(-1, -1)
    glTexCoord2f(1, 0)
    glVertex2f(1, -1)
    glTexCoord2f(1, 1)
    glVertex2f(1, 1)
    glTexCoord2f(0, 1)
    glVertex2f(-1, 1)
    glEnd()

However, when I tried to change it out to render using a VBO I could not see well... anything:

def GenVBO():
    # gen VBO for a quad # glBufferSubData(GL_ARRAY_BUFFER, offset, len(dataArray)*4, dataArray)
    VBO = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, VBO)
    glBufferData(GL_ARRAY_BUFFER, 64, None, GL_STATIC_DRAW)
    glBufferSubData(GL_ARRAY_BUFFER, 0, 32, (GLfloat * 12)(-1, -1, 0, 0, 0, 0, 1, -1, 0, 1, 0, 0))
    glBindBuffer(GL_ARRAY_BUFFER, 0)
    return VBO


def draw(texture: Texture, VBO):
    texture.Bind()
    glBindBuffer(GL_ARRAY_BUFFER, VBO)
    glEnableClientState(GL_VERTEX_ARRAY)
    glEnableClientState(GL_TEXTURE_COORD_ARRAY)
    glVertexPointer(2, GL_FLOAT, 32, None)
    glTexCoordPointer(2, GL_FLOAT, 32, ctypes.c_void_p(8))
    glDrawArrays(GL_QUADS, 0, 4)

I do not get any errors, just a blank screen, I have also tried to move around by changing my perspective with a movement script, but still no output.

And just in case it's relevant, here is the main script:

def main():
    pygame.init()
    display = (800, 600)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
    glEnable(GL_TEXTURE_2D)
    glEnable(GL_BLEND)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
    glTranslatef(0.0, 0.0, -5)
    texture = LoadImage("test.png")
    VBO = GenVBO()
    while True:
        down = pygame.key.get_pressed()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
        # (the movement script is here)
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        draw(texture, VBO)
        pygame.display.flip()
        pygame.time.wait(10)

Solution

  • You have 2 possibiliets:

    1. (x0, y0, u0, v0, x1, y1, u1, v1, ...)

      In this case stride is 16 bytes, because each attribute tuple has 4*4 bytes (x, y, u, v). The offset of the vertices is 0 and the offset of the texture coordinates is 8 bytes:

      bufferData = (GLfloat * 16)(-1, -1, 0, 0, 1, -1, 1, 0, 1, 1, 1, 1, -1, 1, 0, 1)
      glBufferData(GL_ARRAY_BUFFER, bufferData, GL_STATIC_DRAW)
      
      glVertexPointer(2, GL_FLOAT, 16, None)
      glTexCoordPointer(2, GL_FLOAT, 16, ctypes.c_void_p(8))
      
    2. (x0, y0, x1, y1, ..., u0, v0, u1, v1, ...)

      In this case stride vor the vertices is 8 bytes and the stride for the texture coordinates is 8 bytes. The offset of the vertices is 0 and the offset of the texture coordinates is 32 bytes (8*4):

      vertexData  = (GLfloat * 8)(-1, -1, 1, -1, 1, 1, -1, 1)
      textureData = (GLfloat * 8)( 0,  0, 1,  0, 1, 1,  0, 1)
      glBufferData(GL_ARRAY_BUFFER, 64, None, GL_STATIC_DRAW)
      glBufferSubData(GL_ARRAY_BUFFER, 0, 32, vertexData)
      glBufferSubData(GL_ARRAY_BUFFER, 32, 32, textureData)
      
      glVertexPointer(2, GL_FLOAT, 8, None)
      glTexCoordPointer(2, GL_FLOAT, 8, ctypes.c_void_p(32))