Communitygithub.com

phido0410/threejs-3d

Three.js、React Three Fiber (R3F)、Drei ヘルパー、Rapier 物理演算、ポストプロセッシングエフェクトを用いた3Dスキル。Web や動画向けの3Dシーン構築に使用します。

threejs-3d とは?

このスキルは、Three.js エコシステムを利用して Web や動画向けの 3D シーンを構築するためのものです。React Three Fiber (R3F)、Drei ヘルパー、Rapier 物理演算、そしてポストプロセッシングエフェクトをサポートし、モデル (GLTF)、ライト、カメラ、環境マップ、物理演算、ブルーム/ビネット/被写界深度などのエフェクトを扱えます。依存関係のバージョン情報 (three 0.186、@react-three/fiber 9.8 など) や React 19 が必要であることが明記されており、開発者は迷わずセットアップできます。また、動画フレームワーク Remotion を使用する場合の注意点(useFrame の代わりに useCurrentFrame を使う、OrbitControls を避けるなど)や、物理シミュレーションをベイクする方法についても詳しく説明されています。このスキールは、Claude Code や Cursor などの AI エージェントが 3D シーンを生成する際のベストプラクティスを提供します。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/phido0410/claude-video-skills/tree/HEAD/skills/threejs-3d

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Three.js 3D スタック

2026-10 時点で確認済み: three 0.186, @react-three/fiber 9.8, @react-three/drei 10.7, @react-three/rapier 2.2, @react-three/postprocessing 3.2 (+ postprocessing 6.39)。Fiber 9 / Drei 10 / Rapier 2 / postprocessing 3 には React 19 が必要です(fiber 9.8 のピア依存: react >=19 <19.4)。

npm i three @react-three/fiber @react-three/drei
npm i @react-three/rapier                         # 物理演算
npm i @react-three/postprocessing postprocessing  # エフェクト
npm i -D @types/three

ベースシーン (Web)

import { useRef, Suspense } from 'react'
import * as THREE from 'three'
import { Canvas, useFrame } from '@react-three/fiber'
import { OrbitControls, Environment, ContactShadows } from '@react-three/drei'

function Box() {
  const ref = useRef<THREE.Mesh>(null!)
  useFrame((_, delta) => { ref.current.rotation.y += delta }) // フレームごとに ref を変更し、setState は絶対に使わない
  return (
    <mesh ref={ref} castShadow>
      <boxGeometry />
      <meshStandardMaterial color="#4a9eff" />
    </mesh>
  )
}

<Canvas camera={{ position: [3, 2, 5], fov: 45 }} dpr={[1, 2]} shadows>
  <ambientLight intensity={0.3} />
  <directionalLight position={[5, 5, 5]} castShadow />
  <Suspense fallback={null}>
    <Box />
    <Environment preset="city" />
  </Suspense>
  <ContactShadows position={[0, -0.5, 0]} opacity={0.5} blur={2} />
  <OrbitControls />
</Canvas>

ルール:

  • 非同期処理 (useGLTF, useTexture, Environment, Text フォント, Physics WASM) はすべて <Suspense> の下に配置します。
  • 初回描画で使用するモデルは、モジュールレベルで useGLTF.preload(url) を呼び出します。
  • シーンのサイズは 1〜10 単位に保ちます。極端に大きい/小さいスケールはシャドウやコントロールを破壊します。
  • MeshStandardMaterial にはライトか <Environment> が必要です。どちらもないと黒く表示されます。

Drei (必要なものだけを選択)

  • カメラ/コントロール: OrbitControls, CameraControls, PerspectiveCamera makeDefault
  • アセット: useGLTF, useTexture, Environment (プリセット: apartment, city, dawn, forest, lobby, night, park, studio, sunset, warehouse), Center, Bounds
  • ステージング: ContactShadows, AccumulativeShadows, Stage, Float, Sparkles, Stars, Cloud
  • マテリアル: MeshTransmissionMaterial (ガラス), MeshReflectorMaterial (反射する床)
  • テキスト: Text (SDF、任意のフォント URL), Text3D (タイプフェース JSON が必要), Html (DOM オーバーレイ)

Rapier 物理演算

import { Physics, RigidBody, CuboidCollider, type RapierRigidBody } from '@react-three/rapier'

<Suspense>
  <Physics gravity={[0, -9.81, 0]} /* debug */>
    <RigidBody colliders="hull" restitution={0.6} ref={bodyRef}>
      <mesh><torusGeometry /><meshStandardMaterial /></mesh>
    </RigidBody>
    <RigidBody type="fixed">
      <CuboidCollider args={[10, 0.1, 10]} /> {/* 半サイズ */}
    </RigidBody>
  </Physics>
</Suspense>
// bodyRef.current?.applyImpulse({ x: 0, y: 5, z: 0 }, true)
  • colliders: "cuboid" (デフォルト), "ball", "hull", "trimesh", false (自分でコライダーコンポーネントを追加)。
  • type: "dynamic" (デフォルト), "fixed", "kinematicPosition", "kinematicVelocity"。
  • timeStep はデフォルトで固定 1/60 です。timeStep="vary" は非決定的です。手動ステップ: useRapier().step(1 / 60)。
  • <Physics> に debug を付けるとコライダーが描画されます。

ポストプロセッシング

import { EffectComposer, Bloom, Vignette, DepthOfField, Noise } from '@react-three/postprocessing'

<EffectComposer>{/* <Canvas> の最後の子要素 */}
  <Bloom luminanceThreshold={0.9} intensity={1.2} mipmapBlur />
  <Vignette offset={0.1} darkness={0.9} />
</EffectComposer>
  • Bloom は luminanceThreshold 以上のピクセルだけをエフェクト対象とします。1 つのオブジェクトを光らせるには: マテリアルに emissive カラー + emissiveIntensity > 1 + toneMapped={false} を設定します。
  • 各エフェクトはフルスクリーンパスを消費します。2〜4 エフェクトで十分です。

動画向け

Remotion (remotion-markup/3d.md を参照): @remotion/three から <ThreeCanvas width height> を使用します。useFrame は使わず、すべてのモーションは useCurrentFrame() から駆動します。さらに:

  • OrbitControls は使用しません。カメラは frame から移動させます (interpolate / spring)。
  • 独自のクロックでアニメーションする Drei ヘルパー (Float, Sparkles, Stars, Cloud, MeshWobbleMaterial) はレンダリング時にちらつきます。これらは使用しないか、モーションを frame から再現します。
  • 物理演算: Remotion はタブ間でフレームを順不同でレンダリングするため、ライブシミュレーションは一致しません。ベイクしてください: @dimforge/rapier3d-compat ( @react-three/rapier の基盤エンジン) を一度初期化し、各フレームに対して world.step() を timestep = 1 / fps で実行し、各ボディの位置と回転をフレームごとに保存します。その後、インデックス frame の変換をレンダリングします。

Remotion 以外 (画面録画、GSAP 駆動) の場合: useFrame は問題ありません。ただし、ショットを繰り返し可能にする必要がある場合は、delta の代わりにタイムライン (tl.time()) から時間を駆動します。

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

関連スキル