シェーディング時の座標空間


どうも篠島です。最近はシェーダー周りの説明をしてきたので、座標空間について少し解説したいと思います。

 

今回のサンプルファイルです。
space.zip

 

シェーダーを作る際のデフォルトの座標空間はカメラ座標空間です。座標変換を行うには Transform VOP で行うのですが、まず分かりやすいように下図のシェーダーを作成しました。シェーディングポイント(P)の位置をそのまま色(Cf)として出力する非常に単純なシェーダーです。

シーン内でGridを作り、スクリーンを覆うようにカメラを配置してレンダリングすると下のような結果が得られます。シェーディングポイントは全てカメラ座標空間での位置として表されます。すなわち画面中心がカメラの原点でもあるので(0,0,0)、そこから右側がX軸、上がY軸になります。Z軸は奥へ向かう方向になります。

 

Gridを回転させてみると、レンダリング結果がオブジェクトの回転に関わらず、カメラ座標空間内の位置で色が変わらないのが分かるかと思います。

 

 

オブジェクト空間

先程のカメラ空間での座標をオブジェクト空間に変換してみます。P に Transform VOP を繋いで Cf に出力します。この時 From Space で指定した座標空間から To Space で指定した座標空間に変換されるので、current から object にすることでオブジェクト空間に変換できます。

このシェーダーを使って先程の回転するGridをレンダリングすると以下のGIFの様になり、シェーディングポイントがオブジェクト空間に変換された事によって、オブジェクトが回転するとそのオブジェクトに色が追従している事が分かります。

 

ワールド座標空間

今度はカメラ座標空間からワールド座標空間に変換してみます。下図の様に To Space で world を指定します。

カメラの配置は下図の様に少し斜めからGridを見ています。

レンダリング結果を見てみると、ワールド座標の位置を元に色が付けられているのが分かるかと思います。

 

NDCスペース

NDC(Normalized Device Coordinate)スペースはXとYの値が標準化されて0~1の値で表される様になっており、Z軸はカメラから奥へ向かうZの値が入ります。

その他スペース

他にも Current Space や Camera Space もあるのですが、Current Space はそのVOPを作成したスペースで、シェーダー内ならばこれは Camera Space  と同じ空間を表します。他にもライトの座標空間の Light Source Space もあります。

 

 

ディスプレイスメント

もしカスタムシェーダーを作成時に、ディスプレイスメントを自由にカスタマイズしたい時など、この座標空間の変換の知識があると便利です。

例えば、ジオメトリにポイントアトリビュートを追加し、そのアトリビュートの分だけディスプレイスメントを適用したいとします。下の図はポイントに追加した Vector タイプのアトリビュートの値を示したもので、真ん中の一点だけ(0,1,0)となっており、Y 方向に 1 だけディスプレイスメントするように設定し、その他のポイントは(0,0,0)にしてあります。

 

シェーダーでディスプレイスメントを下のように作ります。本来であればDisplace along Normal VOPを使うと簡単なのですが、理解を深めるために原始的な方法でポイントの移動先を手動で計算し(といっても足し算だけですが)、計算結果をdisplacement_output に繋いでいます。元のオリジナルのポイントの位置に対して、SOP 内で設定したVector型のアトリビュート disp を Add VOP で加算しています。Shading Normal VOP でディスプレイスメント後の法線計算、そしてProperty VOP でDisplacement Bound というプロパティを設定しています。このプロパティは絶対必要で、これが無いとレンダリングのタイルの外に頂点が移動してレンダリングが正しく表示されなくなったりします。

 

レンダリングすると結果は下の様になります。この時、真ん中のポイントアトリビュートだけが(0,1,0)の値を持っているので、中心のポイント部分だけがディスプレイスされますが、シェーダーはカメラ座標で位置を計算しているのでオブジェクトが回転してもスクリーンの上方向にディスプレイスメントがかかってしまっています。

 

オブジェクトの回転に沿ってディスプレイスメントも回転させたい場合は、ディスプレイスメントの計算をオブジェクトスペースで行えばいいわけです。元のジオメトリの P をオブジェクト空間に持ってきて、その中で計算をしてから P を カメラ空間に戻します。するとディスプレイスメントが正しくオブジェクトの回転に追従するようになります。

 

補足

今回はディスプレイスメントのサンプルで位置を扱いましたが、方向を表すベクトルだったり、法線を変換する場合は、Interpretation を Direction Vector や Normal にする必要があります。前回の RayTrace VOP の記事でレイを飛ばす方向をコントロールしましたが、この時に Interpretation を Direction Vectorにしています。