yii.
← Writing
Flutter 技術 · · 10 min read

When Flutter Hits the 3D Wall — Fluorite

How Toyota Built a Console-Grade Game Engine with Flutter + C++

Original talk: FOSDEM 2026 Speakers: Jamie Kerber (Very Good Ventures, Senior Engineer / Fluorite Lead Engineer) Representing: Joel Winarski (Toyota Connected North America, Principal Engineer / Fluorite Founder)


Preface: When Flutter Hits the 3D Wall#

Toyota is already shipping Flutter in production cars. The 2026 RAV4’s in-vehicle infotainment system runs on Flutter’s embedded stack. But traditional Flutter only does 2D, and for automotive use cases, that’s not enough.

Picture this: you need a 3D interactive owner’s manual where drivers can rotate the car model, tap a tire to check pressure, or drag a slider to adjust suspension height. Real-time hardware status visualization, environment map projection. All of that needs a game engine.

The problem? None of the existing game engines can properly integrate with Flutter embedded. Toyota Connected’s answer? Build one from scratch.

When I first saw this talk title, I figured it was another “company open-sources their internal tool” story. After watching it, I realized the problem they’re tackling is far more complex than I expected. And it’s not just Toyota’s problem.


1. Why Existing Game Engines Don’t Cut It#

Toyota’s team didn’t skip their homework. They tested every major option on the market, and the verdict was clear: all of them failed.

Start with the proprietary engines. Unity and Unreal require shipping proprietary blobs with your Linux distribution — that immediately kills Yocto compatibility. In the embedded Linux world, Yocto is the standard build system; you can’t work around it. Worse, each native view spawns an entire engine instance, and the frame rate suffers badly. Add licensing fees that can run into millions of dollars per year, and the math just doesn’t work for an automaker.

What about Godot, the open-source option? No licensing issues there, but on a Raspberry Pi 5, just booting up takes over 20 seconds. A driver gets in, starts the car, the screen lights up, and then waits 20 seconds to see the 3D interface? That’s a patience test, not a user experience.

Then there’s Flutter GPU (Impeller). On paper, the perfect fit: native Flutter integration, Dart language, Hot Reload. In practice? Stable on iOS, unstable on Android, unusable on Linux / macOS / Windows. For an in-vehicle system running embedded Linux, it might as well not exist.

After testing everything, Toyota’s conclusion was stark:

No solution can simultaneously deliver Flutter integration + embedded support + high-performance 3D + open-source licensing.

So they decided to build their own.

This reflects a deeper gap in the Flutter ecosystem. Flutter has won the 2D UI game, but the moment you need low-level graphics capabilities, there’s nothing under your feet. AR filters, point cloud visualization, even moderately advanced shader effects all force Flutter developers to throw work back to the native side via platform channels. Fluorite is trying to fill that gap for the entire ecosystem, not just Toyota.


2. What Is Fluorite?#

Think of it like building a house. Flutter is your interior designer — buttons, lists, animations, page transitions, it handles all the 2D stuff. But now you want an interactive 3D screen wall in the living room. You wouldn’t tear down the whole house to rebuild it; you’d find a module that fits into the existing structure.

Fluorite is that module.

It’s an open-source 3D game engine from Toyota Connected, delivered as a Flutter package that integrates directly into your app. No extra runtime, no platform view hacks. Add one line to pubspec.yaml, and you’ve got a 3D engine.

In short, FluoriteView is a Widget.

This design direction is right. Flutter developers think of Widgets as “lightweight, composable, put it anywhere.” Fluorite keeps that mental model instead of handing you a foreign object that needs special handling. It follows Flutter’s layout system and can sit anywhere: inside a Column, on a Stack, in a TabView tab. You can put multiple FluoriteView instances on the same screen, each showing a different 3D perspective.

And 3D game objects can interact with Flutter UI widgets through Provider / Riverpod / Bloc. Every state management solution you already know just works.


3. Technical Architecture#

Fluorite isn’t built from scratch. Think of it like a sandwich: the top layer is the Dart API you interact with, the middle is the C++ core handling performance, and the bottom rests on two proven open-source engines.

The top layer is the Dart API. Developers only touch this layer — creating Entities, attaching Components, writing behavior scripts, all in Dart.

The middle layer is the C++ ECS core. Why not write it all in Dart? Because embedded devices have limited memory and CPU. C++ gives the team precise control over memory allocation and processing pipelines, squeezing maximum performance out of low-end hardware like a Raspberry Pi.

The bottom layer has two pillars:

  • Google Filament handles 3D rendering. Same engine that powers Android’s system UI, fully GPU-accelerated on Vulkan 1.1+, with PBR (physically-based rendering), HDR lighting, and a custom shader pipeline based on a GLSL superset
  • SDL3 handles cross-platform I/O, unifying input/output and window management across different embedded devices

One sentence to sum up the architecture: Dart for logic, C++ for performance, Filament for rendering, SDL3 for platform abstraction.


4. ECS — You Already Know This#

If you’ve ever attached a Transform component in Unity, congratulations — you’ve already used Entity Component System (ECS).

ECS is the most popular architecture pattern in game engines. Think of it like LEGO: an Entity is a blank baseplate, nothing on its own; Components are the bricks you snap onto it — position, collider, 3D model, behavior script; a System scans all Entities every frame, finds the ones with specific Component combinations, and executes logic.

Fluorite’s API follows the exact same pattern — the only difference is the language switches from C# to Dart:

