Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrong alpha blending when rendering on a QGLFramebufferObject

Tags:

qt

opengl

I write an OpenGL based vector graphics renderer for my application. It needs to render to a framebuffer object rather to the screen directly. Since I write the application in Qt, I use a QGLFramebufferObject which is a wrapper class for a OpenGL framebuffer object.

I created a minimal example which shows a wrong result I also get when rendering more complex stuff (for example using a fragment shader which sets colors with a non-one alpha value). I just render a red circle and a half-transparent green one on a black cleared screen, and then the same on the 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");
}

The result looks like this on the screen (scaled 400%):

enter image description here

The rendering to the QGLFramebufferObject looks like this (also scaled 400%):

enter image description here

Note that this image is not fully opaque, so here it is the same image with a checkerboard added behind it:

enter image description here

Even the area in which the two circles overlap isn't fully opaque. And the anti-aliasing looks pretty ugly.

How does this happen? And how can I fix this?

I already tried:

  • Different blend functions.
  • Explicitly disabling the depth buffer, stencil buffer and sampling on the QGLFramebufferObject. I'm not sure if the QGLFramebufferObject default format adds something I don't want.
like image 513
leemes Avatar asked Nov 13 '22 23:11

leemes


1 Answers

Try the following:

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

This forces a specific pixel format and also disables rendering to a texture by using multisampling (otherwise QT always renders to a texture). That might produce different results. You can also experiment with the format.

Also, what is your hardware? My maximal point size is only 64 pixels (GTX 260), you are trying to render 100 pixel points. That might be an issue. Are any OpenGL errors generated? Does the same happen on small points?

You might also try hinting (if it's possible in QT):

glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);

But i wouldn't expect this to change anything.

like image 172
the swine Avatar answered Nov 15 '22 12:11

the swine