Three.js에서 gltfpack 모델 불러오기

이 도구의 출력 파일을 GLTFLoader로 불러오려면 Meshopt 압축에는 MeshoptDecoder를, KTX2 텍스처에는 KTX2Loader를 추가하세요. 파일에 필요한 확장 기능은 결과 패널에서 확인하세요.

버전이 맞는 의존성 설치

기존 Vite 앱처럼 ES 모듈 번들러를 사용하는 npm 프로젝트에서 예제를 사용하세요. 아래 버전은 이 사이트의 뷰어와 같습니다. JavaScript 파일을 브라우저에서 직접 여는 것만으로는 패키지 이름을 사용한 import가 작동하지 않습니다.

npm install [email protected] [email protected]

설치된 Three.js 패키지의 Basis 트랜스코더 파일을 public 디렉터리에 복사하세요. public 디렉터리를 사이트 루트로 제공하는 일반적인 구성이라면 아래 파일은 /basis/에서 접근할 수 있습니다. KTX2Loader와 같은 Three.js 버전의 파일을 사용하세요.

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

불러오기 전에 디코더 연결

최적화 파일을 public/models/optimized.glb에 두고 id가 model인 canvas를 만드세요. 다음 코드를 애플리케이션 시작 모듈로 사용하세요. 불러온 모델의 경계에 맞춰 카메라를 조정하고 애니메이션이 있으면 첫 번째를 재생합니다.

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

확장과 실패한 요청 확인

증상확인 사항
Meshopt 디코더 오류loadAsync 전에 setMeshoptDecoder를 호출하고 번들에 meshoptimizer 패키지를 포함하세요.
KTX2 텍스처가 로드되지 않음GLTFLoader에 KTX2Loader를 설정하고 렌더러로 detectSupport를 호출한 뒤 트랜스코더 URL을 확인하세요.
모델이나 WASM 파일 대신 HTML이 반환됨파일이 없으면 애플리케이션 페이지로 대체 응답될 수 있습니다. HTTP 상태, 응답 내용, 배포 기본 경로를 확인하세요.

엄격한 Content Security Policy를 쓰는 사이트에서는 콘솔에서 Web Worker나 WebAssembly 차단 여부를 확인하세요. 애플리케이션의 worker와 WASM 제공 방식을 적절히 설정하고 오류를 감추려고 정책을 제거하지 마세요. 네트워크 응답 성공만으로 디코딩 성공을 확인할 수는 없습니다.

예제는 두 종류의 출력을 모두 불러오도록 두 디코더를 설치합니다. PNG나 JPEG를 유지한 파일에는 KTX2Loader가 필요 없습니다. WebP는 브라우저와 로더 지원이 필요하지만 Basis 트랜스코더는 사용하지 않습니다. 모델을 반복해서 교체하는 앱에서는 이전 지오메트리, 재질, 텍스처를 해제하고 KTX2 로더도 더 이상 필요 없으면 해제하세요.

Three.js GLTFLoader · Three.js KTX2Loader

다른 출력 호환성 요구 사항 확인 →

엔진 참고 자료: gltfpack

최적화 도구 열기 ↗