PDA

View Full Version : Cannot read GL_DEPTH_COMPONENT using QOpenGLWidget outside of paintGL() function



amaltsev
03-03-2018, 06:33 AM
Hi all. The problem seems to be special for Qt5 class QopenGLWidget. Similar code works properly under MFC implementation using GLEW.
I try to use glReadPixels with GL_DEPTH_COMPONENT to read the z depth value of the point under the mouse cursor. The z value is simply not read and the consequent glGetError() call returns GL_INVALID_OPERATION code which in turn means there is no depth buffer. I set glEnable(GL_DEPTH_TEST) in initializeGL() of my GLWidget derived from QOpenGLWidget. I also call glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); in painGL().
If I check glIsEnabled(GL_DEPTH_TEST) it returns GL_FALSE in my picking function (outside of paintGL()) and GL_TRUE in paintGL() where the rendering code actually is. How can it be? I would assume that GL_DEPTH_TEST is either always enabled or always disabled. Anyway I do not disable it by myself. Does anyone know does QOpenGLWidget do some strange things with depth buffer between paintGL() calls?

Dark Photon
03-03-2018, 10:19 AM
Have you tried calling grabFramebuffer()?

The docs say that QOpenGLWidget internally renders to an off-screen FBO. So my guess is that where you're calling glReadPixels(), that FBO is just not bound and instead some other framebuffer is. If so, you either need to:


use a Qt API to query the contents for you (e.g. grabFramebuffer()), or
coax Qt to bind that FBO for you first before glReadPixels() on your side is going to work (e.g. makeCurrent()), or
coax Qt into giving you the FBO framebuffer handle so you can bind it yourself before glReadPixels() on your side is going to work.

Keep in mind that there are other reasons that glReadPixels() (https://www.khronos.org/opengl/wiki/GLAPI/glReadPixels) might return GL_INVALID_OPERATION, though I suspect your guess is the most likely reason here.
Some related threads:


QOpenGLWidget (https://doc.qt.io/qt-5/qopenglwidget.html) (Qt 5.1)
Easiest way for offscreen rendering with QOpenGLWidget (https://stackoverflow.com/questions/31323749/easiest-way-for-offscreen-rendering-with-qopenglwidget)
QTBUG-47185 - Hidden QOpenGLWidget does not render() (https://bugreports.qt.io/browse/QTBUG-47185)

amaltsev
03-04-2018, 03:56 AM
Have you tried calling grabFramebuffer()?

The docs say that QOpenGLWidget internally renders to an off-screen FBO. So my guess is that where you're calling glReadPixels(), that FBO is just not bound and instead some other framebuffer is. If so, you either need to:


use a Qt API to query the contents for you (e.g. grabFramebuffer()), or
coax Qt to bind that FBO for you first before glReadPixels() on your side is going to work (e.g. makeCurrent()), or
coax Qt into giving you the FBO framebuffer handle so you can bind it yourself before glReadPixels() on your side is going to work.

Keep in mind that there are other reasons that glReadPixels() (https://www.khronos.org/opengl/wiki/GLAPI/glReadPixels) might return GL_INVALID_OPERATION, though I suspect your guess is the most likely reason here.
Some related threads:


QOpenGLWidget (https://doc.qt.io/qt-5/qopenglwidget.html) (Qt 5.1)
Easiest way for offscreen rendering with QOpenGLWidget (https://stackoverflow.com/questions/31323749/easiest-way-for-offscreen-rendering-with-qopenglwidget)
QTBUG-47185 - Hidden QOpenGLWidget does not render() (https://bugreports.qt.io/browse/QTBUG-47185)



Many thanks! Yes I have tried grabFramebuffer(). It has worked. But it is only able to obtain a 32-bit QImage which I can e.g. redirect into external file. What I need is the depth buffer.
Anyway you are right the FBO is not bound at the position of code where I need it. I need to find out the way to bind the FBO within QOpenGLWidget.

amaltsev
03-04-2018, 11:18 AM
The solution is calling makeCurrent() prior to the glReadPixels call. makeCurrent() ensures the FBO binding and then the depth buffer is available for reading. Thanks for good idea!