Ryuten.ioにおけるパーティクルの描画 / PixiJS midlevel API
- 2024-08-05
Ryuten.io におけるパーティクルの描画 [元記事]
Ryuten には様々な種類の要素が存在しますが、その一つにパーティクルタイプがあります。そして時には、プレイヤーの目に数千ものパーティクルが映ることがあります。
Ryuten は、ゲームビジュアルのレンダリングに Pixi.js を使用しています。Pixi.js は、インタラクティブなグラフィック、HTML5 ゲーム、アニメーション Web サイトを作成するために使用できる、無料のオープンソース 2D レンダリングシステムです。使いやすい API を提供しており、開発プロセスを高速化するのに役立ちます(生の WebGL コードを書く場合と比較して)。
バージョン 5 では、Pixi.js は ミドルレベル API のサポートをリリースしました。この機能により、ゲームの特定のセクションに対して、よりきめ細かい制御と、よりパフォーマンスの高いコードを書くことができるようになりました。
WebGL がどのように物体をレンダリングするかについての簡単な説明
- 頂点をいくつか用意します。
- これらの頂点は処理され、プリミティブを作成するために使用されます。
- これらのプリミティブはラスタライズされ、フラグメントに変換されます。
- フラグメント内の各ピクセルが処理され、最終的なピクセルデータが出力されます。
Pixi.js を使用した通常のパーティクルのレンダリング
- Pixi.js は、2 つの三角形を使用して、4 つの頂点を持つ長方形のメッシュを作成し、その上にテクスチャを重ねます。
- ここでは、50px x 50px のパーティクルをレンダリングしていると仮定しましょう。
- ピクセル数 = 50 * 50 = 合計 2500 ピクセル
- つまり、頂点シェーダーは 4 つの頂点を処理し、フラグメントシェーダーは 2.5k ピクセルを処理します。
Pixi.js の通常レンダリングと低レベル API の使用
- ミドルレベル API を使用するとよりきめ細かい制御が可能になるため、長方形ではなく六角形、つまり 4 つの三角形と 6 つの頂点を使用します。
- ここでは、50px x 50px のパーティクルをレンダリングしていると仮定しましょう。
- ピクセル数 = ((3 x √3) / 2) x (25 x 25) = ~1624 ピクセル
- この場合、頂点シェーダーは 6 つの頂点を処理し、フラグメントシェーダーは 1.6k ピクセルを処理します。
注:この場合、ミップマッピングに関連する理由により、テクスチャには常に余分なヘッドルームがあるため、パーティクルのレンダリング中にテクスチャのクリッピングは発生しません。
比較
頂点は 2 つとわずかに増加しただけですが、ピクセル数は 2.5k から 1.6k に減少しました(約 36% 減)。
GPU の統計情報を正確に測定する方法がないようだったため、v-sync を無効にし、ブラウザから FPS 制限を削除して、両方の方法を使用して毎秒可能な限り多くのフレームをレンダリングすることにしました。
通常の方法では、ゲームは平均で ~160 FPS を達成できました。
一方、ミドルレベル API を使用することで、ゲームは平均で ~200 FPS を達成できました。
- どちらのシーンもまったく同じで、画面上に約 2.5k 個のパーティクルが表示されています。
結論
ミドルレベル API の使用には、確かにより多くの作業、時間、メンテナンスコストが必要になりますが、その代わりに、より多くのパワーと制御が得られます。この場合、パーティクルレンダリングシステムを約 25% 向上させることができました。