OptiXを用いたレンダリング例(1)~Closest Hit Programの例

ここからはOptiXを用いた具体的かつ、ごく基礎的なレンダリング例を見ていくことにしよう。

視線方向にレイを投げて最初の衝突が判定されるとClosest Hit Programが起動する。なお、ここから近隣に対して局所的なレイを新しく投げて遮蔽具合を探査すればAmbient Occlusionが実現できる。ここで光源と視線と法線の3パラメータを使ってライティング計算すれば普通のピクセル陰影処理が実現出来る。もちろん、同時にテクスチャを読み出して適用することも出来る。そう、Closest Hit Programはかなりピクセルシェーダに近い存在といえるのだ。

Closest Hit Programはピクセルシェーダに近い存在

下の例は面の向きごとに着色しただけのものだ。

面の向きごとに適当に着色した例

これではあまりにもつまらないのでランバート・ライティング(法線ベクトルと光源ベクトルだけで計算される、視線に依存しない拡散反射モデルの基本形)を適用して、さらに、視線レイの衝突箇所から光源に向かって新しいレイを投げて、遮蔽があるかどうかをチェックするプロセスをいれて、影も付けてやる。

そう、レイトレーシング法では、影生成は別パスのレンダリングではなく、順方向のパス一回だけで生成できてしまうのだ。

衝突点から光源に向かって新たなレイを投げて影かどうかの判定

ランバートライティングと影生成はこれだけのClosest Hit Programで記述できる

これに映り込みを適用するには、その視線レイの衝突箇所から反射方向に新たなレイを飛ばして二次反射箇所以上の衝突箇所を求め、その色を拾って来て陰影計算に役立てる。複数回の反射をサポートする場合は、反射するたびにそこから拾ってきた色の影響を少なくするような処理をくわえれば相互反射の表現なども実装できる。ここもレイトレーシング法の強健な部分だと言えよう。

なおここで強調しておきたいのは、新しいレイを投げるとシステム側の処理が増大していくことになるわけだが、このあたりはちゃんとOptiX側がマネージメントしてくれるのでプログラマが心配する必要はない。

映り込みは視線方向のレイの衝突箇所から、その反射方向に新たなレイを飛ばして次の衝突先から色を取ってくるようにして実現される

続いて、このシーンに環境マップを適用することを考える。

レイトレーシング法において、背景の描画に相当するのは、投げたレイがどこにも衝突せずに無限遠の彼方に行ってしまったときの処理に相当する。背景を環境マップにして、これを映り込ませる表現を行うには、視線レイがオブジェクトに衝突して、そこから鏡面反射させたレイが無限遠に行ってしまった際に、環境マップをサンプルすることで実現される。

前出のサンプルシーンで背景が水色で、床に映り込んだ空がやや水色っぽかったのは、その無限遠に逃げたレイに対して「水色」の固定色を返していたためだ。

この「投げたレイが何にも衝突しなかった」ときの処理をプログラマブルに記述できるのが「Miss Program」になるのだ。

OptiXにおける、衝突出来なかったレイの処理を行うのがMiss Programシェーダ

前出のサンプルシーンでは単色で返していた

無限遠に行ってしまったレイで環境マップをサンプルすれば環境マップベースの背景や、環境マップが映り込んだ情景を表現できる

環境マップを参照させるようにしたサンプルシーン。遠方の背景描画、そしてその背景が床に映り込むようになる

さらに、フレネル反射の処理を適用してリアリティを向上することも出来る。

OptiXにはよく用いられる反射関数が組み込み実装されており、この場合だとフレネル反射の近似一般形であるSchlickのフレネル反射関数を用いることになる。

実際の処理系としてはレイがオブシェクトを掠めるように衝突/反射したときには反射したレイが取ってきた内容を支配的にし、レイが垂直に近い形で衝突すれはするほど、この衝突した対象物のその時点での陰影結果が支配的に出るようにする。

Schlickのフレネル近似式を導入して環境マップの映り込み表現にフレネル反射の表現を導入。このあたりのプログラマビリティの柔軟性は現行のGPUのプログラマブルシェーダに通ずるものがある

四角柱の足元にはほとんど映り込みがないが、相対的に視線が掠めるような角度で入射することになる遠方では環境マップの映り込みが支配的となる

逆に視線そのものを床に張り付かせると四角柱の根本にも視線が掠めることになり、床に鮮明な鏡像が出るようになる

なお、衝突したところの処理は、反射方程式以外の処理を盛り込んでも良い。

例えば、ある一定の太さ、一定の間隔で、特定の色を返すようにすれば、格子筋模様を表現できる。そう、いわゆるプロシージャルテクスチャが定義できるのだ。

下図がその格子筋のプロシージャルテクスチャをClosest Hit Programで定義したときの例だ。

格子筋のプロシージャルテクスチャをClosest Hit Programで記述した例

さらにノイズ関数などを駆使してより高度なプロシージャルテクスチャを定義することも出来る。下図はその一例で、鏡面反射のClosest Hit Programに、特定条件下で部分的にサビ模様を出すようにしたプロシージャルテクスチャのサンプルだ。写真を見ても、ほとんどプログラムコードは読めないが、ここではそのプログラムコード自身の内容よりも、高度なClosest Hit Programの書きようよっては画像テクスチャを用いることなく、プロシージャルテクスチャによる説得力の高い表現が出来る可能性の方に着目して欲しい。

鏡面反射とサビのプロシージャルテクスチャを盛り込んだClosest Hit programの一例

動画
ここまでの結果をムービーとしたもの