Charger les modèles gltfpack dans Three.js

Un GLB optimisé peut nécessiter plus que GLTFLoader seul. Ce guide couvre la configuration du chargeur pour les sorties Meshopt et KTX2 de cet outil. Il ne choisit pas les paramètres de compression ; utilisez le panneau de résultats pour voir les extensions requises par votre fichier exporté.

Installer les dépendances correspondantes

Utilisez cet exemple dans un projet npm avec un bundler de modules ES, tel qu'une application Vite existante. Les versions ci-dessous correspondent à la visionneuse de ce site. Les importations nues ne fonctionnent pas en ouvrant simplement le fichier JavaScript dans un navigateur.

npm install [email protected] [email protected]

Copiez les fichiers du transcodeur Basis du package Three.js installé dans votre répertoire public. Avec un répertoire public conventionnel servi à la racine du site, les fichiers ci-dessous seront disponibles sous /basis/. Conservez-les de la même version Three.js que KTX2Loader.

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

Connectez les décodeurs avant de charger

Placez le fichier optimisé sur public/models/optimized.glb et créez un canevas avec un modèle d'identification. Utilisez ce qui suit comme module de saisie de votre candidature. Il adapte la caméra aux limites chargées et lit la première animation lorsqu'elle est présente.

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

Vérifiez l'extension et la demande ayant échoué

SymptômeVérifier
Erreur du décodeur MeshoptAppelez setMeshoptDecoder avant loadAsync et conservez le package meshoptimizer dans le bundle.
Les textures KTX2 ne se chargent pasDéfinissez KTX2Loader sur GLTFLoader, appelez detectSupport avec le moteur de rendu et vérifiez l'URL du transcodeur.
HTML renvoyé à la place d'un modèle ou d'un fichier WASMUn fichier manquant peut se retrouver sur votre page de candidature. Vérifiez l'état HTTP, le contenu de la réponse et les chemins de base de déploiement.

Sur un site avec une politique de sécurité du contenu stricte, vérifiez la console pour les Web Workers bloqués ou WebAssembly. Configurez délibérément le travailleur de votre application et la livraison WASM ; ne supprimez pas la stratégie uniquement pour masquer une erreur. Une réponse réseau réussie ne suffit pas à confirmer que le décodage a réussi.

L'exemple installe les deux décodeurs afin de pouvoir charger l'une ou l'autre sortie. Les fichiers qui conservent les textures PNG ou JPEG n'ont pas besoin de KTX2Loader. WebP nécessite la prise en charge du navigateur et du chargeur, mais n'utilise pas le transcodeur Basis. Dans une application avec des changements de modèle répétés, éliminez les anciennes géométries, matériaux et textures ; libérez le chargeur KTX2 lorsqu’il n’est plus nécessaire.

Three.js GLTFLoader · Three.js KTX2Loader

Vérifiez les autres exigences de compatibilité de sortie →

Référence moteur : gltfpack

Ouvrez l'optimiseur ↗