Kitchen scene rendered by Hydrogent with Screen Space Ambient Occlusion effect applied.
We needed to add screen space ambient occlusion to our project with the following requirements:
Use cosine-weighted AO and have the ability to use a large radius
We used Intel's implementation of Screen Space Occlusion as the basis for our implementation [Intel-XeGTAO]
The following table enumerates all external inputs required by SSAO.
Name | Format | Notes |
---|---|---|
Depth buffer | APPLICATION SPECIFIED (1x FLOAT) | The depth buffer for the current frame provided by the application. The data should be provided as a single floating point value, the precision of which is under the application's control. |
Normal buffer | APPLICATION SPECIFIED (3x FLOAT) | The normal buffer for the current frame provided by the application in the [-1.0, +1.0] range. Normals should be in world space. |
The effect uses a number of parameters to control the quality and performance of the effect organized into the HLSL::ScreenSpaceAmbientOcclusionAttribs
structure. The following table lists the parameters and their descriptions.
Name | Notes |
---|---|
Effect radius | World-space ambient occlusion radius. |
Effect falloff range | Gently reduces sample impact as it gets out of the 'Effect radius' bounds. |
Radius multiplier | Use different value as compared to the ground truth radius to counter inherent screen space biases. |
Depth MIP sampling offset | Controls the main trade-off between performance (memory bandwidth) and quality (temporal stability is the first affected, thin objects next). |
Temporal stability factor | The value is responsible for interpolating between the current and previous frame. |
Spatial reconstruction radius | Controls the kernel size in the spatial reconstruction step. Increasing the value increases the deviation from the ground truth but reduces the noise. |
The effect can be configured using the ScreenSpaceAmbientOcclusion::FEATURE_FLAGS
enumeration. The following table lists the flags and their descriptions.
Name | Notes |
---|---|
FEATURE_FLAG_HALF_PRECISION_DEPTH | Use half-precision fixed-point format for depth values in the SSAO computation |
FEATURE_FLAG_HALF_RESOLUTION | Compute SSAO at half resolution of the target render texture |
FEATURE_FLAG_UNIFORM_WEIGHTING | By default, we compute AO using the GTAO algorithm. This flag enables the computation of AO using the HBAO algorithm |
To integrate SSAO into your project, include the following necessary header files:
Now, create the necessary objects:
Next, call the methods to prepare resources for the PostFXContext
and ScreenSpaceAmbientOcclusion
objects. This needs to be done every frame before starting the rendering process.
Now we invoke the method PostFXContext::Execute
. At this stage, some intermediate resources necessary for all post-processing objects dependent on PostFXContext
are calculated. This method can take a constant buffer directly containing an array from the current and previous cameras (for this method, you can refer to this section of the code [0] and [1]). Alternatively, you can pass the corresponding pointers const HLSL::CameraAttribs* pCurrCamera
and const HLSL::CameraAttribs* pPrevCamera
for the current and previous cameras, respectively. You also need to pass the depth of the current and previous frames (the depth buffers should not contain transparent objects), and a buffer with motion vectors in NDC space, into the corresponding ITextureView* pCurrDepthBufferSRV
, ITextureView* pPrevDepthBufferSRV
, ITextureView* pMotionVectorsSRV
pointers.
Now we need to directly invoke calculation of SSAO. To do this, we call the ScreenSpaceAmbientOcclusion::Execute
method. Before this, we need to fill the passed structures ScreenSpaceAmbientOcclusionAttribs
and ScreenSpaceAmbientOcclusion::RenderAttributes
with the necessary data. Refer to the Input resources section for parameter description.
Now, you can directly obtain a ITextureView
on the texture containing the SSAO result using the method ScreenSpaceAmbientOcclusion::GetAmbientOcclusionSRV
. After this, you can apply SSAO in your rendering pipeline using the formula below.
The parameter $F$ is the Fresnel Schlick coefficient. You can use the approximation FresnelSchlickWithRoughness
from this article [Sébastien Lagarde, Adopting a physically based shading model]
As we mentioned earlier, we use the [Intel-XeGTAO] implementation as a starting point for our algorithm. For a deeper understanding of the context and nuances involved, it is recommended to review the documentation available in the implementation's repository.
Modifications made from the original algorithm version include: