GUIDE 01 · RENDERING

Render worlds.
Keep Flutter.

Glint owns the 3D viewport while Flutter keeps layout, navigation, state, text, accessibility, and every overlay around it.

Choose a viewport

Scene3D

A declarative widget for product pages, viewers, scrollable experiences, and scenes controlled by Flutter state.

GlintGameView

A ticker-driven viewport for games and simulations. Its onFrame callback returns the complete render state.

COMPOSE

Both are ordinary Flutter widgets. Put HUD, buttons, sheets, text, and navigation in the same Stack; no platform view or WebView is involved.

Build a declarative scene

Use Node3D for local transforms and child hierarchy. Scene3D resolves world transforms, camera projection, bounds, culling, gestures, and the GPU fallback.

lib/product_view.dartDART
Scene3D(
  camera: const OrbitCamera(
    position: Vector3(0, 1.4, 5),
    target: Vector3(0, .8, 0),
  ),
  children: const [
    Node3D(
      name: 'shoe',
      model: Model.asset('assets/models/shoe.glb'),
      transform: Transform3D(
        orientation: GlintQuaternion.identity,
      ),
    ),
  ],
  lights: const [
    EnvironmentLight(asset: 'assets/environments/studio.hdr'),
    DirectionalLight(direction: Vector3(.5, -1, -.4)),
  ],
  gestureMode: GlintGestureMode.scrollAware,
  showStats: true,
)

Use scrollAware inside a vertical page: horizontal one-finger drags orbit, vertical drags remain available to the page, and two-finger gestures control the scene.

Return a game frame

Advance gameplay with delta time, then return a camera, model instances, and optional particle batches. Instance transforms remain authoritative in authored model units.

lib/game_view.dartDART
GlintGameView(
  models: {
    'car': const Model.asset('assets/models/car.glb'),
    'track': const Model.asset('assets/models/track.glb'),
  },
  onFrame: (dt) {
    simulation.update(dt);
    return GlintGameFrame(
      camera: GlintGameCamera(
        position: simulation.cameraPosition,
        target: simulation.cameraTarget,
      ),
      instances: [
        GlintGameInstance(
          model: 'car',
          transform: simulation.carTransform,
        ),
        const GlintGameInstance(model: 'track'),
      ],
      particles: simulation.particleBatches,
    );
  },
)

Light the scene

EnvironmentLight

Image-based diffuse and specular lighting from an equirectangular HDR environment.

DirectionalLight

Sun-like direct light with optional directional shadow rendering.

PointLight

World-space inverse-square light with an optional range cutoff.

SpotLight

A point light narrowed by inner and outer cone angles—useful for torches and headlights.

The renderer packs at most eight combined point and spot lights per frame. Keep long-lived world lighting deliberate and reserve short-lived slots for effects such as impacts.

Work with PBR materials

Imported glTF materials provide base color, texture, metallic, and roughness. Override an instance at runtime without mutating the shared model.

material_override.dartDART
const paint = Material3D(
  color: Color(0xff3157f6),
  metallic: .72,
  roughness: .22,
);

final instance = GlintGameInstance(
  model: 'car',
  material: paint,
  transform: chassis.toTransform(),
);
LIMIT

Glint 0.2 imports base-color textures and factors. Authored normal/ORM maps and Draco-compressed geometry are not yet part of the loader.

Connect 3D to Flutter

Use onModelTap for triangle-accurate picking and Label3D for real Flutter widgets anchored to model-space points. Labels can remain visible, fade, or hide when geometry occludes them.

interactive_scene.dartDART
Scene3D(
  children: nodes,
  onModelTap: (hit) => setState(() => selected = hit.triangleIndex),
  labels: const [
    Label3D(
      anchor: Vector3(.4, 1.2, 0),
      occlusion: Label3DOcclusion.hide,
      child: FeatureChip(label: 'Camera'),
    ),
  ],
)