Framebuffer Example

Render into a framebuffer and use it as a texture.

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 initializeGL 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 paintGL 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:

Images:

© 2019 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.