5

我为我的应用程序编写了一个基于 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 默认格式是否添加了我不想要的东西。
4

1 回答 1

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);

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

于 2012-11-09T12:40:55.070 回答