[Babylon.js #01] 環境構築とWebGPUの夜明け(Hello World)

1.はじめに(Why WebGPU?)

Three.js(R3F) の対抗馬の1つでもある「Babylon.js」に以前から興味があったので、環境構築とハローワルド的な球体表示までやってみたので、備忘録メモです。

Web界隈も、WebGL(OpenGL)から、WebGPUへ進化しつつあるようなので、それも含めて出来るだけ実装していく予定です。


1. WebGLの限界と、WebGPUの登場

長年、Webブラウザ上の3D表現は WebGL(OpenGL ESベース)が支えてきました。しかし、GPUのハードウェア性能が劇的に進化する中で、WebGLの古い設計思想(ステートマシンモデル)がボトルネックとなり、GPU本来のパワーを引き出しきれない場面が増えてきました。 そこで登場したのが、次世代グラフィックスAPI WebGPU です。


2. WebGPUは何がすごいのか?

WebGPUは、最新のネイティブAPI(Vulkan、Metal、DirectX 12)に近い低レベルな制御を可能にします。主なメリットは以下の2点です。

  • 描画負荷の劇的な低減: CPUとGPUの通信オーバーヘッドが大幅に削減され、数万個のオブジェクトを描画するような高負荷なシーンでもスムーズに動作します。
  • コンピュートシェーダー(Compute Shaders)の解禁: これが最大の革新です。従来の「描画」だけでなく、物理演算やパーティクルシミュレーション、AI処理などの「計算」をGPU上で爆速に行えるようになりました。(今回の連載で扱うMMDの物理演算や、大量のパーティクル表現などでも威力を発揮します)

3. なぜBabylon.jsなのか?

WebGPUを「生」のコード(Raw WebGPU)で書くのは非常に難解で、初期化だけでも大量のコードが必要です。 しかし、Babylon.js は世界で最も早くWebGPUに完全対応したエンジンの一つです。開発者は EngineWebGPUEngine に書き換えるだけで、既存の知識を活かしたままWebGPUのパワーを手に入れることができます。

本連載では、このBabylon.jsを使って、最新のWebGPU環境で「自作の3Dキャラクター(MMD)をブラウザ上で躍らせる」ところまでを一気に駆け抜けます。

2. 環境構築:Vite + TypeScript で始める

まずはプロジェクトの土台を作ります。
2026年現在、フロントエンド開発のデファクトスタンダードである Vite を使用します。爆速のHMR(ホットリロード)は、3D開発の試行錯誤において強力な武器になります。

2-1. プロジェクトの作成

ターミナルを開き、以下のコマンドを実行してプロジェクトを作成します。フレームワークはシンプルに Vanilla、言語は TypeScript を選択します。

# プロジェクト作成(対話形式で進める場合)
npm create vite@latest babylon-webgpu-app

# または、オプション指定で一発作成(推奨)
npm create vite@latest babylon-webgpu-app -- --template vanilla-ts

作成されたディレクトリに移動し、依存関係をインストールしておきます。

cd babylon-webgpu-app
npm install

2-2. Babylon.js パッケージの導入

次に、Babylon.js のコアライブラリをインストールします。 かつては巨大な単一ファイル (babylon.js) を読み込んでいましたが、現在は ES6 Modules 対応のパッケージ (@babylonjs/core) を使うのが標準です。これにより、Tree Shaking(不要なコードの削除)が効き、ビルドサイズを抑えることができます。

npm install @babylonjs/core

さらに、今回のゴールである「MMDモデル(PMX/BPMX)」や、一般的な3Dモデル(glTF/GLB)を読み込むために必要なローダーも追加しておきましょう。

npm install @babylonjs/loaders

Note:

  • @babylonjs/core: エンジン、シーン、メッシュ、ライトなどの基本機能。
  • @babylonjs/loaders: .pmx, .glb, .obj などの外部ファイルを読み込むためのプラグイン集。

2-3. 不要なファイルの削除

Vite が自動生成したサンプルコードは不要なので、掃除しておきます。

  1. style.css の中身を空にする(または削除)。
  2. main.ts の中身をすべて消す。
  3. counter.ts などの不要なファイルがあれば削除。

これで、真っさらなキャンバス(main.ts)に Babylon.js のコードを書く準備が整いました。

3. コード解説 (main.ts):WebGPUの鼓動を聴く

環境が整ったところで、いよいよ main.ts に命を吹き込みます。 WebGPU を使用する場合、従来の WebGL (Engine クラス) とは初期化のプロセスが決定的に異なります。

まずは、最小構成のコード全体像を見てみましょう。

import { WebGPUEngine, Scene, Vector3, FreeCamera, HemisphericLight, MeshBuilder } from "@babylonjs/core";

// WebGPUの初期化は非同期で行う必要があるため、async関数でラップします
async function createScene() {
    // 1. HTMLのCanvas要素を取得
    const canvas = document.getElementById("renderCanvas") as HTMLCanvasElement;

    // 2. WebGPUEngine のインスタンス化
    // 従来の new Engine(canvas) ではなく、WebGPU専用のクラスを使用します
    const engine = new WebGPUEngine(canvas);

    // 3. 非同期初期化(ここが最重要!)
    // WebGLとは異なり、GPUデバイスの確保完了まで待機する必要があります
    await engine.initAsync();

    // --- ここからは通常のBabylon.jsと同じ ---
    const scene = new Scene(engine);

    // カメラ:自由に動き回れるフリーカメラ
    const camera = new FreeCamera("camera1", new Vector3(0, 5, -10), scene);
    camera.setTarget(Vector3.Zero());
    camera.attachControl(canvas, true);

    // ライト:全体を照らす環境光
    const light = new HemisphericLight("light1", new Vector3(0, 1, 0), scene);
    light.intensity = 0.7;

    // メッシュ:基本の球体
    const sphere = MeshBuilder.CreateSphere("sphere", { diameter: 2, segments: 32 }, scene);
    sphere.position.y = 1;

    // 地面
    MeshBuilder.CreateGround("ground", { width: 6, height: 6 }, scene);

    // 4. レンダーグループの開始
    engine.runRenderLoop(() => {
        scene.render();
    });

    // 5. リサイズ処理
    window.addEventListener("resize", () => {
        engine.resize();
    });
}

// 実行
createScene();

3-1. なぜ Engine ではなく WebGPUEngine なのか?

Babylon.js で WebGL を扱う際は Engine クラスを使用しますが、今回はあえて WebGPUEngine を明示的に使用しています。これには明確な理由があります。

  • WebGPU機能へのフルアクセス: Engine クラスでもオプションで WebGPU を有効化できますが、WebGPUEngine を直接使うことで、Compute Shader(計算シェーダー)や高速な描画パイプラインといった、WebGPU固有の強力な機能へアクセスする準備が整います。
  • 未来への投資: 現在はまだ「実験的」な側面もありますが、ブラウザの進化に合わせてこのクラスが標準になっていく未来を見据え、最新のAPIセットに慣れておくことが重要です。

3-2. await engine.initAsync():必須の非同期処理

ここが WebGL 開発者が最もハマりやすいポイントです。 WebGL コンテキストは canvas.getContext('webgl') で同期的に(一瞬で)取得できましたが、WebGPU は違います。

  1. ブラウザが GPU アダプターを探しに行き (requestAdapter)
  2. 見つかったアダプターから論理デバイスを要求する (requestDevice)

このプロセスは物理的なハードウェアとの通信を含むため、非同期(Promise) で行われます。 そのため、new WebGPUEngine(canvas) をしただけでは、まだエンジンの中身は空っぽです。必ず await engine.initAsync() を呼び出し、GPU の準備が完全に整うのを待つ必要があります。この 1行を忘れると、何も描画されずにエラーになります。

4. 動作チェック:Hello World!

コードの準備ができたら、いよいよブラウザで実行してみましょう。 ターミナルで以下のコマンドを入力し、開発サーバーを起動します。

npm run dev

起動後に表示されるURL(例: http://localhost:5173/)にアクセスしてください。 画面中央に、グレーの地面の上に浮かぶ白い球体 が表示されれば成功です! マウスでドラッグすると視点が動き、ホイールで拡大縮小もできるはずです。これが WebGPU でレンダリングされた、記念すべき最初の 3D シーンです。

4-1. 画面が真っ白?トラブルシューティング

もし画面に何も表示されない場合は、焦らず以下のポイントを確認してください。

  • Canvas ID の不一致: HTML (index.html) 内の <canvas> タグの ID と、main.ts で取得している ID が一致しているか確認しましょう。

  • index.html: <canvas id="renderCanvas"></canvas>

  • main.ts: document.getElementById("renderCanvas")

  • CSS の設定漏れ: Canvas のサイズが 0 になっている可能性があります。style.css に以下の記述を追加して、画面いっぱいに広げてください。

html, body, #renderCanvas {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    overflow: hidden; /* スクロールバー消し */
}
  • WebGPU 非対応ブラウザ: お使いのブラウザが古い、または WebGPU が無効化されている可能性があります。
  • Chrome / Edge: 最新版(v113以降)であればデフォルトで有効です。
  • Firefox / Safari: 設定で有効化が必要な場合があります(about:config や開発者メニューなど)。
  • コンソール(F12キー)に Uncaught (in promise) Error: WebGPU is not supported と出ていたら、残念ながらその環境では動きません。

5. まとめ:WebGPU時代の幕開け

今回行ったステップを振り返ってみましょう。

  • モダンなビルド環境: npm create vite で瞬時に立ち上がる、快適な開発ベースを作成。
  • パッケージ管理: @babylonjs/core によるモジュールベースの導入で、軽量かつ管理しやすい構成に。
  • WebGPUの初期化: WebGPUEngineawait initAsync() を使い、次世代グラフィックスAPIへの扉を開きました。

画面に映っているのはただの「白い球体」かもしれませんが、その裏側では従来のWebGLとは全く異なる、最新のGPUパイプラインが動いています。 このシンプルな球体が表示されたということは、「ブラウザがGPUの真の力を引き出す準備ができた」 という証明でもあります。