| name | three-dart-fundamentals |
| allowed-tools | Read, Glob |
| description | three_dart scene setup, WebGL renderer in Flutter, Scene, PerspectiveCamera, WebGLRenderer, Object3D hierarchy, animation loop. Use when setting up 3D scenes in Flutter with three_dart, creating cameras, configuring renderers, or managing 3D object transforms in a Flutter app. |
three_dart Fundamentals
Iron Law
Always call renderer.dispose() in the widget dispose() method — failing to do so leaks the WebGL context, causing a crash after ~8 widget recreations on mobile.
Flutter uses the three_dart package — a Dart port of Three.js. API concepts are identical
to Three.js; only syntax changes (Dart instead of JavaScript).
pubspec.yaml
dependencies:
three_dart: ^0.0.15
flutter_gl: ^0.0.10
Quick Start
import 'package:flutter/material.dart';
import 'package:three_dart/three_dart.dart' as THREE;
import 'package:three_dart_jsm/three_dart_jsm.dart' as THREE_JSM;
class ThreeDScene extends StatefulWidget {
const ThreeDScene({super.key});
@override
State<ThreeDScene> createState() => _ThreeDSceneState();
}
class _ThreeDSceneState extends State<ThreeDScene> {
late THREE.WebGLRenderer renderer;
late THREE.Scene scene;
late THREE.PerspectiveCamera camera;
late THREE.Mesh cube;
@override
void initState() {
super.initState();
_initScene();
}
void _initScene() {
scene = THREE.Scene();
camera = THREE.PerspectiveCamera(75, 1.0, 0.1, 1000);
camera.position.z = 5;
final geometry = THREE.BoxGeometry(1, 1, 1);
final material = THREE.MeshStandardMaterial({'color': 0x00ff00});
cube = THREE.Mesh(geometry, material);
scene.add(cube);
scene.add(THREE.AmbientLight(0xffffff, 0.5));
final dirLight = THREE.DirectionalLight(0xffffff, 1.0);
dirLight.position.set(5, 5, 5);
scene.add(dirLight);
}
void _animate(double delta) {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
@override
Widget build(BuildContext context) {
return THREE_JSM.ThreeDartWidget(
onSetupRenderer: (r) => renderer = r,
onAnimate: _animate,
scene: scene,
camera: camera,
);
}
@override
void dispose() {
renderer.dispose();
super.dispose();
}
}