Many copies in one draw: the source
Open the live demo · Read the guide · View on GitHub
Regions the guide quotes: batch (line 28), instances (line 47), scene (line 67), motion (line 80), check (line 98).
1/// Sixty-four coloured copies stored in one `InstancedMeshNode`.
2library;
4import 'dart:math' as math;
6import 'package:flutter3d/flutter3d.dart';
7import 'package:flutter3d_showcase/src/demo/demo.dart';
8import 'package:vector_math/vector_math.dart';
10final class InstancingDemo extends ShowcaseDemo {
11 static const int instanceCount = 64;
13 double rotationSpeed = 0.25;
14 double _angle = 0.0;
16 late final InstancedMeshNode _field;
19 void configureView(DemoContext context) {
20 context.orbit
21 ..distance = 16.0
22 ..pitch = 0.52
23 ..yaw = 0.55;
24 }
27 Scene build(DemoContext context) {
28 _field = InstancedMeshNode(
29 DeviceMesh.upload(
30 context.device,
31 const CapsuleShape(
32 radius: 0.28,
33 height: 0.55,
34 segments: 20,
35 rings: 6,
36 ).build(),
37 ),
38 Material(
39 name: 'instance material',
40 baseColor: Vector4(1.0, 1.0, 1.0, 1.0),
41 roughness: 0.48,
42 ),
43 capacity: instanceCount,
44 name: 'capsule field',
45 );
47 const int side = 8;
48 for (var i = 0; i < instanceCount; i++) {
49 final int x = i % side;
50 final int z = i ~/ side;
51 final double height = 0.7 + 0.3 * math.sin(x * 0.9 + z * 0.65);
52 final Matrix4 transform = Matrix4.identity()
53 ..setTranslationRaw((x - 3.5) * 1.35, height, (z - 3.5) * 1.35)
54 ..rotateY((x + z) * 0.24)
55 ..scaleByDouble(1.0, 0.85 + height * 0.2, 1.0, 1.0);
56 _field.addInstance(
57 transform,
58 color: Vector4(
59 0.3 + x / 12.0,
60 0.32 + z / 13.0,
61 0.78 - (x + z) / 36.0,
62 1.0,
63 ),
64 );
65 }
67 final Scene scene = Scene()
68 ..ambientColor = Vector3(0.45, 0.52, 0.68)
69 ..ambientIntensity = 0.13
70 ..add(_field)
71 ..add(
72 LightNode(name: 'sun', intensity: 3.2)
73 ..setLocalForward(Vector3(-0.5, -0.8, -0.32)),
74 );
75 return scene;
76 }
79 void update(DemoContext context, double dt) {
80 _angle = (_angle + dt * rotationSpeed) % (math.pi * 2.0);
81 _field.setRotationYawPitchRoll(_angle, 0.0, 0.0);
82 }
85 List<DemoControl> controls(DemoContext context) => <DemoControl>[
86 SliderControl(
87 'Field rotation',
88 min: 0.0,
89 max: 1.5,
90 value: () => rotationSpeed,
91 onChanged: (double value) => rotationSpeed = value,
92 format: (double value) => value.toStringAsFixed(2),
93 ),
94 ];
97 void verify(Scene scene, FrameResult frame) {
98 if (_field.count != instanceCount ||
99 _field.capacity < instanceCount ||
100 frame.instances < instanceCount ||
101 frame.drawCalls < 1) {
102 throw StateError('the instanced field was not drawn');
103 }
104 }
105}