In this post, I am going to show how I implemented ambient occlusion in my DirectX 12 rendering engine.
It is a shading and rendering technique used to calculate how exposed each point in a scene is to ambient lighting. The interior of a tube is typically more occluded (and hence darker) than the exposed outer surfaces, and the deeper you go inside the tube, the more occluded (and darker) the lighting becomes. Ambient occlusion can be seen as an accessibility value that is calculated for each surface point. In scenes with open sky, this is done by estimating the amount of visible sky for each point, while in indoor environments only objects within a certain radius are taken into account, and the walls are assumed to be the origin of the ambient light. The result is a diffuse, non-directional shading effect that casts no clear shadows but that darkens enclosed and sheltered areas and can affect the rendered image’s overall tone. It is often used as a post-processing effect.
Unlike local methods such as Phong shading, ambient occlusion is a global method, meaning that the illumination at each point is a function of other geometry in the scene. However, it is a very crude approximation to full global illumination. The appearance achieved by ambient occlusion alone is similar to the way an object might appear on an overcast day.
You can see in the following picture, the difference with/without ambient occlusion.
We generate sample kernels within a hemisphere, oriented along the surface normal at each pixel. As the renderer is a deferred renderer, then we have all the needed data (depth information, normal vectors at view space, etc.)
We also generate a set of random values used to rotate the sample kernel, to minimize “banding” artifacts. You can see in the following picture, a scene with/without banding artifacts.
We can also reduce trading banding for high-frequency noise by blurring the result. You can see in the following picture, a scene with blur pass.
and this is a picture without blur pass.
You can see a demo in the following video that shows SSAO in the engine.
The repository is located here
The references I used to learn about this topic are the following:
As post title mentions, this was the first approach to screen space ambient occlusion. It is not correct as explained in this GameDev post. I plan to investigate further and implement this correctly.