Skip to content

The web

The renderer is compiled to WebAssembly and draws into a canvas that Flutter lays out as a platform view. WebGL 2 is the target, at Filament feature level 1, so the web gets the slimmer lit surface too. Platform support covers what runs on Web Workers and how big the files are.

A Mac with Apple silicon For the materials step, which goes through the Mac setup. Linux would need that step ported, and nobody has tried
Emscripten 5.0.4 Exactly that version. About 1.9 GiB installed
CMake and Ninja For Filament’s own build. Homebrew has both, and Xcode’s clang does the compiling
A clone of the engine At the commit your app is on
A clone of Orblit’s Filament fork Built once, which took 12 minutes 55 seconds here

Keep both clones on a path with no spaces in it. Here’s why.

Terminal window
git clone https://github.com/emscripten-core/emsdk ~/emsdk
cd ~/emsdk
./emsdk install 5.0.4
./emsdk activate 5.0.4

Then, in every shell that builds the renderer:

Terminal window
source ~/emsdk/emsdk_env.sh
export EMSDK="$HOME/emsdk"

It has to be 5.0.4 rather than “latest”, because that’s the version the fork pins and its CI builds with. What emsdk calls latest moves.

The web build links against Orblit’s fork of Filament rather than Google’s release, because there’s no release built for WebAssembly. So it’s built from source:

Terminal window
git clone https://github.com/ChxisB/orblit-filament.git ~/src/orblit-filament
cd ~/src/orblit-filament
./build.sh -p wasm release

That builds Filament’s desktop tools first, matc among them, then cross-compiles the engine. out/cmake-wasm-release came to 53 MiB. You only need to do it again when the engine moves to a newer Filament.

If the fork’s path has a space in it, one of Filament’s own samples, web/filament-js, fails to link, and Ninja stops there. Everything the renderer needs has been built by then except one archive. Running ninja libfilament-iblprefilter.a in out/cmake-wasm-release finishes it, but a path with no spaces saves you the trouble.

The renderer you build has to match the Dart side your app resolved, because they talk through a C ABI that nothing checks. So clone the engine at the commit in your app’s pubspec.lock:

Terminal window
cd path/to/your_app
REF=$(grep -A6 '^ orblit_filament:' pubspec.lock | awk '/resolved-ref/ { gsub(/"/, "", $2); print $2 }')
git clone https://github.com/ChxisB/orblit.git ~/src/orblit
git -C ~/src/orblit checkout "$REF"
Terminal window
cd ~/src/orblit
ORBLIT_GENERATED_SET=webgl2 ORBLIT_MATC_BACKENDS=opengl \
ORBLIT_MATC="$HOME/src/orblit-filament/out/cmake-release/tools/matc/matc" \
bash packages/orblit_filament/darwin/setup.sh

This is the Mac setup, told to compile a second set of materials for OpenGL, which is what WebGL 2 runs on. It does the ordinary Mac setup along the way, which is why the web build needs a Mac.

Terminal window
cd ~/src/orblit
ORBLIT_FILAMENT_WASM_SRC="$HOME/src/orblit-filament" \
bash packages/orblit_filament/native/web/build.sh

It refuses to start without the materials from step 4. It writes orblit_renderer.js and orblit_renderer.wasm into packages/orblit_filament/native/web/host/.

Copy both files into your app’s web/ directory:

Terminal window
cp ~/src/orblit/packages/orblit_filament/native/web/host/orblit_renderer.{js,wasm} \
path/to/your_app/web/

Then load the script in web/index.html, before Flutter’s own:

web/index.html
<script src="orblit_renderer.js"></script>
<script src="flutter_bootstrap.js" async></script>

It’s a plain script rather than a module, and it finds the .wasm beside itself from its own URL. Then:

Terminal window
flutter run -d chrome

Only Chrome has been tried: headless Chrome with SwiftShader standing in for the GPU, and, for the texture work, Chrome in real time. Safari and Firefox haven’t been run at all.

orblit_renderer.js is 679 KB (440 KB gzipped), because it carries the texture decoder that runs on Web Workers, and the .wasm is 7.57 MB.