Nanite フォリッジは、Nanite 仮想化ジオメトリ レンダリングを使用して高密度、高精細なフォリッジを大規模に実現する、一連の統合システムです。 Nanite フォリッジは、インスタンス化、スキンメッシュ、ボクセル化、アニメーション、マテリアル特性といった新旧の技術を駆使し、広大な景観のあるオープン ワールドを、元のフレームコストの数分の 1 で高品質にレンダリングします。 組み合わせることで、生き生きとしたアニメーション フォリッジを使用して、より強固なワールドを作り出すことができます。
Nanite フォリッジの目標とその方向性を理解するには、過去に有効だった方法が、将来このような完全に実現された世界を作成する上で効率的ではないことを理解することが重要です。
ここでは、「古い方法」でのフォリッジ作成が Nanite フォリッジに適さない理由をいくつか見ていきます。
Alpha Masking (アルファ マスキング) | 100% Nanite Triangle Representation (100% Nanite 三角形表現) | World Position Offset (WPO) Material (ワールド位置オフセット マテリアル) |
Alpha Masking (アルファ マスキング):Nanite は、オーバードローが大量に発生するだけでなく、潜在的に高負荷のマスク関数を実行する必要があるため、アルファ マスキングと相性がよくありません。 また、アルファ マスキングを使用すると、フォリッジは本来表現可能な幾何学的複雑さではなく、平面のカードとしてレンダリングされ続けます。
Full Nanite Triangle Representation (完全な Nanite 三角形表現): クラスタ カリングが最適ではなくなり、遠景の簡素化も不十分になります。 また、各フォリッジ タイプを保存するには、大量のディスク容量が必要です。
World Position Offset (WPO) (ワールド位置オフセット):これまで、マテリアルで WPO を使用してフォリッジの葉や枝を動かすことで、風をシミュレートしていました。 ですが、これは Nanite が得意とする描画方法とはあまり相性が良くありません。というのも、WPO は頂点ごとの計算を追加し、さらにマテリアルが頂点をどのように動かすかを事前に知る方法がないため、クラスタ境界を保守的に設定せざるを得ず、最適とは言えない状態になってしまうからです。
何がうまくいかないのかがわかったところで、Nanite フォリッジ パイプラインを使って、葉や針葉の 1 本 1 本まで完全にモデル化した樹木をレンダリングする様子を見てみましょう。 このパイプラインは、メモリ効率、パフォーマンス、そして詳細度 (LOD) メッシュを必要とせずに高度なダイナミック性を実現しながら、広大なオープン ワールドにスケールする必要があります。
これを実現するために、Nanite フォリッジは、以下の 3 つのシステムで構成されています。
Nanite アセンブリは、フォリッジの微細なインスタンスとなる「パーツ」です。 これにより、メモリとディスク容量を大幅に削減できます。
Nanite ボクセルは、カメラの距離に基づいて三角形のディテール、アニメーション、マテリアルのプロパティを維持する、ピクセル サイズに近い集合ボクセルです。 三角形はシームレスにボクセルに切り替わることで、高密度で動的な集合三角形メッシュのレンダリングの問題を解決します。 これらのボクセルは画面上では小さいため、目に見えません。
Nanite スキニングでは、ボーン階層を介して風をシミュレートするシステムなど、フォリッジの動的な動作を定義します。 風アニメーションのシミュレーションに WPO を使用しないことで、Nanite フォリッジで最適なクラスタ境界を使用できます。
以下の例は、これらがどのように連携して動作するかを示しています。 カメラが細部にズームインすると、松葉の 1 本 1 本まで、木がいかに緻密に表現されているかがわかります。 カメラが離れると、Nanite クラスターが十分に小さくなり、シームレスにボクセルに移行します。 これにより、遠くの木はビルボードや LOD に頼ることなく、遠くからでもボリュメトリックな外観を維持することができます。
この木は、以下のようになります。
4,100万個の三角形
12 個の固有のアセンブリ パーツ
2160 個のアセンブリ パーツ インスタンス
850 個のスケルタル ボーン
Nanite フォリッジを有効にする
プロジェクトの Nanite フォリッジを有効にするには、[Projec Settings (プロジェクト設定)] > [Rendering (レンダリング)] で、[Nanite Foliage (Nanite フォリッジ)] のボックスにチェックを入れます。 変更を有効にするには、エディターを再起動します。
Nanite アセンブリ
Nanite アセンブリは、Nanite フォリッジの主要なコンポーネントであり、木の枝や葉など、繰り返し使用される複雑なジオメトリのレンダリングを効率的に処理するように設計されています。 アセンブリは、スタティック メッシュ アセットとスケルタルメッシュ アセットの両方で機能し、小さく、高精細なパーツの「マイクロ インスタンス化」が可能です。 最大で 65,000 個の他のメッシュのインスタンスを含めることができます。 これらのインスタンスは、アセンブリの「パーツ」と呼ばれます。 このアプローチにより、ディスク容量とストリーミング容量を大幅に節約できますが、クラスタ カリング時のパフォーマンスはわずかに低下します。
Nanite アセンブリは、パーツ メッシュのクラスタを取得し、ビルド時にパーツのジオメトリを複製することなく、最終メッシュの階層にエンコードすることで機能します。 ランタイムでは、Nanite はクラスタ カリングの過程で階層を下降しながら、パーツ インスタンスの最終的なトランスフォームをオンデマンドで計算します。
Nanite 非対応のプラットフォームでは、パーツの三角形が変換され、1 つのメッシュに統合されます。 その後、通常の Nanite フォールバック メッシュと同様に動作する、フォールバック メッシュを生成するために簡素化されます。
アセンブリは Nanite フォリッジの重要な部分です。 使用しないと、Unreal Fest The Witcher 4 テクニカル デモで見られたような広大な森をレンダリングする際に、ディスク容量やストリーミング メモリが不足します。 たとえば、デモで最も大きな木の UASSET ディスク容量は、3.5 ギガバイト (Gb)から、約 29 メガバイト (Mb) に減少しました。 あるビューの木 1 本のみのストリーミング メモリは、約 36 MB から約 2.7 MB に減少しました。 このような削減により、シーン内に数十種類の木のバリエーションを 50 万インスタンス配置し、それぞれの木が 100 万〜1,000 万ポリゴンの高精細であったとしても描画が可能になります。
Unreal Engine でのアセンブリの使用と作成の詳細は、「Nanite アセンブリ」を参照してください。
Nanite ボクセル
Nanite ボクセルは、ピクセル サイズのボクセルで、表現するジオメトリのディテール、アニメーション、マテリアルのプロパティを維持し、木の葉などのボリュメトリックな外観を維持します。 遠景で葉の形状が失われるのを防ぐ、これまでの Nanite 技術では、簡素化プロセスでそれらが削除されると、残った三角形にサーフェス領域を追加することで十分機能していました。 これは、遠景で簡素化された葉の塊をレンダリングする際に、フォリッジ ジオメトリが疎になってしまうのを防ぐための対策でした。
ラスタライズ処理
Nanite ボクセルは、遠距離での簡素化の間、集合ジオメトリ (切断された要素) の一般的なシルエットを保持することができます。 これらのボクセルが有効なメッシュのクラスタを簡素化する場合、Nanite ビルダーによって、最大 128 個の 4x4x4 のボクセル レンガのクラスタにボクセル化されます。 ボクセル表現の簡素化誤差は、簡素化によって三角形からボクセルに切り替えるかどうかの決め手となります。三角形を使用するよりも誤差が小さくなる場合は、ボクセルに切り替わります。
ランタイム時には、ボクセル クラスタは三角形クラスタとは別にビニングされ、特別なシェーダ順列によってラスタライズされます。 クラスタは深度バケットに分類され、前から後ろにラスタライズされます。これにより、早期 Z テストの利点が活かされ、最終結果は一般に、ラスタライズされた三角形よりも遠距離で優れたパフォーマンスを発揮します。
以下は、スタンドアーン アセットと The Witcher 4 テクニカル デモで視覚化されたボクセル化プロセスの例です。
シェーディング プロセス
1 つのボクセルで覆われた領域内には、異なる法線のある複数のサーフェスが含まれることがあります。 ボクセルごとに単一の法線を格納する代わりに、法線の分布を格納します。 これは、マテリアル粗さがシェーディングに使用されるマイクロファセットの分布を制御する方法と概念的に似ています。
GBuffer に書き込む場合、法線はこの分布からピクセルごとに確率的に選択されます。 将来のリリースでは、粗さと同様に、分布がシェーディングで直接考慮されるようになります。 これはノイズを低減するもので、 Witcher 4 のデモではすでに使用されています。
これには、分布の統計を格納するための追加データが必要です。 現在、これは頂点カラーのアルファチャンネルに格納されているため、既存のデータはオーバーライドされます。 これは将来、頂点カラーとは独立した別のデータに移行する可能性があります。
Nanite ボクセルを有効にする
Nanite ボクセル化を有効にするには、以下の手順を実行します。
スタティック メッシュの [Details (詳細)] パネルで、[Nanite Settings (Nanite 設定)] カテゴリを確認します。
Shape Preservation (形状保持) を見つけ、ドロップダウンで [Voxelize (ボクセル化)] を選択します。
[Voxelize (ボクセル化)] を設定すると、このドロップダウンの下の一部のプロパティが編集可能になります。 これらは、誰もが自分のプロジェクトに合わせて調整することを意図したものではありません。 一部はまだ開発中で、実際には意図したとおりに動作しないか、まったく動作しないものもあります。 これらの設定は、Unreal Engine の今後のバージョンで Nanite フォリッジの完成に伴って、変更または削除される可能性があります。
Nanite フォリッジのアニメーションに Nanite スキニングを使用する
ゲームにおけるフォリッジの風のアニメーションは、その多くがマテリアル (通常、木の枝や葉に使用されるマテリアル) のワールド位置オフセット (WPO) を使用して行われます。 特定の頂点に対する WPO は 任意のオフセット量になり得るため、アーティストは、フォリッジ用マテリアルに対して、最悪のケースを想定した最大 WPO ディスプレースメントを設定しておく必要があります。これは、フォリッジのカリング (不要部分を描画しない処理) を正しく行うために、カリング境界に余裕を持たせるためです。 ただし、その結果、過度に慎重な境界になり、高いオーバードロー負荷につながる可能性があります。
WPO によって頂点シェーダーのロジックも変更されるため、各マテリアルは個別のディスパッチにビニングされ、GPU 負荷が増加します。 多くのマテリアルでは、これらのプログラム可能なラスタ ビンが、パフォーマンスの問題になることがあります。
Nanite スキニングは、この問題を解決します。スキニング マトリックスからより正確な境界を計算し、すべてで固定関数ラスタライザーを使用できるためです。
以下のショットでは、10 万個のボーンが更新されています。GPU で約 0.1 ミリ秒しかかからないので、Nanite フォリッジは高速かつスケーラブルです。 アニメーションは特定の画面サイズよりも小さい木に自動的に適用されず、風は遠く離れた木にも影響を与え、没入感が向上します。 これは、スケルタル メッシュを使用している草や茂みにも適用されます。
Dynamic Wind プラグイン
これは実験段階のプラグインです。
Dynamic Wind (ダイナミック ウィンド) プラグインは、Nanite フォリッジと連携するように設計されています。 これには、特定のスケルタル メッシュ用のDynamic Wind Skeletal Data (ダイナミック ウィンド スケルタル データ) アセットを使用した、いくつかの追加設定が必要です。 このアセットのデータによって、スケルトンのボーンが Simulation Groups (シミュレーション グループ) に分類されます。これにより、システムによるシミュレーション内のボーンチェーンを論理的に識別できるようになり、グループごとに風の影響を調整できるようになります。
このプラグインは、プラグイン ブラウザ [Rendering (レンダリング)] カテゴリで有効にできます。
このプラグインは、.JSON ファイルから必要なデータをインポートするためのスクリプト化されたアセット アクションを提供します。 また、スケルトンに適用してこのデータを提供するための Universal Scene Description (ユニバーサル シーン デスクリプション (USD)) スキーマと、USD から JSON ファイルを作成するためのサンプル Python スクリプトも含まれています。
ダイナミック風トランスフォーム プロバイダ データ
Dynamic Wind Data (ダイナミック風データ) アセットのユーザー データを含むスケルタル メッシュは、このデータを使用して、インスタンス化されたスキン メッシュ コンポーネントで風のアニメーションを制御できます。
スキン メッシュで風を有効にするには、コンポーネントの [Transform Provider (トランスフォーム プロバイダ)] ドロップダウンを使用して[Transform Provider Data (トランスフォーム プロバイダ データ)] を選択します。 これにより、メッシュに新しい Dynamic Wind Data (ダイナミック風データ) アセットが作成されます。
このアセットは、コンポーネントを風システムに登録するために必要です。 これは、他の目的には役立ちません (現時点で)。
現在の制限事項は、以下のとおりです。
近距離フィールドなど、物理ベース シミュレーションを追加する。
グローバルな風向のみをサポートする。
プレイヤーやオブジェクトとのコリジョンは発生しない。
ダイナミック風スケルタルデータは、JSON ファイルでインポートする必要がある。
将来的には、USD インポート時に自動で取り込まれる予定。
ダイナミック風トランスフォーム プロバイダ データに調整を加える。
Nanite スキニング パフォーマンスのヒント
Nanite スキニングは、フォリッジの風の動きに対して WPO よりも効果的ですが、パフォーマンスについては注意が必要です。
次のことに留意してください。
Virtual Shadow Map (仮想シャドウマップ (VSM)) のパフォーマンスを高めるには、遠方のアニメーションを無効にする必要があります。
無効になっているインスタンス化されたメッシュは、スキン処理されていないラスタ ビンに切り替わり、固定機能スタティック メッシュ (バインド ポーズ) のようにレンダリングされます。
オブジェクトが画面上で小さい場合にスキニングを無効にするには、コンポーネントにAnimation Min Screen Size (アニメーションの最小画面サイズ) を使用します。
これは、World Position Offset Disable Distance (ワールド位置オフセットの無効化距離) 設定と似ていますが、常に有効です。 0 のままであれば、グローバル デフォルト値 (アニメーションが停止しているときのオブジェクトの画面サイズの 1/10 (0.1)) が使用されます。 これは、コンソール コマンド
r.Skinning.DefaultAnimationMinScreenSizeを使用して変更できます。