Processing math: 100%

Friday, January 23, 2015

BSSRDF Importance Sampling 3 - exponential falloff sampling on 1D and 2D space

Take one more look on our BSSRDF integration equation:
L(xo,ωo)=AΩLi(xi,ωi)S(xi,ωi,xo,ωo)cos(θ)dωdA


The solid angle part seems to be easier since we already got methods to sampling lights at specified intersection point for our previous work on BRDF integration. The area integral part is more interesting: how we integrate the BSSRDF surface. Sure the naive way will be uniform sample the BSSRDF surface area, but look at that dipole model we got, that radically symmetric fast falloff: how much variance we gonna suffer before converge the clean render if we do things by uniform sampling? (and how much ray casting we gonna do to figure out the projection point on surface?) There are definitely some better ways......we should definitely try importance sampling.

OK importance sampling, then what is the dominant factor in that Rd equation? In Jensen01, he mentioned "we use standard Monte Carlo techniques to randomly sample the surface with density (σtreσtrd) at some distance d from xo" which means he suggests the dominant factor to be σtreσtrd, though I feel σtreσtrd/d2 is the closest one. Jensen said the word, let's try it~ time to brush up the inverse method sampling


-------------------------------WARNING DEAD END ENTRY!-------------------------------
I actually fail to get this answer derived out and change the route at last, but still think I should write down what I thought at that time...if you know how to get this derivation out right, please definitely let me know! I'm really curious about it

pdf in 2D space: pdf(x,y)=ceσtrx2+y2 where c is the constant we try to figure out to normalize the pdf
transform it into polar coordinate, the Jacobian is:
Jr=(dxdrdxdθdydrdydθ)=r

so pdf(r,θ)=rpdf(x,y)=creσtrr
cdf(r,θ)=2π00pdf(r,θ)drdθ=2πc0reσtrrdr=1

now integration by part:

uvdr=uvuvdr
u=r and dvdr=eσtrr =>
v=eσtrr/σtr and dvdr=1
0reσtrrdr=reσtrrσtr|r=r=00eσtrrσtrdr=1σ2tr(σtr+1)eσtrr|r=r=0=1σ2tr=12cπ
c=σ2tr2π
pdf(r,θ)=σ2tr2πreσtrr

almost there, now integrate out the θ part to get the marginal pdf(r)=σ2trreσtrr
then cdf(r)=r0σ2trreσtrrdr=1(σtrr+1)eσtrr
and now we just need to get the inverse function of r......and then I stuck........I can't seem to find a easy way to inverse this function......

By doing some google work, it seems that I bump into something called Laplace Transform Inverse , and this stuff kinda out of my college freshman level calculus....Hery 03 seems use a precompute table to solve this sampling part, he also kindly offered the source code for precomuting process, but I'm not sure if I really get what that code does......maybe go learn some advanced calculus can shed some lights for me on this issue, until then, I need to find some workaround.....

-----------------------------------EXIT OF THE DEAD END-----------------------------------

How about Gaussian? Like I mentioned in previous post, we can approximate dipole model with weight sum of Gaussian filters, plus Gaussian's falloff speed is higher than the above exponential falloff, consider there's a (1+σtrd)/d3 factor the above pdf didn't take into account. Maybe Gaussian turned out to be a better fit?


Out of curiosity, I throw in the above 3 normalized equation into some online math drawing tool, the result shows up in above image: green for eσtrd (the Jensen suggestion), red for eσtrd2 (Gaussian, which is my guess), blue for (1+σtrd)eσtr/d3 (which is probably the closest factor to dipole model, but looks really hard to figure out the inverse function) , and ya, Gaussian actually fit closer to the dipole model in this case. Worst of all, it falls off with d increase so it's always better than uniform sample. importance sampling works as long as the pdf is closer to original function, but doesn't need to perfectly fit, right?

So we try to do things Gaussian way now, let's try the inverse method again:

pdf in 2D space: pdf(x,y)=ceσtr(x2+y2) where c is the constant we try to figure out to normalize the pdf
so pdf(r,θ)=rpdf(x,y)=creσtrr2
cdf(r,θ)=2π00pdf(r,θ)drdθ=2πc0reσtrr2dr=2πc(eσtrr22σtr|r=r=0)=cπσtr=1
c=σtrπ
pdf(r,θ)=σtrπreσtrr2

integrate out the theta factor:
pdr(r)=2σtrreσtrr2
cdf(r)=r0pdf(r)=eσtrr2|r0=1eσtrr2
inverse function:
ξ=1eσtrr2
r=ln(1ξ)σtr
and we can further simplified it to:
r=ln(ξ)σtr
since ξ is uniform distribution between 0 and 1
and θ=2πξ

whew~~that's much easier than the previous one....

The above case works when we assume the sample distribute in the whole 2D space( >, how if we want to sample on a disc with radius Rmax? You can actually just replace the integration range to Rmax to derive it out the result. I'll just list the result here directly since it's almost the exact same process:
r=ln(1ξ(1eσtrR2max))σtr
θ=2πξ
pdf(x,y)=(σtrπeσtrr(x2+y2))/(1eσtrRmax)
The reason I brought up this explicit radius version is that we gonna use it later and the original BSSRDF Importance Sampling paper use this as their sampling method. This post basically explain how that equation in paper come out. :)  (it may looks tiny different but if you replace the 12v in paper with σtr , they are exactly the same thing)

