flutter3d
Showcase Changelog 38 packages API reference

Plan a frame before drawing: the source

since 0.7.0 Scene and geometry

Regions the guide quotes: scene (line 26), settings (line 56), plan (line 61), controls (line 76), check (line 91).

1/// A dry-run frame graph compared with the frame that followed it.
2library;
3
4import 'package:flutter3d/flutter3d.dart';
5import 'package:flutter3d_showcase/src/demo/demo.dart';
6import 'package:vector_math/vector_math.dart';
7
8final class FrameGraphDemo extends ShowcaseDemo {
9 bool bloom = true;
10 bool antiAlias = true;
12 late final Scene _scene;
13 List<String> _planned = const <String>[];
14 List<String> _skipped = const <String>[];
16 @override
17 void configureView(DemoContext context) {
18 context.orbit
19 ..distance = 6.5
20 ..pitch = 0.25
21 ..yaw = 0.45;
22 }
24 @override
25 Scene build(DemoContext context) {
26 final Material bright = Material(
27 name: 'bright metal',
28 baseColor: Vector4(0.7, 0.2, 0.08, 1.0),
29 emissive: Vector3(1.0, 0.16, 0.03),
30 emissiveStrength: 2.5,
31 metallic: 0.62,
32 roughness: 0.22,
33 );
34 _scene = Scene()
35 ..ambientColor = Vector3(0.38, 0.46, 0.64)
36 ..ambientIntensity = 0.12
37 ..add(
38 MeshNode(
39 DeviceMesh.upload(
40 context.device,
41 const TorusShape(radius: 1.15, tubeRadius: 0.38).build(),
42 ),
43 bright,
44 name: 'emissive torus',
45 ),
46 )
47 ..add(
48 LightNode(name: 'sun', intensity: 3.0)
49 ..setLocalForward(Vector3(-0.45, -0.82, -0.35)),
50 );
51 return _scene;
52 }
54 @override
55 RenderSettings settings(DemoContext context) {
56 final RenderSettings next = RenderSettings(
57 bloom: BloomSettings(intensity: bloom ? 0.65 : 0.0),
58 antiAlias: AntiAliasSettings(enabled: antiAlias),
59 );
61 final CompiledFrameGraph graph = context.renderer.planFrame(
62 scene: _scene,
63 views: <RenderView>[context.view],
64 settings: next,
65 );
66 _planned = <String>[
67 for (final FrameGraphNode node in graph.order) node.name,
68 ];
69 _skipped = <String>[
70 for (final SkippedPass pass in graph.skipped) pass.name,
71 ];
72 return next;
73 }
75 @override
76 List<DemoControl> controls(DemoContext context) => <DemoControl>[
77 ToggleControl(
78 'Bloom pass',
79 value: () => bloom,
80 onChanged: (bool value) => bloom = value,
81 ),
82 ToggleControl(
83 'Antialias pass',
84 value: () => antiAlias,
85 onChanged: (bool value) => antiAlias = value,
86 ),
87 ];
89 @override
90 void verify(Scene scene, FrameResult frame) {
91 final List<String> drawn = <String>[
92 for (final FramePass pass in frame.passes) pass.name,
93 ];
94 if (_planned.isEmpty ||
95 !_planned.contains('scene') ||
96 !_planned.contains('composite') ||
97 bloom && !_planned.contains('bloom') ||
98 antiAlias && !_planned.contains('antialias') ||
99 !_sameNames(_planned, drawn) ||
100 _skipped.any(drawn.contains)) {
101 throw StateError('the planned graph did not match the drawn frame');
102 }
103 }
106bool _sameNames(List<String> left, List<String> right) {
107 if (left.length != right.length) return false;
108 for (var i = 0; i < left.length; i++) {
109 if (left[i] != right[i]) return false;
110 }
111 return true;