Cargar modelos gltfpack en Three.js

Un GLB optimizado puede necesitar más que un GLTFLoader solo. Esta guía cubre la configuración del cargador para la salida Meshopt y KTX2 de esta herramienta. No elige configuraciones de compresión; use el panel de resultados para ver qué extensiones requiere su archivo exportado.

Instalar dependencias coincidentes

Utilice este ejemplo en un proyecto npm con un paquete de módulos ES, como una aplicación Vite existente. Las versiones siguientes coinciden con el visor de este sitio. Las importaciones simples no funcionan simplemente abriendo el archivo JavaScript en un navegador.

npm install [email protected] [email protected]

Copie los archivos del transcodificador Basis del paquete Three.js instalado en su directorio público. Con un directorio público convencional servido en la raíz del sitio, los archivos siguientes estarán disponibles en /basis/. Manténgalos de la misma versión Three.js que KTX2Loader.

node -e "require('fs').cpSync('node_modules/three/examples/jsm/libs/basis', 'public/basis', {recursive:true})"

Conecte los decodificadores antes de cargar

Coloque el archivo optimizado en public/models/optimized.glb y cree un lienzo con un modelo de identificación. Utilice lo siguiente como módulo de entrada de su solicitud. Ajusta la cámara a los límites cargados y reproduce la primera animación cuando está presente.

<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);
}

Verifique la extensión y la solicitud fallida

SíntomaControlar
Error del decodificador MeshoptLlame a setMeshoptDecoder antes que loadAsync y mantenga el paquete meshoptimizer en el paquete.
KTX2 las texturas no se carganConfigure KTX2Loader en GLTFLoader, llame a detectSupport con el renderizador y verifique la URL del transcodificador.
HTML devuelto en lugar de un modelo o archivo WASMEs posible que un archivo faltante esté llegando a la página de su aplicación. Verifique el estado de HTTP, el contenido de la respuesta y las rutas base de implementación.

En un sitio con una política de seguridad de contenido estricta, verifique en la consola si hay trabajadores web bloqueados o WebAssembly. Configure deliberadamente el trabajador de su aplicación y la entrega WASM; no elimine la política sólo para ocultar un error. Una respuesta exitosa de la red por sí sola no confirma que la decodificación haya sido exitosa.

El ejemplo instala ambos decodificadores para poder cargar cualquiera de las salidas. Los archivos que mantienen las texturas PNG o JPEG no necesitan KTX2Loader. WebP necesita compatibilidad con el navegador y el cargador, pero no utiliza el transcodificador Basis. En una aplicación con cambios repetidos de modelo, deseche la geometría, los materiales y las texturas antiguos; suelte el cargador KTX2 cuando ya no sea necesario.

Three.js GLTFLoader · Three.js KTX2Loader

Verifique otros requisitos de compatibilidad de salida →

Referencia del motor: gltfpack

Abra el optimizador ↗