Playable build – updated
In Unity, full-screen image effects, such as screen-space ambient occlusion (SSAO), bloom and tone-mapping, can only be applied after everything else has rendered. You can optionally flag image effects to render between opaque and transparent stuff, but that doesn’t help me because image effects wipe the stencil buffer, which I need for object highlighting.
Previously there were many things about the rendering order in the game that were just plain wrong. For example, SSAO was being applied after water and atmosphere / fog, and 3D UI elements were being bloomed and tone-mapped. Ideally you want to be able to interleave image effects and other rendering at will. The only way to do this in Unity is to use multiple cameras (with only the first one clearing the screen, the rest rendering on top). Here is how I have things set up now to achieve the correct rendering order:-
- Clear screen.
- Render opaque objects (e.g. terrain and other solid objects).
- Render object highlighter mask texture using stencil values written by object shaders. This has to be done before any image effects, as they wipe the stencil values.
- Render SSAO full-screen image effect.
- Render atmosphere / fog as a full-screen image effect.
- Render transparent objects (e.g. water), these apply atmosphere / fog in their shaders.
- Render object highlighter full-screen image effect, using mask rendered earlier.
- Render sun shafts, bloom and tone-mapping image effects.
- Clear depth only.
- Render 3D UI elements.
- Render 2D UI / menus etc.
- Render anti-aliasing full-screen image effect.
Unfortunately, using multiple cameras like this exposes some long standing bugs in Unity which really screwed me up for a while. Luckily there are known workarounds for these, for more info you can check out these threads:-
I’ve also fixed some issues with SSAO that were causing black speckly artifacts to show on the distant terrain. Now that SSAO looks much nicer, I’ve enabled it by default. I’ve also fixed a bunch of other bugs and issues!