植物メッシュを地面の高さに合わせる処理の最適な手法について

お世話になっております。

表題の件について

現在、背の低い草などの植物を、地面(ランドスケープと、岩などの一部スタティックメッシュ)に吸着させる用途で、RVTに書き込んだ高さを植物マテリアルで読み込んで同じ高さになるようにWPOを変更する対応を行うことを検討しています。

その場合の最適化として、RVTサンプル処理をカスタムノード化して動的分岐(Dynamic Branch)として記述し、必要なインスタンスでのみRVTの読み込みを行う予定です。

「Per Instance Custom Data」等で「地面に吸着するかどうか」のフラグをインスタンスごとに設定し、カスタムノード内でそのフラグを見てRVTを読み込むかどうかの分岐を行うイメージです。

使用する植物は、1つのStaticMesh内に複数の草を含んでいます。ISMのインスタンス数を減らしNanite IDの枯渇を防止するためです。

---

以上を踏まえ、下記について見解をお聞かせいただいてもよろしいでしょうか?

  • RVTへ書き込んだHeightを使う手法が、植物の地面への吸着実現の方法として適切か
    • 処理負荷の観点からもっと良い方法があればご教示いただけると幸いです。
  • 上記手法が適切な場合、「Runtime Virtual Texture Sample Param」ノードで行われているRVTサンプル処理をカスタムノードの処理として書き起こす方法を知りたい

ご確認のほど、よろしくお願いいたします。

[Attachment Removed]

お世話になっております。

メッシュの位置を調整することについては幾つかの方法が考えられますが、何が最適であるかは様々な条件により異なります。

それぞれの負荷についても具体的には実際の実行環境およびゲーム中の様々な状況下で測定して頂く必要があります。

①WPO による移動

常に配置のためのシェーダー実行コストがあるはずですが、地形が頻繁に変化する場合であってもそのタイミングで特別に負荷が上昇したりしないという点でリスクが低い方法ではあると言えるかもしれません。

なお、調べた限りではマテリアルの Custom ノードは RVT のサンプリングに対応していないようです。

②ISMインスタンスの移動

UInstancedStaticMeshComponent::UpdateInstanceTransform によりインスタンスを移動させる方法も考えられます。

実行中に地形が変化しない場合、エディタで配置処理を完結させることができればこちらが優位になるかと思います。

地形は LineTrace 等により検出することになります。

③PCGの利用

PCG は UE5.7 から Production Ready となっています。

再配置ではなく生成ということになりますが、要件によってはこちらを利用できるかもしれません。

負荷の生じるタイミングは②に似るかと思いますが、GPU も使用されます。

https://dev.epicgames.com/documentation/ja-jp/unreal-engine/procedural-content-generation-overview#spawn-the-static-meshes

よろしくお願いいたします。

[Attachment Removed]

[mention removed]​

ご回答、誠にありがとうございます。

>②ISMインスタンスの移動

>③PCGの利用

これらについてはそれぞれインスタンスのトランスフォームを更新する形のため、地面の高さに正しく沿わせる場合は1つのインスタンスにつき植物が1つ含まれているような想定の実装になるかと思います。

そのため、大量に植物を配置した時のInstance ID枯渇を懸念しているのですが問題ないでしょうか?もしくは対策がありますでしょうか?

手元で検証した限り、Nanite FoliageによりVoxel化されたインスタンスもInstance IDを消費しておりましたので、Nanite Foliageの使用時にもID枯渇を考慮する必要があると考えています。

>①WPO による移動

現在検討しているのはこちらになります。

1インスタンスの中に複数の植物を含めても、インスタンス内の植物をそれぞれの場所の地面の高さに沿わせることができ、Instance IDの枯渇の防止もできると考えています。

ただランタイムでのRVTテクスチャサンプルを含むためやや負荷が高いことが分かっており、前者の②・③の方法でInstance IDの懸念がない場合はそれらの手法を選択する可能性が高いです。

よろしくお願いいたします。

[Attachment Removed]

ご確認ありがとうございます。

手元で確認したところ、IDの上限が16,777,216として設定されているようです。

SceneDefinitions.h
 
#define INSTANCE_ID_NUM_BITS				(24u) // Max of 16,777,216 instances in the buffer

実際にPCGを使用して大量の草インスタンスを配置してみたところ、画像のようにInstance Id がオーバーフローしている旨のメッセージが表示され、表示されないインスタンスが出てくる見た目となりました。

Instance Id は描画しうるすべてのインスタンスに振られるようです。

[Image Removed]

現在オープンワールドのプロジェクトを作成しており植物以外にも大量のオブジェクトが配置される想定のため、現実的に16,777,216を超えるIDが消費されるケースがあると考えています。

仮に最も配置が多くなりがちな植物のインスタンス数を抑える必要があるとなった場合、1インスタンスの中に複数の植物メッシュを含めた上で「①WPO による移動」による実装にするのが対応策となりそうです。

最適化目的ではRVT読み込み処理の動的分岐は可能であれば試したいです。

マテリアルの Custom ノードは RVT のサンプリングに対応していなそうだとご回答いただいておりますが、

例えば既存の実装を参考に自前でRVTサンプリング処理を作成するなど可能なのでしょうか?

実現への足がかりとなる方法など、ご存知でしたらご教示いただけますと幸いです。

[Attachment Removed]

ご確認ありがとうございます。

ISM の扱うインスタンス数の明示的な制約について、ドキュメントやソースコード上を調べた限りでは特に見つかりませんでした。

手元のプロジェクトで単に100万インスタンスほどを配置してみましたが動作が重くなるくらいでした。

各種リソースの消費はありますので無限に配置することはできませんが、通常は数について心配する必要はないかと思います。

よろしくお願いいたします。

[Attachment Removed]

>手元で確認したところ、IDの上限が16,777,216として設定されているようです。

失礼いたしました。

ご指摘の通り、シーン全体に対して上限が設定されているようです。

>自前でRVTサンプリング処理を作成するなど可能なのでしょうか?

参考にするとすれば UMaterialExpressionRuntimeVirtualTextureSample クラスおよびそれを参照している部分ということになりそうですが、おそらく難易度は高いです。

動的分岐が目的ということであればこれについて試行した記事がありますのでこちらが参考になるかと思います。

https://qiita.com/suzuki_takashi/items/88f033d07669da81f6eb

よろしくお願いいたします。

[Attachment Removed]