高度な戦略とテクニックで PixiJS アプリケーションを次のレベルに引き上げましょう
この投稿では、CPU / メモリの両方の観点から pixiJS 内の複数の要素のレンダリングを最適化するさまざまな方法について説明します。たとえば、キャッシュを行わずにすべてのフレームを再レンダリングする (CPU 使用率の点で優れたパフォーマンスが得られる) 場合と、レンダリングされたグラフィックスをメモリにキャッシュする場合の違いを考えてみます。これにより、シーン内のグラフィックスの数に比例してメモリ使用量が増加します。
このような最適化に対処するための戦略は多数あります。特に注目すべきはデータ指向設計です。これは、より伝統的に一般的なオブジェクト指向のプログラミング方法とは根本的に異なる一連のアプローチを提示します。
その他の主な方法には、より構造化された形式のカリングと利用が含まれます。たとえば、C# の NativeArray や TypeScript の TypedArray などです。これらにより、メモリ バッファの管理が大幅に強化され、キャッシュ ミスが制限される可能性がありますが、エンジニアリングの豊富な経験やカスタマイズも必要になります。
この投稿では、ベスト プラクティスを含む、PixiJS を使用した WebGL 環境の最適化の 1 つの有効な方法であるオブジェクト指向アプローチに焦点を当てます。これにより、PixiJS アプリケーションの速度と効率を向上させる、よく組織された手段が提供されます。
次回の記事では、もう 1 つの強力な最適化アプローチであるエンティティ-コンポーネント-システム アプローチについて説明します。 ECS のアプローチは驚くほどデータ指向であり、高性能環境での PixiJS の最適化に関しては斬新な外観を提供します。この記事では、引き続き Medium で ECS アプローチの核心を詳しく説明します。
Pixi アプリケーションのパフォーマンスを最適化し、さらに向上させるために、もっと改善できることが常にあるということを常に覚えておいてください。より優れているとは、最も最適化されたり、最速になったりすることを意味するものではありません。最適な解決策は、リソースを過剰に拡張することなく潜在的なユーザーを満足させるのに十分な最適化を行いながら、プロジェクトの期限を確実に守るための、最適化に投資する時間とその投資収益とのトレードオフの問題です。
このセクションでは、PixiJS アプリケーションを最適化する最良の方法を説明します。
このセクションは公式のヒントに基づいているため、チェックする価値があります!
残りの議論は、Pixi グラフィックス、スプライト、メッシュ、およびデフォルトの Pixi コンテナの代わりにパーティクル コンテナをいつ使用するかを中心に展開します。この章では、PixiJS プロジェクトが機能し、最大限の効率でレンダリングされるように、オブジェクト指向のコンテキストですべてを最適に使用する方法を明確に示します。
Pixi グラフィックを効果的に使用するには、Pixi グラフィックが内部でどのように機能するかを理解する必要があります。それでは、Pixi でグラフィックス オブジェクトを作成する非常に基本的な例を示すことから始めましょう:
const graphics = new PIXI.Graphics(); graphics.beginFill(0xff0000); graphics.drawRect(0, 0, 200, 100); graphics.endFill();
ただし、この単純な実装で重要なのは、「内部で」何が起こっているかです。この種のグラフィックを作成する際、Pixi は GraphicsGeometry オブジェクトと呼ばれるものを作成します。そのオブジェクトの形状とサイズは、描画している形状に対して指定した寸法とプロパティに基づいて決まります。最終的な Geometry オブジェクトは、Graphics オブジェクト内の GeometryList 内に保存されます。
PIXI.Graphics を使用して何かを描画するたびに、GeometryList が更新されることに注意してください。場合によっては、このリストをクリアしたいだけで、同時に Graphics オブジェクトを維持したいことがあります。そこで .clear() メソッドが活躍します。このプロセスがどのように機能するかを知ることは、Pixi がアプリ内でグラフィックを処理およびレンダリングする方法に直接影響するため、Pixi を使用する際に非常に役立ちます。
PixiJS で 100 個の Graphics オブジェクトを作成するユースケースを通じて、最適化戦略を探ってみましょう。
function createGraphics(x, y) { const graphic = new PIXI.Graphics(); graphic.beginFill(0xDE3249); graphic.drawCircle(x, y, 10); graphic.endFill(); return graphic; } for (let i = 0; iこのシナリオでは、100 個のグラフィックス オブジェクトすべてが同じ幅と高さを共有している場合、ジオメトリを再利用することで最適化できます。
GraphicsGeometry を参照として渡す
円用の単一のジオメトリを作成し、それを再利用します:
// Create a single geometry for a circle const circleGeometry = new PIXI.Graphics(); circleGeometry.beginFill(0xDE3249); circleGeometry.drawCircle(0, 0, 10); // Draw a circle at the origin circleGeometry.endFill(); // Function to create a graphic using the circle geometry function createCircle(x, y) { const circle = new PIXI.Graphics(circleGeometry.geometry); circle.x = x; circle.y = y; return circle; } // Create 100 circles using the same geometry for (let i = 0; iこのメソッドは、オブジェクトごとにジオメトリを複製するのではなく、同じジオメトリを参照することでメモリ使用量を大幅に削減します。
オールインワングラフィックスオブジェクトを描画
静的なグラフィックスまたは複雑な構造の場合、すべての要素を 1 つの Graphics オブジェクトに描画することも別の最適化手法です:
const graphics = new PIXI.Graphics(); // Draw 100 circles using the same PIXI.Graphics instance for (let i = 0; iこのアプローチでは、新しい Graphics オブジェクトを作成する代わりに、単一の Graphics インスタンスの GeometryList に新しいジオメトリを追加します。この方法は、より複雑なグラフィック構造の場合に特に効率的です。
PixiJS で CacheAsBitmap の力を活用する
PixiJS 内の最も強力な機能の 1 つは CacheAsBitmap です。基本的に、エンジンはグラフィックスをスプライトのように扱うことができます。これにより、特定のケースではパフォーマンスが大幅に向上する可能性があります。
オブジェクトが頻繁に更新されない場合にのみ CacheAsBitmap を使用します。
グラフィックスの大きなバッチをビットマップとしてコンテナにキャッシュできます。 100 個のグラフィックスを再レンダリングする代わりに、Pixi はスナップショットを取得し、それをビットマップとして事前レンダリングします。
常にメモリ使用量を考慮してください。キャッシュされたビットマップは大量のメモリを使用します。
cacheAsBitmap は慎重に使用する必要があります。めったに更新する必要がないオブジェクトに適用すると、最も効果的です。たとえば、静的またはまれにしか変更されない数千のグラフィックスがある場合、それらをビットマップとしてキャッシュすると、レンダリングのオーバーヘッドが大幅に削減されます。
100 個の個別のグラフィックを再レンダリングする代わりに、PixiJS はこれらの「スナップショット」を取得し、単一のビットマップとしてレンダリングできます。これが実装方法です:
const graphicsContainer = new PIXI.Container(); // Add your graphics to the container // ... // Cache the entire container as a bitmap graphicsContainer.cacheAsBitmap = true;
ただし、メモリの使用量に注意することが重要です。キャッシュされたビットマップは大量のメモリを消費する可能性があります。したがって、cacheAsBitmap はレンダリングの負荷を大幅に軽減できますが、より多くのメモリを使用することと引き換えになります。このトレードオフは、アプリケーションの特定のニーズと制約に基づいて慎重に検討する必要があります。
要約すると、cacheAsBitmap は、PixiJS、特に静的またはほとんど更新されないグラフィックスのパフォーマンスを最適化するための効果的なツールです。複雑なグラフィックスを単一のビットマップとして扱うことでレンダリングを簡素化しますが、メモリ フットプリントへの影響とのバランスをとることが重要です。
PixiJS のメモリ効率に関しては、一般にスプライトがグラフィックスよりも優れています。これは、同じ形状またはテクスチャを共有する複数のオブジェクトを扱う場合に特に顕著です。 100 個の円グラフィックを作成する例をもう一度見てみましょう。今回はスプライトを使用します。
まず、単一の円グラフィックのジオメトリからテクスチャを作成します。
const circleGraphic = new PIXI.Graphics(); circleGraphic.beginFill(0xDE3249); circleGraphic.drawCircle(0, 0, 10); circleGraphic.endFill(); // Generate a texture from the graphic const circleTexture = app.renderer.generateTexture(circleGraphic); Next, we use this texture to create sprites: // Function to create a sprite using the circle texture function createCircleSprite(x, y) { const sprite = new PIXI.Sprite(circleTexture); sprite.x = x; sprite.y = y; return sprite; } // Create and add 100 circle sprites to the stage for (let i = 0; iこのアプローチでは、グラフィックスを再レンダリングしてオブジェクトごとに増大するジオメトリ リストを管理する代わりに、1 つのテクスチャを作成し、それを複数のスプライトにわたって再利用します。これにより、レンダリングの負荷とメモリ使用量が大幅に削減されます。
制限と創造的な解決策
この方法の制限の 1 つは、作成したテクスチャによって制限されることです。ただし、ここでは創造性が鍵となります。 PIXI.Graphics を使用してさまざまな形状のテクスチャを生成し、スプライトに適用できます。特に効率的なアプローチは、1x1 ピクセルのビットマップのような BaseTexture を作成し、それをすべての長方形のスプライトに再利用することです。スプライトのサイズを異なる次元に変更すると、冗長性を持たずに複数のスプライトにわたって同じ BaseTexture を利用できます。 例えば:
// これにより、16x16 の白いテクスチャが作成されます const BaseTexture = PIXI.Texture.WHITE; // このbaseTextureをすべての長方形に使用します const sprite= new PIXI.Sprite(baseTexture); スプライト.ティント = 0xDE3249; // スプライトの色を設定します sprite.position.set(x, y); スプライト.幅 = 幅; スプライト.高さ = 高さ;// This creates a 16x16 white texture const baseTexture = PIXI.Texture.WHITE; // Use this baseTexture for all rectangular shapes const sprite= new PIXI.Sprite(baseTexture); sprite.tint = 0xDE3249; // Set the sprite color sprite.position.set(x, y); sprite.width = width; sprite.height = height;このメソッドを使用すると、.tint() を使用すると、色合いが追加のシェーダー効果として GPU に直接適用されるため、完全な再レンダリングをトリガーせずにスプライトに色を付けることができます。パーティクル コンテナで 100k のスプライトを使用する
このテクニックの威力を説明するために、滑らかな 60 FPS を維持しながら、ランダムな色合いを持つ 100,000 個の個別のスプライトを実行し、それぞれのスプライトをフレームごとに変換することを想像してください。
PixiJS の最適化についてさらに詳しく読むには、renderTexture テクニックを深く掘り下げた、PixiJS のオリジナル作成者の 1 人による洞察力に富んだ記事を強くお勧めします。
ここで見つけることができます
すごい! ここまでたどり着いたなら、PixiJS の最適化についてのこの深い掘り下げに最後まで付き合ってくれて心から感謝したいと思います。ここで共有した洞察とテクニックがあなたのプロジェクトにとって有益であると感じていただければ幸いです。次回の記事にご期待ください。そこでは、Entity-Component-System (ECS) アプローチと NativeArrays の力についてさらに詳しく説明します。これらの方法により、PixiJS アプリケーションのパフォーマンスと効率性が新たな高みに引き上げられます。読んでいただきありがとうございます。また次回でお会いしましょう!
免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。
Copyright© 2022 湘ICP备2022001581号-3