2d Co-ordinates with FBOs

I’ve been having trouble trying to understand the difference between the matrices used when drawing a rectangle to an FBO and when rendering to the screen (I had thought they shouldn’t be different?).
In particular, I’m trying to make a small 100x100px FBO and set it up with standard co-ordinates (0, 0 - topleft, 100,100 - bottom right).

both

setMatricesWindow(100,100)

and

CameraOrtho cam(0, 100, 100, 0, -1, 1);
gl::setMatrices(cam);

give me an identical but totally messed up coordinate system as follows:

void cinder_VBO_testApp::setup()
{
    _fbo = gl::Fbo::create(100, 100, true, false, false);
}

void cinder_VBO_testApp::draw()
{
    {
        gl::ScopedFramebuffer fbScp( _fbo );        
        gl::ScopedMatrices();

        CameraOrtho cam(0, 100, 100, 0, -1, 1);
        gl::setMatrices(cam);
        //gl::setMatricesWindow(100,100); - this gives the same result as above

        gl::color(0.5,0.5,0);
        
        gl::drawSolidRect( Rectf(1, 80, 15, 99)); //WHAT?!! these numbers seem totally arbitrary, I found them through trial and error
        
    }
    gl::setMatricesWindow(getWindowSize());
	gl::clear( Color( 0, 0, 0 ) );
    gl::draw(_fbo->getColorTexture(), Rectf(0,0,getWindowSize().x, getWindowSize().y));
}

This gives me the following:

Whereas if I do the same without the Fbo bound it works as expected:

void cinder_VBO_testApp::draw()
{
    gl::setMatricesWindow(100,100);
	gl::clear( Color( 0, 0, 0 ) );
    gl::color(0.5,0.5,0);
    gl::drawSolidRect( Rectf(10, 10, 90, 90));
}

gives me:

Hi,

when rendering to an Fbo that has a different size than the window, you need to properly set the so-called viewport, too. Like so:

void MyApp::draw()
{
    // We're currently rendering to the main window
    // and Cinder has set the correct viewport already.

    // Now, we want to render to an Fbo. We're going
    // to use the `gl::Scoped*` classes, so let's enter
    // a new, temporary scope:
    {
        // Bind the Fbo.
         gl::ScopedFrameBuffer scpFbo( mFbo );

        // Set the viewport to the size of the Fbo:
        gl::ScopedViewport scpViewport( mFbo->getSize() );

        // Set the model, view and projection matrices to
        // render in 2D. No camera needed if you're simply
        // want to draw to the Fbo's canvas:
        gl::ScopedMatrices scpMatrices;
        gl::setMatricesWindow( mFbo->getSize(), true );

        // Now, draw something.
        gl::clear();

        gl::ScopedColor scpColor( 1, 1, 1 );
        gl::drawSolidCircle( 0.5f * mFbo->getSize(), 25.0f );
    }

    // Thanks to the scoped variables, the Fbo is unbound,
    // our viewport, matrices and draw color are restored to 
    // their previous state, so we can start drawing to our
    // main window immediately.
    gl::draw( mFbo->getColorTexture() );
}

See this great tutorial for more information. I also wrote a post about it a long time ago, which you can find here.

-Paul

2 Likes

Aaaah thank you.
I was initially looking for viewport setting in all the wrong places and decided finally that setMatricesWindow must do that as a part of its’ procedure. The clarification on the differences between aspect ratio and the viewport in the articles clear that up perfectly.

Also, thanks for taking the time and being so quick to respond!

1 Like