[WIP] Directional GTAO (HDRP)

Directional GTAO

Directional GTAO is a fast and versatile screen-space ambient occlusion effect with many additional rendering features. It makes use of Compute Shaders and SRP Custom Pass system, targeting high visual quality.

GTAO is the core of the algorithm and at the current moment, it is the most advanced and practical approach to calculating ambient occlusion in screen-space. I used the original paper and the most recent open-source implementation called XeGTAO as my primary sources. I also looked into Amplify Occlusion and HDRP’s native GTAO to see if they do something differently (spoiler: not really).

Here’s the list of main features that makes this AO different from other AO implementations out there and from HDRP’s native AO algorithm:

Directional Injection accounts for real-time light sources in the scene during AO calculation. It can make occlusion more realistic if used carefully. Not meant as a general replacement for regular shadowmaps but can help to hide their bias and/or cover small details where shadowmap resolution isn’t sufficient. Basically, it’s a mix of Micro-Shadows and Contact Shadows:

7851594--996168--upload_2022-1-29_19-39-2.gif

Bent Normals are generated alongside the main AO effect and can be used to augment AO directionality further and/or calculate GTSO (Ground Truth Specular Occlusion), which will be added soon:

Masking allows you to select which objects will receive and cast occlusion on a per-layer basis. It operates in 4 modes:

  • Affect - Only selected objects will cast occlusion (onto other objects and themselves)
  • Exclude - Only selected objects will cast occlusion (onto other objects but not themselves)
  • Receive - Only selected objects will receive occlusion (from other objects and themselves)
  • Self - Only selected objects will receive occlusion (only from themselves)

7851594--996174--upload_2022-1-29_19-43-57.gif

The byproduct of the Affect and Exclude modes is that objects that are NOT on the selected layer(s) are completely omitted from AO calculation and therefore do not create typical disocclusion screen-space artifacts:
Without Masking (All objects participate in AO)

7851594--996177--upload_2022-1-29_19-46-40.gif

With Masking (Moving box does not participate in AO)

7851594--996180--upload_2022-1-29_19-53-45.gif

Thickness-Aware option makes the AO radius dependent on the real object thickness instead of assuming that all objects are infinitely thick or forcing some unified value on the whole scene like it’s typically done in screen-space effects:


I’m thinking of exposing the thickness buffer. Since it’s already calculated you may as well use it for some other cool thickness-dependent effects, like this one.

Pre-Pass mode forms a mask used to early-out of the AO and avoid rendering areas where no occlusion is expected anyway. It will also avoid rendering AO for all unnecessary objects defined by the Masking mode (described above), so you will be rendering only the pixels covered by the objects you chose (and the area of occlusion around them if set to Affect or Exclude) instead of the whole screen, as it’s typically done, thus saving a lot of performance:

Temporal Accumulation and Temporal Upscaling are used to gather more samples throughout the time (a span of several frames) getting rid of the noise. Most AO implementations (HDRP’s native one included) have an option to render AO in a half-resolution format and then upscale it to the target frame size with a bilateral upsampling, which may lead to the blurred result (because such upscale is virtually a blur filter that tries to preserve edges). I decided to do Temporal Accumulation and Upscaling in a single pass, reconstructing the final higher-resolution image like Unity’s TAAU or UE Screen Percentage does (from the conceptual point of view):


Note that this upscaling is done exclusively for the AO effect and leaves the main rendering resolution intact, so it can be used together with the native TAAU or TAA and/or other anti-aliasing and upscaling techniques provided by the engine.

Off-Screen Buffer rendering makes it possible to output AO (and Bent Normals) not directly to the Camera, but to a separate Color Buffer provided by the HDRP Custom Pass system. This way, you can sample AO and Bent Normals in your shaders (Shader Graphs too) or Custom Passes in any way you see fit. For example, you can plug Bent Normals into the respective input in the SG Master Stack to use it for the native specular occlusion system, or you can use AO as a mask for the edge-wear effect or some purely non-pbr artistic reasons. This also means that you can enable and disable AO on a per-material basis:


This screenshot demonstrates how AO can be used as a mask to drive the patina effect of the material made in Shader Graph. Note how AO is applied only to a certain material.
Shader Graph setup

So, these are all features that I’ve implemented so far. Now it’s time to clean the code and test everything to make it production-ready.

Here are my short-term plans which are supposed to be finished before the release or as a “day-one” patch:

  • Documentation
  • Hi-Z Buffer (Serves as an acceleration structure)
  • GTSO (Ground Truth Specular Occlusion)
  • Better integration with HDRP lighting (Like “Direct Lighting Strength” slider in the HDRP AO)
  • Multibounce & Color-Bleeding (First light bounce approximation)
  • Support for all light types for the Directional Injection (now only the Directional Light is supported)
  • Ability to modify Normal Buffer with Bent Normals (Better directionality and more realistic lighting

My long-term (after publication) plans are:

  • Potential URP support (haven’t looked into URP at all, so can’t promise 100%)
  • Bakery SH support (use baked SH lightmaps to drive directionality instead of real-time lights).
  • Extend it to full Global Illumination (most likely a separate asset)

I’ll be posting development updates here and on Twitter

Please, note that some screenshots above are done during the early development stages and do not reflect how the final AO will look.

22 Likes

Sounds very promising! Great thread, tons of info.

Bent normals would be a big help for scenes without baking. Color-bleeding, multiBounce, GTSO, all of it sounds awesome :smile:
Looking forward to it!

4 Likes

Thanks for the kind words:)
I hope I will be able to submit it for publication soon!

2 Likes

Update:
While developing the promised “Multibounce & Color-Bleeding” feature, I found that it’s possible to do way more than that. The GTAO algorithm turned out to be an ideal candidate for the full-scale Screen-Space Global Illumination that can outperform a typical SSGI ray-marcher. Moreover, it’s possible to accumulate both AO and GI at the same time, so there’s no need to trace the frame twice.

So, I decided to explore this opportunity and the result of this exploration you can find in this thread . I called it “H-Trace” (where “H” stands for “Horizon” since it’s a horizon-based method). Essentially, it’s a combination of Global Illumination and Ambient Occlusion in screen-space.

H-Trace is entirely based on the GTAO described in this thread. ATM I’m trying to figure out if I can transfer all (or most of) features described here to H-Trace. After that, there are 3 options:

  1. Release only H-Trace as a unified 2-in-1 solution for AO and GI.
  2. Release H-Trace as a unified 2-in-1 solution for AO and GI, but also release Directional GTAO as a “Lite” version for AO only.
  3. Release both H-Trace and Directional GTAO as separate assets.
7 Likes

Do you have an estimate on when you are going to release this? Looks amazing!

Awesome, is this the Amplify Occlusion replacement I’ve been waiting for?

It is amazing when you gonna release it?