ウェブアプリのWebGLに関するベストプラクティス
WebGLは、GPUを利用して高いパフォーマンスを実現するグラフィックスライブラリです。高品質のビジュアルと複雑なアニメーションをブラウザに直接描画できます。このライブラリにより、ブラウザでOpenGL ES(低レベルの3DグラフィックスAPI)が利用可能になります。追加のインストール、拡張機能、プラグイン、アドオンは何も必要ありません。標準に準拠しているため、サポート対象のブラウザでは、さまざまなライブラリ、一般的なシェーダー、ゲームエンジンなどのグラフィックスエンジンがWebGLに対応しています。
VegaウェブアプリでのWebGLの動作
Vegaウェブアプリはv132で、WebGL 2.0をサポートしています。Vegaでは、ChromiumのWebGLレイヤーがカスタマイズなしで使用されます。これは、AndroidのWebViewやLinuxのChromiumとほとんど同じように機能します。
追加の詳細情報は、デバイスにWebViewアプリを読み込み、ソースURIとしてhttps://webglreport.com/?v=2(英語のみ)を指定すると確認できます。
Platform: Linux x86_64
Browser User Agent: Mozilla/5.0 (Linux; OS 1.1; AFTCA002 userdebug/1343; wv) AppleWebKit/537.36 (KHTML, like Gecko) Mobile Chrome/118.0.5993.159 Safari/537.36
Context Name: webgl2
GL Version: WebGL 2.0 (OpenGL ES 3.0 Chromium)
Shading Language Version: WebGL GLSL ES 3.00 (OpenGLES GLSL ES 3.0 Chromium)
Vendor: WebKit
Renderer: WebKit WebGL
Unmasked Vendor: Mesa
Unmasked Renderer: Mali-G310 (Panfrost)
Antialiasing: Available
ANGLE: No
Major Performance Caveat: No
サポートされている拡張機能
以下は、WebGLでサポートされている拡張機能の一覧です。
- EXT_color_buffer_float(英語のみ)
- EXT_color_buffer_half_float(英語のみ)
- EXT_disjoint_timer_query_webgl2(英語のみ)
- EXT_float_blend(英語のみ)
- EXT_texture_filter_anisotropic(英語のみ)
- EXT_texture_norm16(英語のみ)
- OES_texture_float_linear(英語のみ)
- WEBGL_compressed_texture_astc(英語のみ)
- WEBGL_compressed_texture_etc(英語のみ)
- WEBGL_compressed_texture_etc1(英語のみ)
- WEBGL_debug_renderer_info(英語のみ)
- WEBGL_debug_shaders(英語のみ)
- WEBGL_lose_context(英語のみ)
- WEBGL_multi_draw(英語のみ)
VegaでWebGLを使用するための戦略
ここで説明する戦略は、パフォーマンスを高めるためにWebGLライブラリを使用するゲーム、TVアプリ、生産性向上アプリに適用されます。DOM/HTMLのレンダリングとメモリ管理の方法はブラウザによって管理されるのに対して、WebGLは直接実装する必要があります。次の一般的なガイドラインに従ってください。
- 複雑な計算を簡素化し、メモリを効率的に管理します。JSとC/C++間の変換はできるだけ直接的にします。
- テクスチャ、アセット、オブジェクトのサイズを削減または制限します。
- 既存のブラウザ設定、GPUオプション、ブラウザツール/ライブラリのうち、ハードウェア用に最適化されているものや、アプリに合わせて微調整できるものは再利用します。
キャンバスへのビデオ表示の回避
ビデオ用のPixiJS API(英語のみ)のように、WebGLにビデオを組み合わせることは避けます。代わりに、HTMLのvideo要素や、その他のウェブベースのビデオプレーヤーライブラリを使用します。Vegaでは、ビデオ再生をプライベートGPUバッファーに直接実装しているため、ビデオからフレームをWebGLテクスチャとして取り出すことはできません。
ドローコールの削減
テクスチャアトラス、インスタンス化(同じオブジェクトの複数のインスタンスのレンダリング)、頂点バッファオブジェクト(VBO)とインデックスバッファオブジェクト(IBO)の使用などの手法によって、複数のオブジェクトを1回のドローコール(バッチ処理)にまとめます。OpenGL ESでは、1フレームあたりのドローコール数を500回未満にしてください。
描画の実行は、setTimeoutとuseEffectではなくrequestAnimationFrameから行います。useEffectやuseMemoを使用する場合は、requestAnimationFrameが使用する値を更新することで、描画されるオブジェクトを変更します。可能であれば、描画したオブジェクトや描画に使用した方程式をキャッシュして、その処理にかかる時間を短縮します。
テクスチャの最適化
テクスチャのサイズを必要最小限の解像度に変更します。圧縮テクスチャ形式(DXTやETCなど)を使用し、ミップマップを取り入れます。テクスチャアトラスを使用することでも、ドローコールとメモリ使用量を削減できます。
複雑なアルゴリズムの簡素化
- 可能な場合は、
highp floatではなくhalfやfloatなどの低精度のデータ型を使用します。 - シェーダーの複雑さと、必要となる計算の回数を最小限に抑えます。
- powやsinなどのリソース負荷の高い関数の代わりに、ルックアップテクスチャを使用します。
- ライトとシャドウが多すぎると、パフォーマンスに影響する可能性があります。ベイクされたライティング(事前レンダリング)を使用するか、リアルタイムライティングを簡素化することを検討してください。
カリングとLODの実装
可能な場合は、LOD、視錐台、オクルージョンカリングのようなアルゴリズムを使用します。滑らかさを向上させるために、詳細レベルを下げ、不可視のオブジェクトは描画しないようにします。相対LODを使用すると、ビュー内のポリゴンが多いときにポリゴンの品質を下げて高負荷に対応できます。
効率的なメモリ管理
- テクスチャ、バッファ、プログラムなどのWebGLオブジェクトは、不要になったら適切に廃棄します。
- メモリの使用状況を注意深く管理して、不要な割り当てと割り当て解除を防ぎます。
- 可能な場合は、クラスではなく構造体(TypeScriptインターフェイス)を使用します。
- 頻繁に使用されるメソッド内では、クラスの再インスタンス化、文字列の連結、計算量の多い方程式を実行しないようにします。
- メモリを事前に割り当て、リストの代わりに配列を使用し、可能な場合はポインターや参照のような共有リソースを使用します。
- オブジェクトプーリングを実装してメモリの断片化を抑えます。
ファイル管理
- スプライトやその他の画像アセットをできるだけ再利用して、ファイルの読み込み時間を短縮します。
- さまざまなライブラリやゲームシステムに用意されている既存のアセットバンドルシステムを活用します。これらは、アセットを圧縮してバンドルし、必要時に読み込むしくみを提供します。
- ファイルの読み込みには、非同期処理または並列処理を使用します。
- MP3やOGGなどの圧縮オーディオ形式を使用します。同じオーディオを繰り返し再生する場合は、読み込むファイルの数が多くなりすぎないようにします。
- サウンドエフェクト(SFX)用のオーディオファイルを連結して、読み込み時間とメモリ使用量を最適化します。
- サウンドエフェクトごとに個別のオーディオファイルを使用するのではなく、時間を指定する方法でオーディオを再生することを検討します。
// 複数のオーディオファイルの代わりに1つのmp3またはoggを用意して、 // 特定の位置から一定時間再生します。これにより、特に同じオーディオが頻繁に // 再生される可能性がある場合に、読み込み時間とメモリ使用量を最適化できます。 // // SFXやバックグラウンドオーディオに便利です。 this.playAudio(2.9088, 0.1437);
ハードウェアアクセラレーション
ハードウェアアクセラレーションはデフォルトでオンになっています。ブラウザでハードウェアアクセラレーションをトリガーするCSSを使用しても、それ以上パフォーマンスが向上することはまずありません。
// ハードウェアアクセラレーションを強制しても効果は望めません。
document.body.style.transform = 'translateZ(0)';
document.body.style.backfaceVisibility = 'hidden';
以下のコードを読み込み時に使用すると、パフォーマンスが少し向上することがあります。powerPreference設定が「high-performance」の場合、エネルギー効率よりもパフォーマンスを優先するようにブラウザに指示します。アンチエイリアスのようなほかの設定によっても、レンダリング時のGPU処理を削減できます。アプリによっては、アンチエイリアスを無効にしても表示上はそれほど気にならない可能性があります。さまざまなデバイスタイプでWebGLコンテキストを再利用する場合は、failIfMajorPerformanceCaveat: falseを使用して、パフォーマンス上の問題があってもWebGLコンテキストを作成するようにブラウザに指示することが役立ちます。
// WebGLコンテキストを最適化します。
const canvases = document.querySelectorAll('canvas');
canvases.forEach(canvas => {
const ctx = canvas.getContext('webgl', {
antialias: false,
powerPreference: 'high-performance',
failIfMajorPerformanceCaveat: false,
});
});
ハードウェアアクセラレーションはデフォルトで有効になっていますが、追加設定を微調整するとアプリでパフォーマンスを強化できます。これは、リソースの少ないデバイスでVegaウェブアプリを実行する場合にWebGLを最適化するために役立ちます。
状態変更の最小化とブロッキング呼び出しの回避
- 状態の変更回数を最小限に抑えます。これを実現するには、異なるシェーダープログラム、テクスチャユニット、レンダリングターゲットを切り替える方法などがあります。
getError()やgetParameter()などのブロッキング呼び出しはパフォーマンスに影響するため、メインスレッドで実行しないようにします。requestAnimationFrameを使用しないときはgl.flush()を使用して、ブラウザでWebGLコマンドがより迅速に実行されるようにします。
関連トピック
Last updated: 2025年10月7日

