すあまの備忘録

誰得内容の自分のための非営利目的備忘録ブログ(筆者がわかっても内緒にしてください)

Solaris - Volume LOPの罠とPayloadでの最適化と読み込み

こねたというか忘れないようにメモ。Batchでレンダーするの前提です。

Volumeでの対応ですが、読み込み方法に関してはジオメトリでも使用可能です。

あくまでキャッシュ読み込んでレンダリングを最適化という感じなのでシェーダーまで込みでアセット化みたいにはなってません。

以下記事の続きで、Solarisレンダリングする際のVolumeの扱いのちょっと深堀。

godofsuama.hatenablog.com

Scene File

vdbUSD_gd.hiplc - Google ドライブ

USD Export時の問題

まず、SOPからの書き出しで以前の記事でString型のusdvolumesavepathというdetailアトリビュートでUSD Export SOPから指定フォルダへVDBを書き出すのを紹介しましたが、以下の問題に当たりました。

1. 巨大なVDBファイルだと書き出しでたまに落ちることがある。
2. VDBとUSD同時に、しかも1ファイルでしか書き出せないので時間がかかる。
3. 中間キャッシュがVDBだったら2回VDBを出して無駄。

ファイルサイズが大きめなので再計算や途中で落ちるのは致命的です。もしかしたら将来的にNano VDBとかが解決してくれるかもしれません。

取り敢えずこれを回避する作戦に出ます。

Volume LOPの問題

USDはVDB Volumeが扱えるので、直接VolumeLOPでVDB Volumeを読み込めます。が、これがBatch RenderingやViewportでの作業で非効率です。

どういうことかというと…

1. Viewportの描画でVDBにアクセスするので巨大なVDBだとViewportが重い。このため複数のVolume LOPがあった際に地獄。
2. USDの使用上、ショットの尺とVDBキャッシュの尺が異なる場合(VDBのが短い場合)前後でHoldされる。
3. Payloadが使えない。
4. Render Scene USD書き出し時に毎フレームVDBを読みに行くのでレンダリングまでにかかる時間が長くなる。(同じVDBファイルでも再度個別に読む)

ということでVolume LOPをどうにかすることにします。

USD化での回避

ざっくり画像のようなHDAを作成して対応します。

1. VDB別途書き出し後にUSD化する。
2. Viewportを軽くするための処理を組み込む(PayloadやProxy)
3. キャッシュとショットの尺が違う場合のHoldを回避する処理をいれる
Render

VolumeLOPでVDBを読み込む。Generate Errors for Missing Filesはオフ。

Cache LOPでVDBキャッシュのフレーム範囲を指定する。

Prune LOPでCache LOPの範囲以外のVisibilityをOFFにする。

Graft Stageで/renderのPrimをScopeのPrimitive Typeで作る。

Configure PrimitiveでPurposeをRenderにし、Proxy Primitiveに/proxyを指定する。

Proxy

SOP Create LOPを作成し、中で以下画像のノードを作成する。FileのFile PathはVolume LOPのFile Pathと同じにし、Retimeの範囲はCache LOPの範囲と同じにする。

FileノードのLoadをInfo Bounding BoxにするとヘッダーからBBOXの情報だけを取得するので速くなるはず。

Set Extents LOPをつなぎ、USD上でBBOXを計算しておく。

/renderと同様にGraft Stageで/proxyを作成する。

Configure PrimitiveでPurposeをProxyにし、Draw ModeをBounding Boxにする。

必要に応じて/renderと/proxyをまとめるPrimを作成する。

USDで書き出す

VDB書き出しとUSDで処理は2回になってしまうが、USD Export SOPだと落ちてしまう場合にこの方法だとほぼ落ちない上に合計の計算時間も速い。 この方法で書き出した場合、USDファイル内にはデフォルトでVDBへの相対パスが書き込まれるのでVDBファイルだけの移動削除をするとレンダリングできなくなる。 ただし、含まれるFieldやキャッシュ尺に変更がなかったりする場合はVDBだけを上書きしても動作する。

読み込みとPayload化

今回はVolumeでの読み込みだが、あらゆるUSDファイルに対して同様の読み込み方法でPayloadにできるので、Viewportを軽くすることができる。

このBackdrop部分をHDA化するのも良いと思う。

Reference LOPをPayloadの設定で作る。この状態でもPayloadにはなっているがHoudiniがデフォルトでPayloadも読み込むため、ロードされてしまう。

Loft Payload Info LOPを作成してつなぐ。

Configure StageでLoad PrimitivesをSet Primitives to Loadにする。

これでConfigure Stage以下は強制Payload状態になり、Viewport上には動かないBBOXが表示される。

レンダリング

そのままだとPayloadは読み込まれない=レンダリングされないことになる。なので、レンダリングする寸前でConfigure Stageを以下画像の設定で作成することですべてをロードする。これでレンダリングできるようになる。

補足

Payloadできているかどうかの確認方法は?

このアイコンがある部分まではPayloadが含まれている。もしくはScene Graph Treeで濃いオレンジ色のPrim

Scene Graph TreeでもPayloadのload,unloadができるのでは?

それぞれload,unloadの設定をしないと行けないこと。ノードの処理よりScene Graph Treeが優先されるのでConfigure Stage等での自動一括処理がしづらいため。

レンダリング直前にすべてLoadするのはなぜか

レンダリングするレイヤーに含まれないものをPrune等で除外してからすべてをLoadすることで本当にレンダリングに必要なものだけをLoadできる。

UnloadでもシェーダーやGeometry Settingsは適応されるのか?

Unloadすると濃いオレンジのトップ階層(Reference LOPで作られた階層)はくるので、ここにアサインなどをすればLoad時に適応される。

Graft Stageを使用したらPayloadがロードされる

使用するとすべてのPayloadが自動的にロードされます。再度unloadにする必要があります。作例だと二重対策でProxyを設定しているのでViewportがすごく重くなることはないですがやっかいです。

回避策としてRestructure Scene Graph LOPを使用してほか階層の子供にすることができます。

ただし、Restructure Scene Graph LOPは下手に使うと階層がぐちゃぐちゃになるため、事前に読み込みの際のReference LOP(Payload)のPrimitive KindをAssemblyなど%kind系のMatching Patternにしておくと簡単に必要なものだけを子供にしたりできます。

Restructure Scene Graph LOPも万能ではなく、現行Stage上のリレーションシップ系(シェーダーアサインなどのコネクション情報やCollection)がPrim Pathが変わることによって高確率で壊れるので実行する箇所は注意が必要です。

bgeo使えるのに何で使わないのか?

せっかくのDCCを跨いで使えるUSDという汎用フォーマットなのにbgeoを使ってしまうと縛りが発生するから。(ファイルフォーマットのプラグインのはずなので使おうと思えば他DCCでも使えはするはず)

SOP(Scene) Import / Geometry Sequenceを使わないのはなぜ?

過去記事にも書きましたが、Batch Render時のRender Scene USD書き出し時にそれらのキャッシュも原則自動変換されるという時間のロスがあります。ライトやカメラ程度なら大したロスになりませんがジオメトリは結構厳しい。 ですか、個人でローカルで使う分にはさほど気にならないです。