简体   繁体   中英

PyOpenGL reading back buffer color

I have one sphere in my Pyqt5 window drawn by PyOpenGL:

Then, I am switching to the back buffer using self.swapBuffers() and then draw again to the back buffer but with a different color.

And with a mouse click, I am trying to read the back buffer color,

But it is giving me the value of the front buffer. The problem here, is it possible to read the value from the back, if so, what is exactly wrong here?

Small example generated with the answer in the link https://stackoverflow.com/a/46259752/3870250

from OpenGL.GL import *
from OpenGL.GLU import *
from PyQt5 import QtGui
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import *
from PyQt5.QtOpenGL import *
import sys

class MainWindow(QWidget):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.widget = GLWidget(self)
        self.statusbar = QStatusBar()
        self.statusbar.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.statusbar.showMessage("Click anywhere on the QGLWidget to see a pixel's RGBA value!")
        layout = QVBoxLayout()
        layout.addWidget(self.widget)
        layout.addWidget(self.statusbar)
        layout.setContentsMargins(5, 5, 5, 5)
        self.setLayout(layout)

class GLWidget(QGLWidget):

    def __init__(self, parent):
        QGLWidget.__init__(self, parent)
        self.setMinimumSize(640, 480)
        #LMB = left mouse button
        #True: fires mouseMoveEvents even when not holding down LMB
        #False: only fire mouseMoveEvents when holding down LMB
        self.setMouseTracking(False)

    def initializeGL(self):
        glClearColor(0, 0, 0, 1)
        glClearDepth(1.0)
        glEnable(GL_DEPTH_TEST)

    def resizeGL(self, width, height):
        #glViewport is needed for proper resizing of QGLWidget
        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(0, width, 0, height, -1, 1)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

    def paintGL(self):
        w, h = self.width(), self.height()
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        Q = gluNewQuadric()

        glTranslatef(w/2, h/2, -w/2*0.1)
        glColor3f(1.0, 1.0, 1.0)
        gluSphere(Q, w/2*0.1, 32, 32)
        glTranslatef(-w/2, -h/2, +w/2*0.1)
        self.swapBuffers()
        glTranslatef(w/2, h/2, -w/2*0.1)
        # print(GlWidget.joint_nodes[i][1], GlWidget.joint_nodes[i][2])
        glColor3f(1.0, 1.0, 0.5)

        gluSphere(Q, w/2*0.1, 32, 32)
        glTranslatef(-w/2, -h/2, w/2*0.1)
        self.swapBuffers()

    def mousePressEvent(self, event):
        x, y = event.x(), event.y()
        self.swapBuffers()
        glReadBuffer(GL_BACK)
        c= glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT)
        print('c = ',c)

    def mouseMoveEvent(self, event):
        pass

    def mouseReleaseEvent(self, event):
        pass

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.setWindowTitle("Color Picker Demo")
    window.show()
    app.exec_()

The following sequence

 self.swapBuffers() glReadBuffer(GL_BACK) c= glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT)

is never going to work. After a buffer swap, the contents of the back buffer become undefined .

I have one sphere in my Pyqt5 window drawn by PyOpenGL. Then, I am switching to the back buffer using self.swapBuffers() and then draw again to the back buffer but with a different color.

Uhm, no you're not doing that. You just render once, and present the rendering content with self.swapBuffers() at the end of paintGL . The contents of the back buffer are now undefined. At mouse click, you swap the buffer again, so the undefined content becomes visible as the front buffer, and the back buffer is undefined again, and read that back. You never even attempt at drawing with a different color.

There is of course a high chance the the GPU is using some kind of swap chain internally, so the "undefined" contents are typically contents of prior frames, but not just the previous one.

Your whole scheme does not make sense. If you want to go the simple rendering approach for the picking, you would not use SwapBuffers at all . Just render to the back buffer, and read back from the back buffer. And when you render the next frame which is to be visible, you overwrite the contents of that same back buffer again, and finally swap the buffers to present it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM