WebGL: Render To Texture

←Back

Related Topics: Texture, Draw 2D Image, Frame Buffer Object

Overview

Sometimes, you need to generate dynamic textures on the fly. Dynamic texturing can be generated by directly rendering the scene onto a texture using Frame Buffer Object (FBO). The most common examples are generating mirroring/reflection effects, dynamic cube/environment maps and shadow maps.

With FBO, we we can eliminate unneccessory bitmap copy to the texture object because we draw the scene onto the texture directly. And, we can use a bigger texture resolution than the actual display width and height.

This page explains how to setup a FBO and render a scene to a texture object in WebGL.

FrameBuffer Class

FrameBuffer class is to create a frame buffer object in WebGL application. It contains a WebGL frame buffer object and 2 FBO attachede images; tex for the color buffer image, and rbo for the depth buffer image. We don't normally retrieve the depth info from RBO (Render Buffer Object), but it is neccessory for depth testing. WebGL v2.0 also supports gl.DEPTH_COMPONENT24 format to store the depth buffer into a texture object, instead of RBO. Use depth property to retreive the depth buffer as a texture during the rendering pipeline. Ther core interfaces of FrameBuffer class are;

FrameBuffer
InterfaceDescription
texID of color attachable image (gl.COLOR_ATTACHMENT0)
depthID of depth attachable image as texture (gl.DEPTH_ATTACHMENT), gl.DEPTH_COMPONENT24
rboID of depth attachable image as RBO (gl.DEPTH_ATTACHMENT), gl.DEPTH_COMPONENT16
init(w,h)Resize this buffer with the given width and height
bind()Bind this before drawing
unbind()Undind this after drawing

A typical usage of FrameBuffer class for render to texture is;


// global object
gl = {};
...

// create FBO and set size
gl.texWidth = 512;
gl.texHeight = 512;
gl.fbo = new FrameBuffer(gl);
gl.fbo.init(gl.texWidth, gl.texHeight);
...

// render to texture
gl.fbo.bind();

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.viewport(0, 0, gl.texWidth, gl.texHeight);
drawSomething();

gl.fbo.unbind();
...

// normal drawing
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

// retrieve texture from FBO
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, gl.fbo.tex);   // get color attachment
gl.bindTexture(gl.TEXTURE_2D, gl.fbo.depth); // get depth attachment
drawAsNormal();
...

Example: Render to Texture

This example is to draw the scene to a FBO first, then apply the FBO texture (color or depth buffer) to a cube for normal drawing. You can resize the framebuffer size using the slider.

Note that WebGL v2.0 is required to store the depth buffer as a texture object rather than a RBO. The texture format for the depth buffer is gl.DEPTH_COMPONENT24 and the data type is gl.UNSIGNED_INT.


decoration Fullscreen Demo: test_rtt.html
decoration GitHub Repo: test_rtt.html

←Back
 
 
Hide Comments
comments powered by Disqus