[Solved] Rendering into an FBO not working as intended


#1

Hey Embers,

@paul.houx has made a series of really cool samples - one of which I’m kind of dissecting and playing around with a bit. Specifically the Depth of Field example shown here:

Now then - I’m trying to have this render into a texture via an FBO. I’ve got plenty of stuff rendering into FBO’s without a problem, but for some reason when I attach the FBO to this code, it doesn’t work as intended. When I try and render the FBO color texture, all I get is black.

In @paul.houx 's code, the final compositing render looks as follows:

if( true ) {
	gl::ScopedColor scpColor( 1, 1, 1 );
	gl::ScopedBlend scpBlend( false );

	gl::ScopedTextureBind scpTex0( mFboSource->getColorTexture(), 0 );
	gl::ScopedTextureBind scpTex1( mFboBlur[1]->getTexture2d( GL_COLOR_ATTACHMENT0 ), 1 );
	gl::ScopedTextureBind scpTex2( mFboBlur[1]->getTexture2d( GL_COLOR_ATTACHMENT1 ), 2 );
	gl::ScopedGlslProg    scpGlsl( mGlslComposite );
	mGlslComposite->uniform( "uInputSourceInvSize", 1.0f / vec2( mFboSource->getSize() ) );
	mGlslComposite->uniform( "uFarRadiusRescale", mFarRadiusRescale );
	mGlslComposite->uniform( "uDebugOption", mDebugOption );

	gl::drawSolidRect( getWindowBounds() );
}

My modified code looks as follows:

// Perform compositing.
if (true) {

	// -- Injection Start
	BreakUnless( mFbo );
	ci::gl::ScopedFramebuffer	scpFbo( mFbo );
	ci::gl::ScopedViewport		scpViewport( { 1280, 800 } /* mFbo->getSize()*/ );

	ci::gl::ScopedMatrices		scpMatrices;
	ci::gl::setMatricesWindow( { 1280, 800 } /* mFbo->getSize()*/ );
	// -- Injection End

	ci::gl::ScopedColor scpColor( 1, 1, 1 );
	ci::gl::ScopedBlend scpBlend( false );

	ci::gl::ScopedTextureBind scpTex0( mFboSource->getColorTexture(), 0 );
	ci::gl::ScopedTextureBind scpTex1( mFboBlur[1]->getTexture2d( GL_COLOR_ATTACHMENT0 ), 1 );
	ci::gl::ScopedTextureBind scpTex2( mFboBlur[1]->getTexture2d( GL_COLOR_ATTACHMENT1 ), 2 );
	ci::gl::ScopedGlslProg    scpGlsl( mGlslComposite );
	mGlslComposite->uniform( "uInputSourceInvSize", 1.0f / ci::vec2( mFboSource->getSize() ) );
	mGlslComposite->uniform( "uFarRadiusRescale", mFarRadiusRescale );
	mGlslComposite->uniform( "uDebugOption", mDebugOption );

	//ci::gl::drawSolidRect( getWindowBounds() );
	ci::gl::drawSolidRect( ci::Rectf( 0, 0, 1280, 800 ) );
}

As you may have guessed, the idea is to have the composition render into the mFbo and then use mFbo->getColorTexture() to eventually display the result. However, all I seem to end up with is black when I do it this way…

If anything pops out as being completely off, I’d be keen to know. Right now I’m just scratching my head as to why attaching the FBO in advance of the final composite render doesn’t work O_o

Thanks in advance,
Gazoo


#2

Hey Gazoo.

Nothing jumps out but could you include your code that actually does the final render? The code you sent renders everything into the fbo ‘mFbo’ but youve missed the bit that renders it to the screen. This is probably just a gl::draw(mFbo->getColorTexture(), getWindowBounds()) but still.

Also you could try using some of the convenience functions to draw say a big pink circle in the fbo too just to check your fbo is behaving properly and that the issue isn’t with your mGlslComposite shader.


#3

Does the Fbo have a depth buffer? You may want to make sure it doesn’t. Also, don’t forget to gl::clear() it.


#4

@felixfaire

The rendering code is as follows:

if (mDrawViaFbo)
{
	gl::draw( mFbo->getColorTexture() );
} 

I have a separate portion of code that renders a cube straight into the FBO which works fine.

@paul.houx

The FBO doesn’t have one, but for fun I’ve tried using an FBO both with and without, with no change.

I’m still actively working on nailing down the problem. My working theory is that it’s somehow related to rendering geometry into one FBO, and then rendering the contents of that FBO into a second FBO. It’s a bit of a weak theory, but so far it’s the best I’ve got to go on, as I seem to have no problems rendering geometry directly into the FBO and displaying that. It’s only when the GLSL program composite (which I’ve now simplified down to effectively just drawing the contents of an input texture) comes in-between that my FBO comes up black.

I’m now building a second application from the ground up with minimal elements to see if I can replicate the issue. I’ll keep you posted!

Cheers,
Gazoo


#5

For situations like these, I’d recommend installing NVIDIA’s Nsight. It allows you to step through your frame and see exactly what’s going on. You can see the frame bufffers and textures in use and check if their settings are correct. This will remove all guess work from it.

I don’t think it’s related to your problem, but I’d like to point out that the DoF effect requires the CoC to be encoded in the alpha channel of the input. See the scene.frag shader of the sample.

-Paul


#6

@paul.houx - Excellent advice. When I first stumbled across NSight a few years ago, I recall reading how it enabled line-by-line debugging only to later understand that this functionality is only properly supported on the Quadro cards. I’ve (foolishly) since shunned NSight a bit.

After spending an hour re-familiarizing myself with its interface - and appreciating that despite it lacking line-by-line debugging for GeForce cards, it offers tremendous insight into the OpenGL context/state - I finally cracked it.

The reason rendering the contents of mFbo yields absolute black, is because the final composite shader uses a vec3 out, leaving the alpha channel untouched. Consequently all pixels have an alpha value of 0. Since blending is - I think by default? - on, this ultimately draws a fully transparent output.

Turning blending off when rendering the contents of mFbo results in the expected output. Ideally, I should modify the composition shader to maintain the alpha out as I’ll be layering the graphics with other stuff.

-Gazoo