✍️ 필사 모드: Web の 3D 開発 2026 — Three.js・R3F・WebGPU・Gaussian Splatting まで(モダン Web 3D スタック徹底ガイド) (日本語)
日本語プロローグ — WebGL は大人になり、WebGPU は昨日になった
2010 年代後半、Web で 3D をやるということは「WebGL をやる」という意味だった。Three.js がその上に人間が書ける抽象を載せ、私たちはシェーダーを 2 セット(WebGL 用 GLSL・WebGPU 用 WGSL)維持しながら暮らしていた。
2026 年 1 月、その風景が完全に変わった。Safari 26 が macOS Tahoe と iOS で WebGPU を正式に出荷したことで、WebGPU は Baseline になった。 Chrome・Edge・Firefox・Safari いずれもデフォルトで ON、グローバルカバレッジは約 95%。残り 5% は Three.js の自動 fallback が WebGL 2 で処理する。
これは一行で終わる変化ではない。
- Three.js r182(2025 年 12 月リリース)が
WebGPURendererを 推奨レンダラー に格上げ。 - TSL(Three Shading Language) — 一度書いたシェーダーが WGSL と GLSL の両方にコンパイルされる。二重メンテ終了。
- React Three Fiber v9 が async
glprop を受け取り、WebGPU 初期化が自然に組み込める。 - Gaussian Splatting がポリゴンメッシュと並んで — ポリゴンを使わずに — フォトリアルなシーンをリアルタイムに描く新しい表現として定着。
- Meshy・Tripo・Rodin は一行のテキストから PBR テクスチャ付きメッシュを吐く。
本稿は 2026 年の Web 3D スタックを 一息で まとめる。最初のシーンを画面に出すコードから R3F・WebGPU・gsplat・AI 3D まで、そしてその間で「どこでどの道具を使うか」を決めるマトリクスまで。
1 章 · レンダリングパイプライン — 3D はどう描かれるか
まず図を一枚。道具を知る前に、道具が 何をするか から見るべきだ。
[Scene Graph]
| (mesh / light / camera のツリー)
v
[CPU: JS] -- matrix / culling / sorting --+
|
v
[Draw Call]
|
GPU パイプライン ────────────────────────┴──────────────
| |
v v
Vertex Shader -> Rasterizer -> Fragment Shader
(頂点変換) (ピクセルに切る) (ピクセル色)
| |
v v
Z-buffer / Blend / Output
|
v
[Framebuffer]
|
v
\<canvas\>
このパイプラインのどこを誰が担当するかが、そのままスタック選択の基準になる。
- CPU 側 — シーングラフ、変換行列、culling、ソート。ここを最後まで担当するのが Three.js。R3F はその上に React 流の宣言を載せる。
- Draw call — GPU に投げる命令単位。少ないほど速い。 Instancing・merge・atlas はすべてこれを減らすための技術。
- シェーダー(Vertex / Fragment) — GPU で動く小さなプログラム。WebGL は GLSL、WebGPU は WGSL。TSL がこの二つを束ねる。
- 出力合成 — Z-buffer、ブレンド、post-processing。
覚える一行: 「Draw call が半分、シェーダーが残り半分。」
2 章 · Three.js — Web 3D の事実上の標準
数字から。Three.js は npm 週次ダウンロード 270 万で、Babylon.js の約 270 倍、PlayCanvas の約 337 倍。「事実上の標準」ではなく そのまま標準 だ。
最小のシーンを描くコード。必要なものは三つ — scene・camera・renderer — それと中に入る mesh。
import * as THREE from 'three'
// 1. Scene — すべてが入るコンテナ
const scene = new THREE.Scene()
// 2. Camera — どこから見るか
const camera = new THREE.PerspectiveCamera(
75, // fov(視野角、degree)
window.innerWidth / window.innerHeight,
0.1, // near clip
1000 // far clip
)
camera.position.z = 5
// 3. Renderer — 2026 年のデフォルトは WebGPURenderer
import { WebGPURenderer } from 'three/webgpu'
const renderer = new WebGPURenderer({ antialias: true })
await renderer.init() // async init — 必須
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
// 4. Mesh = Geometry + Material
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshStandardMaterial({ color: 0x44aa88 })
const cube = new THREE.Mesh(geometry, material)
scene.add(cube)
// 5. Lights — Standard マテリアルはライトがないと黒く出る
scene.add(new THREE.AmbientLight(0xffffff, 0.4))
const dir = new THREE.DirectionalLight(0xffffff, 1.0)
dir.position.set(5, 10, 7.5)
scene.add(dir)
// 6. Loop — requestAnimationFrame ではなく setAnimationLoop
renderer.setAnimationLoop(() => {
cube.rotation.x += 0.01
cube.rotation.y += 0.01
renderer.render(scene, camera)
})
三点だけ強調する。
await renderer.init()— WebGPU は async。これを忘れると最初のフレームが黒い。MeshStandardMaterialはライトが必須 — 画面が黒ければ、まずライトを疑う。setAnimationLoop—requestAnimationFrameの代わり。WebXR が自動で組み込まれる。
これがすべての Three.js コードの骨格。残りはこの上に積むだけだ。
3 章 · React Three Fiber + drei — React 流の 3D
命令形のコードは小さいうちは綺麗だが、シーンが 50 ノードを超えると一気にスパゲッティになる。React Three Fiber(R3F) は Three.js を React のコンポーネントツリーで表現する。
同じ cube を R3F で書き直すと:
import { Canvas } from '@react-three/fiber'
import { OrbitControls, Environment } from '@react-three/drei'
function Cube() {
return (
<mesh rotation={[0, 0.4, 0]}>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="hotpink" />
</mesh>
)
}
export default function Scene() {
return (
<Canvas camera={{ position: [0, 0, 5], fov: 75 }}>
<ambientLight intensity={0.4} />
<directionalLight position={[5, 10, 7.5]} intensity={1} />
<Cube />
<OrbitControls />
<Environment preset="city" />
</Canvas>
)
}
結果は同じ。ただし:
- シーングラフが React ツリー。条件付きレンダリング・state・hooks がそのまま使える。
<Canvas>がリサイズ・レンダーループ・ピクセル比を勝手に拾う。- drei — Poimandres チームのヘルパーライブラリ。
OrbitControls・Environment・useGLTF・Html・Textといった日常使いの道具が揃う。
R3F v9 の WebGPU — async gl prop
R3F v9 では gl prop を async factory で受け取れる。WebGPU の async 初期化が自然に組み込める。
import { Canvas } from '@react-three/fiber'
import { WebGPURenderer } from 'three/webgpu'
<Canvas
gl={async (props) => {
const renderer = new WebGPURenderer(props)
await renderer.init()
return renderer
}}
>
{/* ...シーン... */}
</Canvas>
2026 年 5 月時点、R3F の WebGPU 統合はまだ完全に滑らかとは言えない — Poimandres チームが積極的に磨いている — が、上のパターンはプロダクションで十分動く。WebGL 2 fallback が必要なら WebGLRenderer を渡せばよい。
useFrame — 毎フレーム hook
R3F で最も React らしい部分。コンポーネントが毎フレーム呼ばれる callback を登録する。
import { useRef } from 'react'
import { useFrame } from '@react-three/fiber'
function Spinner() {
const ref = useRef(null)
useFrame((state, delta) => {
if (ref.current) ref.current.rotation.y += delta
})
return (
<mesh ref={ref}>
<torusKnotGeometry args={[1, 0.3, 128, 32]} />
<meshStandardMaterial color="orange" />
</mesh>
)
}
delta は前フレームからの経過秒数。フレームレートに揺れないアニメーションの起点。
4 章 · WebGPU と TSL — シェーダー二本立てが一本に
WebGL と WebGPU の差を一行: WebGL は OpenGL ES 2.0 の Web 移植、WebGPU は Vulkan・Metal・DX12 世代のモダン GPU API。
実務的に何が変わるか:
- Draw call コストが低い — draw call が多いシーン(パーティクル・大量インスタンス)で 2〜10 倍速くなる。
- Compute shader が一級市民 — GPGPU(パーティクル・物理・シミュレーション・post)がメインパイプライン内で自然。
- WGSL — WebGL の GLSL に代わる新しいシェーダー言語。
最後がいつも頭痛の種だった。WebGL 用の GLSL を、WebGPU 用に WGSL で書き直す必要があった。TSL がそれを終わらせる。
TSL = Three Shading Language. ノードベースのシェーダー抽象。一度書けば Three.js が内部で WGSL(WebGPU 用)と GLSL(WebGL 用)の両方にコンパイル する。
シンプルなノイズシェーダー(マテリアル色を sin で揺らす例):
import { MeshStandardNodeMaterial } from 'three/webgpu'
import { uniform, vec3, mix, sin, time, positionLocal } from 'three/tsl'
const speed = uniform(1.0)
const wave = sin(positionLocal.y.mul(8.0).add(time.mul(speed)))
const color = mix(vec3(0.1, 0.4, 0.9), vec3(1.0, 0.4, 0.2), wave.mul(0.5).add(0.5))
const material = new MeshStandardNodeMaterial()
material.colorNode = color
positionLocal・time・mix・sin すべてノード。JavaScript でシェーダーを組み立てる。GLSL も WGSL も手書きしない。
参考までに小さな WGSL 片(TSL が内部でこんな感じのものを生成する):
@fragment
fn fs_main(@location(0) uv: vec2<f32>) -> @location(0) vec4<f32> {
let c = mix(vec3(0.1, 0.4, 0.9), vec3(1.0, 0.4, 0.2), sin(uv.y * 8.0) * 0.5 + 0.5);
return vec4(c, 1.0);
}
要するに — 2026 年は手書きする機会がほぼない。 TSL が処理する。WGSL は一度読んで literacy をつける程度で十分。
5 章 · glTF — 3D の JPEG
ポリゴンモデルを Web に運ぶ標準は glTF 2.0。「3D の JPEG」と呼ばれる。PBR マテリアル・アニメーション・skinning・Draco 圧縮までワンファイルに収まる。
Three.js の loader:
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
const draco = new DRACOLoader()
draco.setDecoderPath('https://www.gstatic.com/draco/v1/decoders/')
const loader = new GLTFLoader()
loader.setDRACOLoader(draco)
loader.load('/models/robot.glb', (gltf) => {
scene.add(gltf.scene)
// gltf.animations には AnimationClip の配列が入る
})
R3F + drei なら一行:
import { useGLTF } from '@react-three/drei'
function Robot() {
const { scene } = useGLTF('/models/robot.glb')
return <primitive object={scene} />
}
useGLTF.preload('/models/robot.glb')
useGLTF は Suspense に統合され、同じモデルを複数箇所で使っても 1 回しかロードしない。preload でネットワークを先回りできる。
glTF 最適化 — 三つだけ覚える
- Draco 圧縮 — 頂点データを圧縮。ファイルサイズが 5〜10 倍小さくなる。
- KTX2 / Basis テクスチャ — JPG・PNG の代わりに GPU がそのまま食える圧縮テクスチャ。メモリ・ロード時間が節約できる。
gltf-transformCLI — 上二つを一発でやってくれる道具。CI に組み込めば二度と気にしなくていい。
npx @gltf-transform/cli optimize input.glb output.glb \
--texture-compress webp --simplify 0.5
6 章 · アニメーション — クリップから spring まで
3D アニメーションは大きく三系統。
- glTF に入った bone / skin アニメーション — Blender・Maya で作ったものをそのまま再生。
- 数学で動くアニメーション —
useFrameの中で回転・移動・拡縮。 - インタラクション駆動 — hover・drag・scroll に反応。たいてい spring 物理 で。
glTF クリップ再生
import { useAnimations, useGLTF } from '@react-three/drei'
import { useEffect } from 'react'
function Robot() {
const { scene, animations } = useGLTF('/models/robot.glb')
const { actions, names } = useAnimations(animations, scene)
useEffect(() => {
actions[names[0]]?.reset().fadeIn(0.3).play()
}, [actions, names])
return <primitive object={scene} />
}
Spring アニメーション — react-spring/three
import { useSpring, animated } from '@react-spring/three'
function Box({ hovered }) {
const { scale } = useSpring({ scale: hovered ? 1.3 : 1.0 })
return (
<animated.mesh scale={scale}>
<boxGeometry />
<meshStandardMaterial />
</animated.mesh>
)
}
値が跳ねず、物理的に自然に 補間される。ポートフォリオ・ランディングページの微細なディテールでは決定的に効く。
7 章 · ポストプロセッシング — 一手で仕上がりが変わる
同じシーンでも Bloom・SSAO・film grain を一回通すと、映像の次元が変わる。標準ライブラリは postprocessing(Vanruesc 製)、R3F ラッパーは @react-three/postprocessing。
import { EffectComposer, Bloom, DepthOfField, Vignette } from '@react-three/postprocessing'
<Canvas>
{/* ...シーン... */}
<EffectComposer>
<Bloom intensity={1.2} luminanceThreshold={0.6} mipmapBlur />
<DepthOfField focusDistance={0} focalLength={0.02} bokehScale={2} />
<Vignette eskil={false} offset={0.1} darkness={1.0} />
</EffectComposer>
</Canvas>
注意点: ポストプロセッシングは フルスクリーンパス。ピクセルが多いほど重い。モバイルでは常に pixelRatio を cap(普通 1.5〜2.0)し、効果は 2〜3 個までに絞る。
8 章 · パフォーマンス — Draw call が半分を決める
3D Web のパフォーマンスはほぼ常に draw call 数 と シェーダーコスト の二点で決まる。2026 年のコアパターン五つ。
1. Instancing — 同じメッシュ 1 万個を一回で
同じ geometry / material のメッシュを大量に描く必要があるとき(木・草・箱の山)、instancing を使えば draw call が 1 に圧縮できる。
import { Instances, Instance } from '@react-three/drei'
<Instances limit={10000}>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="white" />
{positions.map((p, i) => (
<Instance key={i} position={p} />
))}
</Instances>
WebGPU では instancing のコストがさらに低い。WebGL で 5,000 インスタンスが上限だったなら、WebGPU では 50,000 が現実的。
2. Frustum culling・LOD
Three.js はデフォルトでカメラ視野外のオブジェクトを描かない(frustum culling)。Mesh.frustumCulled はデフォルト true — OFF にしないこと。 LOD(Level of Detail)はカメラ距離に応じてメッシュ解像度を切り替える。
import { Detailed } from '@react-three/drei'
<Detailed distances={[0, 10, 50]}>
<HighPolyMesh />
<MidPolyMesh />
<LowPolyMesh />
</Detailed>
3. マテリアル・ジオメトリ共有
同じマテリアル・ジオメトリはメモリ上に 1 個だけ。R3F ではコンポーネント外で生成して共有する。
4. テクスチャ — KTX2 と mipmap
JPG・PNG は CPU で decode してから GPU にアップロード。KTX2(Basis Universal)は GPU が圧縮されたまま食える。 ロードが速く、VRAM も節約。
5. pixelRatio を cap
Retina で devicePixelRatio = 3 なら画面ピクセルが 9 倍。常に cap する。
<Canvas dpr={[1, 2]}> {/* min 1, max 2 */}
9 章 · WebXR — VR・AR を Web で
setAnimationLoop 一行と WebXRManager のおかげで、Three.js の WebXR はほぼ無料。R3F には @react-three/xr がある。
import { XR, createXRStore, XROrigin } from '@react-three/xr'
const store = createXRStore()
<button onClick={() => store.enterVR()}>VR に入る</button>
<Canvas>
<XR store={store}>
<XROrigin />
{/* ...シーン... */}
</XR>
</Canvas>
WebGPU + WebXR は 2026 年では意外と軽い — Apple Vision Pro・Quest 3・Quest 3S すべて WebGPU 基盤の WebXR を安定して動かす。マーケティング・教育・ヘルスケア領域で急速に採用が広がっている。
10 章 · Three.js vs Babylon.js vs PlayCanvas
エンジン比較を短く。
| 項目 | Three.js | Babylon.js | PlayCanvas |
|---|---|---|---|
| ライセンス | MIT | Apache 2.0 | MIT(エンジン) |
| 強み | 巨大な ecosystem・サンプル・コミュニティ | ゲーム機能が豊富(physics・audio・material editor) | ビジュアルエディタ・cloud IDE |
| 弱み | ゲーム機能は自分で組む | Ecosystem が小さい | Code-first は弱い |
| WebGPU | r182 でデフォルト推奨 | Babylon 7+ で stable | エンジンレベルで対応 |
| 週次 npm DL | ~2.7M | ~10K | ~8K |
| 得意領域 | Portfolio・product・art・viz | ブラウザゲーム・simulation | 広告・ゲーム・configurator |
一行のおすすめ:
- 創作・art・portfolio・product viz → Three.js(+ R3F)。
- ゲーム的なインタラクション・物理重視 → Babylon.js。
- エディタで視覚的に協業したい → PlayCanvas。
Ecosystem の大きさは強い。迷ったら Three.js。
11 章 · Gaussian Splatting — ポリゴンなしのフォトリアル 3D
ここから新しいページだ。
Gaussian Splatting(以下 gsplat) はポリゴンメッシュではない。シーンを 数百万個の小さな 3D ガウシアン点群(各自に位置・色・透明度・方向性を持つ楕円体)で表現する。カメラがその点群を画面に「splat(投影して広げる)」してイメージを作る。
ポリゴンメッシュ: Gaussian Splatting:
┌── 頂点・面データ ┌── 数百万個のガウシアン
├── UV・テクスチャ │ (position・SH 色・scale・rotation・α)
├── normals・materials ├── テクスチャなし
└── ライトでシェーディング └── 撮影時のライティングが焼き込まれる
なぜ興奮するのか?
- フォトリアル — 30 枚〜数百枚の写真 / 動画から学習。出力がほぼ写真と同じ。
- リアルタイム — GPU フレンドリー。Web で 60fps が可能。
- メッシュモデリングがゼロ — Blender も、UV も、テクスチャも、normal も不要。カメラさえあれば成立する。
- NeRF の後継 — NeRF が学術的マイルストーンだったとすれば、gsplat は実務的な道具(学習が速く、リアルタイムレンダー)。
限界もはっきりしている
- ライティングが「焼き込み」 — シーンを動的にライティングするのが難しい。
- 衝突・物理シミュレーションが難しい — メッシュではないから。
- 編集が面倒 — SuperSplat のような専用エディタが必要。
- ファイルが大きい — 数十〜数百 MB。
要するに — 既存の空間をまるごとキャプチャして見せる ことには無敵。不動産・文化財・博物館・コンサート・イベント・展示。
2026 年のツール風景
- Polycam — モバイルキャプチャの市場リーダー。iOS LiDAR + photogrammetry + gsplat。平均 4.7、iOS レビュー 54 万件。最も入りやすい入口。
- Luma AI — クラウド処理で 視覚品質が最高 と評価される無料 gsplat プラットフォーム。Embed 対応。
- SuperSplat — PlayCanvas エンジン上の 無料オープンソースのブラウザ gsplat エディタ。ライブアノテーション・hotspot・post(bloom・vignette)・カメラアニメーション・WebXR まで。HTML viewer 出力で GitHub Pages・Netlify・Vercel にそのままホスト可能。
- NeRF Studio — 研究志向。ローカル学習・実験に強い。
Web に載せる — @mkkellogg/gaussian-splats-3d
Three.js 互換の軽量 gsplat viewer。R3F 環境で:
import { GaussianSplats3D } from '@mkkellogg/gaussian-splats-3d'
import { useThree } from '@react-three/fiber'
import { useEffect } from 'react'
function Splat({ url }) {
const { scene, camera, gl } = useThree()
useEffect(() => {
const viewer = new GaussianSplats3D.Viewer({
threeScene: scene,
camera,
renderer: gl,
selfDrivenMode: false,
})
viewer.addSplatScene(url)
return () => viewer.dispose()
}, [url, scene, camera, gl])
return null
}
ブラウザで数百万のガウシアンを 60fps で描く。5 年前なら SF だった。
12 章 · AI で 3D を作る — Meshy・Tripo・Rodin
最後の一系統。テキストや画像から 3D メッシュを生成する AI。 2026 年ではもう実験ではなく、ワークフローの一部だ。
三強。
- Meshy 6 — 最もバランスの良いプロダクト。Text-to-3D、image-to-3D、PBR テクスチャ、トポロジー制御、幅広いエクスポート。生成 40〜60 秒。「デフォルト推奨。」
- Tripo AI — 最速生成(20〜30 秒)。デフォルトが賢く、初期摩擦が最も低い。テキスト・画像両対応。
- Rodin AI(Gen-2) — 100 億パラメータ。最高品質。 キャラクター・構造化アセットに強い。生成 60〜180 秒。
ワークフロー例:
- コンセプト — Tripo で素早くバリエーション 30 秒。
- 気に入った候補 — Meshy で PBR をきれいに通し直す。
- 最終キャラクター — Rodin Gen-2 で高品質メッシュ。
- glTF にエクスポート して Three.js / R3F のシーンに入れる。
Idea ─▶ Tripo (探索)
└─▶ Meshy (refine、PBR)
└─▶ Rodin (finish、キャラクター)
└─▶ glTF
└─▶ R3F で useGLTF
現実的な注意: AI 生成メッシュはトポロジーが綺麗ではない。ポートフォリオ・viz・ゲームバックグラウンド には十分だが、リギング・アニメーションが重要なキャラクター は通常 Blender で retopo を一度かける必要がある。
13 章 · 「何で何を作るか」 — ユースケースマトリクス
| ユースケース | スタック | 補足 |
|---|---|---|
| 開発者ポートフォリオ | R3F + drei + Bloom | drei の Float / Text を一つまみで十分 |
| プロダクトコンフィギュレータ | R3F + glTF + KTX2 | 色・テクスチャの選択肢はマテリアル差し替え |
| 不動産バーチャルツアー | gsplat(Luma・Polycam)+ SuperSplat | フォトリアル・実空間 |
| 博物館・展示 | gsplat + WebXR | Hotspot・アノテーション |
| ブラウザゲーム | Babylon.js または Three.js + Rapier | 物理・衝突が必要 |
| データ可視化 | R3F + カメラワーク | Instancing をフル活用 |
| AR マーケティング | R3F + @react-three/xr + WebXR | iOS Quick Look も併用 |
| インタラクティブアート | Three.js + TSL(シェーダー自作) | ノードシェーダーで自由度 |
| キャラクター中心のインタラクション | R3F + AI 生成(Rodin)+ Mixamo リターゲット | トポロジー整備を一度 |
| LiDAR キャプチャ資産 | Polycam → glTF or gsplat | スマホのみで完結 |
Rule of thumb:
- 「空間をまるごと見せる」 → gsplat。
- 「操作できる必要がある(色・オプション・物理)」 → ポリゴン(glTF)+ R3F。
- 「小さく作って素早く出す」 → R3F + AI 生成。
14 章 · ポートフォリオサイトを作る — 30 分レシピ
最も多い最初のプロジェクト。骨格を一気に見る。
import { Canvas } from '@react-three/fiber'
import { OrbitControls, Environment, Float, Text3D, useGLTF, ContactShadows } from '@react-three/drei'
import { EffectComposer, Bloom } from '@react-three/postprocessing'
import { Suspense } from 'react'
function Hero() {
const { scene } = useGLTF('/hero.glb')
return <primitive object={scene} scale={1.4} />
}
export default function Portfolio() {
return (
<Canvas camera={{ position: [0, 0, 6], fov: 50 }} dpr={[1, 2]}>
<color attach="background" args={['#0a0a0a']} />
<Suspense fallback={null}>
<Environment preset="studio" />
<Float speed={1.5} rotationIntensity={0.4} floatIntensity={0.8}>
<Hero />
</Float>
<ContactShadows position={[0, -1.6, 0]} opacity={0.6} blur={2.4} />
</Suspense>
<OrbitControls enableZoom={false} />
<EffectComposer>
<Bloom intensity={0.8} mipmapBlur />
</EffectComposer>
</Canvas>
)
}
チェックリスト:
- モデルは Meshy / Tripo で生成するか、Sketchfab の CC0 から取得 →
gltf-transform optimizeを一回。 - 背景は単色 + Environment HDR 一枚(studio / city)。
- Float・ContactShadows・Bloom で「AI 生成っぽさ」を隠す。
dpr={[1, 2]}で retina の暴走を止める。- モバイルでは Bloom を OFF(media query + 条件付きレンダリング)。
エピローグ — Web は本当に 3D になった
2026 年の Web 3D は、もはや「一度見たら終わるデモ」の枠ではない。プロダクトページ、不動産、博物館、広告、学習ツールが日常的に 3D を敷いている。その日常の道具は:
- Three.js + R3F — ポリゴンベースの標準スタック。
- WebGPU + TSL — シェーダー二本立てが一本に。
- Gaussian Splatting — カメラさえあればフォトリアルな空間。
- AI 3D 生成 — テキスト一行でメッシュ。
最後に二つ残す。
14 項目チェックリスト
- WebGPURenderer をデフォルトにし、WebGL 2 fallback を確認したか?
renderer.init()の async 処理を忘れていないか?- glTF が Draco・KTX2 で圧縮されているか?
- Instancing が必要な大量メッシュを普通に描いていないか?
pixelRatioをモバイルで cap したか?- Frustum culling を OFF にしていないか?
- 同じ material / geometry を重複生成していないか?
- ポストプロセッシングの数をモバイルで減らしたか?
- Suspense でローディング UX を整えたか?
- WebXR 進入はユーザージェスチャ(click)内で呼んでいるか?
- gsplat 資産は圧縮フォーマット(SPZ・KSPLAT)でエクスポートしたか?
- AI 生成メッシュのトポロジーを(必要なら)一度整理したか?
setAnimationLoopは一箇所だけ回っているか(重複ループなし)?- 最初のフレームが黒い場合、ライト不足 / init 漏れではないか?
アンチパターン 10
- WebGPU コードで
await renderer.init()を抜かして最初のフレームが黒。 - ライトなしで
MeshStandardMaterialを使い真っ黒。 - 同じモデルインスタンスを毎フレーム再ロード。
frustumCulled = falseを念のため ON にする。- JPG・PNG を圧縮せずそのまま GPU へ。
- デスクトップ・モバイル同じ
dpr設定。 - ポストプロセッシング 5 個をモバイルでも回す。
- AI 生成メッシュをトポロジー整理せずキャラクターリギングに使う。
- gsplat をポリゴンワークフロー(編集・物理)で扱おうとする。
useGLTFの代わりにコンポーネント毎にGLTFLoader.loadを直接呼ぶ。
次回予告
次回候補: WebGPU compute shader 実戦 — GPGPU でパーティクル 100 万、Gaussian Splatting ワークフロー — キャプチャから Web 埋め込みまで、R3F + Rapier 物理エンジン — インタラクティブ 3D ゲームを 1 時間で。
"Web は本当に 3D になった。ポリゴンはメッシュに、写真はガウシアンに、テキストは AI に。その間を繋ぐのは依然 Three.js だ。"
— Web の 3D 開発 2026、終わり。
参考 / References
- Three.js 公式
- Three.js WebGPURenderer マニュアル
- Three.js GitHub リリースノート
- React Three Fiber ドキュメント
- drei ヘルパーライブラリ
- @react-three/postprocessing
- @react-three/xr
- WebGPU W3C 仕様
- WGSL 仕様
- TSL — Three Shading Language フィールドガイド
- Babylon.js 公式
- PlayCanvas 公式
- SuperSplat — gsplat エディタ
- Polycam — モバイル 3D キャプチャ
- Luma AI
- NeRF Studio
- Meshy AI
- Tripo AI
- Rodin AI (Hyper3D)
- gltf-transform — 最適化 CLI
- Mkkellogg gaussian-splats-3d
현재 단락 (1/395)
2010 年代後半、Web で 3D をやるということは「WebGL をやる」という意味だった。Three.js がその上に人間が書ける抽象を載せ、私たちはシェーダーを 2 セット(WebGL 用 G...