home / skills / pluxity / pf-frontend / three-expert

three-expert skill

/.claude/skills/three-expert

This skill helps you develop and optimize Three.js and React Three Fiber scenes with GLTF/instancing patterns, enhancing interactivity and performance.

npx playbooks add skill pluxity/pf-frontend --skill three-expert

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
5.7 KB
---
name: three-expert
description: Three.js/React Three Fiber 전문가. "3D", "Three.js", "R3F", "모델" 관련 질문 시 사용.
allowed-tools: Read, Write, Glob, Grep, mcp__plugin_context7_context7__resolve-library-id, mcp__plugin_context7_context7__query-docs
---

# Three.js/R3F 전문가

$ARGUMENTS Three.js 관련 질문에 답변하고 구현을 도와드립니다.

---

## @pf-dev/three 패키지 구조

```
packages/three/src/
├── components/
│   ├── Canvas.tsx           # R3F Canvas 래퍼
│   ├── SceneLighting.tsx    # 조명 설정
│   ├── SceneGrid.tsx        # 그리드 헬퍼
│   ├── Stats.tsx            # 성능 통계
│   ├── GLTFModel.tsx        # GLTF 로더
│   └── FBXModel.tsx         # FBX 로더
├── stores/
│   ├── useFacilityStore.ts  # 시설물 상태
│   ├── useAssetStore.ts     # 에셋 상태
│   └── useFeatureStore.ts   # Feature 상태
├── hooks/
│   ├── useModel.ts          # 모델 로딩
│   └── useInteraction.ts    # 인터랙션
└── utils/
    └── instancing.ts        # GPU Instancing
```

---

## 주요 패턴

### 기본 씬 설정

```tsx
import { Canvas, SceneLighting, SceneGrid, Stats } from "@pf-dev/three";

function Scene() {
  return (
    <Canvas
      camera={{ position: [10, 10, 10], fov: 50 }}
      shadows
    >
      <SceneLighting />
      <SceneGrid size={100} />
      <Stats />

      {/* 3D 오브젝트들 */}
      <MyModel />
    </Canvas>
  );
}
```

### GLTF 모델 로딩

```tsx
import { GLTFModel } from "@pf-dev/three";

function Building() {
  return (
    <GLTFModel
      url="/models/building.glb"
      position={[0, 0, 0]}
      scale={1}
      onLoad={(gltf) => {
        console.log("Model loaded:", gltf);
      }}
      onClick={(event) => {
        console.log("Clicked:", event.object.name);
      }}
    />
  );
}
```

### 인터랙션 (Hover, Select)

```tsx
import { useInteraction } from "@pf-dev/three";

function InteractiveModel({ url }) {
  const { hovered, selected, bind } = useInteraction();

  return (
    <GLTFModel
      url={url}
      {...bind()}
      onPointerOver={() => console.log("hover")}
      onPointerOut={() => console.log("out")}
      onClick={() => console.log("click")}
    >
      {hovered && <Outline color="yellow" />}
      {selected && <Outline color="blue" />}
    </GLTFModel>
  );
}
```

---

## GPU Instancing (대량 오브젝트)

```tsx
import { useMemo } from "react";
import { InstancedMesh } from "three";

function Trees({ positions }: { positions: [number, number, number][] }) {
  const mesh = useMemo(() => {
    const temp = new THREE.Object3D();
    return positions.map((pos, i) => {
      temp.position.set(...pos);
      temp.updateMatrix();
      return temp.matrix.clone();
    });
  }, [positions]);

  return (
    <instancedMesh args={[undefined, undefined, positions.length]}>
      <cylinderGeometry args={[0.5, 0.5, 3]} />
      <meshStandardMaterial color="brown" />
      {mesh.map((matrix, i) => (
        <primitive key={i} object={matrix} attach={`instanceMatrix-${i}`} />
      ))}
    </instancedMesh>
  );
}

// 또는 @pf-dev/three의 유틸리티 사용
import { createInstances } from "@pf-dev/three";

const instances = createInstances(geometry, material, transforms);
```

---

## 자주 묻는 질문

### Q: 성능이 느려요

**A: 최적화 방법**
1. GPU Instancing 사용 (동일 오브젝트 100개 이상)
2. LOD (Level of Detail) 설정
3. Frustum Culling 확인
4. 텍스처 압축 (KTX2)
5. Draco 압축 모델 사용

```tsx
<Canvas
  gl={{
    antialias: false,       // 안티앨리어싱 끄기
    powerPreference: "high-performance",
  }}
  frameloop="demand"        // 필요할 때만 렌더
>
```

### Q: 모델이 안 보여요

**A: 체크리스트**
1. 경로 확인 (`/public` 폴더)
2. 스케일 확인 (너무 작거나 큼)
3. 카메라 위치 확인
4. 조명 확인

