pythonopenglpygamepyopenglvertex-buffer

OpenGL pygame cannot get buffers working reliably with vertextPointer and colorPointer


So I'm pretty sure I'm just doing something wrong here with how I'm calling the OpenGL. I've provided an example below where about 30% of the time it shows the semi transparent vertex colored squares on top of a red background. The other 70% of the time it only shows the red background. I tried commenting out various opengl commands to see if I could get it working reliably. This is my attempt at a "minimum" reproducible example from a much larger program.

I tried adding z coordinates to the points and setting GL_DEPTH_TEST but it made no difference it still doesn't work 70% of the time.

Strangely sometimes it will get in a state where the program will work every other time for afew times but perhaps that's just a coincidence.

Also when it does work it works fine and cycles through all the colors for the different squares until the program terminates, so it makes me think it's something wrong with the initialization or some race condition or something.


import OpenGL.GL as gl
import numpy as np
import pygame as pg
from pygame import locals as pg_locals
import time


class OpenGLWindow:
    def __init__(self):
        self.use_color_buffer = 0

        flags = pg_locals.DOUBLEBUF | pg_locals.OPENGL | pg_locals.RESIZABLE
        self.pg_window = pg.display.set_mode(
            (800, 600),
            flags,
            vsync=1,
        )

        # gl.glTexEnvf(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_MODULATE)
        # gl.glEnable(gl.GL_DEPTH_TEST) # we are disabling this for now because the texture z depth and overlay elements aren't configured right yet.
        gl.glEnable(gl.GL_BLEND)
        gl.glEnable(gl.GL_COLOR_MATERIAL)
        gl.glColorMaterial(gl.GL_FRONT_AND_BACK, gl.GL_AMBIENT_AND_DIFFUSE)
        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
        # gl.glEnable(gl.GL_TEXTURE_2D)

        # gl.glLoadIdentity()

        self.setup_buffers_2()

    def setup_buffers_2(self):
        self._vertexBuffer = gl.glGenBuffers(1)
        self._colorBuffers = gl.glGenBuffers(3)
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._vertexBuffer)
        vertices = np.array(
            [0.5, 0.5, 0, 0.5, 0, 0, 0.5, 0, -0.5, -0.5, 0, -0.5, 0, 0, -0.5, 0],
            dtype="float32",
        )
        gl.glBufferData(gl.GL_ARRAY_BUFFER, vertices, gl.GL_STATIC_DRAW)  # Error
        for n in range(3):
            gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._colorBuffers[n])
            colors = []
            for p in range(8):
                for c in range(3):
                    colors.append((p % 4) * 0.25 if c == n else 0)
                colors.append((p % 4) * 0.25)
            print(colors)
            gl.glBufferData(
                gl.GL_ARRAY_BUFFER, np.array(colors, dtype="float32"), gl.GL_STATIC_DRAW
            )

    def cleanup_buffers_2(self):
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._vertexBuffer)
        gl.glDeleteBuffers(1, self._vertexBuffer)
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
        for n in range(3):
            gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._colorBuffers[n])
            gl.glDeleteBuffers(3, self._colorBuffers)
            gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)

    def render_opengl_2(self):
        gl.glClearColor(1.0, 0.0, 0.0, 1.0)
        gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)

        gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
        gl.glEnableClientState(gl.GL_COLOR_ARRAY)
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._vertexBuffer)
        gl.glVertexPointer(2, gl.GL_FLOAT, 0, 0)
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._colorBuffers[self.use_color_buffer])
        gl.glColorPointer(4, gl.GL_FLOAT, 0, 0)
        gl.glDrawArrays(gl.GL_QUADS, 0, 8)

        pg.display.flip()

        self.use_color_buffer += 1
        self.use_color_buffer %= 3


window = OpenGLWindow()

# window.render_opengl_2()
# time.sleep(1)
# window.cleanup_buffers_2()

try:
    for _ in range(30):
        window.render_opengl_2()
        time.sleep(0.1)
finally:
    window.cleanup_buffers_2()

Solution

  • The last parameter of glVertexPointer is of type const GLvoid *. So the argument has to be None or ctypes.c_void_p(0), but not 0:

    gl.glVertexPointer(2, gl.GL_FLOAT, 0, 0)

    gl.glVertexPointer(2, gl.GL_FLOAT, 0, None)
    

    The same applies to glColorPointer.