How to take the samples is a big concern as it will impact what will occlude and how much. The currently best implementations takes random samples in a hemisphere in the direction of the normal. This limits the amount of self occlusion. Another problem is that if you only take the depth into consideration then a flat surface might occlude itself because of the perspective. By also comparing the normal when calculating the AO, this problem will go away.
One of the hard parts of implementing SSAO is to choose the correct smoothing technique. Because of the big cost of taking occlusion samples you want to take as few samples as possible but this will give much noise in the SSAO so the result needs smoothing. Just doing a simple gaussian blur will not be good as the blur will make the SSAO bleed. Instead a blur that considers the depth and/or normals is needed. One of those is the bilateral filter which often is used in combination with SSAO.
The steps of a simple SSAO implementation:
- Render the scene. Save the linear depth in a texture. Save the normals in eye space in a texture.
- Render a full screen quad with the SSAO shader. Save the result to a texture.
- Blur the result in X
- Blur the result in Y
- Blend the blurred SSAO texture with the scene, or use it directly when rendering the scene.
An optimization is to render the SSAO in a lower resolution than the screen and upsample it when blurring. Another optimization is to store both the normals and the depth in a single texture.
Probably one of the best implementations of SSAO is this one by NVIDIA (although it’ rather slow). The SDK 10 has a paper about the technique and also source code!
And here’s three papers/presentations from NVIDIA describing their SSAO in detail:
Some information of how Starcraft II will use SSAO is included in this paper ( see chapter 5.5 ):
A link to a description of the SSAO implementation in the game Two Worlds:
The paper and game that started it all (look in the chapter 188.8.131.52):
One of the papers that probably inspired the Crysis team:
A simple but smart SSAO implementation, here with well commented shader source code:
A gamedev.net thread with lots of discussion about SSAO