SAO
Extends:
Configures Scalable Ambient Obscurance (SAO) for a Scene.
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, XKTLoaderPlugin} from "xeokit-sdk.es.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.15;
sao.bias = 0.5;
sao.scale = 1.0;
sao.minResolution = 0.0;
sao.numSamples = 10;
sao.kernelRadius = 100;
sao.blendCutoff = 0.1;
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.xkt"
edges: true
});
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"
edges: true,
saoEnabled: true
});
structure.on("loaded", () => {
const electrical = xktLoader.load({
id: "electrical",
src: "./models/xkt/WestRiverSideHospital/electrical.xkt",
edges: true
});
electrical.on("loaded", () => {
const plumbing = xktLoader.load({
id: "plumbing",
src: "./models/xkt/WestRiverSideHospital/plumbing.xkt",
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;
}
}
});
Member Summary
Public Members | ||
public set |
Sets the SAO bias. |
|
public get |
Gets the SAO bias. |
|
public set |
Sets the SAO blend cutoff. |
|
public get |
Gets the SAO blend cutoff. |
|
public set |
Sets the SAO blend factor. |
|
public get |
Gets the SAO blend scale. |
|
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 for each fragment. |
|
public get |
Gets the maximum area that SAO takes into account when checking for possible occlusion for each fragment. |
|
public set |
Sets the SAO minimum resolution. |
|
public get |
Gets the SAO minimum resolution. |
|
public set |
Sets the number of SAO samples. |
|
public get |
Gets the number of SAO samples. |
|
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 |
destroy() 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 |
destroy() Destroys this component. |
|
public |
Logs an error for this component to the JavaScript console. |
|
public |
Fires an event on this component. |
|
public |
Returns true if there are any subscribers to the given event on this component. |
|
public |
Tests if this component is of the given type, or is a subclass of the given type. |
|
public |
Logs a console debugging message for this component. |
|
public |
Cancels an event subscription that was previously made with Component#on or Component#once. |
|
public |
Subscribes to an event on this component. |
|
public |
Subscribes to the next occurrence of the given event, then un-subscribes as soon as the event is subIdd. |
|
public |
scheduleTask(task: *) Schedule a task to perform on the next browser interval |
|
public |
Logs a warning for this component to the JavaScript console. |
Public Members
public set blendCutoff: Number source
Sets the SAO blend cutoff.
Default value is 0.3
.
Normally you don't need to alter this.
public get blendCutoff: Number source
Gets the SAO blend cutoff.
Default value is 0.3
.
Normally you don't need to alter this.
public set blendFactor: Number source
Sets the SAO blend factor.
Default value is 1.0
.
Normally you don't need to alter this.
public get blendFactor: Number source
Gets the SAO blend scale.
Default value is 1.0
.
Normally you don't need to alter this.
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.15
.
public get intensity: Number source
Gets the degree of darkening (ambient obscurance) produced by the SAO effect.
Default value is 0.15
.
public set kernelRadius: Number source
Sets the maximum area that SAO takes into account when checking for possible occlusion for each fragment.
Default value is 100.0
.
public get kernelRadius: Number source
Gets the maximum area that SAO takes into account when checking for possible occlusion for each fragment.
Default value is 100.0
.