- Qt 5.5
- Qt Canvas 3D
- Framebuffer Example
- Qt 5.5.1 Reference Documentation

# Framebuffer Example

The Framebuffer Example shows how to render into a framebuffer, create a texture of it, and apply the texture to an object in normal on-screen rendering.

The example has a moving and rotating cube, which has another textured cube drawn into it via the framebuffer object. The cube in the framebuffer can be rotated using Sliders from Qt Quick Controls.

## Preparing the Framebuffer

We first define the variables we need for the render-to-texture framebuffer:

    var rttFramebuffer;
    var rttTexture;
    var rttWidth = 512;
    var rttHeight = 512;

Then, in the `initGL` function, we create the framebuffer object:

    // Create the framebuffer object
    rttFramebuffer = gl.createFramebuffer();
    rttFramebuffer.name = "OffscreenRenderTarget";
    gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer);

## Creating the Texture

After the creation of the framebuffer, we create the texture:

    // Create the texture
    rttTexture = gl.createTexture();
    rttTexture.name = "OffscreenRenderTargetTexture";
    gl.bindTexture(gl.TEXTURE_2D, rttTexture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
    gl.texImage2D(gl.TEXTURE_2D, 0,
                  gl.RGBA, rttWidth, rttHeight,
                  0, gl.RGBA, gl.UNSIGNED_BYTE,
                  null);
    gl.generateMipmap(gl.TEXTURE_2D);

Then we need to bind the texture as a color attachment, create and bind a render buffer, and bind the depth attachment:

    // Bind the texture as color attachment, create and bind a depth buffer
    gl.framebufferTexture2D(gl.FRAMEBUFFER,
                            gl.COLOR_ATTACHMENT0,
                            gl.TEXTURE_2D, rttTexture, 0);
    var renderbuffer = gl.createRenderbuffer();
    gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
    gl.renderbufferStorage(gl.RENDERBUFFER,
                           gl.DEPTH_COMPONENT16,
                           rttWidth, rttHeight);
    gl.framebufferRenderbuffer(gl.FRAMEBUFFER,
                               gl.DEPTH_ATTACHMENT,
                               gl.RENDERBUFFER, renderbuffer);

## Rendering into the Framebuffer

In `renderGL` function, we first need to draw the scene into the framebuffer. We start by binding the framebuffer object and setting a viewport:

    // bind the FBO and setup viewport
    gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer);
    gl.viewport(0, 0, rttWidth, rttHeight);

Then, we need to bind the loaded texture we want to use in rendering into the framebuffer object:

    // Bind the loaded texture
    gl.bindTexture(gl.TEXTURE_2D, cubeTexture);

And then we can draw the textured cube into the framebuffer:

    // Draw the cube to the FBO
    gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);

## Using the Framebuffer as a Texture

First, we bind the render-to-texture right after drawing, and generate mipmaps:

    // Bind the render-to-texture and generate mipmaps
    gl.bindTexture(gl.TEXTURE_2D, rttTexture);
    gl.generateMipmap(gl.TEXTURE_2D);

Then we need to bind the default framebuffer (screen), and set up the viewport:

    // Bind default framebuffer and setup viewport accordingly
    gl.bindFramebuffer(gl.FRAMEBUFFER, 0);
    gl.viewport(0, 0,
                canvas.width * canvas.devicePixelRatio,
                canvas.height * canvas.devicePixelRatio);

And finally, we draw the on-screen view:

    // Draw the on-screen cube
    gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);

Files:

- canvas3d/framebuffer/qml/framebuffer/framebuffer.js
- canvas3d/framebuffer/qml/framebuffer/main.qml
- canvas3d/framebuffer/main.cpp
- canvas3d/framebuffer/framebuffer.pro
- canvas3d/framebuffer/framebuffer.qrc