Temporal anti-aliasing: the source
Open the live demo · Read the guide · View on GitHub
Regions the guide quotes: railing (line 38), motion (line 66), settings (line 80), clips (line 102), reported (line 128).
1/// Temporal anti-aliasing: the scene drawn a fraction of a pixel off each
2/// frame and blended into a history of the frames before it.
3///
4/// Quoted by `temporal_anti_aliasing.md` and shown whole in the Source tab.
5library;
7import 'dart:math' as math;
9import 'package:flutter3d/flutter3d.dart';
10import 'package:flutter3d_showcase/pages/post/post_stage.dart';
11import 'package:flutter3d_showcase/src/demo/demo.dart';
12import 'package:vector_math/vector_math.dart';
14final class TemporalAntiAliasingDemo extends ShowcaseDemo {
15 bool temporal = true;
16 bool swapWall = true;
17 double historyWeight = 0.9;
18 double sharpen = 0.25;
19 TemporalClip clip = TemporalClip.aabb;
21 /// Seconds since the page opened, which is what moves the railing.
22 double _time = 0.0;
24 late final SceneNode _railing;
25 late final Material _wallPaint;
28 void configureView(DemoContext context) {
29 context.orbit
30 ..distance = 3.5
31 ..pitch = 0.0
32 ..yaw = 0.0;
33 context.orbit.target.setValues(0.0, 0.0, 0.0);
34 }
37 Scene build(DemoContext context) {
38 Material flat(Vector4 colour) =>
39 Material(lighting: LightingModel.unlit, baseColor: colour);
40 final DeviceMesh cube = DeviceMesh.upload(
41 context.device,
42 CuboidShape().build(),
43 );
44 _wallPaint = flat(Vector4(0.75, 0.25, 0.5, 1.0));
45 final Material barPaint = flat(Vector4(0.0, 0.0, 1.0, 1.0));
47 _railing = SceneNode(name: 'railing');
48 for (int i = -6; i <= 6; i++) {
49 _railing.add(
50 MeshNode(cube, barPaint, name: 'bar $i')
51 ..setPosition(i * 0.45, 0.0, 0.0)
52 ..setRotationYawPitchRoll(0.0, 0.0, 0.3)
53 ..setScale(0.04, 6.0, 0.04),
54 );
55 }
56 final MeshNode wall = MeshNode(cube, _wallPaint, name: 'wall')
57 ..setPosition(0.0, 0.0, -0.3)
58 ..setScale(20.0, 20.0, 0.1);
59 return Scene()
60 ..add(wall)
61 ..add(_railing);
62 }
65 void update(DemoContext context, double dt) {
66 _time += dt;
67 _railing.setPosition(0.25 * math.sin(_time * 1.5), 0.0, 0.0);
68 // Pink and yellow. Pink lies inside the YCoCg box that yellow and the
69 // blue bars span, so the box keeps it as history.
70 final bool yellow = swapWall && (_time ~/ 2).isOdd;
71 if (yellow) {
72 _wallPaint.baseColor.setValues(1.0, 1.0, 0.0, 1.0);
73 } else {
74 _wallPaint.baseColor.setValues(0.75, 0.25, 0.5, 1.0);
75 }
76 }
79 RenderSettings settings(DemoContext context) => RenderSettings(
80 antiAlias: AntiAliasSettings(
81 temporal: TemporalSettings(
82 enabled: temporal,
83 historyWeight: historyWeight,
84 sharpen: sharpen,
85 clip: clip,
86 ),
87 ),
88 );
91 List<DemoControl> controls(DemoContext context) => <DemoControl>[
92 ToggleControl(
93 'Temporal resolve',
94 value: () => temporal,
95 onChanged: (bool v) => temporal = v,
96 ),
97 ToggleControl(
98 'Swap the wall colour',
99 value: () => swapWall,
100 onChanged: (bool v) => swapWall = v,
101 ),
102 ChoiceControl(
103 'History clip',
104 options: <String>[
105 for (final TemporalClip c in TemporalClip.values) c.name,
106 ],
107 index: () => clip.index,
108 onChanged: (int i) => clip = TemporalClip.values[i],
109 ),
110 SliderControl(
111 'History weight',
112 min: 0,
113 max: 0.98,
114 value: () => historyWeight,
115 onChanged: (double v) => historyWeight = v,
116 ),
117 SliderControl(
118 'Sharpen',
119 min: 0,
120 max: 1,
121 value: () => sharpen,
122 onChanged: (double v) => sharpen = v,
123 ),
124 ];
127 void verify(Scene scene, FrameResult frame) {
128 expectPassOrDecline(frame, 'temporal resolve');
129 }
130}