ofFbo clearing question

Just wondering why these two different pieces of code draw differently.
The image used in the two pieces of code is a transparent png of a circular gradient. In the version that uses the fbo it looks like it’s premultiplied or something. I can’t really tell what is going on.

  
  
    glClearColor(0.0, 0.0, 0.0, 0.0);    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  
    for(int i=0; i<100; i++){  
        int randX = ofRandom(0, ofGetWidth());  
        int randY = ofRandom(0, ofGetHeight());  
        img.draw( randX, randY );  
    }  
  

  
  
    fbo.begin();  
    glClearColor(0.0, 0.0, 0.0, 0.0);    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  
    for(int i=0; i<100; i++){  
        int randX = ofRandom(0, ofGetWidth());  
        int randY = ofRandom(0, ofGetHeight());  
        img.draw( randX, randY );  
    }  
    fbo.end();  
    fbo.draw(0,0);  
  

2 Likes

could you post the whole code + img?

do you have ofEnableAlphaBlending() on?

what ofSetColor() are you currently drawing with? are you drawing with alpha? if you’re drawing with alpha, make sure you draw the fbo with full alpha.

also, you shouldn’t have to do glClearColor, just use ofClear() or ofBackground()

Does the following fix the issue? Try:

  
glEnable(GL_BLEND);  
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);  
fbo.draw(0, 0);  
glDisable(GL_BLEND);  

All relevant code looks like this:

  
  
void testApp::setup(){  
    img.loadImage("gradient.png");  
    ofSetVerticalSync(true);  
    fbo.allocate( ofGetWidth(), ofGetHeight() );  
      
    ofEnableAlphaBlending();  
}  
  
//--------------------------------------------------------------  
void testApp::update(){  
      
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
    ofBackground(100);  
      
    ofSetColor(0);  
    ofDrawBitmapString( ofToString( ofGetFrameRate() ), 10, 12);  
      
    ofSetColor(255);  
    fbo.begin();  
        ofClear(0,0,0);  
        for(int i=0; i<100; i++){  
            int randX = ofRandom(0, ofGetWidth());  
            int randY = ofRandom(0, ofGetHeight());  
              
            img.draw( randX, randY );  
        }          
    fbo.end();  
    fbo.draw(0, 0);    
}  
  

Of the two screenshots attached, the gray background uses fbos, and the black background is with all the fbo lines commented out. The gradient attached is the image being drawn. I noticed this png with alpha weirdness in the last project I did and ran out of time to remedy it, just hoping to understand and hopefully avoid it for my next one. Thanks all for the replies, and astellato, I tried your clearing method but it didn’t seem to work for me.

here’s a working version:

  
  
	fbo.begin();  
	ofBackground(100, 255);  
	ofEnableAlphaBlending();    
	  
	ofSetColor(255);  
	for(int i=0; i<100; i++){    
		int randX = ofRandom(0, ofGetWidth());    
		int randY = ofRandom(0, ofGetHeight());    
		  
		img.draw( randX, randY );    
	}            
	ofClearAlpha();  
	fbo.end();  
	fbo.draw(0, 0);  
	  
	ofSetColor(0);    
	ofDrawBitmapString( ofToString( ofGetFrameRate() ), 10, 12);  
  

that will draw the same thing regardless of whether the fbo is commented out or not.

two notes:

1 your version looked “wrong” not because the alpha is being applied twice. first it’s applied when you’re drawing the image to the fbo: the alpha is used to blend all the things you’re drawing. then the alpha is used to blend the fbo with the background when you draw the fbo. ideally, using an fbo would be exactly the same as not using an fbo, but i’m not sure how to get around this in this case.

2 i added ofClearAlpha(), which “drops” the alpha channel by setting it to 255. this means that drawing to the fbo is exactly like drawing to the screen, except you can’t blend the fbo with the screen now.

Hey,

I have a similar problem.

If I draw 2 fbos in another, clean, fbo and then draw that fbo on the screen then alpha from one of the inside fbo’s propagates to the main fbo that is drawn on the screen.

If I draw 2 fbos (mainFbo, effectFbo) directly on the screen then works as it should: background image stays in the back and over it are two fbos with correct alpha propagation - no background image is seen through.

This is the relevant code:

backImage.draw(0,0,…) // this is the background image

mainDrawFbo.begin();
   ofClear(255,255,255);
   mainFbo.draw(0,0);  // some effects from ofxFX are drawn here
   effectFbo.draw(0,0); // png image with alpha is here
 mainDrawFbo.end();

mainDrawFbo.draw(0,0);

Is this thread related? I had a similar problem and my solution was to perform all alpha masking in the final rendering. I’m sure that won’t apply to all scenarios but it’s a workaround.

I think it could be fixed using glBlendFuncSeparate or glBlendFuncSeparatei (must be accessible somewhere around the OF API).

Pixels can be drawn using a function that blends
the incoming (source) RGBA values with the RGBA values
that are already in the frame buffer (the destination values).

1 Like

Great, tnx, that helped a lot! I fixed it using glBlendFuncSeparate!

Glad I could help. Mind sharing your code? I remember huge performance drops when trying to use that function.

Sorry for the late replay. I didn’t notice much of a frame rate drop.

Here is what I did:

mainDrawFbo.begin();
        ofClear(255,255,255);
        glPushMatrix();
            glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
            mainFbo.draw(0, 0);
            effectFbo.draw(0, 0);
        glPopMatrix();
mainDrawFbo.end();
2 Likes