Framebuffer Objects (FBO) and Render To Texture (RTT)

In order to use an image of a texture as colour buffer, we first create the texture and set all relevant texture parameters. (Note that it is important to set the texture parameters in a correct way, see http://www.opengl.org/wiki/Common_Mistakes#Creating_a_Texture)

// create a new Texture object
var myTexture = gl.createTexture();
// bind the texture as active one in order to set parameters
gl.bindTexture(gl.TEXTURE_2D, myTexture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

// to allocate memory for the texture call texImage2D with a null pointer, this tells openGL we want to have the memory allocated, but have no image to transfer to yet.

// void TexImage2D( enum target, int level, int internalformat, sizei width, sizei height, int border, enum format, enum type, const void *data );
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, myFBWidth, myFBWidth, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);

Now specify that the image (for level 0) of texture shall be used as colour buffer for the framebuffer.

//void FramebufferTexture2D( enum target, enum attachment, enum textarget, uint texture, int level );
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, myTexture, 0);

Note that you can attach buffers to multiple Color Attachment points, for example the different images ob a cubemap texture to COLOR_ATTACHMENT0 to COLOR_ATTACHMENT5
For the depth buffer we do not use a texture, but a render buffer. So we create a render buffer object, allocate the memory for it and specify the render buffer as depth component of the frame buffer.

var myRenderbufferForDepth = gl.createRenderbuffer();

gl.bindRenderbuffer(gl.RENDERBUFFER, myRenderbufferForDepth);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, myFBWidth, myFBHeight);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, myRenderbufferForDepth);

After setting up everyting, we clean up by setting everything back to default in order to prevent that following calls change our objects.

gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);

So now we have set everything up we need to enable rendering to a texture.
For this example we specify two shader programs, one shader program for rendering a grid into a texture image, and one as follow up, displaying the texture on a full screen quad using multiple texture lookups per pixel for gaussian blur.

float4 newColor = coord;
float3 grid10 = abs(round(coord.xyz*10.0)-coord.xyz*10.0)/10.0;
float3 grid2  = abs(round(coord.xyz* 2.0)-coord.xyz* 2.0)/ 2.0;
if (grid10.x < 0.005 ||
    grid10.y < 0.005 ||
    grid10.z < 0.005  )
  newColor = float4(1.0, 1.0, 1.0, 1.0);
if (grid2.x < 0.005 ||
    grid2.y < 0.005 ||
    grid2.z < 0.005  )
  newColor = float4(1.0, 1.0, 0.0, 1.0);

Comments are closed.