C++ QOpenGLWidget和glReadPixels及深度缓冲区
作为我使用QOpenGLWidget在QT中制作的3D网格查看器的一部分,我需要为用户提供单击模型内节点的功能。为了将选择仅限于可见节点,我尝试在选择算法中包含glReadPixels(GLU深度分量) 我的问题是glReadPixels(depth)总是返回0。下面代码中的所有错误输出也返回0。glReadPixels(红色)返回正确的值:C++ QOpenGLWidget和glReadPixels及深度缓冲区,c++,qt,opengl,C++,Qt,Opengl,作为我使用QOpenGLWidget在QT中制作的3D网格查看器的一部分,我需要为用户提供单击模型内节点的功能。为了将选择仅限于可见节点,我尝试在选择算法中包含glReadPixels(GLU深度分量) 我的问题是glReadPixels(depth)总是返回0。下面代码中的所有错误输出也返回0。glReadPixels(红色)返回正确的值: GLenum err = GL_NO_ERROR; QTextStream(stdout) << "error before
GLenum err = GL_NO_ERROR;
QTextStream(stdout) << "error before reading gl_red = " << err << endl;
GLfloat winX, winY, myred, mydepth;
winX = mousex;
winY = this->height() - mousey;
glReadPixels(winX,winY,1,1,GL_RED,GL_FLOAT, &myred);
QTextStream(stdout) << "GL RED = " << myred << endl;
err = glGetError();
QTextStream(stdout) << "error after reading gl_red = " << err << endl;
glReadPixels(winX,winY,1,1,GL_DEPTH_COMPONENT,GL_FLOAT, &mydepth);
QTextStream(stdout) << "GL_DEPTH_COMPONENT = " << mydepth << endl;
err = glGetError();
QTextStream(stdout) << "error after reading gl_depth = " << err << endl;
在我的主文件中,我显式地将我的OpenGL版本设置为具有glReadPixels(GL_DEPTH_组件)功能的版本(与OpenGL ES 2.0相反):
我的glReadPixels(深度)不工作的问题是否与我对深度缓冲区的处理有关
在调用glReadPixels之前,我是否需要“激活”深度缓冲区以便能够从中读取?或者我需要让我的顶点着色器显式地将深度位置写入其他对象吗?QOpenGLWidget可用于底层FBO,如果启用了多重采样,则无法简单地从该FBO读取深度分量。最简单的解决方案是将样本设置为零,因此您的代码如下所示:
QSurfaceFormat format;
format.setVersion(2, 1);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setDepthBufferSize(32);
format.setSamples(0);
QSurfaceFormat::setDefaultFormat(format);
或者,您可以使用多重采样,但在可以复制深度缓冲区的情况下,需要额外的FBO,而不需要多重采样
class MyGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
//
// OTHER WIDGET RELATED STUFF
//
QOpenGLFramebufferObject* mFBO = nullptr;
MyGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//
// DRAW YOUR SCENE HERE!
//
QOpenGLContext *ctx = QOpenGLContext::currentContext();
// FBO must be re-created! is there a way to reset it?
if(mFBO) delete mFBO;
QOpenGLFramebufferObjectFormat format;
format.setSamples(0);
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
mFBO = new QOpenGLFramebufferObject(size(), format);
glBindFramebuffer(GL_READ_FRAMEBUFFER, ctx->defaultFramebufferObject());
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO->handle());
ctx->extraFunctions()->glBlitFramebuffer(0, 0, width(), height(), 0, 0, mFBO->width(), mFBO->height(), GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT, GL_NEAREST);
mFBO->bind(); // must rebind, otherwise it won't work!
float mouseDepth = 1.f;
glReadPixels(mouseX, mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &mouseDepth);
mFBO->release();
}
};
QSurfaceFormat format;
format.setVersion(2, 1);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setDepthBufferSize(32);
format.setSamples(0);
QSurfaceFormat::setDefaultFormat(format);
class MyGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
//
// OTHER WIDGET RELATED STUFF
//
QOpenGLFramebufferObject* mFBO = nullptr;
MyGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//
// DRAW YOUR SCENE HERE!
//
QOpenGLContext *ctx = QOpenGLContext::currentContext();
// FBO must be re-created! is there a way to reset it?
if(mFBO) delete mFBO;
QOpenGLFramebufferObjectFormat format;
format.setSamples(0);
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
mFBO = new QOpenGLFramebufferObject(size(), format);
glBindFramebuffer(GL_READ_FRAMEBUFFER, ctx->defaultFramebufferObject());
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO->handle());
ctx->extraFunctions()->glBlitFramebuffer(0, 0, width(), height(), 0, 0, mFBO->width(), mFBO->height(), GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT, GL_NEAREST);
mFBO->bind(); // must rebind, otherwise it won't work!
float mouseDepth = 1.f;
glReadPixels(mouseX, mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &mouseDepth);
mFBO->release();
}
};