// A bouncing ball — looks almost identical to Unity's GameObject
final bouncingBall = Entity(
  name: 'BouncingBall',
  components: [
    Transform(
      position: Vector3(0, 5, 0),   // Starting position: 5m in the air
      scale: Vector3(1, 1, 1),
      rotation: Quaternion.identity(),
    ),
    SphereCollider(radius: 0.5),     // Collision boundary
    ModelRenderable(asset: 'assets/ball.glb'),  // 3D model
    BehaviorScript(
      onCreate: (entity) { /* initialization logic */ },
      onUpdateFrame: (entity, deltaTime) {
        // Per-frame update: gravity, bounce, displacement
      },
    ),
  ],
);

Transform, Collider, Renderable, Behavior Script — if you’re coming from Unity, Unreal, or Godot, you could recognize these with your eyes closed.

Fluorite also provides a Hierarchical Scene Graph for building complex nested object structures. The car body is a parent Entity, the four wheels are child Entities, each wheel has a tire pressure sensor attached — exactly the same as any other game engine.

Near-zero migration cost: if you can build a scene in Unity, you can build one in Fluorite.

That said, “low migration cost” mainly applies if you have game dev experience. If you’re a pure Flutter developer who’s never touched a game engine, the ECS mindset is different from your usual Widget tree. Widgets are declarative UI descriptions. ECS is a per-frame system loop. There’s a learning curve. Fluorite wraps ECS behind a Dart API, so you don’t need to understand system scheduling to start building things. But if you want to go beyond demo-level scenes, understanding ECS data flow becomes necessary.


5. How Artists and Developers Collaborate#

Traditional game development has a persistent pain point: artists create 3D models, hand them to developers, and developers spend hours marking interactive regions, setting collision boundaries, and binding events. When artists revise the model, developers redo the whole thing.

Fluorite’s answer: Model-Defined Touch Trigger Zones.

The idea: let 3D artists mark interactive areas directly in Blender using naming conventions. For a car model, the artist labels each tire with trigger_tire_FL, trigger_tire_FR, and so on. On the dev side, you just write: “When trigger_tire_FL is tapped, open the tire pressure panel.”

What it looks like in practice:

  • Tap a tire on the 3D car model → adjust tire pressure values
  • Drag a Flutter Slider → real-time update of the 3D pressure indicator
  • Game state and Flutter UI stay perfectly in sync

The biggest win: artists and developers can work completely in parallel. Artists adjust models in Blender while developers write interaction logic in Dart, exchanging assets via GLTF/GLB format without waiting on each other.


6. Dart-First Developer Experience#

What makes Fluorite different from everything else fits in one sentence: you write game logic in Dart, UI in Flutter, both in the same project.

What does that actually mean in practice?

UI and game logic are both in Dart. No context-switching between C# and Dart. State management, model classes, and utility functions are all shared; no maintaining two codebases. Hot Reload, Widget Inspector, and DevTools all work. Tweak a camera orbit distance, hit save, and the 3D scene updates in under a second. Compare that to other game engines’ compile times of tens of seconds. And the entire pub.dev ecosystem is directly usable.

Here’s how it stacks up against the alternatives:

Fluorite is the only solution that checks every box on this table.


7. A Reality Check: Where Are the Risks?#

The tech is solid. But before committing, there are a few things worth thinking through.

The Impeller shadow. Flutter’s official Impeller rendering engine is still under active development. If Impeller adds Linux and desktop 3D capabilities in two years, Fluorite’s positioning gets awkward. Do you go with the official solution, or the third-party engine? Fluorite’s ECS architecture and embedded optimizations are things Impeller won’t provide, but the overlap is worth watching.


8. Roadmap and Asset Formats#

Completed#

  • C++ ECS core engine
  • Filament 3D rendering integration
  • Dart API layer
  • Hierarchical scene graph
  • Model-defined touch trigger zones
  • Hot Reload support
  • PBR materials + HDR lighting
  • Custom shader pipeline

In Progress / Planned#

  • Jolt Physics integration — rigid body / soft body physics simulation, attached as Components
  • CLI / GUI tools — supporting designer and developer workflows
  • Full cross-platform support — embedded Linux (including Yocto), iOS, Android, macOS, Windows, game consoles
  • SDL3 Dart API — exposing SDL3 capabilities to the Flutter community as a package

Asset Formats#

Currently supported formats: 3D models use GLTF / GLB (fully compatible with Blender), textures support KTX, HDR and other common formats, shaders use a GLSL superset.

If you have existing GLTF assets from Unity / Unreal / Godot, you can port them to Fluorite in minutes.


9. What This Means for Flutter Developers#

Fluorite is a 3D game engine, but the bigger picture is this: Flutter is moving from “UI toolkit” to “application platform.”

Flutter started as a mobile-only framework, then expanded to Web, Desktop, and embedded. Every time, people said “Flutter isn’t suited for this,” and every time, a team proved them wrong with a shipping product. Fluorite is the latest step. Toyota showed that Flutter can run console-grade 3D rendering.

That doesn’t mean every Flutter developer needs to learn ECS tomorrow. But if your next project needs 3D product visualization, AR interaction, data visualization, or a simple game, you no longer have to leave the Flutter ecosystem.

What you can do right now:

  1. Watch fluorite.game for when the repo goes public. Once it does, run the example project. Even if you don’t end up using it, understanding what Dart + 3D feels like is worth the hour.
  2. Track Impeller’s desktop progress. If you care about 3D but don’t need embedded, Impeller might be lighter-weight. Follow both, pick a side when the time is right.
  3. Look at your current projects. Where are you limited by 2D? Product model displays, spatial data visualization, and gamified onboarding. These used to require WebView or platform channel workarounds. Now there’s a native option.

Fluorite doesn’t have a public repo yet, but I’m tracking fluorite.game. The moment it opens up, I’ll try it. Some things you can’t judge from a talk alone; you have to write code yourself.

Flutter’s 3D story is just beginning. Fluorite might not be the final answer, but it’s the only one seriously trying.


Resources#

本文原刊登於 Medium。