Ambient light
Open the live demo · Read the source · View on GitHub
Scene.ambientColor and Scene.ambientIntensity are the flat term a
surface falls back to wherever no direct light reaches it. They are what
keeps the far side of a lit object from going pure black, and the only
light source in a scene that otherwise has none at all.
Step 1: One light, and a side it never reaches #
A single key light from one side leaves the far side of the ball with nothing but the ambient term to read by. That is what makes the effect visible: a scene lit evenly from everywhere would show nothing when the ambient term changed.
// One light from one side only, so the far side of the ball is lit by
// nothing but the ambient term below.
_scene = Scene()
..add(ball)
..add(
LightNode(name: 'key', intensity: 3.0)
..setLocalForward(Vector3(-0.8, -0.2, -0.2)),
)
..ambientColor = Vector3(0.55, 0.65, 1.0)
..ambientIntensity = ambientIntensity;
Step 2: Move the slider #
ambientIntensity is read back into the scene every frame, so raising it
lifts exactly the shadowed side and leaves the lit side alone.
_scene.ambientIntensity = ambientIntensity;
Step 3: What this page checks #
The test cannot compare two pictures, so it checks the wiring instead: the scene's ambient intensity is the number the slider set, and there really is only one direct light, which is what leaves a side for the ambient term to fill in the first place.
if (scene.ambientIntensity != ambientIntensity) {
throw StateError('the scene ambient did not track the slider');
}
if (scene.lights.length != 1) {
throw StateError(
'this page needs exactly one direct light to leave a '
'side for the ambient term to fill',
);
}
if (frame.drawCalls < 1) {
throw StateError('the ball was not drawn');
}