Yet another screen-space ambient occlusion filter, or ambient obscurance, as defined by the authors on the paper. For UPBGE 0.2.5 and RanGE.
This is actually a composite filter, consisting of 3 passes, following the paper: a first pass to calculate the occlusion, and two passes to perform a cross-bilateral filtering, using the depth as ‘determinator’, much like the Compositor bilateral blur node.
A trick to improve the performance, set as default, is to render the occlusion pass to an off-screen buffer half the resolution, then, to properly preserve the edges, the horizontal bilateral blur is rendered to another off-screen buffer, full width and half height; finally, the vertical blur is done at full resolution, directly applying the occlusion. All of this is done with the Filter manager, using 3 out of the 8 passes available, starting with the pass number given by the ‘ssao’ filter Actuator. Both ‘Filter 2D’ actuators connected to the Script controller are there only to provide the shader base codes, which will be completed by the script with a “header” containing the selected options.
A ‘Normal’ type render attachment is required; if you are not getting any occlusion, you probably forgot to set it up.
I added quite a few options to the filter setup.
quality
: 0, 1 or 2 corresponding to low, mid and high presets, they affect both the occlusion and the bilateral filtering.
FullResolutionAO
: self explanatory, uses a full resolution buffer for the occlusion. Greater quality occlusion, poorer performance. Combined with ‘quality’, they effectively provide 6 quality settings.
useBayerPattern
: Traditionally a random noise pattern is used to perform the sampling, I added the Bayer option, as the regular pattern is easier to smooth out during the bilateral blur passes. Enabled by default.
radius
: the occlusion radius, in Blender Units (or Meters).
intensity
and contrast
: These are both part of the Alchemy algorithm. While ‘intensity’ controls the darkness, ‘contrast’ controls the falloff of the occlusion, is the exponent of a power operation, like a gamma function. The falloff is linear when contrast is 1.0, values greater than 1.0 curve the falloff making it darker, lower values than 1.0 make it brighter. Compare the effect of intensity and contrast set to 2.0:
In my opinion increasing the contrast usually provides better results.
luminanceInfluence
(0.0…1.0): Controls how much the luminance/brightness affects the occlusion. When set to 1.0, full white won’t show any occlusion.
aoSaturation
(0.0…1.0): I usually notice that when the occlusion is applied by a simple ‘multiply’ operation, colors tend to desaturate, this setting attempts to preserve the original color saturation. (GIF comparison)
Admittedly, setting this to 1.0 may be too much. Around 0.7 or 0.8 is good enough. I added this option based on my personal preferences.
aoCutoff
: A depth cutoff value that allows the radius to be increased when calculating the occlusion against geometry in front of or behind the current fragment. 1.0 uses just the radius distance, 2.0 is a good number, too large values will produce a dark halo around objects.
normalAttchIndex
: The index of the normal attachment, this is essential for the filter to work.
blurCheckNormals
: Uses the normal pass in addition to the depth, to improve the bilateral blurring, by performing a dot product operation.
In order to improve the performance, the normal is stored in the same buffer with the occlusion, in a single texture fetch the occlusion and the normals are sampled, although as you can see in the picture on the edges where the normal takes most effect, when using a half the resolution for the occlusion, the normals will be half resolution too. Anti-aliasing can help reduce that issue, but only if it’s as a post-process, but there are more reasons to choose it.
When using multisampled anti-aliasing, the normal attachment will be anti-aliased too, this produces an incorrect self occlusion around geometry, where the normal blends, due to anti-aliasing, with the normal of geometry behind. Additionally, the depth buffer is always aliased, as it should, so the bilateral blurring will always produce aliased edges. For all that, I suggest using the FXAA option if you choose to use AA, as post-process anti-aliasing methods specially target deferred shading techniques such as ambient occlusion.
The
radius
, intensity
, contrast
and aoCutoff
properties can be updated in game. All other settings are hard coded for performance reasons.
Sources, references, further reading
Alchemy Screen-Space Ambient Obscurance
Scalable Ambient Obscurance
Tesseract game engine, by Lee Salzman
NVIDIA DesignWorks Samples bilateral blur
Last but not least
Alchemy-AO-UPBGE.blend (923.8 KB)