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

时间:2012-09-06 19:18:24

标签: qt opengl

我为我的应用程序编写了一个基于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%):

enter image description here

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

enter image description here

请注意,此图片并非完全不透明,因此这里的图片与添加了棋盘格的图片相同:

enter image description here

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

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

我已经尝试过:

  • 不同的混合功能。
  • 在QGLFramebufferObject上显式禁用深度缓冲区,模板缓冲区和采样。我不确定QGLFramebufferObject默认格式是否会添加我不想要的内容。

1 个答案:

答案 0 :(得分: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);

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