Communitygithub.com

zipang/Three.js 및 glTF 웹 파이프라인

3D 에셋(.glb 및 .gltf)을 최적화하고 Three.js, React Three Fiber, GSAP, gltf-transform을 사용하여 인터랙티브 웹 애니메이션에 통합합니다. 압축(Draco, Meshopt, KTX2), 피벗 및 애니메이션 설정, 웹 렌더링에 사용합니다.

Three.js 및 glTF 웹 파이프라인란 무엇인가요?

이 스킬은 Blender 또는 vcad 모델을 작고 효율적인 `.glb` 파일로 변환한 후 Three.js에서 빠르게 로드하고 애니메이션 처리하는 엔드투엔드 파이프라인을 제공합니다. 3D 아티스트와 개발자는 이 스킬의 명확한 내보내기 체크리스트를 따라 노드 이름 지정, 피벗 설정, 변환 적용, 지오메트리 예산 관리 등 모델 최적화의 모범 사례를 따를 수 있습니다. `@gltf-transform/cli` 도구 모음을 사용하여 Meshopt 또는 Draco 압축, 텍스처 압축(WebP, KTX2), 중복 제거 등 웹 성능을 향상시키는 CLI 기반 최적화를 수행합니다. 마지막으로, 이 스킬은 Draco 및 Meshopt 디코더 지원과 함께 GLTFLoader를 사용한 강력한 Three.js 통합 코드, 절차적 애니메이션(노드 변환 기반)과 베이크된 클립(AnimationMixer 기반)이라는 두 가지 애니메이션 접근 방식, 금속 재질의 사실적인 PBR 조명을 위한 환경 맵 설정, 드로우 콜 최소화, 텍스처 재사용, 효율적인 메모리 해제 등 성능 규칙을 제공합니다. 이 파이프라인은 Claude Code, Cursor, Codex 등 다양한 AI 에이전트에서 사용할 수 있으며, 설치가 간편한 Bun 런타임에서 실행됩니다.

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

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Three.js 및 glTF 웹 파이프라인은(는) 무엇을 하나요?

이 스킬은 Blender 또는 vcad 모델을 작은 .glb 파일로 변환하는 단계를 다룹니다. 파일은 빠르게 로드되어야 하며 Three.js에서 쉽게 애니메이션 처리될 수 있어야 합니다.

1. Blender 및 vcad 내보내기 체크리스트

노드 이름

  • 각 움직이는 부품에 명확하고 안정적인 이름을 지정하세요: Head, Visor, Eye_L, Eye_R, Torso_Door, Wheel_FL, Wheel_FR, Steering_Wheel.
  • 그러면 Three.js에서 model.getObjectByName("Torso_Door")로 부품을 찾습니다.

피벗

  • 루트 원점을 모델 베이스의 중심에 배치하세요. Three.js에서 모델은 Y = 0인 지면에 놓입니다.
  • 각 관절 부품의 피벗을 회전축에 배치하세요. 예: 도어 힌지, 바퀴 중심, 목 베이스, 안테나 베이스.

변환

  • 내보내기 전에 모든 변환을 적용하세요.
  • 스케일은 1, 1, 1이어야 합니다. 회전은 0, 0, 0으로 재설정되어야 합니다.
  • 이 규칙은 절차적 애니메이션 중 드리프트와 전단을 방지합니다.

지오메트리 예산

  • 하나의 재질을 공유하는 정적 메시는 결합하세요. 이 단계는 드로우 콜을 줄입니다.
  • 스크립트가 단독으로 애니메이션 처리하는 경우에만 메시를 분리하여 유지하세요. 소프트 변형에는 Armature와 함께 SkinnedMesh를 사용하세요.
  • 히어로 에셋당 수천 개의 삼각형을 목표로 하세요. 배경 소품의 경우 1,000개 미만의 삼각형을 목표로 하세요.

2. @gltf-transform/cli를 사용한 CLI 최적화

이 프로젝트는 Bun을 사용합니다. bunx로 도구를 실행하세요. Node.js가 있는 머신에서는 npx도 작동합니다.

# 메시, 텍스처, 애니메이션 표시
bunx @gltf-transform/cli inspect model.glb

# 웹용 전체 최적화: Meshopt + WebP + 정리
bunx @gltf-transform/cli optimize model.glb model-optimized.glb \
  --compress meshopt \
  --texture-compress webp \
  --texture-size 2048

# 대안: Draco 지오메트리 압축
bunx @gltf-transform/cli draco model.glb model-draco.glb

Meshopt 또는 Draco

  • Meshopt (EXT_meshopt_compression) 디코딩이 매우 빠릅니다. 정점 순서를 유지하고 애니메이션 키프레임과 모프 타겟도 압축합니다. 애니메이션 에셋에 사용하세요.
  • Draco (KHR_draco_mesh_compression) 는 밀집된 정적 메시에 대해 가장 작은 파일을 제공합니다. 예: 자동차 차체 및 스캔. 디코더는 시작 시 더 많은 시간이 소요됩니다.

기타 유용한 단계

# 중복 메시 및 사용되지 않는 데이터 제거
bunx @gltf-transform/cli dedup model.glb model.glb

# 텍스처를 KTX2(BasisU)로 변환
bunx @gltf-transform/cli etc1s model.glb model-ktx2.glb

각 단계 후에 파일을 확인하세요. 파일 크기, 삼각형 개수, 텍스처 크기를 확인하세요.

3. Three.js 통합

Draco 및 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);

두 가지 애니메이션 방법

  1. 노드 변환을 사용한 절차적 애니메이션. 로봇, 차량 및 기타 강체 부품에 이 방법을 사용하세요. 예: 바퀴 회전, 도어 열기, 헤드 추적, 안테나 흔들기.
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. THREE.AnimationMixer를 사용한 베이크된 클립. Blender에서 가져온 복잡한 사이클(걷기, 춤, 얼굴 모프)에 이 방법을 사용하세요.
const mixer = new THREE.AnimationMixer(root);
const idleClip = THREE.AnimationClip.findByName(gltf.animations, 'Idle');
if (idleClip) {
  mixer.clipAction(idleClip).play();
}

// 렌더 루프에서:
// mixer.update(clock.getDelta());

금속 부품을 위한 PBR 조명

금속 재질(metalness > 0.8)은 Three.js에서 주변에 아무것도 없을 때 검게 보입니다. 환경 맵을 설정하세요:

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

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

scene.environmentIntensity를 사용하여 반사 강도를 조정하세요. 금속 에셋의 경우 톤 매핑을 THREE.ACESFilmicToneMapping으로 유지하세요.

성능 규칙

  • 메시 그룹당 하나의 재질. 각 재질은 하나의 드로우 콜을 발생시킵니다.
  • 텍스처를 재사용하세요. 작은 텍스처를 하나의 아틀라스로 압축하세요.
  • renderer.outputColorSpace = THREE.SRGBColorSpace로 설정하세요. glTF 로더가 텍스처 색상 공간을 설정합니다.
  • 하나의 에셋이 여러 번 나타날 때 THREE.InstancedMesh를 사용하세요.
  • 모델을 제거할 때 해제하세요: 씬을 순회한 다음 geometry.dispose() 및 material.dispose()를 호출하세요.

관련 스킬