Sunday, August 7, 2011

JOGL Part 2 - The Deferred Renderer

In this part I will write about the deferred renderer I use and how I configured it. But first things first: what is deferred rendering? It's an alternative to the "standard" forward rendering method. When I first used OpenGL I (and I think many others) used this very simple method:

foreach Object o
  render Object o with all lights
 end
 
Simple Forward Rendering

Every object gets drawn with a shader that handles every light source in the scene. A major drawback of this method is that its very hard to handle large amounts of different lights (point-, spot-, ..., directional lights). The shader will soon have a loop around many "ifs" to determine the correct light formula. That's not very optimal. It gets even more complicated when shadows are added to the scene.

One way to simplify this is to use a multi-pass method. Objects will be drawn multiple times with different shaders and lights. This could look something like this:

foreach Object o
   foreach Light l
    if o is in lightradius of l
     render Object o with Light l
    end
   end
  end
  
Iterating over objects
foreach Light l
  foreach Object o in lightradius of l
   render Object o with Light l
  end
 end
  
Iterating over lights

This method simplifies the shader management. You can have different shaders for different light sources. But there are still drawbacks. Both methods use a nested loop for lights and objects - if one light or object is added to the scene, everything has to be drawn again.

Deferred rendering separates the drawing and lighting of objects into two passes. First the objects are drawn into an off-screen buffer. Then this buffer is lit to achieve the final scene. In code terms, it's something along those lines: