【UE5】えちえちなソフトボディシミュレーションを作ってみた – Unreal Engine 5.6

Unreal Engine

水ノ茉(こおり)の宣伝

叡智でえっちな同人作品を予定中…

Ci-en R18

同人作品の宣伝

  • 準 備 中 . . .

プラグインの宣伝

  • 準 備 中 . . .
  • 準 備 中 . . .

始まり

こういう表現ができる内製ソフトボディシミュレーションを作ったので紹介です。

お名前はReinPhysicsシリーズのReinSoftBodyちゃんです。

またの名をえちえちソフトボディシミュレーションです。

リポジトリ

準備中。

同人作品の開発が落ち着いたら公開するわ。

ソフトボディシミュレーションとは?

基本的にはクロスシミュレーションの亜種です。

根幹のアルゴリズムもPBD(Position Based Dynamics)を使用しています。

制約はエッジとボリュームの2種類です。

エッジはクロスと同様に、形状の維持を司る制約です。エッジを弱くすると垂れやすくなります。

ボリュームは、内部構造の維持を司る制約です。ボリュームが弱いと良く言えば柔らかいです。悪く言うと押し戻しが弱過ぎて、強く凹ませ過ぎると戻らなくなります。かと言って強すぎると内なるエネルギーを放出しようとして暴れ散らかします。

プラグインにお引越し

ReinClothと同様にプラグインで動作させるためにお引越し大作戦です。

ただ単に移植しても面白味が薄いので、劣った設計は見直して刷新していきます。

ということで第1世代とはお別れ。第2世代の誕生です。

エッジとボリューム

プラグイン設計に対応したソフトボディの爆誕です。

Dispatch発行の最小化

ReinClothの先行実証を参考にDispatchを可能な限りまとめる方針です。

エッジとボリュームのどちらかの最大数を元にスレッド数を決定します。

シェーダーの方はこんな感じで動的分岐で処理していきます。

これにより約0.2msほど負荷が改善しています。

uint BatchIndex = GetUnWrappedDispatchThreadId(GroupId, GroupThreadIndex, THREADGROUP_SIZEX);

BRANCH
if (BatchIndex < NumEdges) { ... }

BRANCH
if (BatchIndex < NumVolumes) { ... }

エッジとボリュームを別々に発行

ひとつにまとめて発行

ヤコビの精度をコストを払って改善

クロスはシミュレーション頂点数をLDSの対応範囲に収めるという制限を課すことで、高速で且つ高精度なシミュレーションを実現できました。しかし、ソフトボディは内部まで頂点がギッシリ詰まっている仕様上、LDSの対応範囲を優に超えます。

高速で且つ高精度を両立することは難しいため、後者の高精度に比重を多めにする方針にします。同様に制限を課せばある程度の両立は望めるかもしれませんが、それによって表現が劣ってしまっては本末転倒なので、思う存分に狂ったことをしていきます。それに、ソフトボディが思う存分暴れられるように、爆速なクロスシミュことReinClothを作ったという背景があるので、予算配分的には無問題なのです。遠慮せずに最強にエッチな見た目を作るために、バカほどコストを注ぎ込めます。無論、表現を削らない範囲での最適化は施します。

ということでヤコビの精度を32bitから64bitに格上げしました。

普通のBuffer

32bit ByteAddressBuffer

64bit ByteAddressBuffer

法線変位

おっぱいをムニムニ触った時の変化を明暗、陰として視認させるために、法線変位を実装します。

おそらく重み付き法線と呼ばれる手法を実装していきます。

処理の概略は以下の通りです。

  1. 面法線を計算
  2. 面を構成する各頂点に算出した面法線を正規化せずに加算
  3. 全ての面の処理が終わったら、各頂点に加算された法線を正規化
  4. 正規化したものを頂点法線として利用

この手法の利点は、とにかく高速なことです。ランタイムと相性抜群なのです。

法線変位なし

法線変位あり

赤丸のところが特に法線変位の影響によるシェーディングが分かりやすいです。

むにゅーん。ぼよーん。

重み付けをしていないので不自然なほど全体的に垂れ下がりますが、背中の肉感、ヤバくない?

ScatterからGatherに変更

法線計算パスが約11,800nsソフトボディ全体では約326,000nsほど掛かっています。

法線計算パス

ソフトボディ全体

現行の設計では2点ほどボトルネックになっています。

  1. 法線計算パスを発行していること
  2. 頂点法線の加算にアトミックを使用していること

これらを解消するために計算方式をScatterからGatherに変えていきます。

ReinClothでは、Gatherに置き換えるだけだと却って負荷が悪化しましたが、物は試しです。

結果は約10,000nsほど削減できました。

コリジョン

触ったり、押し付けたりする表現のためにコリジョンを実装していきます。

コリジョンの最大数は512個です。指にコリジョンを付けると結構消費するので、このくらいあった方が安心なのです。とはいえ、愚直に512個を処理すると負荷がエグいので、頂点あたりがそのフレームで影響を受けられるコリジョン数に制限を課して、最適化をしています。

スフィアコリジョン

ボックスコリジョン

これで机の角も出来ますね。ナニがとは言わんけど。

ワールド空間

シミュレーションの進行をローカル空間ではなく、ワールド空間で行うように変更です。これで重力の影響が直感的になりました。

アニメーション変位

アニメーションとコンポーネントやアクターのSRTの影響を変位として受けられるようにしました。これで揺れ揺れアニメーションの表現の幅が加速します。

レイキャスト

おっぱいを触れるようにレイキャストの対応です。

スレッド違反することなく無事にReadbackも成功です。

1フレームの遅延はGPUの都合上、仕方がないのです。

おわり!!!

クロスと内容が重複することも相まってあんまり筆が乗らなかった。

これで筆者は描画と物理の両方を操る能力を手に入れました。

つまり表現という分野においては最強になりました。

むふふ。たのしみ。