Deferred Rendering

Deferred Rendering and Multiple Render Targets

Deferred rendering splits shading into two passes: the first stores each visible pixel's surface data in several textures at once, the second lights every pixel once from them. The twenty-first part of webgl-helper.js generalizes Framebuffers and Shadows's framebuffer to one color texture per format:

webgl-helper.js, twenty-first part: a framebuffer with multiple render targetsJavaScript
// Section 3.15: a framebuffer with multiple render targets: one texture per format in
// formats, on COLOR_ATTACHMENT0, 1, 2..., all enabled with drawBuffers(), plus a depth texture
GLH.targets = function (gl, width, height, formats) {
  gl.getExtension('EXT_color_buffer_float');          // makes RGBA16F and RGBA32F renderable
  const fbo = gl.createFramebuffer(), T = gl.TEXTURE_2D, W = WebGL2RenderingContext;
  const texture = (format, attachment) => {
    const t = gl.createTexture(), name = Object.keys(W).find((k) => W[k] === format);
    const filter = /\dU?I$|DEPTH/.test(name) ? gl.NEAREST : gl.LINEAR;  // integer, depth
    gl.bindTexture(T, t);
    gl.texStorage2D(T, 1, format, width, height);
    const settings = [[gl.TEXTURE_MIN_FILTER, filter], [gl.TEXTURE_MAG_FILTER, filter],
      [gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE], [gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE]];
    settings.forEach(([key, value]) => gl.texParameteri(T, key, value));
    gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, T, t, 0);
    return t;
  };
  gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
  const attachments = formats.map((format, i) => gl.COLOR_ATTACHMENT0 + i);
  const textures = formats.map((format, i) => texture(format, attachments[i]));
  gl.drawBuffers(attachments);                        // fragment output i -> attachment i
  const depth = texture(gl.DEPTH_COMPONENT24, gl.DEPTH_ATTACHMENT);
  const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  if (status !== gl.FRAMEBUFFER_COMPLETE) throw new Error(`Incomplete framebuffer: ${status}`);
  return { fbo, textures, depth, width, height };
};

Subsections