Communitygithub.com

zipang/Pipeline Web de Three.js y glTF

Optimiza activos 3D (.glb y .gltf) e intégralos en animaciones web interactivas con Three.js, React Three Fiber, GSAP y gltf-transform. Útil para compresión (Draco, Meshopt, KTX2), configuración de pivotes y animación, y renderizado web.

¿Qué es Pipeline Web de Three.js y glTF?

Este skill define un pipeline completo para convertir modelos 3D de Blender o vcad en archivos .glb optimizados para la web, que carguen rápido y se animen fácilmente en Three.js. Cubre desde la exportación con buenas prácticas (nombres de nodos, pivotes, transformaciones, presupuesto de geometría) hasta la optimización por línea de comandos con @gltf-transform/cli (compresión Meshopt o Draco, conversión de texturas a WebP o KTX2). También incluye la integración en Three.js con un cargador robusto que soporta Draco y Meshopt, dos métodos de animación (procedimental con transformaciones de nodos o clips horneados con AnimationMixer), configuración de iluminación PBR con mapas de entorno y reglas de rendimiento. Es ideal para desarrolladores que trabajan con Three.js, React Three Fiber, GSAP o cualquier stack web que use modelos glTF. El skill está basado en la documentación SKILL.md y proporciona ejemplos de código prácticos y comandos CLI.

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

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

¿Qué hace Pipeline Web de Three.js y glTF?

Este skill cubre los pasos para convertir un modelo de Blender o vcad en un archivo .glb pequeño. El archivo debe cargar rápido y animarse fácilmente en Three.js.

1. Lista de verificación de exportación para Blender y vcad

Nombres de nodos

  • Nombra cada parte móvil con un nombre claro y estable: Head, Visor, Eye_L, Eye_R, Torso_Door, Wheel_FL, Wheel_FR, Steering_Wheel.
  • Luego Three.js encuentra la parte con model.getObjectByName("Torso_Door").

Pivotes

  • Coloca el origen raíz en el centro de la base del modelo. En Three.js, el modelo se asienta en el suelo en Y = 0.
  • Coloca el pivote de cada parte articulada en su eje de rotación. Ejemplos: bisagra de puerta, centro de rueda, base de cuello, base de antena.

Transformaciones

  • Aplica todas las transformaciones antes de exportar.
  • La escala debe ser 1, 1, 1. La rotación de reposo debe ser 0, 0, 0.
  • Esta regla evita desviaciones y deformaciones durante la animación procedural.

Presupuesto de geometría

  • Une mallas estáticas que compartan un material. Este paso reduce las llamadas de dibujo.
  • Mantén una malla separada solo si un script la anima por sí sola. Usa un SkinnedMesh con un armazón para deformación suave.
  • Apunta a unos pocos miles de triángulos por activo principal. Apunta a menos de 1,000 triángulos para elementos de fondo.

2. Optimización CLI con @gltf-transform/cli

El proyecto usa Bun. Ejecuta la herramienta con bunx. npx también funciona en máquinas que tengan Node.js.

# Muestra mallas, texturas y animaciones
bunx @gltf-transform/cli inspect model.glb

# Optimización completa para la web: Meshopt más WebP más limpieza
bunx @gltf-transform/cli optimize model.glb model-optimized.glb \
  --compress meshopt \
  --texture-compress webp \
  --texture-size 2048

# Alternativa: Compresión de geometría Draco
bunx @gltf-transform/cli draco model.glb model-draco.glb

Meshopt o Draco

  • Meshopt (EXT_meshopt_compression) decodifica muy rápido. Mantiene el orden de los vértices y también comprime fotogramas clave de animación y objetivos de morfología. Úsalo para activos animados.
  • Draco (KHR_draco_mesh_compression) da el archivo más pequeño para mallas estáticas densas. Ejemplos: carrocerías y escaneos. El decodificador cuesta más tiempo al inicio.

Otros pasos útiles

# Elimina mallas duplicadas y datos no utilizados
bunx @gltf-transform/cli dedup model.glb model.glb

# Convierte texturas a KTX2 (BasisU)
bunx @gltf-transform/cli etc1s model.glb model-ktx2.glb

Revisa el archivo después de cada paso. Confirma el tamaño del archivo, el conteo de triángulos y el tamaño de las texturas.

3. Integración con Three.js

Cargador robusto con Draco y 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);

Dos métodos de animación

  1. Animación procedural con transformaciones de nodos. Usa este método para robots, vehículos y otras partes rígidas. Ejemplos: giro de rueda, apertura de puerta, seguimiento de cabeza, balanceo de antena.
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 horneados con THREE.AnimationMixer. Usa este método para ciclos complejos que vienen de Blender: caminar, bailar y morfologías faciales.
const mixer = new THREE.AnimationMixer(root);
const idleClip = THREE.AnimationClip.findByName(gltf.animations, 'Idle');
if (idleClip) {
  mixer.clipAction(idleClip).play();
}

// En el bucle de renderizado:
// mixer.update(clock.getDelta());

Iluminación PBR para piezas metálicas

Un material metálico (metalness > 0.8) se ve negro en Three.js cuando no hay nada que lo refleje. Configura un mapa de entorno:

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

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

Usa scene.environmentIntensity para ajustar la intensidad del reflejo. Mantén el mapeo de tono en THREE.ACESFilmicToneMapping para activos metálicos.

Reglas de rendimiento

  • Un material por grupo de malla. Cada material cuesta una llamada de dibujo.
  • Reutiliza texturas. Empaqueta texturas pequeñas en un solo atlas.
  • Configura renderer.outputColorSpace = THREE.SRGBColorSpace. El cargador glTF establece los espacios de color de las texturas.
  • Usa THREE.InstancedMesh cuando un activo aparece muchas veces.
  • Libera un modelo cuando lo elimines: recorre la escena, luego llama a geometry.dispose() y material.dispose().

Skills relacionados