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

lee*_*mes 5 opengl qt

我为我的应用程序编写了一个基于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");
}
Run Code Online (Sandbox Code Playgroud)

结果在屏幕上显示如下(缩放400%):

在此输入图像描述

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

在此输入图像描述

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

在此输入图像描述

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

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

我已经尝试过:

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

the*_*ine 1

请尝试以下操作:

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

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

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

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

glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
Run Code Online (Sandbox Code Playgroud)

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