drei とアセット
@react-three/drei は R3F 公式の「便利コンポーネント詰め合わせ」。 カメラ操作・環境光・GLTF・テキスト・shader・物理シャドウまで、よくある定石が宣言的に揃っている。 R3F を使うなら drei も入れるがデフォルトでいい。
導入
npm install @react-three/drei
全 import すると巨大バンドルになる。必ず named import で必要なものだけ:
import { OrbitControls, Environment, useGLTF } from "@react-three/drei"
カメラ・コントロール
<OrbitControls />
マウスでぐるぐる回せる定番カメラ。これを置くだけで使える。
import { OrbitControls } from "@react-three/drei"
<Canvas>
<OrbitControls
enableDamping
dampingFactor={0.1}
enablePan={false}
enableZoom
minDistance={2}
maxDistance={20}
minPolarAngle={0}
maxPolarAngle={Math.PI / 2} {/* 地面より下に潜らない */}
minAzimuthAngle={-Infinity}
maxAzimuthAngle={Infinity}
autoRotate
autoRotateSpeed={1}
target={[0, 0, 0]}
/>
...
</Canvas>
その他のコントロール
| コンポーネント | 用途 |
|---|---|
<PointerLockControls /> | FPS 風(マウスをロックして視点回転) |
<FlyControls /> | 飛行 |
<FirstPersonControls /> | 地表を歩く視点 |
<TrackballControls /> | 制限なしのトラックボール |
<CameraControls /> | シネマティック(drei 製、API がリッチ) |
<PresentationControls /> | 商品紹介向けの「見せる」回転 |
<TransformControls /> | Blender 風ガイザー(移動/回転/スケール) |
<DragControls /> | オブジェクトをドラッグ |
<MapControls /> | Google Maps 風の操作(パン優先) |
カメラコンポーネント
<PerspectiveCamera makeDefault position={[3,2,5]} fov={50} /><OrthographicCamera makeDefault zoom={50} /><CubeCamera />— 反射用 6面カメラ<PerspectiveCamera makeDefault>内で children を入れるとカメラに追従する HUD が作れる
環境光・空・背景
<Environment />
HDR 画像で環境光(IBL)を作る。Standard / Physical Material が一気にリアルになる。
import { Environment } from "@react-three/drei"
<Environment preset="city" />
<Environment preset="sunset" background /> {/* 背景にも反映 */}
<Environment files="/hdr/studio.hdr" background /> {/* 自前 HDR */}
<Environment files={["px","nx","py","ny","pz","nz"]} path="/cubemap/" /> {/* CubeMap */}
プリセット: apartment / city / dawn / forest /
lobby / night / park / studio / sunset / warehouse。
環境光を JSX で組む(Lightformer)
既製プリセットでは足りない時、ライトを並べた仮想空間を IBL 化できる:
import { Environment, Lightformer } from "@react-three/drei"
<Environment background={false} resolution={256}>
<Lightformer position={[5, 5, 5]} scale={[2, 2, 1]} intensity={1} />
<Lightformer position={[-5, 0, 0]} scale={3} color="#9bd1ff" intensity={0.5} />
</Environment>
空
<Sky />— 大気散乱モデルの空<Stars />— 星空<Cloud />/<Clouds />— ボリューメトリック雲<Sparkles />— キラキラ
影
<ContactShadows />— 床に落ちる柔らかい接地影(軽い)<AccumulativeShadows />+<RandomizedLight />— 高品質ベイク影。静的シーン用<BakeShadows />— シャドウマップを1回計算して固定
商品スタジオの定番: <Stage />
ライト + 環境光 + 接地影 + カメラ調整を全部入りで提供。プロトタイプ最強。
import { Stage } from "@react-three/drei"
<Canvas shadows>
<Stage environment="city" intensity={0.5} adjustCamera shadows="contact">
<MyModel />
</Stage>
</Canvas>
アセット読み込み
useGLTF
import { useGLTF } from "@react-three/drei"
function Model() {
const { scene, nodes, materials, animations } = useGLTF("/robot.glb")
return <primitive object={scene} />
}
useGLTF.preload("/robot.glb")
DRACO や KTX2 もサポート:
// 内部で DRACOLoader / KTX2Loader を自動セットアップ
const gltf = useGLTF("/compressed.glb")
gltfjsx に GLB をドロップすると、JSX のコードが生成される。
コマンドラインなら npx gltfjsx model.glb -t(TS 出力)。生成された JSX を貼って細部を調整するのが圧倒的に楽。
useTexture
import { useTexture } from "@react-three/drei"
// 配列で複数読み込み
const [map, normal, rough] = useTexture([
"/wall_color.jpg", "/wall_normal.jpg", "/wall_rough.jpg",
])
// オブジェクトでマップ名を直接渡す
const props = useTexture({
map: "/wall_color.jpg",
normalMap: "/wall_normal.jpg",
roughnessMap: "/wall_rough.jpg",
aoMap: "/wall_ao.jpg",
})
<meshStandardMaterial {...props} />
その他のローダー
useFBX(path)— Autodesk FBXuseVideoTexture(src)— 動画テクスチャuseCubeTexture(files, opts)— CubeMapuseEnvironment(opts)— HDR を動的にuseAnimations(animations, ref)— AnimationMixer 管理
テキスト・3D テキスト
<Text />
SDF(signed distance field)方式の高品質 3D テキスト。
import { Text } from "@react-three/drei"
<Text
fontSize={1}
color="#7dd3fc"
anchorX="center"
anchorY="middle"
font="/fonts/Inter-Bold.ttf" {/* 任意のフォント */}
outlineWidth={0.02}
outlineColor="#000"
maxWidth={5}
textAlign="center"
>
Hello R3F
</Text>
<Text3D />
押し出しのある立体テキスト。font プロパティに JSON フォントを渡す。
import { Text3D, Center } from "@react-three/drei"
<Center>
<Text3D font="/fonts/helvetiker_regular.typeface.json" size={1} height={0.2}>
Hello
<meshStandardMaterial color="#fbbf24" />
</Text3D>
</Center>
HTML を 3D に置く: <Html />
DOM のボタンやツールチップを 3D 空間に portal する。 詳しくは インタラクション参照。
マテリアル系
<MeshTransmissionMaterial />— ガラス。屈折・厚みを表現<MeshReflectorMaterial />— 鏡面床。実時間反射<MeshDistortMaterial />— 表面が歪むエフェクト<MeshWobbleMaterial />— ぐにゃぐにゃ動く<MeshDiscardMaterial />— 透明扱い(オクルージョン用)shaderMaterial(uniforms, vertex, fragment)— 自作 GLSL を簡単に
import { MeshTransmissionMaterial } from "@react-three/drei"
<mesh>
<sphereGeometry args={[1, 64, 64]} />
<MeshTransmissionMaterial
transmission={1}
thickness={0.5}
roughness={0}
ior={1.5}
chromaticAberration={0.05}
distortion={0.1}
/>
</mesh>
鏡面床
import { MeshReflectorMaterial } from "@react-three/drei"
<mesh rotation-x={-Math.PI / 2}>
<planeGeometry args={[20, 20]} />
<MeshReflectorMaterial
blur={[300, 100]}
resolution={1024}
mixBlur={1}
mixStrength={2}
color="#101010"
/>
</mesh>
レイアウト系
| コンポーネント | 用途 |
|---|---|
<Center /> | 子要素のバウンディングから中央寄せ |
<Bounds /> | 子全体が画面に収まるようカメラを自動調整 |
<Resize /> | 子要素を一定サイズに正規化 |
<Float /> | ふわふわ浮遊 |
<Backdrop /> | 無限の壁・床(写真背景の白ホリゾント) |
<ScrollControls /> + <Scroll /> | スクロールに連動 |
<Bounds /> の例
import { Bounds } from "@react-three/drei"
<Bounds fit clip observe margin={1.2}>
<MyModel />
</Bounds>
パフォーマンス・最適化系
| コンポーネント | 用途 |
|---|---|
<Detailed /> | LOD(距離で別モデルに切替) |
<Instances /> + <Instance /> | InstancedMesh の宣言的ラッパ |
<Merged /> | 静的メッシュを 1 つに合体(draw call 削減) |
<Preload all /> | シーン全体を GPU に転送して初回フリーズを防ぐ |
<BakeShadows /> | シャドウを 1 回だけ計算 |
<AdaptiveDpr /> | FPS 低下時に DPR を下げる |
<AdaptiveEvents /> | FPS 低下時にイベントを止める |
<PerformanceMonitor /> | FPS を監視してコールバック |
<Instances /> の例
import { Instances, Instance } from "@react-three/drei"
<Instances limit={1000} range={1000}>
<coneGeometry args={[0.5, 1.5, 8]} />
<meshStandardMaterial color="#22c55e" />
{trees.map((t, i) => (
<Instance key={i} position={t.pos} rotation={t.rot} scale={t.scale} color={t.color} />
))}
</Instances>
3D UI コンポーネント
<Hud />— 別シーンを上に重ねる(HUD レイヤ)<Image />— 画像を 3D の板として表示<RoundedBox />— 角丸ボックス<Decal />— デカール(曲面に貼るシール)<Outlines />— メッシュにアウトラインを付ける<Edges />— エッジ表示<Gltf />— GLTF をそのまま JSX として読み込み
デバッグ系
<Stats />— FPS / メモリ表示(左上)<Grid />— 床のグリッド<Helper />/useHelper— Three.js ヘルパーを宣言的に<Loader />— 全体のロード進捗 UI(Canvas の外)<TransformControls />— 編集ガイザー- leva(外部)— リアルタイム調整 UI
leva でデバッグ UI
npm install leva
import { useControls } from "leva"
function DebugBox() {
const { color, scale, rotate } = useControls({
color: "#7dd3fc",
scale: { value: 1, min: 0.1, max: 3, step: 0.01 },
rotate: false,
})
const ref = useRef<THREE.Mesh>(null!)
useFrame((_, dt) => { if (rotate) ref.current.rotation.y += dt })
return (
<mesh ref={ref} scale={scale}>
<boxGeometry />
<meshStandardMaterial color={color} />
</mesh>
)
}
キーボード入力
<KeyboardControls /> + useKeyboardControls。
インタラクション参照。
postprocessing(@react-three/postprocessing)
ポストエフェクト(Bloom / DoF / Vignette / Outline 等)は別パッケージ。 詳細は シェーダ・ポストプロセス。
VR / AR — @react-three/xr
WebXR でヘッドセット・ハンドトラッキングに対応。drei とは別パッケージ。
import { XR, createXRStore, XROrigin } from "@react-three/xr"
const store = createXRStore()
<button onClick={() => store.enterVR()}>VR 開始</button>
<Canvas>
<XR store={store}>
<XROrigin>
<Scene />
</XROrigin>
</XR>
</Canvas>
drei はトップレベル import すると大きい。
ツリーシェイク済みでも数百 KB。named import で必要なものだけ使うのが基本。
バンドル分析(vite-bundle-visualizer 等)で時々確認すると吉。