```tsx
// 디버깅용 박스 추가
<mesh position={[0, 0, 0]}>
  <boxGeometry args={[1, 1, 1]} />
  <meshBasicMaterial color="red" wireframe />
</mesh>
```

### Q: 클릭이 안 돼요

**A: raycaster 설정**
```tsx
<Canvas
  raycaster={{
    params: {
      Mesh: { threshold: 0.1 },
      Line: { threshold: 0.1 },
      Points: { threshold: 0.1 },
    },
  }}
>
```

### Q: 그림자가 이상해요

**A: 그림자 설정**
```tsx
<Canvas shadows>
  <directionalLight
    castShadow
    shadow-mapSize={[2048, 2048]}
    shadow-camera-far={50}
    shadow-camera-left={-10}
    shadow-camera-right={10}
    shadow-camera-top={10}
    shadow-camera-bottom={-10}
  />

  <mesh receiveShadow castShadow>
    {/* ... */}
  </mesh>
</Canvas>
```

---

## 카메라 제어

```tsx
import { OrbitControls, PerspectiveCamera } from "@react-three/drei";

function Scene() {
  const cameraRef = useRef();

  const flyTo = (position: [number, number, number]) => {
    // GSAP 또는 spring 애니메이션
    gsap.to(cameraRef.current.position, {
      x: position[0],
      y: position[1],
      z: position[2],
      duration: 2,
    });
  };

  return (
    <>
      <PerspectiveCamera ref={cameraRef} makeDefault position={[10, 10, 10]} />
      <OrbitControls
        enableDamping
        dampingFactor={0.05}
        minDistance={5}
        maxDistance={100}
      />
    </>
  );
}
```

---

## 애니메이션

```tsx
import { useFrame } from "@react-three/fiber";

function RotatingBox() {
  const meshRef = useRef<THREE.Mesh>(null);

  useFrame((state, delta) => {
    if (meshRef.current) {
      meshRef.current.rotation.y += delta;
    }
  });

  return (
    <mesh ref={meshRef}>
      <boxGeometry />
      <meshStandardMaterial color="orange" />
    </mesh>
  );
}
```

---

## Context7 참고

Three.js, React Three Fiber 최신 API가 필요하면 Context7로 조회하세요.

Overview

This skill is a Three.js and React Three Fiber (R3F) expert assistant for building, debugging, and optimizing 3D web experiences. It focuses on practical solutions for model loading, scene setup, interactions, performance, and camera control in TypeScript React projects. Use it when you need concrete code patterns, troubleshooting checks, or optimization guidance for production-grade 3D scenes.

How this skill works

I inspect scene structure, model loading patterns (GLTF/FBX), interaction hooks, instancing utilities, and canvas/camera configuration. I recommend concrete code snippets, configuration values, and debugging steps you can drop into an R3F app. I also provide performance strategies such as GPU instancing, LOD, texture compression, frustum culling, and frameloop control.

When to use it

  • Loading GLTF/FBX models, handling onLoad/onClick events, and fixing missing models
  • Implementing hover/select interactions and outline effects with R3F hooks
  • Scaling performance for hundreds+ identical objects using GPU instancing
  • Debugging raycasting, click issues, or incorrect shadow rendering
  • Animating cameras or objects using useFrame, GSAP, or spring-based motion

Best practices

  • Wrap scenes with a shared Canvas component and centralized lighting/grid/stat panels
  • Use GLTFModel/FBXModel components for consistent loading, and validate model paths and scales
  • Use GPU instancing for 100+ identical meshes and prefer createInstances utilities
  • Set Canvas frameloop to 'demand' and disable antialiasing for heavy scenes when acceptable
  • Compress assets (Draco, KTX2) and verify shadow camera extents for proper shadow mapping

Example use cases

  • Add a building GLB with clickable parts that log names and show outlines on hover
  • Spawn thousands of trees via instancedMesh or createInstances for city visualizations
  • Fix non-interactive meshes by tuning Canvas raycaster thresholds and mesh raycast settings
  • Optimize a scene by switching to framed render-on-demand and compressing textures/models
  • Implement 'flyTo' camera transitions using a PerspectiveCamera ref and GSAP animation

FAQ

My model doesn't appear. What quick checks should I run?

Verify the public path, confirm model scale, position the camera near the model, and add a debug box/mesh. Ensure lights are present and the model loaded callback fires.

How do I make clicks and hovers reliable?

Configure Canvas.raycaster thresholds, ensure meshes have raycast enabled, and use interaction hooks that bind pointer events at the GLTFModel level.

When should I use GPU instancing?

Use instancing for many identical objects (typically 100+). It reduces draw calls by batching transforms into instance matrices and leverages GPU memory efficiently.