Three.jsでWebGPUを使う|WebGPURendererへの移行ガイド
みなさんこんにちは。フロントエンドエンジニアのしゅん(@shun_webdesign)です。
前回、TSLとは?WebGPU時代の新しいシェーダーの書き方という記事で「これからはWebGPUの時代だよ」という話をしました。今回はその実践編として、Three.jsのプロジェクトを実際にWebGPUで動かすところを、コードを交えて見ていきます。
「WebGPUって全部書き直しになるんじゃ…」と身構えるかもしれませんが、結論から言うとそんなことはありません。Three.jsを使っていれば、移行は驚くほど小さな差分で済みます。この記事では、最小の変更点・対応確認のやり方・つまずきやすいポイントまで、ひととおりまとめます。
Table of Contents
そもそもWebGPUに移行する意味は?
軽くおさらいです。WebGPUはWebGLの後継で、2026年に主要ブラウザすべてで標準搭載になりました。GPUをより直接的に扱えるので、ざっくりこんなメリットがあります。
- 描画パフォーマンスが上がりやすい(特にオブジェクトが多いシーン)
- コンピュートシェーダーが使える(GPUで大量の計算を回せる。パーティクルや物理表現に強い)
- TSLという新しいシェーダーの書き方が使える(→ [TSLとは?])
これから新しく作るなら、WebGPU前提にしておくと将来的に得をします。
WebGPURendererとは
Three.jsでWebGPUを使う窓口になるのが WebGPURenderer です。これまで使ってきた WebGLRenderer の、WebGPU版だと思ってもらえればOKです。
うれしいのは、WebGPUに対応していない環境では自動的にWebGLにフォールバックしてくれること。つまり「対応ブラウザではWebGPUで、非対応なら従来のWebGLで」描画してくれます。ユーザーの環境を選ばずに出せるので、移行のリスクがかなり下がります。
【実践】小さなシーンを丸ごと移行してみる
言葉だけだとピンと来ないので、箱がくるくる回るだけの最小シーンを、WebGLからWebGPUに移してみましょう。
まず、これまで(WebGL)のコードです。
import * as THREE from "three";
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, innerWidth / innerHeight, 0.1, 100);
camera.position.z = 3;
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
const cube = new THREE.Mesh(
new THREE.BoxGeometry(),
new THREE.MeshNormalMaterial()
);
scene.add(cube);
renderer.setAnimationLoop(() => {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
});
これをWebGPUに移すと、変わるのはたった2行です。
import * as THREE from "three";
import { WebGPURenderer } from "three/webgpu"; // ← 追加
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, innerWidth / innerHeight, 0.1, 100);
camera.position.z = 3;
const renderer = new WebGPURenderer({ antialias: true }); // ← ここだけ変更
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
const cube = new THREE.Mesh(
new THREE.BoxGeometry(),
new THREE.MeshNormalMaterial()
);
scene.add(cube);
renderer.setAnimationLoop(() => {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
});
差分は three/webgpu から WebGPURenderer を読み込む ことと、レンダラーの生成を差し替える ことだけ。Scene・Camera・Mesh・Geometry といった基本の登場人物はまるごとそのまま使えます。世界の作り方は変わらない——ここが「移行が小さく済む」最大の理由です。
async初期化のコツ
ひとつだけ気をつけたいのが、WebGPURendererは初期化が非同期(async)だという点です。
といっても難しくはなくて、上の例のように setAnimationLoop を使えば、中で初期化を待ってから描画を始めてくれます。普段づかいならこれで十分です。
一方、初期化のタイミングを自分で制御したいとき(最初の1フレームを手動で描きたい等)は、await で待ってから描く書き方になります。
const renderer = new WebGPURenderer({ antialias: true });
await renderer.init(); // 初期化を待つ
renderer.render(scene, camera); // ここで初めて手動描画してOK
このあたりの作法はバージョンで少し変わることがあるので、three.js公式のサンプル集(WebGPUのexample)を一度のぞいておくと安心です。
WebGPU対応の確認とフォールバック
前述のとおりWebGPURendererは非対応環境で自動的にWebGLへフォールバックしますが、「今WebGPUで動いているのか、WebGLなのか」を自分で知りたいこともあります。
ざっくり確認するだけなら、ブラウザがWebGPUに対応しているかは navigator.gpu の有無で分かります。
if (navigator.gpu) {
console.log("この環境はWebGPUに対応しています");
} else {
console.log("WebGPU非対応 → WebGLで動きます");
}
逆に「検証のためにあえてWebGLで動かしたい」ときは、レンダラー生成時に forceWebGL を渡せば強制的にWebGLバックエンドになります。
const renderer = new WebGPURenderer({ forceWebGL: true });
このフォールバックの仕組みがあるおかげで、「WebGPUにしたら一部のユーザーで真っ白」みたいな事故を避けやすくなっています。
つまずきやすいポイント3つ
実際に移行するとき、僕がつまずいたポイントを3つ挙げておきます。
1. importのパスを間違えるWebGPURenderer は three 本体ではなく three/webgpu から読み込みます。ここを three から読もうとして「無い」となるのが定番のつまずきです。
2. OrbitControlsなどのアドオンはそのまま使えるOrbitControls やローダー(GLTFLoader 等)といったアドオンは、これまでどおり three/addons/... から読み込んで普通に動きます。ここは安心してOKです。
3. ポストプロセスは「ノードベース」に変わる
ここが一番大きな違いです。WebGLでよく使う EffectComposer +各種Passという書き方ではなく、WebGPUでは ノードベースのポストプロセス(TSLで書くパス)に変わります。ブルームやグリッチなどエフェクトを多用しているプロジェクトは、ここだけ書き換えが必要になると思っておきましょう。
マテリアルとTSLの関係
WebGPURendererは、これまでの MeshStandardMaterial のような標準マテリアルもそのまま扱えます。なので「まず動かす」だけなら、マテリアル周りは気にしなくて大丈夫。
一方で、シェーダーで独自表現をしたくなったら、TSL(Three.js Shading Language) とノードマテリアル(MeshBasicNodeMaterial など)の出番です。WebGPURenderer + TSL の組み合わせが、これからの「自作シェーダー」のスタンダードになっていきます。詳しくは [TSLとは?] にまとめています。
移行の進め方(いきなり全部やらない)
最後に、実プロジェクトを移すときのおすすめの順番を。
- まずレンダラーだけ差し替えて、いつものシーンが表示されるか確認する
- 標準マテリアルのままで見た目が崩れていないかチェック
- ポストプロセスを使っていれば、そこをノードベースに置き換える
- 余裕が出たら、自作シェーダーをTSLに移していく
一気にやろうとすると詰まりやすいので、「動く状態をキープしながら一段ずつ」が安全です。
まとめ
- WebGPUはWebGLの後継。Three.jsは
WebGPURendererで対応済み - 移行の基本は「
three/webgpuから読み込んで、レンダラーを差し替えるだけ」 - Scene / Camera / Mesh はそのまま使える=既存知識がムダにならない
- 非対応環境には自動でWebGLフォールバック。
navigator.gpuで対応確認もできる - 注意は import元・ポストプロセスのノードベース化 の2つ
- 独自表現をするなら TSL + ノードマテリアル へ
「WebGPU移行」と聞くと身構えますが、Three.jsを使っていれば入口はとても小さいです。まずはレンダラーを差し替えて、いつもの箱を回すところから試してみてください。
次は、TSLの土台になる [GLSL入門] や、全体像をつかむ Three.js入門ガイド もあわせてどうぞ。それでは、よいThree.jsライフを🌊