Skip to content

Add screen-space ambient occlusion - #501

Merged
tomconder merged 1 commit into
mainfrom
ssao
Sep 20, 2026
Merged

tomconder merged 1 commit into
mainfrom
ssao

Conversation

@tomconder

Copy link
Copy Markdown
Owner

Summary

  • Hemisphere-kernel SSAO (Crytek/Rendu-style), sampled against the depth prepass's depth and a new view-space normal MRT target, depth-aware blurred, then multiplied into the ambient term in pbr.slang.
  • Depth prepass extended to also write view-space normals; light cubes (position-only geometry) read as "no surface" via a zero-normal sentinel.
  • Debug UI: new SSAO tab (enable toggle, radius slider), and the old flat "Ambient Occlusion" scalar slider is removed — it was a placeholder for real AO that's now redundant, so SceneAmbient::occlusion defaults to 1.0 (no extra attenuation) and stays available as an optional multiplier on top of SSAO for artist tuning.

Fix folded in

While bringing up the feature, SSAO's raw/blur render targets read back as all-zero regardless of the occlusion math, which showed up as the whole scene going black with SSAO enabled. Root cause: the renderer leaves GL_BLEND enabled globally, the SSAO targets are single-channel GL_R16F (no alpha), and the shader's undefined alpha meant every write blended away to the framebuffer's zeroed initial contents instead of landing. Ssao::process() now disables blending for the pass, the same way the depth prepass already does for its own MRT writes.

Test plan

  • Clean build (MSVC release + debug), no new compiler warnings.
  • pre-commit run --all-files passes (clang-format, cpplint, shellcheck, etc.).
  • Manual visual check at true default scene lighting (0 point lights): SSAO on shows full brightness with correct, subtle contact-shadowing in corners and under geometry; SSAO off matches pre-feature brightness.
  • Toggled SSAO on/off and the radius slider live via the debug UI.

Hemisphere-kernel SSAO against the depth prepass's depth and a new
view-space normal target, depth-aware blurred and multiplied into
ambient. The depth prepass gains an MRT normal output for it, and
the old flat ambient-occlusion scalar becomes an optional multiplier
on top of the real per-pixel result instead of a stand-in for it.

Blending is left on globally by the renderer; the SSAO passes render
to alpha-less R16F targets, so leaving it enabled here silently
blended every write away to zero. Disable it for the pass like the
depth prepass already does for its own MRT writes.
@github-actions github-actions Bot added sponge Sponge engine changes game Game changes labels Sep 20, 2026
@tomconder
tomconder merged commit 10064ed into main Sep 20, 2026
8 checks passed
@tomconder
tomconder deleted the ssao branch September 20, 2026 23:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

game Game changes sponge Sponge engine changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant