flutter3d_backend 0.6.0
flutter3d_backend: ^0.6.0 copied to clipboard
Picks the graphics backend a build draws through: Impeller on a desktop, WebGL2 in a browser, and a software rasteriser at runtime if Impeller will not start.
flutter3d_backend #
Which graphics backend a build draws through, chosen at compile time.
import 'package:flutter3d_backend/flutter3d_backend.dart';
final device = await openDevice(width: 1280, height: 720);
openDevice returns a GraphicsDevice from flutter3d_hardware. No backend
appears in any signature: on a desktop or a phone the device is
flutter3d_impeller's, in a browser it is flutter3d_webgl's, and web-or-native
is a conditional export rather than a runtime branch — flutter_gpu does not
compile for the web and dart:js_interop does not compile for macOS, so a file
importing both could target neither.
Two backends are reached at run time instead, because what decides them is not
visible to a compiler. On the native half, flutter3d_cpu's software rasteriser
is where a build lands when Impeller will not start. On the browser half:
flutter build web --dart-define=FLUTTER3D_WEBGPU=true
asks for flutter3d_webgpu first and falls back to WebGL2 where the browser has
no navigator.gpu or hands out no adapter. Off unless a build asks, and that
is about size rather than about WebGPU: the probe has to be able to call both
openers, so a build that has it carries both backends and one that has not folds
the branch away. On apps/flutter3d_demo_strategy that is 376,649 bytes of
main.dart.js — 2,529,865 off against 2,906,514 on, 14.9% more script and
368 KiB on the whole of build/web. Whether a particular game pays it is the
game's call, the same way its resolution and shadow budget are.
An ordinary web build still draws through WebGL2, and that is the decision this default records rather than an accident of which backend was written first. WebGL2 is the browser backend with a recorded reference set behind it and the one three shipped games have been looked at on; moving every browser build onto the newer API by having the probe on would change what those games draw without anybody having asked, and would charge every one of them the bytes above. So the choice is a game's to make, and making it is one flag.
What it does not decide #
Resolution and shadow budget stay in the application. kFixedResolution tells a
caller whether the backend renders to a fixed internal target — true in a
browser, where a WebGL canvas resets its drawing buffer when it is resized —
and what size is the game's own trade against its own scene. The three games
in this repository answer it differently and each says why where the number is.
Why it is a package #
The conditional import and openDevice were three files in each of three games,
byte-identical in two of them down to the paragraph explaining the conditional.
flutter3d_session was the obvious home and is the wrong one: it would have to
depend on both backends, and then apps/flutter3d_editor — which opens a file, changes it
and writes it back, and has no browser build to choose for — would pull WebGL
through it. Session stays backend-neutral, which is what lets it be mounted over
a CpuDevice in its own tests.
Part of flutter3d, an independent
implementation of a 3D engine for Flutter — not a fork or a binding of
another engine, and not affiliated with the Flutter team. Three switchable
rendering backends: Impeller via Flutter GPU, WebGL2, and a software
rasteriser. glTF, OBJ and .f3d loading, six lighting models, shadows, bloom,
skinning, animation, BVH culling and picking; a deterministic fixed-step game
layer with collision, navigation, positional audio, and gamepad and touch
input. Three example games — shooter, platformer, racing — each built on its
genre package: flutter3d_game_shooter,
flutter3d_game_platformer,
flutter3d_game_racing. A new game starts from the
editor's scaffold, which writes one from a template: https://flutter3d.pleion.dev/first-project/.
Documentation: https://flutter3d.pleion.dev.