Framebuffer Objects

WebGL doesn't let you just walk in and render to a texture. You must first set up a framebuffer object (FBO). When you first set up a WebGL context, a default framebuffer object is created automatically. This default framebuffer object has two attachments: the color framebuffer that is drawn to your screen and a depth buffer that is used to sort fragments. When you create your own framebuffer objects, you can give it other kinds of attachments, namely textures.

Rendering to textures is useful for many different applications. With them you can dynamically generate skyboxes. Or you generate alternative views of the scene that appear in mirrors or portals. You can use them to achieve motion blur or post-processing effects like edge detection. For now, however, you only care about shadows.

To perform shadow mapping, you need a map of the depths of the surfaces that the light "sees". You don't need the colors of these surfaces. Therefore, your framebuffer object needs a depth attachment but not a color attachment.

This JavaScript function creates a brand new framebuffer object whose depth attachment is a depth texture that you've made previously.

function initializeDepthFbo(depthTexture) {
  const framebuffer = gl.createFramebuffer();
  gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTexture, 0);
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  return framebuffer;

Now you've got the pieces in place to render to a texture.