Depth of Field Shader
I’m still working on Cargo, an adventure game made using the Blender Game Engine. I recently finished a big refactor of the code, allowing the player to move from one level to the next (this was blocked by a bad design decision early on). After many months, I can finally work on new features.

That should mean expanding the story into a fully-playable game. But sometimes you need to take a break and have some fun, right? So for the last week, I have been working on a depth of field shader in GLSL. A few of these already existed for Blender games, but none were released with compatible licences. Also, I have been meaning to try my hand at some GLSL for a while.
It turns out that DoF shaders are remarkably easy to write: it’s just like a normal blur filter, but you vary the filter radius depending on the depth of the pixel from the camera. To stop colour from close objects from bleeding into the background, the weight of nearer samples should be modulated by how “in focus” they are, as described on page 10 in the paper Real-Time Depth of Field Simulation. The hardest part was working out how the depth buffer is scaled; the discussion determining depth of z-buffer on the WebGL mailing list was very helpful.

The results are great! With 32 samples you get a nice, smooth blur, with only a few artefacts along the edge of an in-focus object. The performance hit is acceptable for small screen sizes and my laptop graphics card, and barely noticeable with faster graphics cards. Note that the samples are evenly spaced and weighted (except as modulated by the depth) – no Gaussian-like smoothing is applied. This makes it easy to get shaped bokeh, as shown below.

Unfortunately you need a very bright object to show shaped bokeh, and maxing-out the brightness using Blender’s materials doesn’t quite cut it. The right-side of the image above has had its contrast increased to show the bokeh more clearly. The filter could apply its own brightness curve to enhance the bokeh, but the lights in the scene might need to be dimmed to account for that.
There is still some tweaking to do, but I’m really happy with these results. It makes the game look more three-dimensional, and emphasises the small scale of the scene.
Update: I have released this shader under the 2-clause (simplified) BSD licence. Download it as text, or integrated in a demo .blend file.




