flutter3d
Showcase Changelog 38 packages API reference

Ambient light: the source

since 0.4.3 Shading and materials

Regions the guide quotes: ambient (line 41), live (line 57), check (line 73).

1/// `Scene.ambientColor` and `Scene.ambientIntensity`: the flat term a surface
2/// falls back to wherever no direct light reaches it.
3///
4/// Quoted by `ambient_light.md` and shown whole in the Source tab.
5library;
6
7import 'package:flutter3d/flutter3d.dart';
8import 'package:flutter3d_showcase/src/demo/demo.dart';
9import 'package:vector_math/vector_math.dart';
11final class AmbientLightDemo extends ShowcaseDemo {
12 double ambientIntensity = 0.35;
14 late final Scene _scene;
16 @override
17 void configureView(DemoContext context) {
18 // Square to the key light's own direction, not merely off to one side:
19 // `yaw = 1.4` looked almost straight down the light's own beam, so the
20 // ball read as fully lit from every frame this page ever drew and the
21 // slider had no side left to brighten. `2.9` looks across the light
22 // instead, which is what puts the terminator in the middle of the
23 // frame — half the ball lit, half carrying nothing but the ambient term.
24 context.orbit
25 ..distance = 4.5
26 ..yaw = 2.9
27 ..pitch = 0.1;
28 }
30 @override
31 Scene build(DemoContext context) {
32 final MeshNode ball = MeshNode(
33 DeviceMesh.upload(
34 context.device,
35 SphereShape(segments: 40, rings: 20).build(),
36 ),
37 Material(baseColor: Vector4(0.7, 0.7, 0.75, 1.0), roughness: 0.6),
38 name: 'ball',
39 );
41 // One light from one side only, so the far side of the ball is lit by
42 // nothing but the ambient term below.
43 _scene = Scene()
44 ..add(ball)
45 ..add(
46 LightNode(name: 'key', intensity: 3.0)
47 ..setLocalForward(Vector3(-0.8, -0.2, -0.2)),
48 )
49 ..ambientColor = Vector3(0.55, 0.65, 1.0)
50 ..ambientIntensity = ambientIntensity;
52 return _scene;
53 }
55 @override
56 void update(DemoContext context, double dt) {
57 _scene.ambientIntensity = ambientIntensity;
58 }
60 @override
61 List<DemoControl> controls(DemoContext context) => <DemoControl>[
62 SliderControl(
63 'Ambient intensity',
64 min: 0,
65 max: 1,
66 value: () => ambientIntensity,
67 onChanged: (double v) => ambientIntensity = v,
68 ),
69 ];
71 @override
72 void verify(Scene scene, FrameResult frame) {
73 if (scene.ambientIntensity != ambientIntensity) {
74 throw StateError('the scene ambient did not track the slider');
75 }
76 if (scene.lights.length != 1) {
77 throw StateError(
78 'this page needs exactly one direct light to leave a '
79 'side for the ambient term to fill',
80 );
81 }
82 if (frame.drawCalls < 1) {
83 throw StateError('the ball was not drawn');
84 }
85 }