Qt 将渲染目标添加到QOpenGLWidget的默认帧缓冲区

Qt 将渲染目标添加到QOpenGLWidget的默认帧缓冲区,qt,opengl,framebuffer,rendertarget,Qt,Opengl,Framebuffer,Rendertarget,我想向QOpenGLWidget的默认帧缓冲区添加第二个渲染目标 原因是我想实现对象拾取,并通过在gl\u FragData[1]中渲染分割掩码来检查用户是否击中了对象。不幸的是,您只能从小部件中检索GLuint句柄,并且没有接受句柄的QOpenGLFramebufferObject构造函数,也没有其他选项来检索帧缓冲区 有没有可能在没有解决方法的情况下将另一个纹理附加到小部件的默认帧缓冲区 我能想到的唯一两个选择是: 1. 使用本机OpenGL调用附加纹理(我宁愿使用纯Qt),就像在初始化中那

我想向QOpenGLWidget的默认帧缓冲区添加第二个渲染目标

原因是我想实现对象拾取,并通过在
gl\u FragData[1]
中渲染分割掩码来检查用户是否击中了对象。不幸的是,您只能从小部件中检索
GLuint
句柄,并且没有接受句柄的
QOpenGLFramebufferObject
构造函数,也没有其他选项来检索帧缓冲区

有没有可能在没有解决方法的情况下将另一个纹理附加到小部件的默认帧缓冲区

我能想到的唯一两个选择是:

1. 使用本机OpenGL调用附加纹理(我宁愿使用纯Qt),就像在初始化中那样(当然我将存储
segmentationTexture
以便以后能够删除它):

然后在
paintGL()中

在OpenGL绘图调用之前,使用
glReadBuffer(GL\u COLOR\u ATTACHMENT1)
gl\u FragData[1]
检索内容。或者,如果这不起作用,只使用原生OpenGL代码生成纹理

2. 创建第二个帧缓冲区对象,将其绑定到
paintGL()
中,然后使用
glBlitFramebuffer
(用于多采样)将内容与默认帧缓冲区交换以显示渲染,但使用第二个帧缓冲区读取
gl\u FragData[1]
。但这感觉有点“恶心”

我想向
QOpenGLWidget
的默认帧缓冲区添加第二个渲染目标

答案很简单,您不能向任何OpenGL默认帧缓冲区对象添加第二个颜色附件

有两类帧缓冲区:当上下文成为当前上下文时,窗口系统提供的与上下文关联的帧缓冲区,以及应用程序创建的帧缓冲区窗口系统提供的帧缓冲区称为默认帧缓冲区。应用程序创建的帧缓冲区(称为帧缓冲区对象)可以根据需要创建,上下文可以与两个帧缓冲区关联,读取和绘制操作各一个。默认帧缓冲区和帧缓冲区对象的区别主要在于用于配置和管理其状态的接口

GL命令对默认帧缓冲区的影响最终由分配帧缓冲区资源的窗口系统控制 GL可在任何给定时间访问默认帧缓冲区的哪些部分,并向GL传达这些部分的结构。因此,没有用于初始化GL上下文或配置默认帧缓冲区的GL命令 类似地,物理显示设备上的帧缓冲区内容的显示(包括通过诸如伽马校正之类的技术对单个帧缓冲区值的转换)不由GL处理

帧缓冲区对象(具有非零名称的对象)与默认帧缓冲区在几个重要方面有所不同。首先,与默认帧缓冲区不同,帧缓冲区对象对于帧缓冲区中的每个逻辑缓冲区都具有可修改的附着点


对于拾取,您只需渲染到单独的
QOpenGLFramebufferObject
,即:

makeCurrent();
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0, 0, width(), height());
QOpenGLFramebufferObject fbo(width(), height(), QOpenGLFramebufferObject::CombinedDepthStencil);
fbo.bind();
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[…] render stuff […]
fbo.release();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glPopAttrib();
QImage fboImage(fbo.toImage());
QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32);

另请参见解释2
QImage
s的需要

也许我的问题在术语上有点误导。至少我说的是QOpenGLWidget的默认帧缓冲区,而不是整个窗口系统。对我来说,这听起来像是小部件创建了自己的帧缓冲区,它使用帧缓冲区渲染内容,然后将其交换到主帧缓冲区。那么你认为小部件的默认缓冲区是否与窗口系统的默认缓冲区相同?对不起,我不明白;)如果它不一样,我应该能够添加一个渲染目标到它,不是吗?啊,好的,我明白了。谢谢你的回答!这实际上也是我的解决方案(参见)。我只是想知道是否可以直接将纹理附加到默认缓冲区,以避免创建自定义帧缓冲区对象。但是谢谢你的回答!
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, buffers);
makeCurrent();
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0, 0, width(), height());
QOpenGLFramebufferObject fbo(width(), height(), QOpenGLFramebufferObject::CombinedDepthStencil);
fbo.bind();
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[…] render stuff […]
fbo.release();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glPopAttrib();
QImage fboImage(fbo.toImage());
QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32);