はじめに
流体シミュレーションをUE内でリアルタイムに行える時代が遂にやってきました。
もちろん、負荷やクオリティ的な課題はまだまだあり、プロダクションで自由に使えるレベルにはまだ達していないですが、限定的な使用ででも色々と試してみたいところです。
用途に応じて負荷やクオリティをチューニングするためにも、仕組みを理解しておきたいところですが、いかんせんアンロックしなければならない知識が多く、一気に全てを理解するというわけにはいかなそうです。
なので、自分自身への備忘録もかねて、調べた内容を細かく記事にしていこうと思います。
留意事項
本記事は、UE5.2及びUE5.3のバージョン時の内容に基づき解説します。
Niagara Fluidは日進月歩で開発が続けられている機能なので、本記事の内容が将来的には当てはまらなくなる可能性があることをご留意ください。
本記事の解説内容
Niagara Fluidは、大別すると2D/3D×Gas/Fluidの4種類があります。
Gasは煙や炎のシミュレーションで、Fluidは液体のシミュレーションになります。
本記事では、3D Gasに焦点を当てて、Niagara Fluidの3D Gasがどのように動いているかの全体的な概要をまずは解説していきます。
(解説の中には、3D Gasに留まらず、Niagara Fluid全体に当てはまる内容もあるかと思います)
中身の詳細な内容は、別の記事で解説していければと思います。
解説
全体像
全体の処理の流れは以下のイメージです。これを踏まえて、以下でSimulationとRenderingに分けて解説していきます。
Simulation部分の概要解説
Source Emitter
HoudiniやEmberGenなどシミュレーションを行えるツールで流体シミュレーションをする場合、煙や炎の発生元となるSource Emitterを用意するのが基本だと思います。
UEのNiagara Fluidでも同じく、基本的にはSource Emitterを作ってParticleを発生させ、density, temperature, velocityなどのattributeを持たせたうえで、それをSimulation(Gas) Emitterで読み込み、Simulationをしています。
※Simulation(Gas) Emitter内で、発生元となる簡単なSourceを作成する機能も一応入ってはいます。
以下は、Grid 3D Gas ExplosionのTemplateですが、以下左のようなSource Emitterを元にして、右の爆発のSimulationが行われています。
Source Emitterの中で重要なのは、Set Fluid Source Attributesモジュールです。
このモジュールで、densityやtemperatureなど、Simulationで使われる値を設定します。
※実際にSimulation Emitterの方で読み込まれるattributeの名前は、Parameter Writesに出ているものになります。
その他のモジュールは、SourceとなるParticleの動きを作ったり、DensityやVelocityなどのパラメータを作るために使われている普通の既存モジュールです。
なので逆に言うと、この辺のやり方はどんなモジュールを使って、どんな方法でやっても問題ないです。
Simulation Emitter
ひとまず、RendererのSource ModeはEmitterになっていてParticleは使われていないこと、そして処理のほとんどは、Simulation Stageで行われていることを押さえておきましょう。
上記文章を読んでもピンとこない人は、過去の以下の記事を参照してみてください。
このEmitterは、Particleを制御する普通のエフェクトとしての使われ方はしておらず、Simulation Stageを使い、3D Grid上でのシミュレーション計算や、Volume Render Textureへの書き込みなどの処理をしています。
詳細な説明は別の記事で行えればと思いますが、ざっくりSimulation Emitterの役割を説明すると、以下のようになります。
- SimulationやRenderingを調整する各種パラメータの設定
- Simulationの計算処理
- 処理結果をVolume Render Textureに書き込む
- RendererやMaterialに設定したパラメータや処理結果を渡す
2,3の説明は本記事では割愛しますが、まず1の各種パラメータを調整する部分については、Emitter Summaryを見ます。
Emitter Summaryは、いつからか使えるようになっていた機能で、パラメータを設定する所で右クリックし、Show in Emitter Summaryにチェックを入れると追加できます。
エンドユーザー用に調整したいパラメータをまとめておく用途で使われ、今回のNiagara Fluidでもたくさんあるパラメータをカテゴリー毎(Simulation, Source, Forcesなど)に分けて調整しやすくなっています。
各パラメータの詳細な説明は別の記事で解説しようと思うので、ここでは、Source Emitterを読み込んでいる所だけ触れておきます。
Sourceカテゴリー内にParticle Attribute Readerを設定している項目があり、そこのEmitter Nameに、Source Emitterの名前を入力することで、読み込めるようにしています。
Particle Attribute Readerに馴染みがない人は、過去の以下の記事を参照してみてください。
次に4のRendererやMaterialに設定したパラメータや処理結果を渡す部分については、まず留意事項として、UE5.2まではMesh Rendererが使われていたのが、UE5.3からはVolume Rendererになっています。
ここに関しては、Rendering部分の解説でも少しまた触れますが、Mesh RendererもVolume Rendererも、多少項目の内容は違うものの、どちらもBindingsでEmitterの各種パラーメータをRendererやMaterialに渡している基本的な所は変わりません。
まとめ
Simulation部分の全体の流れをおさらいすると、Source Emitterでdensityなどのattributeを持たせたParticleを発生させ、Simulation Emitterでそれらの値を読み込み、設定した各種パラメータを元にシミュレーションの計算処理をし、処理結果や設定パラメータをRendererとMaterialに渡す、という流れになります。
次は、それらを受け取ったRendererやMaterialが、その値を元にどうRenderingしていくかという話になります。
Rendering部分の概要解説
Volume Rendering
煙や炎のレンダリングは、Volume Renderingになります。
おそらくレイマーチングのような手法で、UEのVolume Renderingの処理実装自体はエンジン内で行われています。
どうすればVolume Renderingを使えるかですが、気にするところはVolumeのタイプと、Materialの2つです。
Volumeのタイプに関して、UEでは元々Volumetric FogとVolumetric Cloudの2つでVolume Renderingが使われていました。
ただ、Volumetric Fogで使用した場合、Self-Shadowが付かないなど色々と制限がありました。そこで登場したのが、Heterogeneous Volumeになります。
Heterogeneous Volumeは、既存のUEのLightingシステムと親和していて、何個でも光源の影響を受け(負荷はあがります)、Self-Shadowもちゃんと効きます。
Niagara Fluidの3D Gasも、このHeterogeneous Volumeを使ってレンダリングされます。
UE5.2では、Mesh Rendererの項目にUse Heterogeneous Volumesがあり、それをオンにすることで、Heterogeneous Volumeとしてレンダリングできるようになっていましたが、UE5.3からはVolume Rendererが追加されていて、それを使えばHeterogeneous Volumeとして認識されるようになっています。
Materialに関してはシンプルで、Material DomainをVolume、Blend ModeをAdditiveにするだけです。
これはVolumeのタイプに関係なく、Volume Rendering用のMaterial共通の設定になります。
Niagara Fluid 3D GasのMaterial概説
次に、Niagaraでシミュレートされたdensityやtemperatureの値がMaterialに渡され、どうVolume Renderingの設定値としてMaterial の最終出力と結び付けられるかをざっくりとみていきます。
また、Material内の各パラメータは基本的に全部、Niagaraから値が設定されるようになっているので、以下の既存のNiagara 3D Gas用Materialについては、Material Instanceでパラメータを調整する必要はありません。
こちらが、3D Gasで使用されているマテリアルの全体像です。各最終出力を見ていきましょう。
VolumeマテリアルのAlbedoは、大気中での光の散乱における色の反射性の設定ですが、普通のSurfaceのマテリアルのBase Colorと同じようなものだと思っておいても問題ないと思います。3D Gasにおいて基本は煙の色付けをしています。
以下のようにボリューム内で違った色を入れる場合は、ColorTexture(Volume Sample)の方を使います。
次に、Emissive Colorは、想像通り発光を制御する出力です。3D Gasでは基本は炎の色付けに使われます。
Niagaraでシミュレートされたtemperatureの値を用いて色の計算がされます。
最後が、Extinctionで、ボリュームの濃さを制御します。これが0の部分はVolumeがないことになります。
Niagaraでシミュレートされたdensityの値を用いて計算されます。
最後に、Niagaraで計算されたdensityとtemperatureの値は、Volume TextureとしてMaterialに渡されます。
Volumeは、3Dのグリッドの各セルが値を持っているので、それをRender Target Volumeに焼き付けて、Materialに渡され、Materialでは、Volume SampleノードでUVW(ボクセルのNormalizeされたIndex)を指定して値を取り出すことができます。
以上で、Rendering部分の大まかな解説は終わりですが、UE5.3から追加されたSparse Volume Textures(SVT)について少しだけ触れておきます。
Sparse Volume Textures(SVT)
Sparse Volumeというものは、Niagara Fluidに限ったものではなく、Houdiniにシミュレーションする時も有効にするかのフラグがあるように、グリッドベースの流体シミュレーション全般に出てきます。
シミュレーションをする際には、任意の解像度の3Dグリッドを置き、その各セルにdensityやtemeperatureなどの値を格納し、シミュレーション計算がされます。また、ボリュームの実体も同じく3Dグリッドの各セル内の値です。
ここで、煙や炎を想像してみてください。それらを覆うような直方体のグリッドを置いたとき、特に角の部分のセルなどは煙がない(Volumeがない)状態になりやすいです。それでもそのセルについてもシミュレーション計算がされているだけでななく、メモリも消費していることになります。
そのような無駄なセルが出ないよう、実際にボリュームがある部分付近のセルだけをメモリ上に保持しておくのがSVTになります。
細かい正確な内部の仕組みはわかりませんが、大雑把には以上のような内容です。
UE5.3からは、Niagara Fluidでの処理が内部的にSVTが使われるようになっているので、メモリや処理負荷が向上しているという話です。
おわりに
詳細に関する説明はしませんでしたが、Niagara Fluid 3D Gasの全体像については、なんとなく把握できたかなと思います。
全体像の部分で、SimulationとRenderingに分けたのには理由があります。
それは、RenderingのHeterogeneous VolumeやSVTについては、Niagara Fluid自体とは別で機能できるからです。
つまり、Simulation部分はHoudiniやEmberGenなどの外部ツールで行い、OpenVDB形式のVolumeデータとしてエクスポートしたものを、UE内に取り込んでRenderingするといったことが可能になっています。
今までは、シミュレーションしたデータをUEに持っていくには、連番素材にしたり、Mesh化してAlembicやVATにするしかなかったですが、これからはVolumeデータでそのまま持って行ってクオリティ高くUE内でレンダリングすることができます。
もちろん、ゲームなどで使うにはまだメモリ等々厳しいですが、プリレンダーとしては使えると思うので、そちらも今後試していきたいところです。
Niagara Fluidしっかり勉強して、UEで高クオリティな作品を作っていきたいですね!