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

时间:2018-06-20 08:26:38

标签: qt opengl framebuffer rendertarget

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

原因是我想实现对象拾取,并通过将分段蒙版渲染到gl_FragData[1]中来检查用户是否击中了对象。不幸的是,您只能从窗口小部件中检索GLuint句柄,并且没有QOpenGLFramebufferObject的构造函数接受该句柄,并且没有其他选择来检索帧缓冲区。

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

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

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

glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject());
QOpenGLTexture *segmentationTexture = new QOpenGLTexture(QOpenGLTexture::BindingTargetBuffer);
// set texture parameters
segmentationTexture.create();
segmentationTexture.bind();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, segmentationTexture.textureId(), 0);
segmentationTexture.release();

,然后在paintGL()

GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, buffers);

在OpenGL绘制调用之前,并使用glReadBuffer(GL_COLOR_ATTACHMENT1);gl_FragData[1]检索内容。或者,如果这行不通,请仅使用本机OpenGL代码生成纹理。

2。 创建第二个帧缓冲区对象,将其绑定到paintGL()中,然后使用glBlitFramebuffer(以考虑多次采样)与默认帧缓冲区交换内容,以显示渲染,但使用第二个帧缓冲区从{{ 1}}。但这感觉有点“讨厌”。

2 个答案:

答案 0 :(得分:1)

  

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

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

请参见OpenGL 4.6 API Compatibility Profile Specification; 2.1. EXECUTION MODEL; page 9

  

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

     

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

请参见OpenGL 4.6 API Compatibility Profile Specification; 9.2. BINDING AND MANAGING FRAMEBUFFER OBJECTS; page 340

  

帧缓冲区对象(名称不为零的对象)在一些重要方面与默认帧缓冲区不同。首先,与默认帧缓冲区不同,帧缓冲区对象为帧缓冲区中的每个逻辑缓冲区具有可修改的附加点。

答案 1 :(得分:0)

对于选择,您可以仅渲染到单独的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);

另请参阅toImage docs来说明需要使用两个QImage