Reference Source
public class | source

SAO

Extends:

Component → SAO

Configures Scalable Ambient Obscurance (SAO) for a Scene.

[Run this example]

Overview

SAO approximates Ambient Occlusion in realtime. It darkens creases, cavities and surfaces that are close to each other, which tend to be occluded from ambient light and appear darker.

The animated GIF above shows the effect as we repeatedly enable and disable SAO. When SAO is enabled, we can see darkening in regions such as the corners, and the crevices between stairs. This increases the amount of detail we can see when ambient light is high, or when objects have uniform colors across their surfaces. Run the example to experiment with the various SAO configurations.

xeokit's implementation of SAO is based on the paper Scalable Ambient Obscurance.

Caveats

Currently, SAO only works with perspective and orthographic projections. Therefore, to use SAO, make sure Camera#projection is either "perspective" or "ortho".

SAO#scale and SAO#intensity must be tuned to the distance between Perspective#near and Perspective#far, or the distance between Ortho#near and Ortho#far, depending on which of those two projections the Camera is currently using. Use the live example to get a feel for that.

Usage

In the example below, we'll start by logging a warning message to the console if SAO is not supported by the system.

Then we'll enable and configure SAO, position the camera, and configure the near and far perspective and orthographic clipping planes. Finally, we'll use XKTLoaderPlugin to load the OTC Conference Center model.

import {Viewer} from "../src/viewer/Viewer.js";
import {XKTLoaderPlugin} from "../src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js";

const viewer = new Viewer({
    canvasId: "myCanvas",
    transparent: true
});

const sao = viewer.scene.sao;

if (!sao.supported) {
    sao.warn("SAO is not supported on this system - ignoring SAO configs")
}

sao.enabled = true; // Enable SAO - only works if supported (see above)
sao.intensity = 0.25;
sao.bias = 0.5;
sao.scale = 500.0;
sao.minResolution = 0.0;
sao.kernelRadius = 100;
sao.blendCutoff = 0.2;

const camera = viewer.scene.camera;

camera.eye = [3.69, 5.83, -23.98];
camera.look = [84.31, -29.88, -116.21];
camera.up = [0.18, 0.96, -0.21];

camera.perspective.near = 0.1;
camera.perspective.far = 2000.0;

camera.ortho.near = 0.1;
camera.ortho.far = 2000.0;
camera.projection = "perspective";

const xktLoader = new XKTLoaderPlugin(viewer);

const model = xktLoader.load({
    id: "myModel",
    src: "./models/xkt/OTCConferenceCenter/OTCConferenceCenter.xkt",
    metaModelSrc: "./metaModels/OTCConferenceCenter/metaModel.json",
    edges: true
});

[Run this example]

Efficiency

SAO can incur some rendering overhead, especially on objects that are viewed close to the camera. For this reason, it's recommended to use a low value for SAO#kernelRadius. A low radius will sample pixels that are close to the source pixel, which will allow the GPU to efficiently cache those pixels. When Camera#projection is "perspective", objects near to the viewpoint will use larger radii than farther pixels. Therefore, computing SAO for close objects is more expensive than for objects far away, that occupy fewer pixels on the canvas.

Selectively enabling SAO for models

When loading multiple models into a Scene, we sometimes only want SAO on the models that are actually going to show it, such as the architecture or structure, and not show SAO on models that won't show it well, such as the electrical wiring, or plumbing.

To illustrate, lets load some of the models for the West Riverside Hospital. We'll enable SAO on the structure model, but disable it on the electrical and plumbing.

This will only apply SAO to those models if SAO#supported and SAO#enabled are both true.

Note, by the way, how we load the models in sequence. Since XKTLoaderPlugin uses scratch memory as part of its loading process, this allows the plugin to reuse that same memory across multiple loads, instead of having to create multiple pools of scratch memory.

const structure = xktLoader.load({
     id: "structure",
     src: "./models/xkt/WestRiverSideHospital/structure.xkt",
     metaModelSrc: "./metaModels/WestRiverSideHospital/structure.json",
     edges: true,
     saoEnabled: true
 });

 structure.on("loaded", () => {

     const electrical = xktLoader.load({
         id: "electrical",
         src: "./models/xkt/WestRiverSideHospital/electrical.xkt",
         metaModelSrc: "./metaModels/WestRiverSideHospital/electrical.json",
         edges: true
     });

     electrical.on("loaded", () => {

         const plumbing = xktLoader.load({
             id: "plumbing",
             src: "./models/xkt/WestRiverSideHospital/plumbing.xkt",
             metaModelSrc: "./metaModels/WestRiverSideHospital/plumbing.json",
                 edges: true
             });
         });
     });
});

