Unity パフォーマンスの最適化 5: レンダリング モジュールの負荷

CPU の負荷

バッチ処理

GPU がレンダリングする前に、CPU はデータをバッチで GPU に送信します。データが送信されるたびに、これはドローコールです。GPU が各バッチをレンダリングするときに、レンダリング状態を切り替えます。ここでのレンダリング状態とは次のことを指します。影響を受けるオブジェクトが画面上にある 外観のレンダリング プロパティまたはマテリアル。シェーダ ボール、ステッカー、カラー、レンダリング モード (透明、半透明) など。

Unity のバッチモード:

優先度:
SRP バッチャー / 静的バッチ処理
GPU インスタンス
化 動的バッチ処理

Draw Call Batching の使用条件
1. Mesh Renderer、Trail Renderer、Line Renderer、Particle System
、Sprite Renderer をサポートし、同じ種類の Renderer のみをバッチ処理できます。Skin レンダラーはサポートされていません。

2. 同じマテリアルを使用する必要があるため、
スクリプトで Render.material の代わりに Renderer.sharedmaterial を使用します。後者はマテリアルのコピーを生成するため、バッチ処理が中断されます。3.
MaterialPropertyBlock を使用するとバッチ処理も中断されますが、複数のマテリアルを使用するよりも高速です
4. 透明オブジェクトのレンダリングは厳密な順序で実行され、バッチ処理は簡単に中断されます 5.
負のスケーリング値は使用しないようにしてください
 

静的バッチ処理:

静的バッチ処理の目的は、描画呼び出しを減らすことではなく、レンダリング前にオブジェクトのさまざまなレンダリング属性を設定する必要があるため、レンダリング ステータスの変化を減らすことです。同じバッチの場合は、一度だけ設定するのが良いでしょう。

静的バッチ処理でドローコールが減らない理由は、静的バッチ処理されたオブジェクトはクリップされる可能性があり、頂点配列をマージするだけですが、頂点インデックスは依然として分離されているため、インデックス値に従ってどのサブメッシュを描画するかを決定できるためです。 10 グリッドの静的バッチはグリッドになりますが、5 番目のグリッドは錐台内にありません。2 つのドローコール、1 番目から 4 番目のサブメッシュ、6 番目から 10 番目のサブメッシュがあり、5 番目はクリップされています。2 つのドローコールがありますが、レンダリングはステータスは一度だけ設定されます

静的にバッチ処理しない場合、これら 10 個のメッシュのシェーダとテクスチャは同じですが、10 回のドローコール、つまり 10 回のバッチで描画され、10 個のレンダリング ステートを設定する必要があります。


追加の詳細:
1. エディターでの静的バッチ処理では、Unity はグリッド データの生成に実行時の CPU リソースを使用しません
2. 実行時の静的バッチ処理では CPU のピークが高くなり、その結果 1 回のフリーズが発生する可能性があります
3. 静的バッチ処理後完了すると、オブジェクトは全体となり静的となり、Transform プロパティは変更できません
4. バッチ処理後のルート オブジェクト staticBatchRoot の Transform プロパティは、
実行時に変更できます 5. ただし、バッチ処理は実行時に実行されます オブジェクト読み取り/書き込みオプションを開く必要があります
 

手動メッシュ結合

手動メッシュ マージは静的バッチ マージに似ていますが、サブメッシュをクリップすることができません。視野内にサブメッシュが 1 つしかない場合は、メッシュ全体が描画されます。

動的バッチ処理

Unity には 2 つのタイプがあり、1 つはメッシュ用で、もう 1 つはパーティクル システムなど動的に生成されるジオメトリ用です。

動的バッチ処理の目的は CPU 時間を削減することですが、バッチ処理自体が CPU を消費するため、バッチ処理の条件は比較的厳しいです。

GPUインスタンス

原則:
要件を満たすすべてのオブジェクトについて、Unity はその位置、ズーム、UV オフセット、ライトマップインデックス、およびその他の関連情報を一度に定数バッファー定数バッファーに保存します。オブジェクトがインスタンスとしてレンダリング プロセスに入るとき、オブジェクトは次のようになります。受信したインスタンス ID に基づいて、最適化効果を達成するために毎回 GPU にデータを送信することなく、後続のレンダリング段階で対応する情報をビデオ メモリから取得するために使用されます。

使用方法
1. マテリアルのインスペクター パネルで [インスタンス化を有効にする] オプションをオンにします。
2. Graphics.DrawMeshInstanced または Graphics.DrawMeshInstancedirdirect を使用して、GPU インスタンスの

MaterialPropertyBlockを手動で呼び出します。

MaterialPropertyBlock を使用して、バッチ処理を中断しないランダムな色を設定します。material.setcolor を直接使用すると、GPU インスタンスに最も適した、最も適さない別のマテリアル ボールであるため、バッチ処理が中断されます。 SRP Batcher の場合

短所:優先度は比較的低く、ドローコールの送信には通常より少し時間がかかります。

アドバンテージ:

  • 静的バッチ処理と比較して、追加のメモリ負荷が発生することはありません。
  • 動的バッチ処理と比較して、厳密な頂点制限はありません
  • これは、MaterialPropertyBlock に非常に適しており、バッチ処理を中断しません。

適用シーン:
草海や森など、同じメッシュを多数描画する必要があるシーン。

SRP バッチャー

同じシェーダ バリアントを使用するマテリアルの場合、つまりシェーダをバッチ処理する場合、シェーダ ボールが一致していなくても、シェーダが一致していれば問題ありません。プロジェクトが SRP パイプラインに切り替わると、情報は次のようになります。 SRP Batcher をオンにすると、Uniform Buffer を事前に生成し、バッチで情報を転送し、Shader 単位で SRP Batcher をバッチ処理するため、CPU の SetPassCall (レンダリング ステータスの設定) の数を効果的に削減できます。パフォーマンスの最適化
 

