Cargar modelos de gltfpack en Three.js
Para cargar los archivos de esta herramienta con GLTFLoader, añade MeshoptDecoder para la compresión Meshopt y KTX2Loader para las texturas KTX2. Consulta en el panel de resultados qué extensiones necesita tu archivo.
Instala dependencias compatibles
Usa este ejemplo en un proyecto npm con un empaquetador de módulos ES, como una aplicación Vite existente. Las versiones indicadas coinciden con las del visor de este sitio. Las importaciones por nombre de paquete no funcionan simplemente abriendo el archivo JavaScript en un navegador.
npm install [email protected] [email protected]
Copia los archivos del transcodificador Basis desde el paquete Three.js instalado al directorio público. Si ese directorio se sirve desde la raíz del sitio, los archivos siguientes estarán disponibles en /basis/. Deben proceder de la misma versión de Three.js que KTX2Loader.
node -e "require('fs').cpSync('node_modules/three/examples/jsm/libs/basis', 'public/basis', {recursive:true})"
Conecta los decodificadores antes de cargar
Coloca el archivo optimizado en public/models/optimized.glb y crea un canvas con el id model. Usa el código siguiente como módulo de entrada de tu aplicación. Ajusta la cámara a los límites del modelo y reproduce la primera animación si existe.
<canvas id="model"></canvas>
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js';
import { MeshoptDecoder } from 'meshoptimizer';
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('#model'), antialias: true,
});
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xeeeeee);
scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 3));
const light = new THREE.DirectionalLight(0xffffff, 3);
light.position.set(3, 5, 4);
scene.add(light);
const camera = new THREE.PerspectiveCamera(45, 1, 0.01, 1000);
const ktx2 = new KTX2Loader()
.setTranscoderPath('/basis/')
.detectSupport(renderer);
const loader = new GLTFLoader()
.setMeshoptDecoder(MeshoptDecoder)
.setKTX2Loader(ktx2);
function resize() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
window.addEventListener('resize', resize);
resize();
try {
await MeshoptDecoder.ready;
const gltf = await loader.loadAsync('/models/optimized.glb');
scene.add(gltf.scene);
const bounds = new THREE.Box3().setFromObject(gltf.scene);
const center = bounds.getCenter(new THREE.Vector3());
const radius = Math.max(bounds.getBoundingSphere(new THREE.Sphere()).radius, 0.01);
const verticalFov = THREE.MathUtils.degToRad(camera.fov);
const horizontalFov = 2 * Math.atan(Math.tan(verticalFov / 2) * camera.aspect);
const distance = 1.2 * radius / Math.sin(Math.min(verticalFov, horizontalFov) / 2);
camera.position.copy(center).add(new THREE.Vector3(1, 0.6, 1).normalize().multiplyScalar(distance));
camera.near = radius / 100;
camera.far = distance + radius * 10;
camera.lookAt(center);
camera.updateProjectionMatrix();
const mixer = new THREE.AnimationMixer(gltf.scene);
if (gltf.animations.length) mixer.clipAction(gltf.animations[0]).play();
const clock = new THREE.Clock();
renderer.setAnimationLoop(() => {
mixer.update(Math.min(clock.getDelta(), 0.1));
renderer.render(scene, camera);
});
} catch (error) {
console.error('Model loading failed:', error);
const message = document.createElement('p');
message.textContent = 'Model loading failed. Check the browser console and network requests.';
document.body.prepend(message);
}
Comprueba la extensión y la solicitud fallida
| Síntoma | Qué comprobar |
|---|---|
| Error del decodificador Meshopt | Llama a setMeshoptDecoder antes de loadAsync y asegúrate de incluir el paquete meshoptimizer en el código empaquetado. |
| Las texturas KTX2 no se cargan | Asigna KTX2Loader a GLTFLoader, llama a detectSupport con el renderizador y comprueba la URL del transcodificador. |
| Se devuelve HTML en lugar de un modelo o un archivo WASM | Si falta un archivo, la solicitud puede acabar devolviendo la página de la aplicación. Comprueba el estado HTTP, el contenido de la respuesta y las rutas base del despliegue. |
Si el sitio aplica una Content Security Policy estricta, comprueba en la consola si se están bloqueando Web Workers o WebAssembly. Configura expresamente cómo sirve tu aplicación los workers y WASM; no elimines la política solo para ocultar un error. Una respuesta de red correcta no confirma por sí sola que la decodificación haya terminado bien.
El ejemplo configura ambos decodificadores para poder cargar cualquiera de los dos resultados. Los archivos que conservan texturas PNG o JPEG no necesitan KTX2Loader. WebP requiere compatibilidad del navegador y del cargador, pero no utiliza el transcodificador Basis. Si tu aplicación cambia de modelo repetidamente, libera la geometría, los materiales y las texturas anteriores; libera también el cargador KTX2 cuando ya no lo necesites.
Three.js GLTFLoader · Three.js KTX2Loader
Consultar otros requisitos de compatibilidad del resultado →
Referencia del motor: gltfpack
Abrir el optimizador ↗