Disabling SAO while camera is moving

For smoother interaction with large models on low-power hardware, we can disable SAO while the Camera is moving:

const timeoutDuration = 150; // Milliseconds
var timer = timeoutDuration;
var saoDisabled = false;

const onCameraMatrix = scene.camera.on("matrix", () => {
    timer = timeoutDuration;
    if (!saoDisabled) {
        scene.sao.enabled = false;
        saoDisabled = true;
    }
});

const onSceneTick = scene.on("tick", (tickEvent) => {
    if (!saoDisabled) {
        return;
    }
    timer -= tickEvent.deltaTime; // Milliseconds
    if (timer <= 0) {
        if (saoDisabled) {
            scene.sao.enabled = true;
            saoDisabled = false;
        }
    }
});

[Run this example]

Member Summary

Public Members
public set

Sets the SAO bias.

public get

Gets the SAO bias.

public set

Sets whether Guassian blur is enabled.

public get

Gets whether Guassian blur is enabled.

public set

Sets whether SAO is enabled for the Scene.

public get

Gets whether SAO is enabled for the Scene.

public set

Sets the degree of darkening (ambient obscurance) produced by the SAO effect.

public get

Gets the degree of darkening (ambient obscurance) produced by the SAO effect.

public set

Sets the maximum area that SAO takes into account when checking for possible occlusion.

public get

Gets the maximum area that SAO takes into account when checking for possible occlusion.

public set

Sets the SAO minimum resolution.

public get

Gets the SAO minimum resolution.

public set

Sets the SAO occlusion scale.

public get

Gets the SAO occlusion scale.

public get

Gets whether or not SAO is supported by this browser and GPU.

Method Summary

Public Methods
public

Destroys this component.

Inherited Summary

From class Component
public get

The Component that owns the lifecycle of this Component, if any.

public

True as soon as this Component has been destroyed

public

ID of this Component, unique within the Scene.

public

meta: *

Arbitrary, user-defined metadata on this component.

public

The parent Scene that contains this Component.

public

The viewer that contains this Scene.

public

clear()

Destroys all Components that are owned by this.

public

Destroys this component.

public

error(message: String)

Logs an error for this component to the JavaScript console.

public

fire(event: String, value: Object, forget: Boolean)

Fires an event on this component.

public

Returns true if there are any subscribers to the given event on this component.

public

isType(type: *): *: Boolean

Tests if this component is of the given type, or is a subclass of the given type.

public

log(message: String)

Logs a console debugging message for this component.

public

off(subId: String)

Cancels an event subscription that was previously made with Component#on or Component#once.

public

on(event: String, callback: Function, scope: Object): String

Subscribes to an event on this component.

public

once(event: String, callback: Function, scope: Object)

Subscribes to the next occurrence of the given event, then un-subscribes as soon as the event is subIdd.

public

warn(message: String)

Logs a warning for this component to the JavaScript console.

Public Members

public set bias: Number source

Sets the SAO bias.

Default value is 0.5.

public get bias: Number source

Gets the SAO bias.

Default value is 0.5.

public set blur: Boolean source

Sets whether Guassian blur is enabled.

Default value is true.

public get blur: Boolean source

Gets whether Guassian blur is enabled.

Default value is true.

public set enabled: Boolean source

Sets whether SAO is enabled for the Scene.

Even when enabled, SAO will only work if supported.

Default value is false.

public get enabled: Boolean source

Gets whether SAO is enabled for the Scene.

Even when enabled, SAO will only apply if supported.

Default value is false.

public set intensity: Number source

Sets the degree of darkening (ambient obscurance) produced by the SAO effect.

Default value is 0.25.

public get intensity: Number source

Gets the degree of darkening (ambient obscurance) produced by the SAO effect.

Default value is 0.25.

public set kernelRadius: Number source

Sets the maximum area that SAO takes into account when checking for possible occlusion.

Default value is 100.0.

public get kernelRadius: Number source

Gets the maximum area that SAO takes into account when checking for possible occlusion.

Default value is 100.0.

public set minResolution: Number source

Sets the SAO minimum resolution.

Default value is 0.0.

public get minResolution: Number source

Gets the SAO minimum resolution.

Default value is 0.0.

public set scale: Number source

Sets the SAO occlusion scale.

Default value is 500.0.

public get scale: Number source

Gets the SAO occlusion scale.

Default value is 500.0.

public get supported: Boolean source

Gets whether or not SAO is supported by this browser and GPU.

Even when enabled, SAO will only work if supported.

Public Methods

public destroy() source

Destroys this component.

Override:

Component#destroy