3D works in a Flutter web app through flutter_scene, which brings its own WebGL2 backend because Impeller does not run in browsers. It needs no flags and runs inside iframes. Measure it in a focused tab at phone size, after the first seconds of shader compiling.
This is for Flutter developers shipping a 3D game or viewer to the browser, or previewing a mobile 3D app on the web. It reflects flutter_scene 0.20.0 to 0.24.3 and Flutter 3.47, as of October 2026, plus our tests in the GrowApps web preview.
In short:
- WebGL2 stands in for Impeller and Flutter GPU in the browser.
- Background tabs throttle frames, so frame counters lie there.
- The 3D backend added about 28 KB to our web bundle.
- Embedding three.js through HtmlElementView breaks the Android build.
flutter_scene brings WebGL2 for the browser
Impeller and Flutter GPU are not available on the web. The Impeller docs say Flutter on the web "currently uses Skia" and "might use Impeller in the future." So flutter_scene ships a WebGL2 backend that stands in for Flutter GPU.
Its README FAQ says this works under both the CanvasKit and Skwasm web renderers, with no extra flags. WebGL2 is the browser graphics API documented on MDN's WebGL2 reference, and it is widely supported in current browsers.
The same code runs in an iframe
We verified a flutter_scene app in the GrowApps preview at 375 by 812 pixels and inside an iframe at 390 by 844. That covers an app embedded in another page, such as a game on a school site or a product viewer inside a shop page.
The web backend added about 28 KB to the bundle in our build. That is small next to the Flutter engine itself and next to any model you load.
Frame counters lie in background tabs
Browsers slow requestAnimationFrame, the timer that drives animation, in tabs that are hidden or unfocused. In our tests, a screenshot tool reading a background tab saw 1 frame per second, while the focused window ran at 58.
So use two numbers. Frames per second is honest only in a focused, visible tab. Milliseconds per render, a stopwatch around the scene's render call, measures the CPU cost and does not depend on the browser's timer. Our performance budget for 3D on phones shows how to add both.
The first seconds are shader compiles
On the web, the browser compiles the engine's shaders when they are first used. Our starter scene's first render took 263 ms. A running average that included it still read 126 ms half a minute later, although the scene was already fast.
Skip the first dozen frames in any counter, and show a loading indicator until the engine has started. A screenshot taken in the first seconds is black and proves nothing.
Window size changes the frame rate
The same build ran about 20 frames per second filling a desktop browser window and 40+ at phone size. A full-screen desktop window has several times the pixels of a phone viewport.
Test at the size your app is for. If it is a phone game previewed on the web, resize the browser to a phone viewport before judging it. If it is a desktop web game, profile at full screen and consider lowering the render resolution.
Two web options that break mobile
Web-only shortcuts can quietly cost you the mobile app:
model_viewer_plusshowed a blank pane in our web preview. Its relative script path failed to load inside the frame.- A bare
HtmlElementViewaround three.js rendered in the preview, but broke the Android export.
Both undercut the point of one Flutter codebase. flutter_scene draws in Flutter on every platform, so the web build and the phone build are the same scene.
Build time grows once with the engine
flutter_scene compiles its shaders during the build. A flutter build web --release took 83 seconds with the package and 24 seconds without it, in our measurement. That is a one-time cost per build, not something users wait for.
How the GrowApps preview runs 3D
Previews in the GrowApps builder are Flutter web; apps using flutter_scene render through its WebGL2 backend. The builder agent is told to judge a scene in a focused tab, at the size the app is for, after the first frames.
Its 3D starter shows a ms/render readout that skips warm-up frames. You can try a 3D app in the GrowApps preview from a compatible desktop browser with WebGL2 enabled.
Check your scene in a focused tab
Open your 3D web build, then open DevTools' device toolbar and pick a phone size. Wait ten seconds, keep the tab focused, and read the frame rate. Switch to another tab and back, and watch the number drop and recover. For what makes a Flutter web app findable in search, read Flutter web SEO and app discovery.