前回に引き続きImportanceSamplingの基礎について勉強したいと思います。
今回も、Bruce WalterさんのNotes on the Ward BRDFを読みたいと思います。
Ward BRDFのspecular項
前回の記事では、Ward BRDFをisotropicな場合に限定したBRDFのImportanceSamplingを考えてみましたが、今回はanisotropicなケースを考えてみたいと思います。
ρsはスペキュラ係数、αx,αyは、接空間におけるx,y方向のroughnessに相当します。αxとαyが同じ値のときはisotropicになり、前回の記事で取り扱った式と同一になります。前回の記事と同様に、一様乱数からの変数変換の式を先に決め、それを偏微分してPDFを導出し、ImportanceSamplingできるようにしたいと思います。
変数変換の式を考える
0~1の一様乱数u,vから、ハーフベクトルの偏角θh,φhへの変換を考えます。変換式は、参照のNotes on the Ward BRDFに記述されているので、以下の立式の理由は後付けです。
まずθhについてですが、前回同様にBRDFのexp()の部分をそのまま使います。理由も前回と同様で、exp()関数を偏微分すれば、そのまま係数項として出てくるはずで、BRDFとPDFを比例関係に近づけることができると思います。
次にφhについてですが、BRDFの式を見ると、αx,αyの値に従って、φ周りで値の大きな領域(specular)が楕円状になることがわかります。例えば、αx>αyならば接空間のx軸方向に広いspecularが現れるはずです。この場合ならx軸に近い角度のφのサンプリングを重点的に行うほうが好ましいと言えます。つまり、φのサンプリングはαx,αyの値にそった楕円状なるのが好ましいといえると思います。以下のように、tan()を使ってx,y軸でαx,αyの比になる楕円状にサンプリングを行います。
上記の逆関数は以下のようになります。
偏微分を先にやる
この後の計算の流れは、前回の記事と同様なので、先にu,vの変数変換式の偏微分を計算します。
PDFの計算
次に、上記の計算結果を用いてPDFの計算をします。exp()の項は最後まで保存されるので省略して書きます。
上記の通り、ハーフベクトルのPDFが求まりました。前回同様に反射ベクトルのPDFとして変換すると以下のようになります。
サンプリングの計算
実際のサンプリングでは、u,vからθh,φhを求めるので、先に記した変換式の逆関数が必要になります。今回は、θhはφhの関数となっているのでφhを先に求める必要があります。
φhを求める際に、arctan()を使っています。この関数は非連続な関数なので、実際にプログラム内で使用する場合は注意が必要です。直接φhを求めずに、sin(φh),cos(φh)を求めて、そのまま使う方法も考えられます。その場合は、以下の様に連続的に求めることができます。
同様の計算が、θhでも可能です。したがって、サンプリングの関数は以下の様になります。
vec3 SampleWard(float u1, float u2, vec3 V) { float sinPhi, cosPhi; { float x = ax * cos(2.0f * PI *u2); float y = ay * sin(2.0f * PI *u2); float len = sqrt(x*x+y*y); sinPhi = y / len; cosPhi = x / len; } float sinTheta, cosTheta; { flaot x = sqrt((cosPhi*cosPhi)/(ax*ax)+(sinPhi*sinPhi)/(ay*ay)); float y= sqrt(-log(u1)); float len = sqrt(x*x+y*y); sinTheta = y / len; cosTheta = x / len; } vec3 H = vec3(sinTheta * cosPhi, sinTheta * sinPhi, cosTheta) return -V + 2.0f * H * dot(H, V) }
一方でモンテカルロ積分のweight関数は以下のようになります。