Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

OpenGL help



  • I'm trying to learn OpenGL using Qt5 to create the context and handle events. I thought that since I'm doing it in Qt anyway, I might as well use Qt-functions (QOpenGLExtraFunctions). I am currently a bit stuck on trying to handle instances in the shaders, and could use a bit of help. The documentation is oftentimes just for C++.

    I could before-this successfully render a number of rotating cubes, but I was doing so with individual draw calls for all of them which bogged the rendering down something massively.

    The code is a little bit too long for pasting here, but here's a link to my working repository, where the branch master is a stable (non-instance buffer) approach, and where the branch instancing contains my attempt at just that.


    The core snippets to describe what I'm trying to do are:

    (lines 160–176 in opengl.py)

            for i, j, k in itertools.product(
                    range(0, 100, 2),
                    range(0, 100, 2),
                    range(0, 100, 2)
            ):
                translation = pyrr.Vector3([0.0, 0.0, 0.0])
                translation.x = i + self.instance_offset
                translation.y = j + self.instance_offset
                translation.z = k + self.instance_offset
                self.instance_array.append(translation)
    
            self.len_of_instance_array = len(self.instance_array)
            self.instance_array = np.array(self.instance_array, dtype=np.float32).flatten()
    
            self.instance_vbo.create()
            self.instance_vbo.bind()
            self.instance_vbo.allocate(self.instance_array, self.instance_array.nbytes)
    

    (lines 192–196 in opengl.py)

            self.glEnableVertexAttribArray(2)
            self.glVertexAttribPointer(
                2, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, VoidPtr(0)
            )
            self.glVertexAttribDivisor(2, 1)
    

    ...with the draw call:

    (lines 99–117 in opengl.py)

        def render(self) -> None:
            self.program.bind()
            vao_binder = QOpenGLVertexArrayObject.Binder(self.vao)
    
            # TODO: switch to Qt functions (doesn't work)
            gl.glUniformMatrix4fv(self.projection_loc, 1, gl.GL_FALSE, self.projection)
            view = self.camera.get_view_matrix()
            gl.glUniformMatrix4fv(self.camera_loc, 1, gl.GL_FALSE, view)
    
            self.glDrawElementsInstanced(
                gl.GL_TRIANGLES,
                len(self.shape.indices),
                gl.GL_UNSIGNED_INT,
                VoidPtr(0),
                self.len_of_instance_array
            )
    
            self.program.release()
            vao_binder = None
    

    ...and my vertex shader is quite simple:

    # version 410 core
    
    layout(location = 0) in vec3 a_position;
    layout(location = 1) in vec3 a_color;
    layout(location = 2) in vec3 a_offset;
    
    uniform mat4 model;
    uniform mat4 projection;
    uniform mat4 camera;
    
    out vec3 v_color;
    
    void main()
    {
        vec3 final_pos = a_position + a_offset;
        gl_Position = projection * camera * model * vec4(final_pos, 1.0);
        v_color = a_color;
    }
    

    Since I'm writing here anyway, I've also run into some other issues that people may have experience with. One of them is that I've had massive issues with null pointers (which is why I use VoidPtr(0))—I've seen others use just 0 and I've read that None is supposed to work in Python but to no avail. And in my drawing calls, I've had to fall back to functions from OpenGL.GL instead of using Qt-wrapped ones.

    Any and all help appreciated.


Log in to reply