こんにちは!金融ソリューション事業部の山下です。
前回の「バーチャルヒューマンをリアルタイムフェイスリグで動かす」の記事に引き続き、最新の3DCG技術を紹介します。
本記事では、特に映画/ゲーム業界等でVFXに活用されているHoudiniを使って、トップ画像のようなフォトリアルな雲をレンダリングします。 雲のような3次元空間上に密度分布を持った現象をシミュレーションする為に、オープンソースのOpenVDBライブラリを利用します。
前提知識
1. Voxel
- 3次元データを表す最小単位です。Voxelが集まったデータをVolumeと呼びます。
- 座標以外にも様々なデータ(濃度、温度、速度)を持たせることで、水、火、煙、雲などの物理シミュレーションにも活用されています。
2. OpenVDB
3次元データを操作する為のデータ規格およびモジュールライブラリです。今回用いるHoudiniや、Blenderなど様々なCGソフトに採用されています。
Academy Software Foundationがオープンソースとして管理しており、2014年にアカデミー賞(科学技術部門)も受賞しています。
- NVIDIAを中心に活発に開発が進められており、直近では以下の新機能が追加されています:
3. Houdini
(画像:https://www.sidefx.com/ja/products/houdini))
- Side Effects Software社が開発する3DCGソフトウェアです。ノードベースプログラミングを採用しており、プロシージャル(手続き的)に可変的なシミュレーションが可能です。(VEXコードというテキストベースのプログラミング言語も利用可能)
- 映画、ゲーム、科学などの業界で、20年以上前から複雑なシミュレーションに活用されており、その功績として2018年にアカデミー賞(科学技術部門)も受賞しています。
- Houdiniでボリュームを扱う際には、Houdini独自VolumeとOpenVBDの2種類の処理方式が利用可能です。
4. Redshift
(画像:https://docs.redshift3d.com/display/redshift3d/redshift3d+Home)
- Redshift Rendering Technologies社(2019年にMaxon社が買収)が開発する3DCGレンダリングソフトウェアです。高速処理が可能になるGPUレンダリングを2014年に世界で始めて商用化しました。
- Maxon社の提供する3DCGツールであるCinema4Dに加えて、Autodesk社のMayaなどでも利用可能です。
- 元はNVIDIA GPUのみに対応しておりましたが、2021年にはmacOSにも対応しました。
シミュレーションの実施
実行環境
手順
1. 雲の元となるポリゴンを作成
2. ポリゴンをボリュームに変換した後、ノイズをかけてディテールを付与
3. マテリアル、ライトを設定して、Redshiftでレンダリング
HoudiniやRedshiftのインストール手順は割愛します。 それでは、始めていきます。
手順1. 雲の元となるポリゴンを作成
ここでは、3つのノードを使用します。
1-1. 球体の作成
最初に、Sphereノードで球体を作成します。
主な設定値は、以下です。
- Primitive Type:「Polygon」
- Frequency:24
ポリゴンの数が少ないとこの後かけるノイズが荒くなってしまうので、適当な数に上げています。 Houdiniの場合、最後になってから増やすのも簡単にできるので、パラメータチューニングは最後に行っても大丈夫です。
1-2. ノイズの付与
次に、Attribute Noise(旧名:mountain)ノードでノイズをかけていきます。
このノードでは様々な種類のノイズを、任意のデータに対してかけることができます。
今回は、先ほど作成したポリゴンの各座標Pに対して、「Sparse Convolution」というノイズをかけています。
主な設定値は、以下です。
- Noise Value
- Amplitude:0.61
- Nise Pattern
- Noise Type:「Sparse Convolution」
- Element Size:0.37
- Offset:4.42
ジオメトリのデータを参照するViewであるGeometry Spreadsheetを見ると、各ポイントの座標が変化しているのが分かります。
変換前:3-1. sphereノードの値
変換後:3-2. mountainノードの値
1-3. Y軸方向に変形
雲のような形にする為、Y軸方向を0.5倍にスケールして押し潰します。 Transformノード内に「Scale」という項目があるので、Y軸の値を0.5に設定します。
これで、雲の元となるポリゴンの作成は完了です。
手順2. ポリゴンをボリュームに変換した後、ノイズをかけてディテールを付与
次に、作成したポリゴンをボリュームデータ(OpenVDB)に変換します。
以下3種類のノードを使用します。
2-1. Cloudノードでボリュームに変換
ポリゴンのボリュームへの変換は、Cloudノードを使用します。
主な設定値は、以下です。
- Source:「Polygon Model」
- Uniform Smpling Divs:「100」
ここで重要なのが、項目「Uniform Smpling Divs」です。この数値によって、Voxelの分割数が決まります。正方形のポリゴンであれば、10倍にすると単純計算では千から100万にVoxelが増える為、適切な数を設定しましょう。
例えばデフォルトの10のままだと、かなりぼやっとした感じになるのが分かります。
CloudノードはOpenVDBを採用しておりますが、Houdiniでは独自のVolumeノードも用意しております。 試しに、両者を比較してみましょう。
先ほどのTransformノードのアウトプットを新しく作成したVolumeノードにも繋ぎます。
それぞれのデータを見てみす。
VolumeノードではVoxel数が40万程度にあるのに対して、
CloudノードではVoxel数が14万強と、大幅に削減されているのが分かります。
Houdini独自のVolumeは、3次元格子内の全てのVoxelデータを保有する為にVoxel数が大きくなっています。 このノードが残っている理由としては、Volume表面の精緻な検出に用いる用途などが挙げられます。
2-2. Cloud Noiseノードで、ノイズを付与
次に、Cloud Noiseノードでノイズをかけていきます。
主な設定値は、以下です。
- Amplitude:0.129
- Element Size:0.6
様々な設定値によって結果が大きく変わるので、自分の気に入る形になるまで調整を繰り返します。
2-3. Volume VOPノードでさらに細かいノイズを部分的に付与
最後に、Volume VOPノードで最終的なアウトプットを出力します。
houdiniでは、ビジュアルプログラミングが可能になるVOPというノードも提供されています。 この中では、値の変換処理や条件分岐など、少し複雑な処理も簡単に記述できます。
Cloudノードによって、雲の濃さを表すdensityという値(Float型)が作成されているので、この値に対して処理を行います。
VOP内の処理詳細は割愛しますが、変換前はほぼ一律になっていたdensityの値を、Perlinノイズを用いて自然なグラデーションに変換します。また外周部分の厚みが薄い部分の値を、条件分岐を用いて0にしています。
実際に結果を確認する為に、Volume Sliceというノードに接続して確認します。
Volumeは、先に挙げたGeometrySpreadsheetのような2次元データとは異なる3次元データですので、デバッグには断面を確認する手法が便利です。
今回はXY平面にスライスして確認します。 各Voxel内でdensityの値は数値(float型)として保持されているので、濃い部分を白く、薄い部分を暗くしたグレイスケールで可視化してみます。
変換前:densityがほぼ一定になっており、全体的に色の濃さが均一になっています。
変換後:densityにPerlinノイズによるばらつきが加わった為、色の濃さも自然にまばらになっています。
以上で、雲のVolumeデータが完成しました。
完成したデータはopenVDBファイルとしてアウトプットします。これでHoudini以外の3DCGソフト(Blenderなど)へimport可能です。 前回記事にて用いたUnreal Engineでは執筆時点(2022年8月)でopenVDBの対応はされていないようですが、オープンソースでプラグインが開発されておりそちらを利用して利用も可能です。
手順3. マテリアル、ライトを設定して、Redshiftでレンダリング
最後に、カメラ、マテリアル、レンダリングの設定を行い完成画像を出力します。
3DCGソフトに不慣れな方は戸惑うかもしれませんが、3Dモデルを実際に2次元の画像や動画に変換する処理はレンダリングと呼ばれ、モデリングやアニメーションとは別のソフトを用いることが一般的です。 HoudiniにもMantraというデフォルトのレンダリング機能が用意されていますが、これはGPUレンダリングに対応していない為、GPUレンダリング対応のレンダラーを用います。 HoudiniではRedshift以外にも様々なレンダリングソフトに対応しており、OTOY社のOctane Renderなども有名です。
レンダリングの設定を行う際に注意すべき点としては、ライト、マテリアルに関してはレンダリングエンジン固有のモジュールを用いる必要がある、という点です。
設定内容が膨大になるので、詳細は省き主要な設定内容のみ記載します。
3-1. カメラ
Houdiniのカメラを使用します。解像度やFocul Lengthの設定など、様々な可能です。
- Enable Photogrametric Exposure:ON
- Enable Depth of Field:ON
3-2. ライト
今回は、Redshiftの提供するRSLightDomeというライトを用います。 ライトには点(Point light)、面(Area light)、太陽光(Directional light)など様々な種類のライトがあります。
今回は、360°で撮影したHDRIテクスチャ画像を光源として使用できるRSLightDomeノードを使用します。 光源として使用するテクスチャ画像は、CC0のPoly Heavenを使用しました。
3-3.テクスチャ
雲の質感を設定します。 RS Volumeノードで、拡散(Scatter)、吸収(Absorption)、発光(Emission)などの値を設定します。
3-4. レンダラー
レンダリングに関する値を設定します。
- Global Illumination:
- Enabled:ON
- Primary GI Engine:Brute Force
- Trace Depth:3
- Sample Filtering
- Filter:「Gauss」
- Size:4
- Redshift → Advanced → Bucket Size:512
今回はBucketRenderingを使用しました。 バケットサイズの設定をしないと処理速度が20倍くらい変わるため注意しましょう。
完成イメージ
完成画像です(LightDomeの背景画像もそのまま残しています)。
私の環境(Apple M1 Max)では、Bucket Renderingで1~10sec程度、ProgressiveRenderingだと1~2分ほどかかりました。
終わりに
いかがでしょうか? 今回はvbdを作成した後にHoudini内でレンダリングまで行いましたが、BlenderなどnanoVDBやneuralVDBに対応している3DCGソフト上であればどこでも扱えます。複数シーケンスとして出力することで、アニメーションがついた表現も可能ですし、OpenVDBはデータ規格だけでなく処理ライブラリも提供されている為、ダイナミックな物理シミュレーションも可能です。
これまで特に映画産業では、雲や炎、水や霧などボリュームデータを用いたシミュレーションは膨大な時間とコンピューティングリソースをかけてプリレンダリングされてきました。 が、OpenVDBの登場により今後はゲームやメタバースなどのリアルタイムインタラクションが求められる環境でも処理が可能になってくると思われます。
現在ISIDはweb3領域のグループ横断組織を立ち上げ、Web3およびメタバース領域のR&Dを行っております(カテゴリー「3DCG」の記事はこちら)。
もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください!
私たちと同じチームで働いてくれる仲間を、是非お待ちしております!
ISID採用ページ(Web3/メタバース/AI)
参考
執筆:@yamashita.yuki、レビュー:@sato.taichi (Shodoで執筆されました)