noah.plus

WebAssemblyでDOMの物理シミュレーション(Google Codelabs)

2018-08-12

Google Developers Codelabsにあるチュートリアルの1つを触ってみた。

WebAssembly Physics and DOM objects (2018)

このチュートリアルでは砂時計を作成する。物理シミュレーションの部分をWebAssembly(wasm)で行うことで、とても高いパフォーマンスを実現している。

砂時計には全部で738個の砂粒がDOM要素として生成されているが、一粒一粒がちゃんと滑らかに動いている。

completed

実際に動作するものは下記のURLから。

hourglass.svg

基本的にはチュートリアル通りに進めていけば間違いない。コードの雛形や砂時計のSVG画像はあらかじめ用意されているので、穴埋め形式で作成してく。

ちなみにこのチュートリアルは30分で終わると記載されていたが、全然そんなことはなかった。心を無にしてひたすらコピペすれば時間内で終わるかも。

以下ハイライト。

SVG画像のセットアップ

これが砂時計の初期状態。

hourglass

砂粒が砂時計からはみ出ないように枠を定義する。(赤線部分)

hourglass_container

emscriptenでwasmモジュールを生成する

物理エンジンにはC言語のライブラリであるChipmunk2Dを利用する。

当然、Chipmunk2Dはそのままだとブラウザ上で動かすことができないので、コンパイルツールチェーンの1つであるemscriptenでwasmに変換する必要がある。

$ git clone https://github.com/juj/emsdk.git
$ cd emsdk
$ ./emsdk install latest
$ ./emsdk activate latest

emscriptenのインストールと有効化。ダウンロードに15分くらいかかった。(ここで目安時間の半分消費)

$ source ~/emsdk/emsdk_env.sh

有効化できたら環境変数を設定する。パスは自分の環境に適宜合わせる。

emscriptenを使えるようにしたら、そのまま作業用のディレクトリ(work)まで移動。

チュートリアルに沿って、コードを入力したらmakeコマンドでwasmファイルを生成できる。

$ make

generated_files

その結果、chipmunk.wasmchipmunk.jsという2つファイルが新たに生成される。

chipmunk.wasmは物理計算を行うChipmunk2DをWasmモジュールにコンパイルしたもの。chipmunk.jsはemscriptenが生成したグルーコードで、ブラウザとwasmモジュールの橋渡しをする。

<script xlink:href="chipmunk.js"></script>
<script><![CDATA[
    var wasm_loaded = false;
    var cm_instance;

    Module.onRuntimeInitialized = function() {
        wasm_loaded = true;
        cm_instance = Module._CM_Instance_new();
    }

]]></script>

このチュートリアルでは便宜的にSVGファイルのなかに直接スクリプトを書いている。

まずchipmunk.js経由でwasmモジュールを読み込み、そのあとModule.onRuntimeInitializedを使って処理を実行している。ちなみに Module.onRuntimeInitializedに指定された関数は、wasmモジュールの読み込みが完了してはじめて呼び出される。

まとめ

大量のDOMをこの程度の負荷で操作できるのは純粋にすごい。

今回のチュートリアルでChipmunk2Dというライブラリを使ったように、WebAssemblyを使えばC言語で書かれた多種多様なライブラリを活用できる。今後より一層、ブラウザ上で実現できることが増えていくのは間違いない。

個人的にはRustでWebAssemblyを使ってみたいので、先日オライリーから発売されたプログラミングRustを「読みたい本」リストに追加した。

2年後くらいにはWebAssemblyができて当たり前とかなってそうなので、これからちゃんとキャッチアップしていきたい。


noah.plus