Thursday, April 3, 2008

Experiments with SSAO (Screen Space Ambient Occlusion)

Its been a real long time since I last posted. So I thought I'd post something. I've been experimenting with the Screen Space Ambient Occlusion (SSAO). The fancy name that was used in Martin Mittring's (Crytek) presentation "Finding Next Gen – CryEngine 2" presented at Siggraph 2007. For those of you who've had the privilege of having played Crysis on the Very High or High settings would notice some immensely cool shading on all the geometry, even though there might not have been more than 1 light in the scene. This is thanks to a crude approximation of an approximation. (Since Ambient Occlusion is in itself an approximation to the indirect lighting problem). This is called Screen Space Ambient Occlusion and is a dynamic Ambient Occlusion method which doesn't need pre processing.

I implemented SSAO in the game engine I'm working on and the results were good, but not as spectacular as I expected. I used 2 color attachments (2 render targets for those more familiar with directX) for the initial rendering of the scene. The second color attachment I used for storing ModelView transformed direction vectors to each pixel on the screen (Eye space normalized eye vectors) and in the alpha component I stored the ModelView distance. Now whats to note here is, SSAO is not only dynamic but also is applied as a post process to the scene. So you can probably add it to your HDR/DOF pass. Just recover the 3D point at that pixel and then compare it with some 3D points around that point in a hemisphere. Then apply noise.

Inigo of RGBA demoscene group explains in this page:

But for some reason his method didn't work directly for me. For example the projection he performs in his loop for the 32 hemisphere 3D points a multiplication with
vec2(.75,1.0); but I found that (.78,1.0); works precisely. Well for me atleast.
You can always try using a gaussian blurred scene texture as a replacement for the 32
iterations. It worked as well as the SSAO in Crysis but with thick white borders.
Anyway, onto screens,

Without SSAO:

With SSAO:

SSAO Contribution to the scene looks like this:

Hope this was useful, I'll probably put some screens and details about my uber
per pixel lighting shader next time, or may be some OMNI directional light sources
that cast shadows. Its pretty old, and even my implementation was done a long time

Apart from the above algorithm, I did implement SSAO with extremely good results
(similar to Crysis and twice as fast) with a gaussian texture obtained from my
bloom pass. But unfortunately I got some ugly artifacts on the border (Outlines).
If anybody manages to fix this, please tell me!

Here are some images of SSAO which uses the Gaussian texture.

I used this equation:
AmbientOcclusion(x,y) = 255 + GaussianAverage(x,y,sigma) - PixelValue(x,y)