Last bonus one, sample in 1D with distribution proportional to eax , this one is used in BSSRDF single scattering and actually the easiest one to derive.

pdf(x)=ceax
cdf(x)=0ceaxdx=caeax|0=ca=1
c=a
pdf(x)=aeax
cdf(x)=x0aeaxdx=1eax
ξ=1eax
x=ln(1ξ)a
simplified to
x=lnξa

Boiling those stuff down to codes are just the following few lines:

/*
* let falloff be a
* since the pdf is proportional to exp(-a * (x * x + y * y))
* let pdf(x, y) = c * exp(-a * (x * x + y * y))
* convert to spherical coordinate:
* pdf(r, theta) = c * r * exp(-a * r * r)
* integrate c * r * exp(-a * r * r) over r (from 0 to inf) and theta = 1 ->
* c = a / pi -> pdf(r, theta) = a / pi * r * exp(-a * r * r) ->
* pdf(x, y) = a / pi * exp(-a * (x * x + y * y))
* marginal pdf(r) = integrage pdf((r, theta) over 0 to 2pi
* = 2 * a * r * exp(-a * r * r)
* conditional pdf(theta|r) = 1 / 2pi
* cdf(r) = integrate 2 * a * r * exp(-a * r * r) over 0 to r ->
* cdf(r) = 1 - exp(-a * r * r)
* cdf(theta) = integrate 1 / 2pi over 0 to theta = theta / 2pi
* inverse method:
* u1 = 1 - exp(-a * r * r) -> r = sqrt(ln(1 - u1) / -a) ->
* r = sqrt(ln(u1) / -a) since u1 is 0-1 uniform distribution
* u2 = theta / 2pi -> theta = 2pi * u2
* transform it back from spherical coordinate:
* x = r * cos(theta)
* y = r * sin(theta)
*/
Vector2 gaussianSample2D(float u1, float u2, float falloff) {
float r = sqrtf(log(u1) / -falloff);
float theta = TWO_PI * u2;
return Vector2(r * cos(theta), r * sin(theta));
}
/*
* similar to the above gaussianSample2D, but the integrate range of r
* from 0 to Rmax, which makes us able to sample a disc with radius Rmax in
* gaussian distribution
*/
Vector2 gaussianSample2D(float u1, float u2, float falloff, float Rmax) {
float r = sqrtf(log(1.0f - u1 * (1.0f - exp(-falloff * Rmax * Rmax))) /
-falloff);
float theta = TWO_PI * u2;
return Vector2(r * cos(theta), r * sin(theta));
}
/*
* integrate c * exp(-falloff * x) from 0 to inf = 1 ->
* c = falloff -> pdf(x) = falloff * exp(-falloff * x)
* cdf(x) = 1 - exp(-falloff * x) -> u = 1 - exp(-falloff * x) ->
* x = -ln(1 - u) / falloff -> simplified to x = -ln(u) / falloff
* since u are [0, 1) uniform distribution
*/
float exponentialSample(float u, float falloff) {
return -log(u) / falloff;
}
float gaussianSample2DPdf(const Vector3& pCenter,
const Vector3& pSample, const Vector3& N, float falloff) {
Vector3 d = pSample - pCenter;
Vector3 projected = d - N * dot(d, N);
return INV_PI * falloff * exp(-falloff * squaredLength(projected));
}
float gaussianSample2DPdf(const Vector3& pCenter,
const Vector3& pSample, const Vector3& N, float falloff, float Rmax) {
return gaussianSample2DPdf(pCenter, pSample, N, falloff) /
(1.0f - exp(-falloff * Rmax * Rmax));
}
float gaussianSample2DPdf(float x, float y, float falloff) {
return INV_PI * falloff * exp(-falloff * (x * x + y * y));
}
float gaussianSample2DPdf(float x, float y, float falloff,
float Rmax) {
return gaussianSample2DPdf(x, y, falloff) /
(1.0f - exp(-falloff * Rmax * Rmax));
}
// project pSample on the plane form by pCenter and N, then calculate
// the corresponding gaussian 2D pdf
float gaussianSample2DPdf(const Vector3& pCenter,
const Vector3& pSample, const Vector3& N, float falloff);
float gaussianSample2DPdf(const Vector3& pCenter,
const Vector3& pSample, const Vector3& N, float falloff, float Rmax);
float exponentialPdf(float x, float falloff) {
return falloff * exp(-falloff * x);
}
And here's some testing result with our freshly cooked sampling strategy, for comparison I put in another set of uniform disc sampling implemented based on Shirly 97

left up: 100 Gaussian sample with max radius 2 and falloff 2
right up: 1024 Gaussian sample with max radius 2 and falloff 2
left down: 100 uniform disc sample with radius 2
right down: 1024 uniform disc sample with radius 2

Now we have the TODO list item 3 in hand. We can start to look into the multiple importance sampling method BSSRDF Importance Sampling proposed, which in my opinion, is the most exciting part for this round.


No comments:

Post a Comment