获得QOpenGLFramebufferObject抗锯齿纹理的替代方法,而不是多采样+比特

Alternative way to get QOpenGLFramebufferObject anti-aliased texture other than multisampling + blitting

本文关键字:比特 采样 方法 QOpenGLFramebufferObject 纹理 获得      更新时间:2023-10-16

我试图在基于windows的设备上在Qt 5.2.1基于小部件的应用程序上进行本地GL绘图时使用的FBO (QOpenGLFramebufferObject)的纹理上实现抗锯齿效果。支持OpenGL ES 2.0。

Qt文档中描述的使用两个QOpenGLFramebufferObject的机制,一个启用了多采样(例如4个采样),另一个不使用多采样作为目标FBO进行下采样,然后从多采样的一个到下采样的一个不工作。

这是因为设备上不支持blit操作,QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()返回false,即使它在支持blit的Win32桌面上正常工作抗锯齿。

有没有其他的方法来实现抗混叠而不使用这个blit操作?最好使用Qt组件来简化实现。


情况详情:
应用程序将GL绘图显示为屏幕背景,并在其上显示控件小部件(按钮、标签等)。GL绘图本身是由我们使用的第三方库完成的。
为此,我们使用QGraphicsViewQGraphicsScene让库绘制背景,并将控件控件添加到要在其顶部绘制的场景中。

除了为QGraphicsView的视口创建的QGLWidget的上下文之外,我们还有一个单独的GL上下文和专门为库创建的fbo,因为库希望自己有一个独占的上下文。上下文共享显示列表和纹理对象,并在库绘制之前和之后切换。

该库根据QTimer回调来模拟所需的每秒帧数。在绘制过程中,多采样FBO将被绑定并在绘制完成后释放,然后被位进到下采样的FBO。

QGraphicsScene::drawBackground()期间,下采样FBO的纹理将使用QGLContext::drawTexture()绘制在视口的上下文中。遗憾的是,这会在设备上产生垃圾,因为不支持从多采样到下采样的FBO的blit操作。

ES 2.0也不支持可以用作FBO附件的多采样纹理/renderbuffers。至少不能没有扩展。因此,ES 2.0不仅缺少blit来支持此功能。

最简单的解决方案是一直到完全超级抽样。质量方面,这可以优于多采样,因为它不仅平滑多边形边缘和交叉点。你要做的是分配一个纹理,它是最终渲染目标大小的数倍(通常是两倍)。渲染到它,然后用一个简单的着色器实现你自己的"blit"downsample。

有一个重要的警告:它非常需要资源。纹理是大小的4倍,所以如果你的渲染表面中等大小,它将使用大量内存。您甚至必须小心不要超过MAX_TEXTURE_SIZE限制。伴随着高内存使用率而来的是显著降低的性能。

至少还有另一种选择,这种方法在多采样广泛使用之前更常用。这个想法是,你渲染帧多次,有一个轻微的偏移,然后平均这些帧。在红皮书中查找"场景抗锯齿",了解如何使用老式OpenGL完成此操作。该代码中使用的累积缓冲区(以及其他大部分内容)早已被弃用,但您可以使用fbo实现相同的想法。