3Dのパフォーマンスと制限

はじめに

Godotは、バランスの取れたパフォーマンスの哲学に従っています。パフォーマンスの世界では、トレードオフが常にあります。トレードオフは、使いやすさと柔軟性のためにスピードを交換することから成ります。これのいくつかの実用的な例は次のとおりです:

  • オブジェクトを大量に効率的にレンダリングするのは簡単ですが、大きなシーンをレンダリングする必要がある場合、非効率になる可能性があります。これを解決するには、レンダリングに可視性の計算を追加する必要があり、レンダリングの効率が低下しますが、同時にレンダリングされるオブジェクトが少なくなるため、全体的に効率が向上します。
  • レンダリングする必要があるすべてのオブジェクトに対して、すべてのマテリアルのプロパティを設定するのも遅くなります。これを解決するために、オブジェクトはコストを削減するためにマテリアル別にソートされますが、並べ替えにはコストがかかります。
  • 3D物理でも同様の状況が発生します。大量の物理オブジェクト(SAPなど)を処理するための最適なアルゴリズムは、オブジェクトの挿入/削除とレイキャスティングが遅くなります。レイキャスティングと同様に、より高速な挿入と削除を可能にするアルゴリズムは、多くのアクティブオブジェクトを処理できません。

そして、これにはもっと多くの例があります!ゲームエンジンは本質的に汎用であるように努めているため、バランスの取れたアルゴリズムは、ある状況では高速で他の状況では遅いアルゴリズムや、高速であるが使いやすさを難しくするアルゴリズムよりも常に好まれます。

Godotは例外ではなく、異なるアルゴリズムに交換可能なバックエンドを持つように設計されていますが、デフォルトのアルゴリズム(または、現在存在する唯一のもの)は、パフォーマンスよりもバランスと柔軟性を優先します。

このチュートリアルの明確な目的は、Godotを最大限に活用する方法を説明することです。

レンダリング

3Dレンダリングはパフォーマンスを得るのが最も難しい分野の1つであるため、このセクションではヒントのリストを示します。

シェーダーとマテリアルを再利用する

Godotレンダラーは、その辺にあるものとは少し異なります。 GPU状態の変化を可能な限り最小限に抑えるように設計されています。class_SpatialMaterial は、同様のシェーダーを必要とするマテリアルの再利用に優れていますが、カスタムシェーダーを使用する場合は、可能な限り再利用するようにしてください。Godotの優先順位は次のようになります:

  • マテリアルの再利用: シーン内の異なるマテリアルが少ないほど、レンダリングは高速になります。シーンに大量のオブジェクト(数百または数千)がある場合は、マテリアルを再利用するか、最悪の場合はアトラスを使用してください。
  • シェーダーの再利用: マテリアルを再利用できない場合は、少なくともシェーダー(またはパラメーターが異なるが同じ構成のSpatialMaterials)を再利用してください。

たとえば、シーンにそれぞれ2万個の異なるマテリアルを持つ2万個のオブジェクトがある場合、レンダリングが遅くなります。それに対し、同じシーンに2万個のオブジェクトがあり、100個のマテリアルのみを使用している場合、レンダリングは非常に高速になります。

ピクセルコストと頂点コスト

モデル内のポリゴンの数が少ないほど、レンダリングが速くなるというのが一般的な考え方です。これは 本当に 相対的であり、多くの要因に依存します。

最新のPCおよびコンソールでは、頂点コストは低くなっています。 GPUはもともと三角形のみをレンダリングしたため、すべての頂点は:

  1. CPUによって変換される必要がありました(クリッピングを含む)。
  2. メインRAMからGPUメモリに送信する必要がありました。

現在、これらはすべてGPU内で処理されるため、パフォーマンスは非常に高くなっています。 3D DCC(Blender、Maxなど)は、編集するためにジオメトリをCPUメモリに保持し、実際のパフォーマンスを低下させる必要があるため、3Dアーティストは通常、ポリカウントパフォーマンスについて誤った感覚を抱いています。真実は、3Dエンジンによってレンダリングされたモデルは、3D DCCがそれらを表示する方法よりもはるかに最適です。

モバイルデバイスでは、話は異なります。 PCおよびコンソールのGPUは、必要なだけ電力グリッドから電力を引き出すことができる強引なモンスターです。モバイルGPUは小さなバッテリーに制限されているため、電力効率を大幅に向上させる必要があります。

