SSAO2 does not behave correctly with dynamically changing camera parameters

I attempted to use SSAO2 in my project, but due to several minor defects, it is currently unusable for my use case.

Below, I will describe the bugs I discovered and the workarounds I found.

  1. Currently, SSAO2 does not dynamically adapt to changes in the camera projection mode.

    Therefore, if you change the camera’s camera.mode from Perspective to Orthographic, or vice versa, it will not function correctly.

    By the way, after this PR, SSAO2 no longer functions properly even when the camera’s initial mode value is fixed to Orthographic.
    FrameGraph: Add support for SSAO2 by Popov72 · Pull Request #17311 · BabylonJS/Babylon.js · GitHub

    The reason lies in the initialization order. When ThinSSAO2PostProcess is first created, this.camera is null, so ORTHOGRAPHIC_CAMERA remains undefined
    Babylon.js/packages/dev/core/src/PostProcesses/thinSSAO2PostProcess.ts at master · BabylonJS/Babylon.js · GitHub

    If you look at this older version of the code, it creates a define using scene.activeCamera to generate the effect, so SSAO2 operates according to the initial mode state of the active camera.
    Babylon.js/packages/dev/core/src/PostProcesses/RenderPipeline/Pipelines/ssao2RenderingPipeline.ts at 0977906a06740921602d09b591c05f61553d9f3b · BabylonJS/Babylon.js · GitHub

  2. The Perspective Camera does not respect camera.fovMode.

    This can be resolved by changing the code like this.
    Babylon.js/packages/dev/core/src/PostProcesses/thinSSAO2PostProcess.ts at master · BabylonJS/Babylon.js · GitHub

    if (camera.mode === Camera.PERSPECTIVE_CAMERA) {
        effect.setMatrix3x3("depthProjection", ThinSSAO2PostProcess.PERSPECTIVE_DEPTH_PROJECTION);
        const viewportSize = Math.tan(camera.fov / 2);
        if (camera.fovMode === Camera.FOVMODE_VERTICAL_FIXED) {
            effect.setFloat("xViewport", viewportSize * this._scene.getEngine().getAspectRatio(camera, true));
            effect.setFloat("yViewport", viewportSize);
        } else {
            effect.setFloat("xViewport", viewportSize);
            effect.setFloat("yViewport", viewportSize / this._scene.getEngine().getAspectRatio(camera, true));
        }
    } else {
    

To fundamentally resolve issue 1, the SSAO2 definition must be dynamically updated based on the camera’s mode.

To address this, I tried adding code immediately below the section in SSAO2RenderingPipeline that assigns the activeCamera.
I added code to memorize the camera’s previous mode and update the define if it differs, but it didn’t work properly.
It seems I need to place that logic somewhere else.
Babylon.js/packages/dev/core/src/PostProcesses/RenderPipeline/Pipelines/ssao2RenderingPipeline.ts at master · BabylonJS/Babylon.js · GitHub

I tried to fix the bug myself, but my skills aren’t up to the task, so I’m asking for help.:innocent:

To add an example of how it malfunctions, it appears like this.

If you do not dynamically change the camera’s mode and fovMode parameters, it will render like this. (normal)

I’ve created a PG that reproduces the issue here. I sincerely hope this problem gets resolved!

Thank you in advance. @Evgeni_Popov

1 Like

Thank you for the detailed report and the reproduction!

Here’s the fix:

2 Likes

I reviewed the PR and found a few things that needed improvement, so I created a new PR. Thank you so much.

1 Like

Oh yes, sorry, I forgot to take fovMode support into account!

Thanks for the PR.

3 Likes