Drawing to an offscreen canvas

In this recipe, we will learn how to draw in an offscreen canvas using the OpenGL Frame Buffer Object (FBO).

We will draw in an FBO and draw it onscreen as well as texture a rotating cube.

Getting ready

Include the necessary files to work with OpenGL and the FBOs as well as the useful include directives.

Add the following code to the top of the source file:

#include "cinder/gl/gl.h"
#include "cinder/gl/Fbo.h"

using namespace ci;

How to do it…

We will use a ci::gl::Fbo object, a wrapper to an OpenGL FBO, to draw in an offscreen destination.

  1. Declare a ci::gl::Fbo object as well as a ci::Vec3f object to define the cube's rotation:
    gl::FbomFbo;
    Vec3f mCubeRotation;
  2. Initialize mFbo with a size of 256 x 256 pixels by adding the following code in the setup method:
    mFbo = gl::Fbo( 256, 256 );
  3. Animate mCubeRotation in the update method:
    mCubeRotation.x += 1.0f;
    mCubeRotation.y += 1.0f;
  4. Declare a method where we will draw to the FBO:
    void drawToFbo();
  5. In the implementation of drawToFbo, we will begin by creating a ci::gl::SaveFramebufferBinding object and then bind mFbo.
    gl::SaveFramebufferBinding fboBindingSave;
    mFbo.bindFramebuffer();
  6. Now we will clear the background with a dark gray color and set the matrices using the FBO's width and height.
    gl::clear( Color( 0.3f, 0.3f, 0.3f ) );
    gl::setMatricesWindowPersp( mFbo.getWidth(), mFbo.getHeight() );
  7. Now we will draw a rotating color cube at the center of the FBO with size 100 and using mCubeRotation to rotate the cube.
    gl::pushMatrices();
    Vec3f cubeTranslate( mFbo.getWidth() / 2, mFbo.getHeight() / 2, 0.0f );
    gl::translate( cubeTranslate );
    gl::rotate( mCubeRotation );
    gl::drawColorCube( Vec3f(), Vec3f( 100, 100, 100 ) );
    gl::popMatrices();
  8. Let's move to the implementation of the draw method. Start by calling the method drawToFbo, clearing the background with black, setting the window's matrices, and enable reading and writing to the depth buffer. Add the following code in the draw method:
    drawToFbo();
    gl::clear( Color( 0, 0, 0 ) ); 
    gl::setMatricesWindowPersp( getWindowWidth(), getWindowHeight() );
    gl::enableDepthRead();
    gl::enableDepthWrite();

    Lets draw our Fbo at the top left corner of the window using mFbo texture:

    gl::draw( mFbo.getTexture(), Rectf( 0.0f, 0.0f, 100.0f, 100.0f ) );
  9. Enable and bind the texture of mFbo:
    mFbo.getTexture().enableAndBind();
  10. Draw a rotating cube at the center of the window using mCubeRotation to define its rotation:
    gl::pushMatrices();
    Vec3f center( getWindowWidth() / 2, getWindowHeight() / 2, 0.0f );
    gl::translate( center );
    gl::rotate( mCubeRotation );
    gl::drawCube( Vec3f(), Vec3f( 200.0f, 200.0f, 200.0f ) );
    gl::popMatrices();
  11. To finalize, unbind the texture of mFbo:
    mFbo.unbindTexture();
    How to do it…

How it works…

The class ci::gl::Fbo wraps an OpenGL FBO.

Frame Buffer Objects are OpenGL objects that contain a collection of buffers that can be used as rendering destinations. The OpenGL context provides a default frame buffer where rendering occurs. Frame Buffer Objects allow rendering to alternative, offscreen locations.

The FBO has a color texture where the graphics are stored, and it can be bound and drawn like a regular OpenGL texture.

On step 5, we created a ci::gl::SaveFramebufferBinding object, which is a helper class that restores the previous FBO state. When using OpenGL ES, this object will restore and bind the previously bound FBO (usually the screen FBO) when it is destroyed.

See also

See the recipe Rotating, scaling, and translating to learn more about OpenGL transformations.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.179.59