canvas から WebGPU へ:ブラウザがゲームプラットフォームになるまで
Flash が終わったとき、ブラウザゲームに代わりのプラグインは必要ありませんでした。ブラウザそのものが、少しずつプラグインになっていたからです。15年ほどのあいだに、ひと握りのオープンな API が、文書を表示するためのソフトをゲームをリリースできる場所へと変えました。
この記事では、それらの API を登場した順にたどり、ゲームを作る人にとって何が変わったのかを見ていきます。(それ以前のプラグインの時代については、Flash ゲームとポータルの時代をどうぞ)
ざっくり年表
- 2004Apple が WebKit に canvas 要素を追加。最初は Dashboard ウィジェットと Safari のためでした。ほかのブラウザも続き、HTML5 の一部になります。
- 2010Mozilla が requestAnimationFrame を提案。タイマーで当て推量するのではなく、ディスプレイに合わせて描画する方法です。
- 2011Khronos が WebGL 1.0 をリリースし、OpenGL ES 2.0 風の GPU 描画がページにやってきます。
- 2013Mozilla が asm.js を発表。Epic と Mozilla が、プラグインなしで Firefox 上で動く Unreal Engine 3 を披露。
- 2014W3C が HTML5 を勧告として公開。
- 2017WebAssembly が主要ブラウザすべてで利用可能に。OpenGL ES 3.0 ベースの WebGL 2 が Chrome と Firefox に搭載。
- 2021Safari 15 が WebGL 2 に対応し、ようやく主要ブラウザすべてで動くように。
- 2023Chrome 113 が、ウェブのために設計されたモダンな GPU API である WebGPU を搭載。
出典:Canvas element、MDN の requestAnimationFrame、WebGL、asm.js、HTML5、WebAssembly、WebGPU。
canvas:描く場所ができた
canvas 以前、素の HTML での「ゲーム」といえば、<div> や画像をページ上で動かすことでした。カードゲームならそれで足りましたが、それ以上はほとんど無理でした。canvas はページに、JavaScript で描き込めるビットマップを与えました。矩形、画像、テキストを、毎フレーム描き直すのです。
2D ゲームは今もこのモデルを使っています。Canvas 2D は今でも一番安全なフォールバックでもあります。どのブラウザ、どのデバイスでも動くので、debuff は WebGL2 のレンダラーの後ろに Canvas 2D のレンダラーを控えさせています。
requestAnimationFrame:時間どおりに描く
初期の canvas ゲームは setInterval でループを回し、16 ms のような数字を選んで祈っていました。タイマーはずれるし、裏のタブでも動き続けるし、画面が実際にいつ更新されるかも知りません。requestAnimationFrame は、次の再描画の直前に呼んでくれるよう、そしてタブが隠れたら止まるようにブラウザに頼む仕組みです。
小さな話に聞こえます。でも、ブラウザゲームがそもそも滑らかに感じられるのはこのおかげで、フレームのペースを今も測る価値があるのもこのためです。それが Myaku の仕事です。
WebGL:GPU がやってきた
Canvas 2D の描画はほとんどブラウザ任せで、何千ものスプライトを詰め込むと遅くなります。WebGL は、シェーダーと頂点バッファを通じて JavaScript から GPU を直接使えるようにしました。突然、ブラウザで何万ものスプライトを描き、ポストプロセスをかけ、3D を描画できるようになったのです。
そのまわりにライブラリが育ちました。PixiJS と Phaser はどちらも2013年に登場し、シェーダーを手書きしなくても 2D ゲームで WebGL を実用的に使えるようにしました(PixiJS、Phaser)。のちに WebGL 2 でインスタンシングや多くのテクスチャフォーマットが標準になりましたが、Safari の対応は2021年までかかったので、多くのエンジンは何年も WebGL 1 の経路を残していました。
サウンドと入力
ゲームにはピクセル以外も必要です。<audio> 要素は音楽プレイヤー向けに作られていて、効果音にはタイミングが甘すぎました。Web Audio API は、ゲームに精密なスケジューリングができるまともなミキシンググラフを与えました(MDN)。Gamepad API でページからコントローラーを読めるようになり(MDN)、Pointer Events API はマウス、ペン、タッチをひとつにまとめました。
この時代のクセがひとつ、今も残っています。プレイヤーがページを操作するまで、ブラウザは音を鳴らしてくれません。だから Web ゲームの多くが「クリックしてプレイ」から始まるのです。
asm.js と WebAssembly:ほかの言語がやってくる
2013年、Mozilla は JavaScript の厳格なサブセットである asm.js に C や C++ からコンパイルでき、ネイティブに近い速度で動くことを示しました。人々の目を引いたのは、Firefox で動く Unreal Engine 3 のデモでした(出典)。
WebAssembly はそのアイデアをきちんとしたバイナリ形式にし、2017年に主要ブラウザすべてで使えるようになりました。Unity や Godot といったエンジンはこれを通じてウェブに書き出しますし、Flash ゲームを遊べる状態に保っているエミュレータの Ruffle もそうです。トレードオフはサイズです。WebAssembly にコンパイルされた大きなエンジンは、ゲーム本体を入れる前から数十メガバイトあることも多いです。すぐ遊べることを重視するなら、これは大問題です。
WebGPU:次の GPU API
WebGL は、今日の GPU よりずっと前に設計された API である OpenGL ES がベースです。WebGPU は Vulkan、Metal、Direct3D 12 といったモダンなネイティブ API を前提に設計され、コンピュートシェーダーも加わりました。Chrome が2023年に搭載し、ほかのブラウザも追いかけています(出典)。
ほとんどの 2D ゲームには今も WebGL2 で十分で、しかもほぼどこでも動きます。WebGPU が一番効いてくるのは、少なくとも今のところ、重い 3D と GPU コンピュートです。
合わせると何になるか
これらの API はどれも、プラグインやインストールが必要な理由をひとつずつ取り除いてきました。
- 描画には canvas と WebGL。
- 滑らかなタイミングには requestAnimationFrame。
- サウンドと入力には Web Audio、Gamepad、Pointer Events。
- ほかの言語で書かれたコードには WebAssembly。
その結果が、リンクから開けて、ほぼすべてのスマホとコンピュータで動くプラットフォームです。タダでは手に入らないのが、小さなダウンロードサイズです。そこは今もエンジン次第です。
debuff の立ち位置
debuff は、このスタックの中で最も広く対応している層を狙っています。WebGL2 と Canvas 2D フォールバック、素の TypeScript、ダウンロードすべき WebAssembly のランタイムはなし。スターターゲームは brotli で約 19 kB で出荷されます。その上に、プラットフォームが与えてくれないものを足しています。決定的なテスト、リプレイ、ライブ調整できるパラメータ、そして一緒にゲームを遊んでくれるコーディングエージェントです。
npm create debuff@latest my-game歴史の話をもっと読むなら:Flash ゲームとポータルの時代とゲームジャムと小さなゲーム。