原理:

SPR Batcher を有効にしない場合のレンダリング プロセスは次のとおりです。各オブジェクトのプロパティは GPU 上に CBuffer を持ちます。これには、トランスフォームなどのゲームオブジェクト プロパティ、マテリアル、ライト マップなどのマテリアル プロパティが含まれます。プロパティが更新されるとデータをリセットする必要があり、マテリアルが追加されるたびに対応する cbuffer が再設定され、CPU を消費します。

オンにすると、プロセスが変更されます。同じシェーダは、トランスフォームなどの異なるプロパティに対して大きなバッファを生成します。ライト マップなどの同じプロパティに対して、それぞれが小さなマテリアルごとに生成します。バッファがある場合状態が変化した場合にのみ変更されます。変換のみが変更された場合、同じ位置のデータはオフセットを介してのみ書き込まれます。

新しく追加されたマテリアルの場合、シェーダは変更されていないため、バッチは変更されません。

従来、CPU を最適化するために Draw Call の数を減らす傾向がありました。Draw Call 自体は、GPU コマンド バッファに数バイト押し込まれるだけです。実際の CPU コストは、DrawCall の前の多くの設定によって決まります。SRP Batcher は DrawCall の数を減らしません、描画呼び出し間のセットアップ コストを削減するだけです レンダリング

パイプライン要件:
URP、HDRP、SRP をサポート、組み込みパイプラインはサポートしません
ゲーム オブジェクト要件:
パーティクルではなく、メッシュまたはスキン メッシュが含まれている必要があります
素材プロパティ ブロック シェーダーは使用できませ
ん互換性のある SRP バッチャー
 

利点:
UniformBuffer 書き込み操作を節約し、動的オブジェクトをサポートし、静的バッチ処理よりも広範囲をサポートすると同時に、メモリ コストがはるかに小さくなり、マテリアルが多い状況にも適用できます。

該当するシナリオ:
シェーダーの繰り返し率は高いが、シェーダー バリアントの数を制御する必要がある
 

4つの方法の比較

優先順位:
SRP バッチャー / 静的バッチング > GPU インスタンス化 > 動的バッチング
該当する状況:
静的バッチング + SRP バッチャー: 主要都市、コピービル
SRP BatcherOnly: さまざまな植生
GPU インスタンス化: 単一タイプの植生
動的バッチング: Ul、パーティクル、スプライト待機

淘汰

GPU がレンダリングする前に、CPU はレンダリング データを GPU に渡す必要があるため、レンダリングする必要のない一部のオブジェクトを最初に削除する必要があります (カリング)。Unity エンジンはビュー錐台カリングをネイティブにサポートしています。つまり、ビュー ボリュームの範囲外のオブジェクトはカリングされ、これらのオブジェクトのデータを処理のために GPU に送信する必要はありません。

Unity では、MeshRenderer、SpriteRenderer、LineRenderer、SkinnedMesh Renderer、TrailRenderer などのすべてのビジュアル コンテンツが Renderer から継承され、Unity のレンダリング プロセス中にフィルタリングされ、錐台カリングの操作が自動的に実行されます。

シーン内で多数のカメラが起動されている場合、それに応じてカリングの総消費時間も増加します。オブジェクトの表示に使用されない場合でも、カリングの実行には時間がかかります。機能は、レンダリングスレッド 

カリンググループ

CullingGroup は Unity が提供する API インターフェースです. Unity 独自の Cu システムや LOD と同じシステムです. Cull の基盤となる機能の一部をユーザーが使用できるように公開することに相当します. Unity - マニュアル: CullingGroup
API

オクルージョン

基本的な導入
カメラは各フレームでカリング操作を実行します。これらの操作は、シーン内のレンダラーをチェックし、
描画する必要のないレンダラーを除外 (カリング)します
。デフォルトでは、カメラは錐台カリングを実行します。

仕組み
シーンに関するデータは Unity エディターで生成され、実行時にカメラが見ることができるものを決定するために使用されます。データを生成するプロセスはベイクと呼ばれます。
オクルージョン カリング データをベイクするとき、Unity はシーンを複数のユニットに分割し、ユニット内のジオメトリと隣接するユニット間の可視性を記述するデータを生成します。その後、Unity はユニットを可能な限りマージして、生成されるデータのサイズを削減します。実行時に、Unity はこれらのベイクしたデータをメモリ内にロードし、カメラごとにロードします。オクルージョン カリング プロパティを有効にすると、データに対してクエリが実行され、カメラが認識できる内容が決定されます。

CullQueryPortalVisibilitylJmbra関数は、CullSendEvents のサブスレッドに表示されます。
この関数は、テスト中にワーカー スレッドにも表示されます。

推奨事項

障害物:

  • 山などの大きなオクルージョン オブジェクトのオクルージョン品質は良好です
  • 森などのブロックが蓄積できないため、大きなブロックオブジェクトを組み合わせるのには適していません。
  • チーズのように隙間が多すぎないように
  • モデリングの際は、意図しないギャップが生じないよう注意してください。
  • 衝突によってカメラが障害物の内部に入らないようにしてください。

隠れたオブジェクト:

  • それらのほとんどは、除去を容易にするために、遮蔽されたオブジェクトとして設定できます。
  • 非常に大きなオブジェクトは、地形など常に表示され、複数の部分に分割することを検討できるため、遮蔽オブジェクトとしては適していません。




 

おすすめ

転載: blog.csdn.net/qq_37672438/article/details/132003379