flutter3d
Showcase Changelog 38 packages API reference

Impeller: the source

since 0.1.0 Backends

Regions the guide quotes: fallback (line 39), settings (line 50), read (line 54).

1/// The desktop and mobile path: `flutter_gpu`, through Impeller, the first
2/// backend `openDevice` tries on a native build.
3///
4/// Quoted by `backend_impeller.md` and shown whole in the Source tab.
5library;
6
7import 'package:flutter/widgets.dart';
8import 'package:flutter3d/flutter3d.dart';
9import 'package:flutter3d_showcase/src/demo/demo.dart';
10import 'package:vector_math/vector_math.dart';
12final class BackendImpellerDemo extends ShowcaseDemo {
13 late final GraphicsDevice _device;
15 @override
16 Scene build(DemoContext context) {
17 _device = context.device;
18 final Material stone = Material(
19 name: 'stone',
20 baseColor: Vector4(0.72, 0.5, 0.32, 1.0),
21 roughness: 0.6,
22 );
23 final MeshNode ball = MeshNode(
24 DeviceMesh.upload(
25 context.device,
26 SphereShape(segments: 24, rings: 12).build(),
27 ),
28 stone,
29 name: 'ball',
30 );
31 return Scene()
32 ..add(ball)
33 ..add(
34 LightNode(name: 'sun', intensity: 3.0)
35 ..setLocalForward(Vector3(-0.4, -1.0, -0.3)),
36 );
37 }
39 // `flutter3d_app`'s native `openDevice` never names a backend. It asks
40 // `flutter3d_hardware`'s registry to open one, having first made sure
41 // Impeller and the software rasteriser have both registered themselves:
42 //
43 // ensureGpuBackendRegistered();
44 // ensureCpuBackendRegistered();
45 // return openRegisteredDevice(width: width, height: height, ...);
46 //
47 // Impeller is tried first; the software device is what a native build
48 // falls back to if flutter_gpu will not start.
50 @override
51 RenderSettings settings(DemoContext context) =>
52 const RenderSettings(wireframe: true);
54 String _report(GraphicsDevice device) =>
55 'wireframe: ${device.supportsWireframe}\n'
56 'blend constant: ${device.supportsBlendColor}\n'
57 'max colour attachments: ${device.maxColorAttachments}\n'
58 'max anisotropy: ${device.maxAnisotropy}';
60 @override
61 Widget? customBody(
62 BuildContext buildContext,
63 DemoContext context,
64 ) => Container(
65 color: const Color(0xFF14161A),
66 padding: const EdgeInsets.all(24),
67 alignment: Alignment.topLeft,
68 child: DefaultTextStyle(
69 style: const TextStyle(color: Color(0xFFE8E8EC), fontSize: 16),
70 child: Text(
71 'On Metal and Vulkan, Impeller answers true to wireframe and can '
72 'open more than one colour attachment; on its OpenGL ES path a '
73 'second attachment aborts the process outright, which is why '
74 'nothing above this asks for one without asking maxColorAttachments '
75 'first. It answers false to a blend constant on every platform, '
76 'because flutter_gpu\'s own RenderPass has no setter for one.\n\n'
77 'What the device actually open right now answers:\n\n'
78 '${_report(context.device)}',
79 ),
80 ),
81 );
83 @override
84 void verify(Scene scene, FrameResult frame) {
85 if (frame.drawCalls < 1) {
86 throw StateError('the ball was not drawn');
87 }
88 // Wireframe is the one capability that differs across all three
89 // backends. This page asks for it unconditionally; whether the frame
90 // actually got it has to match what the device that opened said it
91 // could do, whichever backend that turned out to be.
92 if (frame.wireframeDeclined != !_device.supportsWireframe) {
93 throw StateError(
94 'wireframeDeclined disagreed with supportsWireframe for the open '
95 'device',
96 );
97 }
98 }