より効率的にするために、モバイルGPUは 多重描画 を回避しようとします。つまりそれは、スクリーン上の同じピクセルが(ライティング計算などで)複数回レンダリングされることです。複数の建物がある町を想像してください。GPUは、描画するまで何が見えて何が隠れているかを知りません。家が描かれ、その前に別の家が描かれる場合があります(同じピクセルで2回レンダリングが行われました!)。通常、PCのGPUはこれをあまり気にせず、より多くのピクセルプロセッサをハードウェアに投入してパフォーマンスを向上させます(ただし、これにより消費電力も増加します)。

モバイルでは、より多くの電力を引き出すことはオプションではないため、画面をグリッドに分割する「タイルベースレンダリング」と呼ばれる手法が使用されます(ほぼすべてのモバイルハードウェアがそのバリアントを使用します)。各セルは、そこに描かれた三角形のリストを保持し、多重描画 を最小化するために深さで並べ替えます。この手法は、パフォーマンスを向上させ、消費電力を削減しますが、頂点のパフォーマンスに大きな負荷がかかります。その結果、描画のために処理できる頂点と三角形が少なくなります。

一般的に、これはそれほど悪いことではありませんが、回避する必要があるモバイルのコーナーケース(めったに発生しない厄介な状況)があります。これは、画面の小さな部分に多くのジオメトリを持つ小さなオブジェクトを配置することです。これにより、モバイルGPUは単一の画面セルに大きな負担をかけ、パフォーマンスが大幅に低下します(他のすべてのセルは、フレームを表示するためにそのセルが完了するまで待機する必要があるため)。

処理時間を短くするために、モバイルで頂点数をあまり気にせず、画面の小さな部分に頂点が集中しないようにします。たとえば、キャラクター、NPC、車両などが遠く離れている場合(小さく見える)は、代わりにより小さい詳細レベル(LOD)モデルを使用します。

頂点コストを考慮する必要がある追加の状況は、次のような頂点ごとに追加の処理があるオブジェクトです:

  • スキニング(骨格アニメーション)
  • モーフ(シェイプキー)
  • 頂点ライトオブジェクト(モバイルで共通)

テクスチャ圧縮

Godotは、3Dモデルをインポートする際にテクスチャを圧縮することができます(VRAM圧縮)。PNGやJPGとくらべると、Video RAM圧縮はサイズの点で及びませんが、しかし描写性能は非常に向上します。

なぜならテクスチャ圧縮は、メモリとGPU間の帯域を減らすことを一番の目的としているからです。

3Dでは、オブジェクトの形状は、テクスチャよりもジオメトリによるところが大きいので、普通は圧縮しても見分けはつきません。2Dの場合、圧縮はテクスチャ内に描かれた形状も変化させてしまうため、違いがより目立つようになります。

注意すべき点として、Androidデバイスでは透過のあるテクスチャの圧縮はサポートされていません(非透過のみ)ので、気をつけてください。

透明なオブジェクト

前述したように、Godotはパフォーマンスを向上させるために、マテリアルとシェーダーでオブジェクトを並べ替えます。ただし、これは透明なオブジェクトでは実行できません。透明なオブジェクトは後ろから前にレンダリングして、作業の背後にあるものとブレンドします。その為、透明なオブジェクトを最小限に抑えるようにしてください!オブジェクトに透明度のある小さなセクションがある場合は、そのセクションを別のマテリアルにしてください。

レベルオブディテール(LOD)

前述したように、頂点の少ないオブジェクトを使用すると、パフォーマンスが向上する場合があります。 Godotにはレベルオブディテールを変更するシンプルなシステムがあり、GeometryInstance ベースのオブジェクトには定義可能な可視範囲があります。複数のGeometryInstanceオブジェクトが異なる可視範囲にあると、LODとして機能します。

インスタンス化を使用する(MultiMesh)

複数の同一のオブジェクトを同じ場所または近くに描画する必要がある場合は、代わりに MultiMesh を使用してみてください。 MultiMeshは、非常に少ないパフォーマンスコストで数十万のオブジェクトを描画できるため、群れ、草、パーティクルなどに最適です。

ライトの焼き込み(ベイク)

通常、少数のライトはパフォーマンスの問題にはなりません。影に関してはもう少し影響が大きいです。一般的に、複数のライトがシーンに影響を与える必要がある場合、ベイク処理(焼き込み)をするのが理想的です(ベイクドライトマップ(焼き込み済ライトマップ))。焼き込みは、間接的なライトバウンスを追加することでシーンの品質を向上させることもできます。

モバイルで作業する場合は、この方法でさらに高速になるため、テクスチャにベイクすることをお勧めします。