Blending FBO's

Dear community,

I’m working on a project where I need to blend FBO’s, but it’s not working out too well. The basic idea is to have a number of layers, all of which are filled with objects, and I want to be able to fade layers in and out. Every layer has a number of inputs so parameters can be controlled (from audio, or from external controls such as MIDI or OSC) and every layer has a setup(), update() and draw() function. In the main application, every layer is set up, updated and drawn.

Every layer has it’s own FBO, and the FBO is drawn like this:

  
  
void Layer::draw(){  
     ofSetColor(255, 255, 255, 255 * opacity);  
     fbo.draw(0,0);  
  
     fbo.begin();  
          // draw stuff  
     fbo.end();  
}  
  

I want the background of the FBO to be transparent, and if drawn objects inside a layers’ fbo have an opacity of <255, I want them to blend with whatever is behind them in the final composition of multiple layers.

If I use just one layer, without any FBO magic, everything is as expected. I called ofSetBackgroundAuto(false), and on every draw() I draw a bunch of ofCircles in the Layer::draw() method. A screengrab of the result is attached.

I tried calling ofSetBackgroundAuto(true), and implementing the Layer::draw() method like this:

  
  
void LayerOne::draw(){  
	ofSetColor(255, 255, 255, 255*opacity);  
	fbo.draw(0, 0);  
  
	fbo.begin();  
	     //draw a bunch of circles  
	fbo.end();  
}  
  

If I clear the fbo (in the constructor, after allocating) with fbo.clear(1,1,1,0) I get a very faint output (see attached image #2). If I clear with fbo.clear(1,1,1,1), I get yet another version of the same visuals (attached image #3).

I’m using OF 0062 as I couldn’t get the github master to compile.

What I’d want is the output as seen on image #1 (without FBO’s) but using FBO’s to be able to do the blending. What am I doing wrong?

Cheers,
Daan

PS. the visuals seen on the attachment are not exactly the same, because they are generated by sound.
PPS. The forum says: “The upload folder is full. Please try a smaller file and/or contact an administrator.” Below are the images as hosted on imageshack.

can this be related?

http://forum.openframeworks.cc/t/alpha-blending-problem:-iphone-fbos-solved/4389/0

Much better! Thanks arturo!

  
  
void LayerOne::draw(){  
	ofSetColor(255, 255, 255, 255*opacity);  
	glEnable(GL_BLEND);  
	glBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR);  
	fbo.draw(0, 0);  
	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);  
	glDisable(GL_BLEND);  
	ofEnableAlphaBlending();  
  
	fbo.begin();  
              // draw stuff  
	fbo.end();  
}  
  

New problem: when using this solution, I cannot fade out a layer. Calling ofSetColor(255,255,255,0) before drawing the FBO has no influence on the result. Any ideas?

Cheers

Before drawing? I’m pretty sure that if in the OF implementation, when you want to affect how a layer is drawn you change the code in between the begin() and end():

  
  
  
fbo.begin();    
ofSetColor(255, 255, 255, 255*opacity);    
// do whatever  
fbo.end();    
}    
  

Yes, but I’d like to do it like this:

  
  
ofSetColor(255, 255, 255, 255*opacity);      
fbo.draw();  
  
fbo.begin();      
     // do whatever    
fbo.end();      
}  
  

so I can set the opacity of a whole layer at once.

I’m still having problems pulling this off. So I’d like to set an opacity for a layer, which has his own FBO, which should blend with other FBO’s (which means the background should be transparent, or just ignored with a certain blendmode). Any ideas?

This is a little tricky b/c you need to blend the colors and the alpha separately to get the effect you’re looking for. Check this:

  
  
void testApp::setup(){  
	  
	ofEnableAlphaBlending();  
	  
	fbo1.setup(1000, 800);  
	fbo2.setup(1000, 800);  
	  
	fbo1.begin();  
	ofClear(0, 0, 0, 0);  
	fbo1.end();  
	  
	fbo2.begin();  
	ofClear(0, 0, 0, 0);  
	fbo2.end();  
  
}  
  
void testApp::update(){  
	  
}  
  
void testApp::draw(){  
	ofClear(0, 0, 0);  
	if(fbosDrawn)  
	{  
		fbo2.draw(0, 0);  
	}  
}  
  
void testApp::mouseDragged(int x, int y, int button){  
	  
	float alpha = ofMap(x, 0, ofGetWidth(), 0.f, 255.f);  
	  
	fbo1.begin();  
  
		ofSetColor(255, 255, 0, alpha);  
	  
		ofCircle(100, 100, 90);  
		ofCircle(100, 300, 90);  
		ofCircle(100, 500, 90);  
	fbo1.end();  
	  
	fbo2.begin();  
	  
		ofClear(0, 0, 0, 0);  
		glEnable (GL_BLEND);  
		glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);  
		  
		ofSetColor(0, 0, 255, 255 - alpha));  
		ofRect(400, 100, 100, 100);  
		ofRect(400, 300, 100, 100);  
		ofRect(400, 500, 100, 100);  
	  
               // have to reset the color, otherwise it's just the same as was set above, the inverse  
		ofSetColor(255, 255, 255, 255);  
		fbo1.draw(0, 0);  
		glDisable(GL_BLEND);  
		  
	fbo2.end();  
	  
	fbosDrawn = true;  
  
}  
  

Works for me, hope that helps.

1 Like

That did it! Thanks Joshua!