Search code examples
pythonopenglpyopengl

Application crashes in PyOpenGL when trying to render Triangle


I struggle dealing with this problem. I have spent my night on it and I do require help. I want to display a simple triangle with the PyOpenGL bindings but my application crashes, plus nothing is rendered. I use for the project a glfw window - nothing particular is done on it - and these are the settings in my initGL function.

glViewport(0, 0, 500, 500)
glClearColor(0, 0, 0, 1)
glClearDepth(1)

glEnable(GL_BLEND); # activates blending mode
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

glEnable(GL_DEPTH_TEST) # enables depth testing

glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)

This is what my game loop looks like:

while not window.shouldClose 
   window.clear()
   render()
   window.swap_buffers()
   window.poll_events()

But I think that the problem that need a fix, is somewhere in the following code. This is the render function called in the game loop:

def render(self):
   glUseProgram(self.shader_program)
   self.mesh_filter.bind()
   self.mesh_filter.render() <- this line make the applicaion crash after few loops
   self.mesh_filter.unbind()
   glUseProgram(0)

And the code for my class MeshFilter:

class MeshFilter():
    def __init__(self, vertices: list, indices: list):
        self.vaoId = glGenVertexArrays(1)
        glBindVertexArray(self.vaoId)
        
        self.count = len(indices)
        self.__allocateIndexBuffer(indices)
        
        self.vbosId = []
        self.__allocateAttributeBuffer(0, 4, vertices)
        
        glBindVertexArray(0)
    
    def __allocateIndexBuffer(self, indices):
        self.eboId = glGenBuffers(1)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.eboId)
        
        self.count = len(indices)
        indices = uint32(indices)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(indices), indices, GL_STATIC_DRAW)
    
    def __allocateAttributeBuffer(self, attribute_index, attribute_size, buffer):
        vboId = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, vboId)
        self.vbosId.insert(attribute_index, vboId)
        
        buffer = float32(buffer)
        glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(buffer), buffer, GL_STATIC_DRAW)
        glVertexAttribPointer(attribute_index, attribute_size, GL_FLOAT, GL_FALSE, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER, 0)
        
    def bind(self):
        glBindVertexArray(self.vaoId);
        for attribute in range(len(self.vbosId)):
            glEnableVertexAttribArray(attribute)
    
    def unbind(self):
        for attribute in range(len(self.vbosId)):
            glDisableVertexAttribArray(attribute)
        glBindVertexArray(0)
        
    def render(self):
        glDrawElements(GL_TRIANGLES, self.count, GL_UNSIGNED_INT, 0)
        
    def destroy(self):
        glDeleteBuffers(1, [self.eboId])
        glDeleteBuffers(len(self.vbosId), self.vbosId)
        glDeleteVertexArrays(1, [self.vaoId])

The meshFilter is called with the following parameters

indices = [0, 1, 2] triangle = [0.6, 0.6, 0, 1.0, -0.6, 0.6, 0, 1.0, 0.0, -0.6, 0, 1.0]

Feel free to ask me for piece of codes, or further explanation.

Edit if i replace the drawElements with glDrawArrays(GL_TRIANGLES, 0, 3), it works perfectly.. So i pressume, the mistake is around the indices storage.


Solution

  • EDIT : SOLUTION

    glDrawElements requires None or the nullptr in ctypes as last argument, not 0 as in my previous Java code.

    Like so, glDrawElements(GL_TRIANGLES, self.count, GL_UNSIGNED_INT, None)