Search code examples
pythonopenglpyqt5framebufferpyopengl

OpenGL FrameBuffer off-screen, on-screen rendering problem with PyQT5


I'm trying to render to a fbo to use glReadPixels. I can render to fbo and read pixel value, but I cannot get it rendering on screen, I get an error like this:

err = 1286, description = b'invalid framebuffer operation',

Here is my steps:

    class MyGLWidget(QOpenGLWidget):
        ...
        ...
        def paintGl():
           ### offscreen rendering ###

           glBindFramebuffer(GL_FRAMEBUFFER, self.fbo);
           glClearColor(0.0, 0.0, 0.0, 1.0);
           glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
           # ... bind texture ...
           # ... shader program...
           # ... VAO
           # ... EBO
           # ... uniforms
           # ... draw

           glBindFramebuffer(GL_FRAMEBUFFER, 0) #<--- The problem is here. i don't know why
    
           ### read pixel ###
           glBindFramebuffer(GL_READ_FRAMEBUFFER, self.fbo)
           glReadBuffer(GL_COLOR_ATTACHMENT0)
           print(glReadPixels(0, 0, _width, _height, _format, _type)) #<-- I got correct value here.

           ### on screen render ###
           glClearColor(0.0, 0.0, 0.0, 1.0) #<---I got an error here
           glClear(GL_COLOR_BUFFER_BIT)
    
           # ... bind texture (color attachment texture)
           # ... shader program...
           # ... VAO
           # ... EBO
           glDrawElements(mode, count, _type, indices)  #<--- If i don't use glClear, I get an error here.
           

The problem is the line glBindFramebuffer(GL_FRAMEBUFFER, 0) If i remove that line, I don't get an error but I get black screen. I don't know what I'm doing wrong or maybe bugs from my graphic card or bugs in QOpenGLWidget. Hope you can help. Thanks in advance.


Solution

  • glBindFramebuffer(GL_FRAMEBUFFER, 0) #<--- The problem is here. i don't know why
    

    From the documentation for QOpenGLWidget (emphasis mine):

    All rendering happens into an OpenGL framebuffer object. makeCurrent() ensure that it is bound in the context. Keep this in mind when creating and binding additional framebuffer objects in the rendering code in paintGL(). Never re-bind the framebuffer with ID 0. Instead, call defaultFramebufferObject() to get the ID that should be bound.