[Solved] Problem w/ blending transparent FBO's with background

#1

What I am trying to do is draw two transparent FBO’s, one containing the other, on top of a backround colour or image. The problem is that the semi-transparent parts of the FBO’s don’t blend correctly. This is a simplified, compact version of my actual project, so that’s the reason for the weird FBO inside another FBO situation.

Changing various GL blendings modes or the colour I clear with changed the result, but so far haven’t solved it. Attached images of the blending bug as well as the entire project as a zip. Thanks in advance.

Project zip

Image 1
Image 2

Edit: relevant part of code follows.

void ofApp::setup()
{
    bit.load( "bit.png" );
    
    canvasFbo.allocate( ofGetWidth(), ofGetHeight(), GL_RGBA );
    staticFbo.allocate( ofGetWidth(), ofGetHeight(), GL_RGBA );
    
    staticFbo.begin();
    ofClear( 255, 255, 255, 0 );
    staticFbo.end();
    updateStatic = true;
}

void ofApp::update()
{
    if ( ofGetFrameNum() % 100 == 0 )
    {
        updateStatic = true;
    }
}

void ofApp::draw()
{
    ofPushStyle();
    ofSetColor( 0, 0, 255 );
    ofDrawRectangle( 0, 0, ofGetWidth(), ofGetHeight() );
    ofPopStyle();
    
    canvasFbo.begin();
    ofClear( 255, 255, 255, 0 );
    
    if ( updateStatic )
    {
        staticFbo.begin();
        bit.draw( ofGetWidth() - 250 - 500, 180, 500, 500 );
        staticFbo.end();
        
        updateStatic = false;
        cout << "static fbo updated" << endl;
    }
    staticFbo.draw( 0, 0, ofGetWidth(), ofGetHeight() );
    
    bit.draw( 250, 40, 500, 500 );
    
    canvasFbo.end();
    ofPushStyle();
    ofSetColor( 255, 255, 255 );
    canvasFbo.draw( 0, 0, ofGetWidth(), ofGetHeight() );
    ofPopStyle();
}
#2

Hi, so what is that you are trying to achieve, visually? can you post some images or specify what is that is not correct in the images you posted. (btw, please post the images inline rather than in a link. You can drag and drop into where you edit your post for doing such)
cheers

#3

Hi Roy.

I have a transparent PNG with semi-transparent drop shadow edges. This image is used in both FBO’s of the code. The problem is that 1. their semi-transparent edges seem to disappear over the background and that 2. the semi-transparent edges can be seen when the they overlap, but it’s not actually the grey drop shadow, but it masks it to the background (if you look closely you can see it’s blue).

The correct way of displaying would be this (made with Photoshop):

#4

Hi,

Premultiply your png image (multiply the r, g, b values by alpha) and put this in draw and after fbo.begin() to enable premultiplied blending: glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );.
The clears should be ofClear( 0, 0, 0, 0 ); (also premultiplied).

1 Like
#5

Had to add glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); after begin() of both FBO’s and also before I draw the main FBO as such. But this worked, thank you.

void ofApp::draw()
{
    ofPushStyle();
    ofSetColor( 0, 0, 255 );
    ofDrawRectangle( 0, 0, ofGetWidth(), ofGetHeight() );
    ofPopStyle();
    
    canvasFbo.begin();
	glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
    ofClear( 0, 0, 0, 0 );
    
    if ( updateStatic )
    {
        staticFbo.begin();
		glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
        bit.draw( ofRandom( ofGetWidth() ), ofRandom( ofGetHeight() ) );
        staticFbo.end();
        
        updateStatic = false;
        cout << "static fbo updated" << endl;
    }
    staticFbo.draw( 0, 0, ofGetWidth(), ofGetHeight() );
    
    bit.draw( 250, 40, 500, 500 );
    
    canvasFbo.end();
	glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
    canvasFbo.draw( 0, 0, ofGetWidth(), ofGetHeight() );
}