PhongのBRDF
PhongのBRDFは、視線の反射ベクトルRとL_iの関数になっています。残りは正規化項(n+1)/(2π)やSpecular係数のk_sといった要素になっています。
今回も極座標系を使いますが、反射ベクトルRを天頂とした極座標を用いて、以下のように式を書きます。
上記の式をモンテカルロ積分するのですが、PDFには正規化Phongの部分をそのまま使えば半球で積分すれば1になるので都合が良いです。なぜ下記の式を積分すると1になるかは、以前に書いた記事「Phongの正規化」を見ていただければ分かると思います。
あとは、前回の記事でも使用した、inversion methodを使って式を導出していきます。MDFとconditional density functionはそれぞれ以下のようになります。
さらに、それぞれのCDFは以下のようになります。
昔の記事でPhongの正規化を行った際と同様の漸化式と部分積分を使って積分します。
φの方は自明なので、導出は省略です。
P(θ)をξ1とし、P(φ|θ)をξ2として、逆関数を求めます。
これを用いたサンプリング用の関数は以下のようになります。
2016-08-21修正。
上記関数で求まるθ,φは、反射ベクトルの摂動です。Samplingの関数は接空間を基準にしています。反射ベクトルを求めるのは簡単ですが、反射ベクトルは単なるベクトルで、空間の概念が無いので、そのままでは摂動させることができません。サンプリングのベクトルを求めるには、反射ベクトル空間が必要になります。下記の例では、入射ベクトルと反射ベクトルの外積のベクトルを補助的に使って、任意軸の回転を用いて、反射ベクトルを摂動させます。特異点がある上に、計算コストが高いのであまり良い方法とは言えないと思います。
vec3 SamplePhong(float u1, float u2, vec3 V) { float theta = acos(pow(1-u1, 1/(n+1))); float phi = 2 * pi * u2; vec3 R = vec3(-V.x, -V.y, V.z); vec3 Ro = cross(V, R); if (length(Ro) < epsilon) { // in the case when V and R are aligned with Z axis. return vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)) } Ro = normalize(Ro); vec3 Rphi = AxisRotation(R, Ro, phi); vec3 Rtheta = AxisRotation(Rphi, R, theta); return Rtheta; }
一方でモンテカルロ積分の式は、以下のようになります。
ここで一点気をつけなくてはならない点があります。サンプリング用のベクトルを返す関数は、視線ベクトルを反射させたものを摂動させているので、法線との角度が90度以上のベクトルを返すことがあります。このベクトルの場合はPhongの値は明らかにゼロですが、モンテカルロ積分の式に視線ベクトルや法線の関数が残っていないので、Liを加算するときには、Liのベクトルを別途チェックする必要があります。
話は逸れて、正規分布とBox Muller transformについて
(レンダリングと一旦離れますが最終的な目標はexp(x)が含まれるBRDFをImportance Samplingすることにあります。ただし、今回はそこまで到達しません。)
ここで、Importance Samplingの確率密度関数:PDFに正規分布が使えないかを考えてみます。 標準正規分布の式は以下のとおりで、全区間の積分は1であることが知られています。したがって、この関数はPDFとしてそのまま使用可能です。
さらに2変数の正規分布について考えます。まずは、これの積分を考えます。
この式を、極座標系に書き換えて積分します。
上記のように置換すると、以下のようになります。
さらに以下のように変数変換を行います。
さて、積分が1だということが分かったので、先ほどの式をそのままPDFとして使用します。x,yが標準正規分布に従うならば、その確率密度は以下のようになるはずです。
MDFとconditional density functionを求めますが、その前に極座標系に変数変換します。
この変数変換のヤコビアンは以下のようになります。確率密度関数p(x,y)は、x,yがある微小領域dx,dyをとる場合の確率ですので、変数変換する際は、ヤコビアンを掛ける必要があります。
したがって、先の確率密度関数は以下のようになります。
inversion methodを使うための積分は簡単なので割愛します。各CDFは以下のようになります。
P(θ)をξ1とし、P(R|θ)をξ2として、逆関数を求めます。
Rは極座標系における半径の平方根だったので、実際の半径:rは、Rの平方根となります。
ξ2が0~1の一様乱数であるとするならば、1-ξ2はξ2と同義であると考えられるので、以下のように書き換えられます。
上記の、2つの一様変数ξ1,ξ2から、2変数の標準正規分布のサンプリングを生成する変換式をBox Muller transformと呼びます。
2016-08-22修正
次回はこの導出を用いて、exp(x)を含むBRDFのImportance Samplingに取り組みたいと思います。
結局次の記事では使いませんでした。ただし、Box-Muller自体は有用で、レンダリングにおいて様々なところで利用されています。