threejs について
Three.jsで3Dウェブ体験を構築する開発者向けのスキルです。WebGPU、シェーダー、React Three Fiberに加え、アセット管理やアニメーション、描画性能の最適化を扱います。
主な機能
- 01WebGPUレンダラーの設定
- 02TSLシェーダーの作成
- 03React Three Fiberのパターン
- 043Dアセットの圧縮と読み込み
- 05シーンの性能最適化
- 06アニメーションとライティングの指針
活用シーン
- 01WebGPU描画の設定
- 02React Three Fiberでのシーン構成
- 03GLTFアセットの読み込みと最適化
- 043Dアニメーションと照明の実装
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ oakoss/ agent-skills --skill threejsインストール後、Claude Code で/threejsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/animation.mdperformance.mdr3f-patterns.mdscene-and-lighting.mdwebgpu-tsl.md詳細
Three.js
概要
Three.js、WebGPU を優先したレンダリング、TSL(Three Shader Language)、React Three Fiber を使用した高性能な 3D ウェブ体験の構築方法を説明します。シーンアーキテクチャ、アセット圧縮、ドローコールの予算管理、React 19/Next.js との統合パターンを扱います。
使用する場面: 3D シーンの作成、WebGPU レンダリングのセットアップ、TSL シェーダーの作成、アセットの最適化(Draco/KTX2)、React Three Fiber のコンポジション、3D コンテンツ向けの Next.js ストリーミング、GLTF モデルの読み込み、ライティングとシャドウの設定、アニメーションの再生とブレンディング。
使用しない場面: 2D キャンバスアニメーション(Canvas API を使用)、単純な SVG グラフィックス、クライアントのハイドレーションを行わないサーバーサイドレンダリング、2022 年以前のハードウェアのみを対象とするプロジェクト。
クイックリファレンス
| パターン | API/アプローチ | 主なポイント |
|---|---|---|
| WebGPU レンダラー | import * as THREE from 'three/webgpu' | 初回のレンダリング前に await renderer.init() を実行する必要があります |
| R3F キャンバス | <Canvas gl={...}> と Suspense | ストリーミングをサポートするには <Suspense> で囲みます |
| フレーム更新 | useFrame((state, delta) => ...) | ref を直接変更し、setState は使用しません |
| TSL シェーダー | import { ... } from 'three/tsl' | ノードベースで、WGSL または GLSL にコンパイルされます |
| インスタンシング | 行列を更新する <instancedMesh> | 繰り返し使用するジオメトリを単一のドローコールで描画します |
| バッチメッシュ | BatchedMesh (r156+) | 異なるジオメトリでマテリアルを共有します |
| Draco 圧縮 | gltf-pipeline -i in.gltf -o out.glb -d | ジオメトリのサイズを最大 90% 削減します |
| KTX2 テクスチャ | toktx を使用した Basis Universal | VRAM 内でも圧縮状態を維持します |
| LOD | 距離しきい値を指定した THREE.LOD | カメラからの距離に応じて詳細レベルを切り替えます |
| オンデマンドレンダリング | <Canvas frameloop="demand"> | シーンの状態が変化したときのみレンダリングします |
| クリーンアップ | アンマウント時に .dispose() を呼び出します | ジオメトリ、マテリアル、テクスチャ |
| コンピュートシェーダー | Fn(() => {...})().compute(count) | GPU 側での物理演算、パーティクル、群れのシミュレーション |
| ライティング | DirectionalLight、SpotLight、HemisphereLight | レンダラーで shadowMap を有効にし、ライトで castShadow を設定します |
| GLTF の読み込み | GLTFLoader + DRACOLoader | ジオメトリ圧縮には Draco を使用し、シャドウにはシーンを走査します |
| アニメーション | AnimationMixer + clipAction() | 毎フレーム clock.getDelta() で更新します |
| クロスフェード | action.fadeOut() / action.fadeIn() | 歩行/走行/待機アニメーションを重み付けしてブレンドします |
| 環境マップ | RGBELoader + PMREMGenerator | PBR 反射を利用するには scene.environment を設定します |
| レイキャスティング | Raycaster.setFromCamera(pointer, cam) | マウス/タッチでオブジェクトを選択できます。GLTF では recursive: true を使用します |
| モーフターゲット | mesh.morphTargetInfluences[index] | 顔のアニメーション、GLTF のブレンドシェイプ |
よくある間違い
| 間違い | 正しいパターン |
|---|---|
useFrame 内で new THREE.Vector3() または new THREE.Color() を割り当てる | 毎フレームの GC 負荷を避けるため、ループの外で事前に確保します |
React プロジェクトで requestAnimationFrame を手動で使用する | フレームごとの更新には R3F の useFrame フックを使用します |
WebGPU 用の renderer.init() を await しない | 競合状態を避けるため、最初のレンダリングの前に必ず await renderer.init() を実行します |
<Suspense> 境界なしでアセットを読み込む | メインスレッドのブロックを防ぐため、<Canvas> を <Suspense> で囲みます |
| 背景や遠くの要素にハイポリモデルを使用する | 描画呼び出しを減らすため、LOD(詳細度)またはインポスターを使用します |
アニメーションのレンダーループ内で setState を使用する | フレームごとの更新には useFrame 経由で ref を直接変更します |
速度がフレームレートに依存している(rotation += 0.01) | フレームレートに依存しない動きにするため、delta を乗算します |
mixer.update() に clock.getDelta() を使用しない | 正しいアニメーション速度にするため、必ず mixer.update(delta) にデルタ時間を渡します |
| 読み込んだ GLTF モデルの破棄を忘れる | 削除時にジオメトリ、マテリアル、テクスチャをトラバースして破棄します |
| レンダラーではシャドウマップを有効にしているが、ライトでは有効にしていない | renderer.shadowMap.enabled と light.castShadow = true の両方を設定します |
カメラの far/near 比が大きい | Z ファイティングを避けるため比率を小さく保ち、near を可能な限り大きく設定します |
委任
- アセットとシーングラフの調査:
Exploreエージェントを使用します - 複数ファイルにわたるシーンのリファクタリングと最適化:
Taskエージェントを使用します - 3D アーキテクチャとレンダリングパイプラインの計画:
Planエージェントを使用します
参考資料
コメント
Markdown 対応