Was macht Three.js und glTF Web-Pipeline?
Diese Fertigkeit beschreibt die Schritte, die ein Blender- oder vcad-Modell in eine kleine .glb-Datei verwandeln. Die Datei muss schnell laden und sich in Three.js einfach animieren lassen.
1. Export-Checkliste für Blender und vcad
Node-Namen
- Benennen Sie jedes bewegliche Teil mit einem klaren und stabilen Namen:
Head,Visor,Eye_L,Eye_R,Torso_Door,Wheel_FL,Wheel_FR,Steering_Wheel. - Three.js findet das Teil dann mit
model.getObjectByName("Torso_Door").
Pivots
- Setzen Sie den Ursprung der Wurzel in die Mitte der Basis des Modells. In Three.js sitzt das Modell dann auf dem Boden bei
Y = 0. - Setzen Sie den Pivot jedes artikulierten Teils auf seine Rotationsachse. Beispiele: Türscharnier, Radmitte, Halsbasis, Antennenbasis.
Transformationen
- Wenden Sie vor dem Export alle Transformationen an.
- Der Maßstab muss
1, 1, 1sein. Die Ruhe-Rotation muss0, 0, 0sein. - Diese Regel verhindert Drift und Scherung während der prozeduralen Animation.
Geometrie-Budget
- Verbinden Sie statische Meshes, die ein Material teilen. Dieser Schritt reduziert die Draw Calls.
- Behalten Sie ein Mesh nur dann separat, wenn ein Skript es allein animiert. Verwenden Sie ein
SkinnedMeshmit einer Armature für weiche Verformung. - Zielen Sie auf einige tausend Dreiecke pro Hero-Asset. Streben Sie unter 1.000 Dreiecke für Hintergrund-Props an.
2. CLI-Optimierung mit @gltf-transform/cli
Das Projekt verwendet Bun. Führen Sie das Tool mit bunx aus. npx funktioniert auch auf Maschinen mit Node.js.
# Meshes, Texturen und Animationen anzeigen
bunx @gltf-transform/cli inspect model.glb
# Vollständige Optimierung für das Web: Meshopt plus WebP plus Bereinigung
bunx @gltf-transform/cli optimize model.glb model-optimized.glb \
--compress meshopt \
--texture-compress webp \
--texture-size 2048
# Alternative: Draco-Geometriekomprimierung
bunx @gltf-transform/cli draco model.glb model-draco.glb
Meshopt oder Draco
- Meshopt (
EXT_meshopt_compression) dekodiert sehr schnell. Es behält die Vertex-Reihenfolge bei und komprimiert auch Animations-Keyframes und Morph-Targets. Verwenden Sie es für animierte Assets. - Draco (
KHR_draco_mesh_compression) ergibt die kleinste Datei für dichte statische Meshes. Beispiele: Autokarosserien und Scans. Der Decoder benötigt mehr Zeit beim Start.
Weitere nützliche Schritte
# Doppelte Meshes und ungenutzte Daten entfernen
bunx @gltf-transform/cli dedup model.glb model.glb
# Texturen in KTX2 (BasisU) konvertieren
bunx @gltf-transform/cli etc1s model.glb model-ktx2.glb
Überprüfen Sie die Datei nach jedem Schritt. Bestätigen Sie die Dateigröße, die Dreiecksanzahl und die Texturgröße.
3. Three.js-Integration
Robuster Lader mit Draco und Meshopt
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
import { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js';
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.7/');
const gltfLoader = new GLTFLoader();
gltfLoader.setDRACOLoader(dracoLoader);
gltfLoader.setMeshoptDecoder(MeshoptDecoder);
const gltf = await gltfLoader.loadAsync('/models/bender-optimized.glb');
const root = gltf.scene;
scene.add(root);
Zwei Animationsmethoden
- Prozedurale Animation mit Node-Transformationen. Verwenden Sie diese Methode für Roboter, Fahrzeuge und andere starre Teile. Beispiele: Radrotation, Türöffnung, Kopfbewegung, Antennenschwanken.
const head = root.getObjectByName('Head');
const door = root.getObjectByName('Torso_Door');
const antenna = root.getObjectByName('Antenna');
function animate(time) {
if (antenna) {
antenna.rotation.z = Math.sin(time * 0.005) * 0.15;
}
if (head) {
head.rotation.y = THREE.MathUtils.lerp(head.rotation.y, targetYaw, 0.1);
}
}
- Gebackene Clips mit
THREE.AnimationMixer. Verwenden Sie diese Methode für komplexe Zyklen aus Blender: Gehen, Tanzen und Gesichts-Morphs.
const mixer = new THREE.AnimationMixer(root);
const idleClip = THREE.AnimationClip.findByName(gltf.animations, 'Idle');
if (idleClip) {
mixer.clipAction(idleClip).play();
}
// In der Render-Schleife:
// mixer.update(clock.getDelta());
PBR-Beleuchtung für Metallteile
Ein Metallmaterial (metalness > 0.8) sieht in Three.js schwarz aus, wenn es von nichts umgeben ist. Setzen Sie eine Umgebungsmap:
import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
const pmremGenerator = new THREE.PMREMGenerator(renderer);
scene.environment = pmremGenerator.fromScene(new RoomEnvironment(), 0.04).texture;
Verwenden Sie scene.environmentIntensity, um die Reflexionsstärke anzupassen. Behalten Sie das Tone-Mapping bei THREE.ACESFilmicToneMapping für Metall-Assets.
Performance-Regeln
- Ein Material pro Mesh-Gruppe. Jedes Material kostet einen Draw Call.
- Texturen wiederverwenden. Packen Sie kleine Texturen in ein Atlas.
- Setzen Sie
renderer.outputColorSpace = THREE.SRGBColorSpace. Der glTF-Loader setzt die Textur-Farbräume. - Verwenden Sie
THREE.InstancedMesh, wenn ein Asset mehrfach vorkommt. - Geben Sie ein Modell frei, wenn Sie es entfernen: Durchlaufen Sie die Szene, dann rufen Sie
geometry.dispose()undmaterial.dispose()auf.