完全にプライベートタイムを使って調べているのでなかなか捗らない(という言い訳をして数週間放置w)ですが、Twitter やコメント欄でいろいろな方に助けて頂きながら少しづつわかったことがあるのでまとめてみます。
・シェーダの割り当て
ボリュームシェーダを使用する際にも、サーフェースシェーダは指定する必要があります。ここでは、”何もしない” シェーダ、transmat を割り当てます。
・parti シェーダについて
Maya には parti シェーダのソースが付属しています(devkit/mentalray/shaders/physics/partishade.cpp)。
このソースの Description を読むとわかるのですが、parti シェーダは GI の使用が前提になっています。この時点で用がないなと見切りますwww
・raymarcherシェーダについて
parti シェーダ同様、ray marcher のソースも付属しています(devkit/mentalray/shaders/base/baseraymarch.cpp)。
コードを眺めてみると、拍子拔けするぐらい単純な構造になっていることがわかります。
ザックリと説明すると
- mib_ray_marcher() から raymarch() 関数を呼ぶ。これが ray marcher の本体
- 二点の mi_call_shader_x() で得られた値を比較する
- 最大分割数未満かつ、値の差が閾値以上なら recurse() 関数を呼ぶ
- 2と3を繰り返す
- 得られた結果を加算する(ここまでが raymarch())
- 最後に値を正規化してやる
これだけです。教科書に出てくる ray marcher そのものです。そして、このコードを読むと幾つか発見もあります。
- 最後に正規化してしまっているので、計算結果がそのまま得られない
- 結局単なる ray marcher なので、mi_call_shader_x() で呼ぶシェーダ次第
- シェーダの計算結果をそのまま足してしまっているので、多分綺麗な結果が得られない
1,2 に関してはコードを読んだそのままです。1 は正規化しないようにすれば解決できます(多分。mental ray のシェーダが、正規化した値しか返せない仕様だったりすると困ります)。2 は、コードを読めば一発でわかりますが、日本語読解力の弱いわたしにはドキュメントを読んだだけじゃわかりません(ぇ。
3 は、ライトを考慮したシェーダネットワークを組もうとすると問題になるのかなと思います。ライトの場合、ray marching した結果の color と alpha を使って光源の値を”削る”(マスクする)必要があると思うので、これ用の仕組みを別途作ってやる必要があります。まあ、サンプリングポイント毎に馬鹿正直に計算していたら重いと思うので Deep Shadow Map のようなものを使って計算するのが無難なのでしょう。
・結論
いろいろ書きましたが、結局 raymarcher はレイ・マーチングを正直に実装しただけのシェーダだったということです。
これだけで何かできるというわけではなく、シェーダネットワークを組むための部品の一つとして使うために存在するものなので、これを元に Phenomena を作るか自分でシェーダを書くのが正しいアプローチなんだろうなーと、至って普通な結論に逹しています。
お久しぶりです!
参考に読ませてもらってます、折角なのでカキコ。
お元気でしたか~?ごぶさたしています。
Volume Rendering 関係の話も投げっぱなしなまま
ほったらかしな感じになってしまっているので、ここはぜひ
hajime さんのお力で迷える子羊(?)に救いの手を
さしのべてください!!おねがいします 🙂