On this page |
bsdf cvex_bsdf(string eval_cvex_shader, string sampler_cvex_shader, ...)
この関数は、1組のcvex
シェーダからBSDF反射率の関数を定義することができます:
片方のCVEXシェーダは反射率の関数を評価し、もう片方のCVEXシェーダはそれをサンプリングします。
最初の2つの引数には、シェーダをVEXソース文字列として渡します。 その後の可変長引数では、シェーダを呼び出した時にシェーダに渡される任意のデータを定義することができます。
Warning
このインターフェースは、Houdiniの将来のバージョンで変更されることになっています。しかし、変更される可能性のある部分は、シェーダの構造の重要部分ではないです。
評価関数 ¶
評価関数は、以下の引数を受け取らなければなりません:
(vector u, vector v, int bounces, int reverse, vector &refl, vector &eval, float &pdf)
u
サーフェスからビューアに向かう出射光の方向。
v
サーフェスからライトに向かう入射光の方向。
bounces
評価される反射のタイプを指定するマスク。
reverse
カメラ(0
)または光源(1
)のどちらから評価するかどうか。
refl
この関数は、BSDFの反射率(アルベド)でこの変数を上書きします。
このアルベドは、すべてのライティング方向の平均の反射率として使われているので、v
ベクトルと関係がありません。
これは、albedo関数が返す値です。
eval
この関数は、指定した方向で評価された反射率でこの変数を上書きします。
MantraにBSDFがデルタ関数であることを示したい場合には、これを0
に設定してください。
デルタ関数は、指定した方向やラインに向かってライトを反射し、ライティングアルゴリズムの特別な場合として処理されて、ノイズの少ない結果を生成します。
デルタBSDFの挙動は(以下の)サンプリング関数で決まります。
pdf
この関数は、指定した方向のサンプリングPDFでこの変数を上書きします。
球上のこの値の積分はluminance(refl)*2*PI
と等価です。完全な重点サンプリングでは、pdf == luminance(eval)
です。
サンプリング関数 ¶
サンプリング関数は、(上記の)評価関数によって定義された分布から重点サンプリングされたランダム反射方向を選択する役割を担っています。
サンプリング関数は、以下の引数を受け取らなければなりません:
(vector u, float sx, float sy, int bounces, vector &refl, vector &v, int &bouncetype, float &pdf)
評価関数がデルタ関数(評価関数のeval
を0に設定)なら、望み通りに自由にサンプリング方向を選択することができます。
そうでないなら、評価関数に一致またはそれに近い分布から方向を選択してください。
sx
とsy
の入力は、高品質なサンプリング分布を生成するために利用可能です。これらの値は、Mantraのピクセルサンプリングパターンから直接初期化されます。
u
サーフェスからビューアに向かう出射光の方向。
sx
0から1の間の均一なランダムな値。2Dサンプリングパターンでsyと相互に関連します。
sy
0から1の間の均一なランダムな値。2Dサンプリングパターンでsxと相互に関連します。
bounces
評価される反射のタイプを指定するマスク。
refl
BSDFの反射率(アルベド)で、サンプリングされる方向のライトのカラーで色付けされます。
この値の輝度は、評価関数のrefl
に合わせてください。サンプリング分布が正確に評価関数に一致しないなら、この値は、評価分布とサンプリング分布の比率に合わせてスケールされます。
v
サーフェスからライトに向かうサンプリングされるライトの方向。
bouncetype
サンプリングで選択される特定のコンポーネントタイプ。
pdf
サンプリングpdf。球上のこの値の積分は定数2*PI
になるはずです。これは、luminance(refl)
の係数による評価関数で生成されたpdf
とは異なることに注意してください。
Houdini13以降、サンプリング関数が直接、評価関数の分布からサンプリングする必要はありません。
別のサンプリング関数を使うには、評価シェーダとサンプリングシェーダの両方がサンプリングされる分布を反映するように、それらのシェーダからpdf
を調整します。
コンポーネントマスクの暗黙的な引数 ¶
評価シェーダまたはサンプルシェーダにint mybounces
出力引数を追加すれば、その出力引数にBSDFのコンポーネントマスクが入ります。
cvex_bsdf()
関数に渡した追加の"label"
可変長引数に対してこのマスクをチェックすることで、そのマスクが適用されているかどうかを調べることができます。
これによって、異なるコンポーネントタイプに対して同じCVEXシェーダソースコードを使用することができます。
コンポーネントラベルビットマスクの詳細は、bouncemaskを参照してください。
カスタム可変長引数 ¶
シェーダ文字列引数に続いてcvex_bsdf()
に渡した追加の"key", value
ペアは、シェーダを呼び出した時にそのシェーダに渡されるカスタム引数を定義します。
F = cvex_bsdf("...", "...", "label", "diffuse", "N", N);
特に、新しいBSDFに対してコンポーネントのタイプ(例えば、"diffuse"
または"reflect"
)を指定したいのであれば、“label”キーワード引数を用意してください。
スペース区切りのリスト(例えば、"label", "reflect refract"
)で複数のラベルを指定することができます。
検証 ¶
cvex_bsdf
評価とサンプリング関数が正しく実装されたかどうか検証する方法が主に2通りあります。
-
1つ目の方法では、Mantraの複数の重点サンプリングアルゴリズムを使用して、別のサンプリングテクニックに対して、ノイズを別にして、 明度でレンダリングが一致するようにすることができます。 これをするためには、(マップを割り当てた)環境ライトを作成して、 MIS Bias パラメータの値を変えてレンダリングします。 MIS Bias は、デフォルトではライトで利用できないので、レンダリングプロパティダイアログから MIS Bias パラメータを追加する必要があります。 -1の値は、BSDFからのみサンプリングすることを意味し、1の値は、光源からのみサンプリングすることを意味します。 サンプリング関数内の
refl
値を検証するには、環境ライトのレンダリングモードを Ray Tracing Background に設定します。 レンダリング結果が-1,0,1の値で(ノイズを別として)同じならば、レイトレース背景に対してシェーダにはバイアスがありません。 -
2つ目の方法では、Verify BSDFオブジェクトを使用して、アルベド、PDF、サンプリング関数のすべてが正しく揃っていて、それらが正しい値に統一されていることを検証することができます。 この方法は、SOPでポイントベースのランダムサンプリングを使用し、さらにBSDFの形状を視覚的に極ポイントクラウドとして表示します。
Examples ¶
サンプル: Diffuse ¶
作成:
F = cvex_bsdf("diffuse_eval", "diffuse_sample", "label", "diffuse", "N", N);
評価シェーダ:
#include "pbr.h" cvex diffuse_eval( vector u = 0; vector v = 0; int bounces = 0; int reverse = 0; export vector refl = 0; export vector eval = 0; export float pdf = 0; int mybounces = 0; vector N = 0) { if (bounces & mybounces) { // reverseを評価する場合、出射光の方向よりも、入射光の方向の方が評価で必要になります。 // selectステートメントは、"reverse"トグルの値に基づいて入れ替わります。 vector vvec = select(reverse, u, v); pdf = max(dot(vvec, normalize(N)), 0); eval = pdf; refl = 0.5; } }
サンプルシェーダ:
#include "math.h" #include "pbr.h" cvex diffuse_sample( vector u = 0; float sx = 0; float sy = 0; int bounces = 0; export vector refl = 0; export vector v = 0; export int bouncetype = 0; export float pdf = 0; int mybounces = 0; vector N = 0) { if (bounces & mybounces) { vector nml = normalize(N); v = set(cos(sx*PI*2), sin(sx*PI*2), 0); v *= sqrt(sy); v.z = sqrt(1-sy); pdf = 2*v.z; // vをnmlの参照フレームに変換します vector framex = normalize(cross(nml, u)); vector framey = cross(nml, framex); v = framex * v.x + framey * v.y + nml*v.z; bouncetype = mybounces; refl = 0.5; // 輝度はアルベドに一致させる必要があります } }
サンプル: Specular ¶
作成:
F = cvex_bsdf("specular_eval", "specular_sample", "label", "reflect", "dir", reflect(I, N));
評価シェーダ:
#include "pbr.h" cvex specular_eval( vector u = 0; vector v = 0; int bounces = 0; int reverse = 1; export vector refl = 0; export vector eval = 0; // デルタBSDF int mybounces = 0; vector dir = 0) { if (bounces & mybounces) refl = 1; }
サンプルシェーダ:
#include "math.h" #include "pbr.h" cvex specular_sample( vector u = 0; float sx = 0; float sy = 0; int bounces = 0; export vector refl = 0; export vector v = 0; export int bouncetype = 0; export float pdf = 0; int mybounces = 0; vector dir = 0) { if (bounces & mybounces) { pdf = 1e6F; v = dir; bouncetype = mybounces; refl = 1; // アルベドに合わせる必要があります } }
See also | |
bsdf |
|
experimental | |
shading |
|