Communitygithub.com

zipang/Pipeline Web Three.js et glTF

Optimisez vos actifs 3D (.glb et .gltf) et intégrez-les dans des animations web interactives avec Three.js, React Three Fiber, GSAP et gltf-transform. Utilisez-le pour la compression (Draco, Meshopt, KTX2), la configuration des pivots et des animations, ainsi que le rendu web.

Qu'est-ce que Pipeline Web Three.js et glTF ?

Cette compétence couvre l'ensemble du pipeline de conversion d'un modèle Blender ou vcad en un fichier .glb léger, prêt à être chargé rapidement et animé facilement dans Three.js. Elle détaille les bonnes pratiques d'exportation : nommage des nœuds, placement des pivots, application des transformations, budget de géométrie et jointure des mailles. Elle présente ensuite les étapes d'optimisation en ligne de commande avec @gltf-transform/cli (compression Meshopt ou Draco, textures WebP ou KTX2, déduplication). Enfin, elle explique l'intégration dans Three.js : chargement robuste avec DRACOLoader et MeshoptDecoder, deux méthodes d'animation (procédurale ou clips cuits avec AnimationMixer), éclairage PBR pour les pièces métalliques, et règles de performance. La compétence est directement applicable à tout projet utilisant Three.js, que ce soit dans un contexte React Three Fiber ou vanilla.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/zipang/bender-agent/tree/HEAD/.agents/skills/threejs-web

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait Pipeline Web Three.js et glTF ?

Cette compétence couvre les étapes qui transforment un modèle Blender ou vcad en un petit fichier .glb. Le fichier doit se charger rapidement et s'animer facilement dans Three.js.

1. Liste de vérification pour l'exportation dans Blender et vcad

Noms des nœuds

  • Nommez chaque pièce mobile avec un nom clair et stable : Head, Visor, Eye_L, Eye_R, Torso_Door, Wheel_FL, Wheel_FR, Steering_Wheel.
  • Three.js trouve ensuite la pièce avec model.getObjectByName("Torso_Door").

Pivots

  • Placez l'origine racine au centre de la base du modèle. Dans Three.js, le modèle repose alors sur le sol à Y = 0.
  • Placez le pivot de chaque pièce articulée sur son axe de rotation. Exemples : charnière de porte, centre de roue, base du cou, base de l'antenne.

Transformations

  • Appliquez toutes les transformations avant l'exportation.
  • L'échelle doit être 1, 1, 1. La rotation de repos doit être 0, 0, 0.
  • Cette règle évite la dérive et le cisaillement lors de l'animation procédurale.

Budget de géométrie

  • Joignez les mailles statiques qui partagent un même matériau. Cette étape réduit les appels de dessin.
  • Gardez une maille séparée uniquement si un script l'anime seule. Utilisez un SkinnedMesh avec une armature pour les déformations souples.
  • Visez quelques milliers de triangles par actif principal. Visez moins de 1 000 triangles pour les accessoires d'arrière-plan.

2. Optimisation en ligne de commande avec @gltf-transform/cli

Le projet utilise Bun. Exécutez l'outil avec bunx. npx fonctionne aussi sur les machines disposant de Node.js.

# Afficher les mailles, textures et animations
bunx @gltf-transform/cli inspect model.glb

# Optimisation complète pour le web : Meshopt plus WebP plus nettoyage
bunx @gltf-transform/cli optimize model.glb model-optimized.glb \
  --compress meshopt \
  --texture-compress webp \
  --texture-size 2048

# Alternative : compression géométrique Draco
bunx @gltf-transform/cli draco model.glb model-draco.glb

Meshopt ou Draco

  • Meshopt (EXT_meshopt_compression) se décode très rapidement. Il conserve l'ordre des sommets et compresse également les images clés d'animation et les cibles de morphing. Utilisez-le pour les actifs animés.
  • Draco (KHR_draco_mesh_compression) donne le fichier le plus petit pour les mailles statiques denses. Exemples : carrosseries et scans. Le décodeur coûte plus de temps au démarrage.

Autres étapes utiles

# Supprimer les mailles dupliquées et les données inutilisées
bunx @gltf-transform/cli dedup model.glb model.glb

# Convertir les textures en KTX2 (BasisU)
bunx @gltf-transform/cli etc1s model.glb model-ktx2.glb

Vérifiez le fichier après chaque étape. Confirmez la taille du fichier, le nombre de triangles et la taille des textures.

3. Intégration Three.js

Chargeur robuste avec Draco et 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);

Deux méthodes d'animation

  1. Animation procédurale avec transformations de nœuds. Utilisez cette méthode pour les robots, véhicules et autres pièces rigides. Exemples : rotation de roue, ouverture de porte, suivi de tête, balancement d'antenne.
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);
  }
}
  1. Clips cuits avec THREE.AnimationMixer. Utilisez cette méthode pour les cycles complexes provenant de Blender : marche, danse et morphings faciaux.
const mixer = new THREE.AnimationMixer(root);
const idleClip = THREE.AnimationClip.findByName(gltf.animations, 'Idle');
if (idleClip) {
  mixer.clipAction(idleClip).play();
}

// Dans la boucle de rendu :
// mixer.update(clock.getDelta());

Éclairage PBR pour les pièces métalliques

Un matériau métallique (metalness > 0.8) apparaît noir dans Three.js lorsque rien ne l'entoure. Définissez une carte d'environnement :

import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';

const pmremGenerator = new THREE.PMREMGenerator(renderer);
scene.environment = pmremGenerator.fromScene(new RoomEnvironment(), 0.04).texture;

Utilisez scene.environmentIntensity pour ajuster la force de la réflexion. Conservez le mappage de tonalité à THREE.ACESFilmicToneMapping pour les actifs métalliques.

Règles de performance

  • Un matériau par groupe de mailles. Chaque matériau coûte un appel de dessin.
  • Réutilisez les textures. Regroupez les petites textures dans un seul atlas.
  • Définissez renderer.outputColorSpace = THREE.SRGBColorSpace. Le chargeur glTF définit les espaces colorimétriques des textures.
  • Utilisez THREE.InstancedMesh lorsqu'un actif apparaît plusieurs fois.
  • Libérez un modèle lorsque vous le supprimez : parcourez la scène, puis appelez geometry.dispose() et material.dispose().

Skills associés