Skip to content

[compat] SSAO2RenderingPipeline (screen-space ambient occlusion) #752

Description

@sdoleg2011

Missing API

SSAO2RenderingPipeline from @babylonjs/core — constructor (name, scene, ratio | { ssaoRatio, blurRatio }, cameras?, forceGeometryBuffer?), the tuning properties (radius, totalStrength, base, samples, maxZ, minZAspect, epsilon, expensiveBlur), dispose(), and the scene.postProcessRenderPipelineManager.attachCamerasToRenderPipeline / detachCamerasFromRenderPipeline pair that apps use to switch it on and off.

Current behavior

It exists but throws LiteCompatError ("SSAO is not implemented in Babylon Lite"). scene.postProcessRenderPipelineManager is undefined.

Use case

Interior / furniture scenes lean on SSAO for contact shading: the gaps between cabinet fronts, inner corners of carcasses, the floor line under plinths. I am moving a kitchen configurator from Babylon.js 9 to Babylon Lite through lite-compat; without SSAO flat-lit furniture loses most of its depth cues, and this was the last rendering feature missing for us (after GlowLayer, #751).

Minimal example

const ssao = new SSAO2RenderingPipeline("ssao", scene, { ssaoRatio: 0.75, blurRatio: 0.75 }, undefined, true);
scene.postProcessRenderPipelineManager.attachCamerasToRenderPipeline("ssao", camera);
ssao.radius = 0.09; // metres
ssao.totalStrength = 0.9;
ssao.base = 0.5;
ssao.samples = 16;
ssao.maxZ = 11;
ssao.minZAspect = 0.2;
ssao.epsilon = 0.01;
ssao.expensiveBlur = true;

Additional context

I have a working implementation in my app-side shim on 1.30.0, again made only of native frame-graph tasks appended after the default scene task:

  1. createGeometryRendererTask with a single VIEW_DEPTH attachment (shared with the glow layer from [compat] GlowLayer (selective glow for emissive meshes) #751).
  2. An AO pass at ssaoRatio of the canvas: view position rebuilt from the linear depth and the projection matrix (perspective and orthographic), the normal derived from neighbouring positions, then the SSAO2 loop as in Babylon.js — Hammersley hemisphere directions with cosθ = 1 − 0.85u, the 16-entry scales table, the radius/minZAspect correction, the epsilon step and range check, the maxZ fade, and clamp(1 − totalStrength·occlusion/N + base).
  3. The expensiveBlur bilateral box filter, horizontal then vertical: 16 taps over ±16 texels, weight 1 / (0.003 + |Δdepth|). This is what turns the thin raw AO lines into the soft wide gradients; with a narrow Gaussian the result looked nothing like Babylon.js.
  4. Composite onto engine.scRT as black with alpha 1 − ao (alphaMode: 2, clear: false), which multiplies the resolved frame by the AO term without touching the default render task.

Measured against Babylon.js 9 on the same scenes, the raw AO maps (strength 1, base 0) match in shape and strength (mean AO 0.9916 vs 0.9935), and the darkening in a 20 mm gap between two cabinet fronts is 0.950 vs 0.959. Cost at 1920×1080 with an uncapped frame rate: 0.67 ms → 1.73 ms per frame on a desktop GPU.

Notes that may be useful whichever way you go:

Happy to contribute this as a PR against babylon-lite-compat (or as a native createSsaoPostProcessTask) if you want it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions