
まえがき
Metroシリーズの最後のゲームのリリース後、私は数時間を費やして内部の研究を行い、技術的な観点から興味深いと思われることを共有することにしました。 詳細な分析を行ったり、シェーダーの逆アセンブルされたコードを調べたりすることはしませんが、ゲームの作成プロセスで開発者が行った高度な決定を示します。
現時点では、開発者はゲームで使用されているレンダリング技術についてまだ話していません。 唯一の公式情報源はGDCレポートであり、インターネット上の他の場所では見つけることができません。 そして、これは面倒です。なぜなら、このゲームはMetroシリーズの以前のゲームから進化した非常に興味深い独自のエンジンで実行されているからです。 これは、 DXRを使用した最初のゲームの1つです。
注:この記事は完全な説明ではありません。追加する価値があるものが見つかった場合は、この記事に戻ります。 おそらく、ゲームの次の段階でしか表示されない側面があるか、詳細を確認しただけなので、何かを見逃したのでしょう。
最初のステップ
このゲームで動作する環境を見つけるのに数日かかりました。 RenderDocとPIXのいくつかのバージョンをテストした後、Nvidia NSightを使用してレイトレーシングの結果を調べることにしました。 レイトレーシングなしでレンダリングを学びたかったのですが、NSightではこの機能の詳細も調べることができたため、そのままにしておくことにしました。 レンダリングの残りの部分では、PIXが適しています。 スクリーンショットは両方のアプリケーションを使用して撮影されました。
NSightには1つの欠点があります-キャプチャのファイルへの保存をサポートしていないため、勉強していたフレームに戻ることができませんでした。
作業の最初の段階で、フレームデバッグアプリケーションとは関係のない別の問題に遭遇しました。レイトレーシング機能には最新のWindows更新プログラムのインストールが必要でしたが、更新プログラムをインストールせずにオプションに含めることができました。 この場合、機能を含めると、起動時にゲームがクラッシュしました。 また、GeForce Experienceは、これらの機能を有効にするために正しいバージョンのWindowsが必要であることについては何も述べていません。 この問題は、両側で対処する必要があります。
完全を期すために、可能な限り最大のパラメーターを使用して実行しているゲームからキャプチャーを行いましたが、DLSSは使用していません。
フレーム分析

完成したフレーム
簡単なレンダリング分析は、レイトレースGIによって実行されるグローバル照明を除いて、かなり標準的な一連の機能を示しています。
画像をレンダリングする前に、前のフレームのスケールが計算キューで縮小され、平均輝度が計算されます。
グラフィックキューは、後処理段階で適用される歪み粒子(カメラ上の液滴)のレンダリングから始まります。 次に、深さの簡単な予備パスにより、Gbufferの前に深さの一部が作成されます。 安reliefをもたらすだけのようです。
GBufferパスは、下の図に従って4つのレンダーターゲットを満たし、深度バッファーの埋め合わせも完了します。


1.アルベドと、場合によってはアルファチャネルのアンビエントオクルージョンを使用したRGBA8形式のターゲット。 一部の表面では非常に暗く見えます。


2.法線と、場合によってはアルファチャネルの表面下散乱マスクを使用して、RGB10A2形式のターゲットを設定します。


3.他の材料パラメーター、おそらくアルファチャンネルの金属性と粗さを持つRGBA8形式のターゲット。 奇妙なことに、この場合のRGBチャンネルにはまったく同じデータが含まれています。

4. 2Dモーションベクトルを使用したRG16F形式のターゲット。
深度が完全に満たされると、線形深度バッファが構築され、スケールが減少します。 これはすべて計算キューで行われます。 同じキュー内で、バッファはシャドウを使用せずに指向性照明に似たもので満たされます。
グラフィックスキューでは、GPUはグローバルイルミネーションの光線をトレースしますが、これについては以下で詳しく説明します。


計算キューは、アンビエントオクルージョン、反射、およびエッジ認識に類似した何かを計算します。
グラフィックキューでは、4段階のシャドウマップがサイズ6k * 6kの32ビット深度マップにレンダリングされます。 詳細については、以下をご覧ください。 有向影のマップが完了すると、不明な理由で3番目のカスケードの解像度が768 * 768に低下します。

シャドウレンダリングプロセスの途中で、奇妙な瞬間があります:詐欺師アトラスは、照明からローカルシャドウをレンダリングする前にいくつかのオブジェクトによって補完されます(詐欺師はここで見つけることができます )。 なりすましバッファとローカルライティングシャドウバッファも6k * 6kテクスチャです。
すべての影が完成すると、照明の計算が開始されます。 レンダリングのこの部分は、不可解です。これは、いくつかの不可解なアクションを実行する多くのレンダリングがあり、追加の調査が必要だからです。

シーンのレンダリングは、正面から照らされたオブジェクト(目、パーティクル)で終了します。 視覚効果は半解像度のバッファーにレンダリングされ、その後ズームを使用して不透明なオブジェクトと合成されます。

最終的な画像は、色調補正とブルーム計算によって実現されます(色調補正を使用してフレームの解像度を下げてから上げます)。 最後に、UIは別のバッファーにレンダリングされ、ブルーム合成とともにシーンの上部に重ねられます。
スムージングが実行される部分が見つからなかったため、後で使用します。
グローバル光線追跡
レイトレースGIによって実行されるグローバルライティングに関する情報。 この加速構造は、ゲーム世界の広い範囲(おそらく数百メートル)をカバーし、あらゆる場所で非常に高いディテールを維持します。 どういうわけかストリーミングしているようです。 加速構造のシーンは、ラスタライズされたシーンと一致しません。たとえば、下の画像の建物はラスタライズされた形式では表示されません。

平面図
ここでは、プレーヤーの位置を囲む4つのタイルを見ることができます。 また、アルファチャネルでテストされているジオメトリがないことも明らかです。 木には幹がありますが、葉も草も茂みもありません。

ビューを閉じる
クローズアップビューでは、オブジェクトの詳細と密度がよりよく見えます。 異なる色の各オブジェクトには、下位レベルの加速構造があります。 この写真にのみ数百があります。

足下のプレイヤーアイテム
興味深いことに、プレイヤーのアイテムも加速構造の一部ですが、何らかの理由で彼の足下にあります。

スキニングが壊れていますか?

スキニングが再び壊れましたか?
スキニングのあるオブジェクトの一部は、加速構造で壊れています。 観察される問題の1つは、メッシュを(子供の足で)伸ばすことです。 別の問題は、スキニングを使用したキャラクターの異なる部分が異なる位置にあるという事実につながります。 ストレッチはありませんが、パーツは互いに分離されています。 これは、グローバルレイトレーシングライティングでは見えないようです。少なくとも、ゲームではまだ気づいていません。

膨大な数のオブジェクト
より一般的な平面では、加速構造内にさまざまなオブジェクトがいくつあるかを確認できます。 それらのほとんどは、グローバルイルミネーションの計算結果に実際には寄与しません。 また、LODスキームがないことも確認できます。 すべてのオブジェクトが完全な詳細で追加されます。 これがレイトレーシングに影響を与えるかどうかを知ることは興味深いでしょう(そうだと仮定します)。

超高LOD、各スケールとスイッチが完全にモデル化
別のスクリーンショットは、プレーヤーから遠く離れたオブジェクトの詳細を示しています。 この図の各スイッチと各スケールは、テクスチャがなくてもはっきりと読み取れます。 このスクリーンショットを撮るためにカメラを移動した場所は、プレーヤーから数十メートルのところにあり、これらの詳細をなくしても写真の品質は低下しませんでした。 おそらく、LODを使用して加速構造を更新するとコストがかかりすぎますが、この更新を非同期で実行できる可能性が高くなります。 この点は間違いなくもっと詳しく調べる価値があります。
指向性シャドウのレンダリング
シャドウのレンダリングの主要部分は単純であり、特別な言及は必要ありませんが、ここには興味深い点があります。

シャドウキャスティングの可能性が低いメッシュ

シャドウマップの詳細

間違ったインデックスバッファを使用しているように見えるメッシュ
加速構造のように、シャドウレンダリングには完全にすべてが含まれているようです。 シャドウマップにほとんど寄与しないオブジェクトもありますが、それでもレンダリングされます。 これが許可のために起こるのか、それともエンジンでそれらを除外する簡単な方法はないのだろうか?
画面スペースに影があっても気づきにくいオブジェクトがあります。 それらをレンダリングするのにそれほど時間はかかりませんが、少し時間を節約するためにそれらを削除できるかどうかを確認するのは興味深いでしょう。
メッシュを調べると、シャドウマップでレンダリングされたメッシュの一部に破損したインデックスバッファーがあるように見えますが、頂点シェーダーの後は正しく見えます(結果はPIXとNSightで同じです)。 これは私が見つけた最高の例ですが、それだけではありません。 たぶん、これはある種の特別なパッケージングの位置ですか?

メッシュのスキニングが不十分なようです
スキニングは、構造の加速だけでなく問題を引き起こしているようです。 興味深いことに、画面上に目に見えるアーティファクトが生じることはありません。
パート2

マイナー修正

前のパートで、GBufferバッファーの3番目のレンダーターゲットには金属性が含まれている可能性が高いと書きましたが、実際には鏡面反射色が含まれているようです。 最初は色が見えず、3つのRGBチャンネルすべてに同じデータが含まれている理由がわかりませんでしたが、それはおそらくシーンに色の反射がなかったためです。 この武器の場合、バッファーにはさらに多くの異なる色が含まれています。
また、ゲームのレンダリングを調査する過程で見つけたお気に入りのテクスチャを追加するのを忘れました。 ゲーム開発の混oticとした性質を常にクリーンアップすることができない場合にそれを実証するため、言及する価値があります。

「私を改善してください!」
透明度の合成とアンチエイリアス
ハーフサイズの透明度バッファーの解像度がどのように増加し、ゲームがアンチエイリアシングを実行する方法を把握しようとすると、興味深いことがわかりました。 何が起こっているのかがはっきりと見えるように、もっとコントラストのあるシーンが必要でした。 幸いなことに、プレイヤーの武器がフレーム間でわずかに移動するフレームをキャプチャできました。

透明度をレンダリングする前に
透明度バッファを合成する前に、バッファにはすでに完全にレンダリングされた画像が含まれており、このフレームには鋭いエッジがないため、これが前のフレームのデータであると仮定するのが論理的です。

現在のフレームの透明度を合成した後
現在のフレームに透明度を追加すると、個々のエッジが壊れていることがわかります。 武器がわずかに右に移動したために起こりました。 一部の雲は透明にレンダリングされますが、地平線(不透明)にクリップされるため、合成によって下部は変更されませんが、現在のフレームの深度バッファーを使用して前のフレームから武器メッシュ上に既にレンダリングされます。

現在のフレームに不透明度を追加した後
いくつかの描画呼び出しの後、合成メッシュと不透明メッシュが実行されます。 この順序でこれを行う特別な理由はないようです。 透明バッファを現在のフレームの不透明オブジェクトのデータに構成することは論理的ですが、これは起こりません。その理由を知ることは興味深いでしょう。

TAAの後
フルフレームの完了後、TAA(時間的平滑化)パスはエッジを平滑化します。 平滑化がどこで行われるのかわからなかったので、私はすでにこれに興味がありました。 ただし、このドローコールの直後にブルームパスのダウンサンプリングが開始され、この1つのドローコールを逃したため、これをスキップしました。
レンズフレア
通常、個々の効果を分析したくありませんが、レンズフレアを実装する方法はたくさんあります。そのため、どの開発者が選んだのか興味がありました。

既製の合成におけるレンズフレア
ほとんどの場合、レンズのフレアはほとんど目立ちませんが、これは美しい効果です。 スクリーンショットで表示するのは難しいので、これにはあまり努力しません。

ブルームバッファのレンズフレア
検索した後、この効果を追加する描画呼び出しを見つけましたが、これはブルームの解像度を上げる最後の段階の後の呼び出しであることがわかりました。 このバッファーでは、その効果がより顕著になります。

ジオメトリレンズフレア
ジオメトリを見ると、レンズフレアは非常に簡単です。 画面上に完成した結果を作成するには、少なくとも6つの四角形が含まれますが、太陽の位置に近づく一連の小さな四角形はありません。 これはかなり標準的なソリューションであると結論付けることができますが、レンダーターゲットシーンでレンズフレアを直接レンダリングする開発者もいれば、後処理として効果を計算する開発者もいます。
地形レンダリング
すべてのオープンワールドゲームで最も興味深い問題の1つは、地形のレンダリングです。 私はこの側面を研究することは興味深いように思えるかもしれませんが、率直に言って、少しがっかりしています。

一見すると、レリーフの断片は、何らかのテッセレーションが実行されているように見えます。 移動中にレリーフが変形する方法により、追加の変位があると仮定することが論理的になります。 さらに、PCでは、ゲームは積極的にテッセレーションを使用するため、安心して使用することは理にかなっています。

おそらく間違ったパラメーターが設定されていたかもしれませんが、ゲームはテッセレーションなしですべてのレリーフフラグメントをレンダリングします。 レリーフの断片ごとに、彼女はこの均一な32 * 32グリッドを使用します。 LODもありません。

頂点シェーダーの後のレリーフフラグメントを見ると、ほとんどの頂点のペアがマージされ、ほぼ完全な16 * 16グリッドを形成していることがわかります(ただし、おそらくレリーフの曲率のため)。 上記の変形は、レリーフがカメラから遠いときにレリーフの標高マップのミップテクスチャを読み取るために発生する可能性があります。
光線追跡のトリック
そして今、誰もが待っていたものについて。
ストリーミングデータ
現時点でのDXR実装の最も興味深い側面の1つは、データを処理する方法です。 最も重要なことは、データが加速構造にどのようにロードされ、どのように更新されるかです。 これをテストするために、2つのキャプチャを取得し、NSightの加速構造を比較しました。

プレイヤーは船の中にいます
最初のキャプチャでは、この画像の中央に見える壊れた船の中に立っていました。 マップの端にある大きな岩を除き、最も近いオブジェクトのみがロードされます。

プレーヤーはこの画像の左上隅に移動しました。
2番目のキャプチャでは、マップの端から離れて、画像の左上端に近づきました。 船とその周りのすべてのものはまだロードされていますが、新しいオブジェクトもロードされています。 興味深いことに、タイル構造を定義できません。 オブジェクトは、距離と可視性に基づいて加速構造にロード/削除できます(平行四辺形を制限する可能性があります)。 さらに、右上のエッジはより詳細に見えますが、そこから離れています。 これについてもっと知るのは面白いでしょう。
救済とその下にあるもの
Metro:地形に関する出エジプト記でのDXR実装のいくつかの側面に言及できます。

第一に、加速構造にレリーフメッシュが含まれていないことは興味深い(特別な場合を除く)。 これらのモンスターは実際には地上でゲームを実行しますが、NSightのデータから判断すると、飛行していると思われるかもしれません。 これは、私たちにとって興味深い質問です。グローバルライティングの実装では、何らかの方法でレリーフを考慮に入れることができますか(高さマップとレリーフマテリアルを使用する場合)。

次の瞬間、私は救済がきちんと整っていれば気付かなかったでしょう。 NSightの加速構造のレベルの開始を見ると、レリーフの下にいくつかのメッシュがあります。

アーティストは、さまざまな理由で、デバッグメッシュをレベルの下に配置することがよくありますが、通常はゲームがリリースされる前に削除されます。 この場合、これらのメッシュはリリースまで生き残っただけでなく、加速構造の一部にもなりました。

上記に加えて、他のメッシュがレリーフの下に散らばっていることを見つけました。 基本的に、彼らはあまり言及する価値はありませんが、これは非常に興味深いものでした-これはレベルの開始点の真下に立っているキャラクターです。 独自のプールもあります。

最後に、加速構造の最後の不思議な要素は、レベルの外側に見える片面メッシュです。 彼らが二国間と見なされない限り、彼らがゲームの絵に貢献する可能性はほとんどありません。 メッシュが両面であっても、再生可能な領域から離れているため、おそらく加速構造を引き伸ばしているだけです。 それらがフィルタリングされていないことは興味深いことです。 この画像には、列車と建物の間の右下隅にある「レリーフメッシュ」の特殊なケースの1つも表示されています。
スキニングによる頭のなさ
メッシュのスキニングの問題についてはすでに説明しましたが、このレベルでは他のことに気付きました。

まず、このモンスターは1つの画像に両方のエラーを示しています。 私はまだそれらの原因を疑問に思っています。

また、コウモリのようなこれらの小さな生き物は、加速構造に頭がないことに気付きました。

別の例。 頭があるはずの穴に注意してください。 頭が見える単一のケースを見たことはありません。

ラスタライズモードの同じ種類のクリーチャー。 頭がはっきりと見えることに注意してください。

そして、これが頭のワイヤーフレームです。
結論として
今日は以上です。 Metro:Exodusの内部をご覧になったことをお楽しみください。
ゲームのレンダリングについては引き続き調査しますが、人々にとって興味深い部分や共有する価値のある部分を見つけない限り、記事の新しい部分を公開しません。