初めまして、今年の1月よりVR室にインターン生としてお世話になっている takapikoX です。
今回、UnityとA-Frameで作ったWebGLによる3Dコンテンツについて、簡単な性能比較を行いました。
目次
今週のお題「私の沼」
ブラウザ上で3次元コンピュータグラフィックスを扱うには
ブラウザ上で3Dグラフィックスを実装するには、WebGLというJavaScript APIによって、ブラウザを通してデバイスのGPUにアクセスする必要があります。
WebGLをそのまま扱うのは高度な技術を必要とするため、簡単に扱うためにThree.jsというJavaScriptライブラリが開発されました。Three.jsに関しては以下のサイトに詳しく書かれています。
A-FrameはこのThree.jsをベースにして開発されたJavaScriptのフレームワークで、ブラウザ上でのVRコンテンツ実装に非常に適しています。実行時、JavaScriptは構文解析、コンパイル+最適化、再最適化といったプロセスを経て実行されます。
A-Frameに関してはこちらで jujunjun110 さんが記事を書いています。ぜひご覧になってください。
Unityで作られたブラウザゲームを出力する場合も同様に、WebGLを使用するようにasm.jsで出力されています。asm.jsはJavaScriptのサブセットで、より高速にJavaScriptを実行することができます。
最近、WebAssembly(通称wasm)という新たなプログラミング言語が登場し、こちらの形式でもUnityからブラウザゲームを出力することができるようになりました。WebAssemblyはブラウザ上でバイナリフォーマットの形で実行することができ、構文解析の必要がなく、さらにJavaScriptに比べて容量が小さくなります。
asm.jsとWebAssemblyについては、以下のリンク先で分かりやすく説明されています。
対応状況
asm.jsはJavaScriptのサブセットのため、最新版のJavaScriptに対応した全てのブラウザ上で動作します。
WebAssemblyに関しては、Google Chrome 57以降、Firefox 22以降で対応しています。
Unity WebGLコンテンツ対応ブラウザは、以下のリンクに示されています。なお、モバイル端末での閲覧は非推奨となっております。
Unity - マニュアル: WebGL のブラウザ間での互換性
A-Frame と Unity を比べる意味
Unityで作成したWebGLコンテンツは現在公式ではVR化することはできません。しかし、Unity WebGLコンテンツをVRに対応させる手法がすでに確立されています。
となると、どちらで作った方が性能が高くなるのか、という点は気になるところです。
今回は、3つのサンプルをUnity,A-Frameで作り、その読み込み時間とFPSを比較します。
実行環境
OS:Windows 10 Pro (64-bit)
CPU:Intel® Core i7
GPU:NVIDIA GeForce GTX 1070
RAM:16.0 GB
ブラウザ:Google Chrome 58(64-bit)
Unity,A-Frameともに、23インチモニターへ全画面出力した状態で、検証を行いました。
今回作ったサンプル
今回の性能比較に当たって、3つのシーンを作成しました。
サンプル1
カメラとライト、背景のみ設置する
サンプル2
空間上にランダムで5000個の立方体オブジェクトを配置する
サンプル3
空間上にランダムで5000個の立方体オブジェクトを配置し、それらを動かす
※全てのページでマウスを使用した見回しを行うことができます。
※できるだけお互いの描画条件を同じにするために、Unity側では動的バッチングの機能を切ってあります。
以下に今回作成したプロジェクトのgithubをおいておきます。
github.com
何を比較するのか
読み込み時間とFPSを比較するといいましたが、実際に何をもって比較するのか、を示しておきます。
読み込み時間の比較
まず、ページの「読み込み」は以下に示した工程で進みます。
「初期処理」の部分にはデコード、構文解析、コンパイル、実行の工程を含みます。
ここでの「読み込み時間」は、「ホームページにアクセスしてから、レンダーループが始まるまで」と定義します。
で、肝心の「レンダーループが始まるタイミング」ですが、インスペクターをみるとレンダーループが始まるタイミングで、UnityもA-Frameもリクエストを送信しているようです。
A-Frame Unity
というわけなので、各サンプルで10回ずつスーパーリロードを行い、これらのリクエストが送信されるまでの時間の平均を「読み込み時間」とします。
FPSの比較
各フレームではフレーム処理、描画の順で処理が行われ、描画が終わると次のフレームに移行するようになっています。
「フレーム処理」は各フレームで行われている諸々の計算を含んでいます。
FPSは、A-Frameでは<a-scene>タグにstatsコンポーネントを付与することで取得でき、Unityでは以下のブログで紹介された方法で取得することができます。
なので、各サンプルでそれぞれ10秒分のFPSを取得し、その平均FPSを比較していきます。
実際の比較
サンプル1での比較
こちらは、どの行程にも負荷をかけていない状態での比較になります。
Unity | A-Frame | |
---|---|---|
読み込み時間[s] | 5.11 | 0.74 |
FPS | 60 | 56.46 |
サンプル2での比較
読み込み時の「初期処理」と、レンダーループでの「描画」に負荷をかけています。
Unity | A-Frame | |
---|---|---|
読み込み時間[s] | 6.13 | 3.94 |
FPS | 60 | 41.73 |
サンプル3での比較
読み込み時の「初期処理」と、レンダーループでの「フレーム処理」と「描画」に負荷をかけています。
Unity | A-Frame | |
---|---|---|
読み込み時間[s] | 6.75 | 4.225 |
FPS | 31.50 | 9.74 |
結果
今回のテストでは、ページにアクセスしてからコンテンツが表示されるまでの読み込み時間はA-Frameが早く、FPSはUnityの方が優秀でカクツキにくい、という結論が出ました。
A-FrameとUnityでは読み込みの時に行われる初期処理が違ってくるため、単純にA-Frameの方が早いというわけではありませんが、このくらいのサイズのプロジェクトならA-Frameの方が読み込み時間が短くなるようです。
ただ、WebAssemblyの利点として、よりコードが肥大化した時にブラウザ側で構文解析、最適化等を行わなくてよくなる、というのがありますので、もっと大規模なプロジェクトで比較してみると、また違った結果が出てくるかもしれません。
FPSでの比較だと、Unityの方が良い結果を残しました。WebAssemblyは処理速度には影響を与えないはずですが、Unityの方はそれ以外の部分でも細かく最適化が行われているのだと思われます。
VRコンテンツにおいて、酔いの防止という観点でFPSは非常に重要なので、描画に負荷がかかると判断したときはUnityを使うことを考慮に入れるとよいでしょう。
気になった点としては、初期処理に負荷をかけた時の読み込み時間の増大がUnityよりもA-Frameの方が大きい点ですね。おそらく、Unityでは処理速度は早いが、読み込み時にコードに書かれた処理以外の初期化処理を多く行っている、ということなのではないでしょうか。
モバイル端末での利用を見据えて
VRコンテンツの配信を考えるにあたって、現在最も普及している有力な候補はモバイル端末だと思われます。なので、モバイル端末のブラウザ上でWebGLコンテンツを配信する場合について考えておきます。
まず、現状モバイルでVRコンテンツを実装する場合、通信速度も含めて読み込み時間を考えるとA-Frameの方が適していると思われます。そもそもUnity WebGLがモバイル端末での利用を非推奨していることもあります。
しかし、将来的にモバイル端末で使用可能なWebブラウザがWebAssemblyに対応すれば、読み込み時間の短縮が期待でき、処理の重いVRコンテンツでのカクツキを抑えるためUnity WebGLを使用するという選択肢も十分考慮に入ってくるように思います。
Unity WebGLのモバイル対応が進めば、Unity WebGLを使用するという選択肢も十分考慮に入ってくるでしょう。
今回初めてベンチマークを行ってみましたが、なかなか奥深いものがありますね!WebAssemblyは最近になって正式対応され始めた新しめの言語なので、もっといろいろ試してみたいです。VRコンテンツを作っていく以上、読み込み速度とFPSは非常に気になるところですので、どんどん広まっていくことを切に願っております。