flutter3d
Showcase Changelog 38 packages API reference

Directional, point and spot lights: the source

since 0.2.0 Shading and materials

Regions the guide quotes: directional (line 56), point (line 62), spot (line 69), live (line 87), check (line 111).

1/// The three punctual light types: directional, point and spot, each with
2/// its own sphere so the difference is easy to read.
3///
4/// Quoted by `punctual_lights.md` and shown whole in the Source tab.
5library;
6
7import 'dart:math' as math;
8
9import 'package:flutter3d/flutter3d.dart';
10import 'package:flutter3d_showcase/src/demo/demo.dart';
11import 'package:vector_math/vector_math.dart';
13final class PunctualLightsDemo extends ShowcaseDemo {
14 double pointRange = 4.0;
15 double spotOuterDegrees = 25.0;
17 late final LightNode _point;
18 late final LightNode _spot;
20 @override
21 void configureView(DemoContext context) {
22 context.orbit
23 ..distance = 7.0
24 ..pitch = 0.25;
25 }
27 @override
28 Scene build(DemoContext context) {
29 final DeviceMesh sphere = DeviceMesh.upload(
30 context.device,
31 SphereShape(segments: 32, rings: 16).build(),
32 );
33 final Scene scene = Scene()
34 ..add(
35 MeshNode(
36 sphere,
37 Material(baseColor: Vector4(0.8, 0.8, 0.8, 1.0)),
38 name: 'sun ball',
39 )..setPosition(-2.2, 0.0, 0.0),
40 )
41 ..add(
42 MeshNode(
43 sphere,
44 Material(baseColor: Vector4(0.8, 0.8, 0.8, 1.0)),
45 name: 'point ball',
46 )..setPosition(0.0, 0.0, 0.0),
47 )
48 ..add(
49 MeshNode(
50 sphere,
51 Material(baseColor: Vector4(0.8, 0.8, 0.8, 1.0)),
52 name: 'spot ball',
53 )..setPosition(2.2, 0.0, 0.0),
54 );
56 final LightNode sun = LightNode(
57 name: 'sun',
58 type: LightType.directional,
59 intensity: 2.0,
60 )..setLocalForward(Vector3(-0.3, -0.6, -0.7));
62 _point = LightNode(
63 name: 'lamp',
64 type: LightType.point,
65 intensity: 6.0,
66 range: pointRange,
67 )..setPosition(0.0, 1.6, 1.2);
69 _spot = LightNode(
70 name: 'torch',
71 type: LightType.spot,
72 intensity: 10.0,
73 range: 6.0,
74 innerConeAngle: 0.0,
75 outerConeAngle: spotOuterDegrees * math.pi / 180.0,
76 )..setPosition(2.2, 2.2, 1.6);
77 _spot.lookAt(Vector3(2.2, 0.0, 0.0));
79 return scene
80 ..add(sun)
81 ..add(_point)
82 ..add(_spot);
83 }
85 @override
86 void update(DemoContext context, double dt) {
87 _point.range = pointRange;
88 _spot.outerConeAngle = spotOuterDegrees * math.pi / 180.0;
89 }
91 @override
92 List<DemoControl> controls(DemoContext context) => <DemoControl>[
93 SliderControl(
94 'Point range',
95 min: 1,
96 max: 10,
97 value: () => pointRange,
98 onChanged: (double v) => pointRange = v,
99 ),
100 SliderControl(
101 'Spot cone (degrees)',
102 min: 5,
103 max: 60,
104 value: () => spotOuterDegrees,
105 onChanged: (double v) => spotOuterDegrees = v,
106 ),
107 ];
109 @override
110 void verify(Scene scene, FrameResult frame) {
111 final Set<LightType> types = <LightType>{
112 for (final LightNode light in scene.lights) light.type,
113 };
114 if (types.length != 3) {
115 throw StateError('expected all three punctual types, found $types');
116 }
117 if (_point.range != pointRange) {
118 throw StateError('the point light range did not track the slider');
119 }
120 if (frame.drawCalls < 3) {
121 throw StateError('not every ball was drawn');
122 }
123 }