WebGLパフォーマンス
WebGLは遅く、複雑な3Dグラフィックスのレンダリングが難しいと誤解されがちです。しかし、多くの例がこの誤解が間違っていることを示しています。それにもかかわらず、開発者の経験はこの先入観を何度も強化しています。
WebGLコードを実行しているハードウェアはブラウザ専用に制限されているわけではありません。では、なぜ開発者はウェブ上で3Dグラフィックスを高速にレンダリングできないと思うのでしょうか?
この記事では、WebGLのパフォーマンス向上のベストプラクティスを紹介し、あなたもウェブ上で高速な3Dレンダリングを実現できるように案内します。
CPUとGPU
3Dアプリケーションでは、一部のコードがCPUで実行され、他のコードがGPUで実行されるという仕組みです。
WebGLはウェブ上でグラフィックスアプリケーションを加速するためにGPUを利用する設計となっています。WebGLは、グラフィックスハードウェアに作業を送信し、結果を取得する関数群と考えることができます。
GPU用の作業を作成するコードはCPU上で実行され、WebGLの場合、JavaScriptを使って制御します。
ブラウザのオーバーヘッド
ブラウザの目的の一つは、ユーザーを潜在的な危険から守ることです。したがって、WebGLを通じたすべての呼び出しの安全性をJavaScriptを介してチェックします。また、ウェブサイトのコードのプロセスを隔離し、そのプロセスとの間の呼び出しを送信可能な形に変換する必要があります。これを「マーシャリング」と呼びます。
マーシャリングとWebGL呼び出しの安全性チェックの両方が、ネイティブ環境の同じ呼び出しに比べてパフォーマンスコストを追加する要因となります。
WebGL呼び出しの回避
WebGLのパフォーマンスを向上させるためには、オーバーヘッドの高い呼び出しを避けるべきです。プロファイリングを通じて特にコストの高い呼び出しを確認できます。WebGLアプリケーションのプロファイリング
以下は意外にコストがかかる呼び出しの一部です:
これらの呼び出しを回避する良い方法は、WebGLの状態を追跡し、本番ビルドでエラーチェックを減らすことです。
描画呼び出しの回避
優れたWebGLパフォーマンスの秘訣は、描画呼び出しをできるだけ減らすことです。以下のWebGL関数を使用する関数が描画呼び出しとして分類されます:
- drawArrays()
- drawElements()
- drawArraysInstanced()
- drawElementsInstanced()
- drawBuffers()
- drawRangeElements()
多くのオブジェクトを一度に描画する単一の関数呼び出しを使用したり、インスタンシングを利用して大規模なメッシュをレンダリングしたり、WEBGL_multi_drawで異なるオブジェクトを同じシェーダーで描画することができます。
3Dエンジンには「バッチ処理」と呼ばれる機能があり、多くの呼び出しを1つのWebGL呼び出しに統合します。Wonderland Engineはこれを極限まで行い、数万の動的オブジェクトを10回未満の描画呼び出しでレンダリングします。
特にモバイル上でのWebGLパフォーマンスは、描画呼び出しの数に大きく依存します。
描画呼び出しの回避(モバイル)
この点を強調するためにセクションを2回設けています。モバイルでは、ブラウザのオーバーヘッドがなくても描画呼び出しが重要です。UnityやGLESを直接使ってネイティブで構築する場合でも、描画呼び出しを少なくする必要があります。
モバイルで優れたWebGLパフォーマンスを目指すなら、描画呼び出しに特に注意を払うべきです。
SafariでのWebGL
Safari(iOSとMacOS)では、意外にも多くのオーバーヘッドが発生するWebGL呼び出しがあります。例えば:
Safari向けに最適化する際にはUniform Buffersの使用に特に注意が必要です。
JavaScript
ブラウザAPIと連携するための言語としてJavaScriptが使われます。JavaScriptにおける最大のパフォーマンス問題は、ガベージコレクションです。この機能は不要となったメモリを自動的に見つけて解放します。
ガベージコレクションのプロセスはWebGLアプリケーションのパフォーマンスを予測不可能で不安定にする可能性があるため、発生するタイミングを制御することはできません。そのため、不適切なタイミングで発生してレンダリングにカクつきを生じさせ、コードが最適化されているにもかかわらず、パフォーマンスが悪く見えることがあります。
安定したフレームレートを得るためには、ガベージのないJavaScriptを書くために厳格な方法を採用してください。
iOS Safariとメモリ
Safariでスムーズに動作するWebGLアプリは少ないです。SafariでのWebGLパフォーマンスには別の課題があります。Safari向けの最適化方法については、私たちのブログをご覧ください。
メモリ制限
iOSでは別の課題があります。ブラウザタブのメモリが非常に制限されており、特に古いiPhoneハードウェアで顕著です。メモリ制限を超えると、タブが再読み込みされたり、フリーズしたりする可能性があります。iPhoneは統一メモリを使用しているため、CPUとGPUのRAMが共有されており、テクスチャとバッファデータ、JavaScriptやWebAssemblyのメモリはすべて制限にカウントされます。