Skip to content

Ambient Occlusion - GTAO

AO is used to depict the effect of objects occluding the surrounding diffuse light when they intersect or come close to each other. It can solve or improve problems such as light leakage, floating, and unrealistic shadows, and can solve or improve the unclear representation of gaps, folds, wall corners, edge lines, and small objects in the scene. It comprehensively improves details, especially shadows in dark areas, enhances the sense of depth and realism of space, and at the same time strengthens and improves the contrast between light and dark, enhancing the artistry of the image. Internally, the engine samples the pixels within a specified screen range and within a specified distance range, and computes an integral to assign the current pixel's AO coefficient.

ts
//Initialize the engine
let engine = await Engine3D.init();

engine.setting.render.postProcessing.gtao.maxDistance = 5;
engine.setting.render.postProcessing.gtao.maxPixel = 50;
engine.setting.render.postProcessing.gtao.darkFactor = 1;
engine.setting.render.postProcessing.gtao.rayMarchSegment = 6;
engine.setting.render.postProcessing.gtao.multiBounce = true;
engine.setting.render.postProcessing.gtao.blendColor = true;

// Add GTAOPost
let postProcessing = this.scene.addComponent(PostProcessingComponent);
postProcessing.addPost(GTAOPost);

//Start rendering
let view = new View3D();
view.scene = this.scene;
view.camera = this.camera;
engine.startRenderView(view);

engine.setting.render.postProcessing.gtao configuration parameters.

ParameterTypeDescription
maxDistancenumberSets the maximum distance when searching the surrounding 3D space during AO sampling.
maxPixelnumberSets the maximum distance when searching the surrounding pixels during AO sampling.
darkFactornumberSets the coefficient of the AO value when output to the screen, 1: full output, 0: no output.
rayMarchSegmentnumberSets the number of marching steps during AO sampling. The larger the value, the better the quality of the AO effect, but the more performance it consumes.
multiBouncebooleanWhether to simulate color bouncing.
blendColorbooleantrue: blend with the mainColor of the GBuffer; false: output only the AO color.

WebGPU is not supported in your browser
Please upgrade to latest Chrome/Edge

<
ts
import { View3D, DirectLight, Engine3D, PostProcessingComponent, LitMaterial, HoverCameraController, KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, CameraUtil, BoxGeometry, TAAPost, AtmosphericComponent, GTAOPost } from '@orillusion/core';
import * as dat from 'dat.gui';

class Sample_GTAO {
    lightObj: Object3D;
    scene: Scene3D;

    async run() {
        let engine = await Engine3D.init({
            setting: {
                shadow: {
                    shadowSize: 2048,
                    shadowBound: 500,
                    shadowBias: 0.05
                }
            }
        });

        this.scene = new Scene3D();
        this.scene.addComponent(AtmosphericComponent).sunY = 0.6;

        let mainCamera = CameraUtil.createCamera3DObject(this.scene, 'camera');
        mainCamera.perspective(60, engine.aspect, 1, 5000.0);
        let ctrl = mainCamera.object3D.addComponent(HoverCameraController);
        ctrl.setCamera(0, -15, 500);
        await this.initScene();

        let view = new View3D();
        view.scene = this.scene;
        view.camera = mainCamera;
        engine.startRenderView(view);

        let postProcessing = this.scene.addComponent(PostProcessingComponent);
        let post = postProcessing.addPost(GTAOPost);
        post.maxDistance = 6;
		post.maxPixel = 15;
        this.gui();
    }

    async initScene() {
        {
            this.lightObj = new Object3D();
            this.lightObj.rotationX = 45;
            this.lightObj.rotationY = 110;
            this.lightObj.rotationZ = 0;
            let lc = this.lightObj.addComponent(DirectLight);
            lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355);
            lc.castShadow = true;
            lc.intensity = 5;
            lc.indirect = 0.3;
            this.scene.addChild(this.lightObj);
        }

        {
            let mat = new LitMaterial();
            mat.roughness = 1.0;
            mat.metallic = 0.0;

            let floor = new Object3D();
            let mr = floor.addComponent(MeshRenderer);
            mr.geometry = new PlaneGeometry(400, 400);
            mr.material = mat;
            this.scene.addChild(floor);

            {
                let wall = new Object3D();
                let mr = wall.addComponent(MeshRenderer);
                mr.geometry = new BoxGeometry(5, 260, 320);
                mr.material = mat;
                wall.x = -320 * 0.5;
                this.scene.addChild(wall);
            }

            {
                let wall = new Object3D();
                let mr = wall.addComponent(MeshRenderer);
                mr.geometry = new BoxGeometry(5, 260, 320);
                mr.material = mat;
                wall.x = 320 * 0.5;
                this.scene.addChild(wall);
            }

            {
                let wall = new Object3D();
                let mr = wall.addComponent(MeshRenderer);
                mr.geometry = new BoxGeometry(320, 260, 5);
                mr.material = mat;
                wall.z = -320 * 0.5;
                this.scene.addChild(wall);
            }

            {
                {
                    let sp = new Object3D();
                    let mr = sp.addComponent(MeshRenderer);
                    mr.geometry = new SphereGeometry(50, 30, 30);
                    mr.material = mat;
                    this.scene.addChild(sp);
                }
            }
        }
    }

    private gui() {
        let postProcessing = this.scene.getComponent(PostProcessingComponent);
        let post = postProcessing.getPost(GTAOPost);

        let GUIHelp = new dat.GUI();
        let f = GUIHelp.addFolder('GTAO');
        f.add(post, 'maxDistance', 0.0, 50, 1);
        f.add(post, 'maxPixel', 0.0, 50, 1);
        f.add(post, 'rayMarchSegment', 4, 10, 0.001);
        f.add(post, 'darkFactor', 0.0, 5, 0.001);
        f.add(post, 'blendColor');
        f.add(post, 'multiBounce');
        f.open();
    }
}

new Sample_GTAO().run();

Released under the MIT License