Search code examples
pythonopenglvbopyopenglvao

PyOpenGL glDeleteBuffers and glDeleteVertexArrays produces an error


When calling glDeleteVertexArrays(1, vao_id) or glDeleteBuffers(1, vbo_id) produces a type error:

Traceback (most recent call last): File "C:\Users\Ollie\AppData\Local\Programs\Python\Python39\lib\site-packages\OpenGL\latebind.py", line 43, in call return self._finalCall( *args, **named ) TypeError: 'NoneType' object is not callable

However when I change the line to glDeleteVertexArrays(1, [vao_id]) (and the same for the vbo) the error goes away. Does this method still free up the memory correctly? is there a different way to go about this? Why do i need to pass it in as a list?

my full code:

import numpy
import glfw
from OpenGL.GL import *

if not glfw.init():
    raise Exception("glfw failed")

glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, GL_TRUE)
glfw.window_hint(glfw.VISIBLE, GL_TRUE)
glfw.window_hint(glfw.RESIZABLE, GL_FALSE)

window = glfw.create_window(720, 480, "triangle", None, None)

if not window:
    glfw.Terminate()
    raise Exception("window failed to create!")

glfw.make_context_current(window)

glClearColor(0.5,0.5,0.5,1)

vertices = [
    -0.5, -0.5, 0.0,
     0.5, -0.5, 0.0,
     0.0,  0.5, 0.0
    ]

vao_id = glGenVertexArrays(1)
glBindVertexArray(vao_id)
glEnableVertexAttribArray(0)


vbo_id = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo_id)

vertices = numpy.array(vertices, dtype=numpy.float32)
glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW)

glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, 0)

while not glfw.window_should_close(window):
    glfw.poll_events()
    glClear(GL_COLOR_BUFFER_BIT)

    glBindVertexArray(vao_id)
    glDrawArrays(GL_TRIANGLES, 0, 3)
    
    glfw.swap_buffers(window)

#no error
glDeleteVertexArrays(1, [vao_id])
glDeleteBuffers(1, [vbo_id])

#error:
#glDeleteVertexArrays(1, vao_id)
#glDeleteBuffers(1, vbo_id)

glfw.terminate()

Solution

  • From the C API documentation you'll see...

    void glDeleteVertexArrays(GLsizei n, const GLuint *arrays);
    

    So the second arg needs to be a GLuint * -- typically either a pointer to a single GLuint or the name of an array of GLuint.

    Translated to python this means you need to provide it with a python array. If vao_id is a single VAO id then changing the second arg from vao_id to [vao_id] creates a temporary array with a single element -- namely vao_id. Similarly for glDeleteBuffers.