在 QGLFramebufferObject 上渲染时错误的 alpha 混合

Posted

技术标签:

【中文标题】在 QGLFramebufferObject 上渲染时错误的 alpha 混合【英文标题】:Wrong alpha blending when rendering on a QGLFramebufferObject 【发布时间】:2012-09-06 19:18:24 【问题描述】:

我为我的应用程序编写了一个基于 OpenGL 的矢量图形渲染器。它需要渲染到帧缓冲区对象而不是直接渲染到屏幕。由于我在 Qt 中编写应用程序,因此我使用 QGLFramebufferObject,它是 OpenGL 帧缓冲区对象的包装类。

我创建了一个最小示例,它显示了在渲染更复杂的东西时我也得到了错误的结果(例如,使用片段着色器将颜色设置为非一个 alpha 值)。我只是在一个黑色的清除屏幕上渲染一个红色圆圈和一个半透明的绿色圆圈,然后在 FBO 上也一样:

void MainWidget::initializeGL()

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glClearColor(0, 0, 0, 0);


void MainWidget::resizeGL(int w, int h)

    glViewport(0, 0, w, h);


void MainWidget::paintGL()

    // DRAW ON THE SCREEN
    
        glClear(GL_COLOR_BUFFER_BIT);
        glPointSize(100);
        glEnable(GL_POINT_SMOOTH);
        glBegin(GL_POINTS);
        glColor4f(1, 0, 0, 1);
        glVertex2f(-.2, 0);
        glColor4f(0, 1, 0, .5);
        glVertex2f( .2, 0);
        glEnd();
    

    QGLFramebufferObject fbo(width(), height());
    fbo.bind();

    // DRAW ON THE FBO USING THE SAME CODE AND THE SAME CONTEXT
    
        glClear(GL_COLOR_BUFFER_BIT);
        glPointSize(100);
        glEnable(GL_POINT_SMOOTH);
        glBegin(GL_POINTS);
        glColor4f(1, 0, 0, 1);
        glVertex2f(-.2, 0);
        glColor4f(0, 1, 0, .5);
        glVertex2f( .2, 0);
        glEnd();
    

    fbo.release();
    fbo.toImage().save("debug.png");

屏幕上的结果如下所示(缩放 400%):

QGLFramebufferObject 的渲染看起来像这样(也缩放了 400%):

请注意,此图像不是完全不透明的,因此这里是相同的图像,后面添加了一个棋盘:

即使两个圆圈重叠的区域也不是完全不透明的。而且抗锯齿看起来很丑。

这是怎么发生的?我该如何解决这个问题?

我已经试过了:

不同的混合功能。 显式禁用 QGLFramebufferObject 上的深度缓冲区、模板缓冲区和采样。我不确定 QGLFramebufferObject 默认格式是否添加了我不想要的东西。

【问题讨论】:

@Nicol Bolas,我回滚了您的编辑,因为它与点平滑无关。渲染三角形时,我得到相同的结果,即使没有平滑。我尝试了很多不同的最小示例。绘制平滑点只是最小的一个。 抱歉,我忘记了 glClearColor 语句。它是完全透明的。将其添加到代码中不会改变任何内容。 【参考方案1】:

尝试以下方法:

QGLFramebufferObjectFormat fmt;
fmt.setSamples(1); // or 4 or disable this line
fmt.setInternalTextureFormat(GL_RGBA8);
QGLFramebufferObject fbo(width(), height(), fmt);

这会强制使用特定的像素格式,并且还会通过使用多重采样禁用渲染到纹理(否则 QT 总是渲染到纹理)。这可能会产生不同的结果。您也可以尝试这种格式。

另外,你的硬件是什么?我的最大点大小只有 64 像素(GTX 260),您正在尝试渲染 100 像素点。这可能是个问题。是否产生任何 OpenGL 错误?小点也会出现同样的情况吗?

您也可以尝试提示(如果在 QT 中可行的话):

glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);

但我不希望这会改变任何事情。

【讨论】:

以上是关于在 QGLFramebufferObject 上渲染时错误的 alpha 混合的主要内容,如果未能解决你的问题,请参考以下文章

在 QGLFramebufferObject 上渲染时错误的 alpha 混合

QPaint 到 QGLFramebufferObject 纹理上?

QGLFramebufferObject浮点纹理

渲染到 QGLFrameBufferObject 与屏幕时 Alpha 合成错误

我可以检测我的脚本是不是正在被 Webpack 处理吗?

Qt OpenGL帧缓冲区到图像