Path Tracing Weights
#1 Members - Reputation: 1031
Posted 31 July 2012 - 07:34 PM
I'm trying to write the simplest possible (no importance sampling, etc.) path tracer from scratch. It will support only diffuse surfaces and area light sources.
A random path should be generated from the camera. Each ray is chosen uniformly from a hemisphere. The path is a maximum length (I realize this introduces bias, but it's a hard constraint. This maximum length can be very large, so the bias can be small).
How can I weight the each step of the path so that this works?
Thanks,
Ian
#2 Members - Reputation: 1031
Posted 01 August 2012 - 01:49 PM
-For each point:
....-Add the emissive color
....-Continue bouncing the ray with probability proportional to the diffuse color. The bounced ray is generated from a cosine-weighted distribution. You can either weight the ray based on the color's overall intensity, xor consider each channel separately).
This self-explanatory OpenCL code I wrote implements both algorithms. My question now is, given that the algorithm works, how can I change it to use weighting? Most simply, if I change the generate_path(...) function to generate unweighted rays over a hemisphere, how would I weight each ray?
Thanks,
Ian
Edited by Geometrian, 01 August 2012 - 01:53 PM.
#3 Members - Reputation: 1031
Posted 02 August 2012 - 05:48 PM
Naturally, hemispherical sampling makes the convergence worse, because it no longer does importance sampling. However, I think this at least shows that my methodology is sound, and it's an important precursor to eventually making bidirectional path tracing. The below picture shows importance sampling on left versus hemispherical sampling with 2.0*cos(theta) weighting on right. The image was rendered with 2004 samples. The key thing to note is that the illumination is the same, even if the hemispherical sampling has higher variance.
Assuming that the ray scatters, it must go on the hemisphere. I speculate that, on average, the weight of a scatter in any direction on the hemisphere must be 1.0 (that is, the integral of the weights over the hemisphere must be 2*pi). For importance sampling, all the weights are one, but the probability of scattering away from the normal is lower. The integral is 2*pi. For cosine weighted, all the weights are cos(theta), but they need to be scaled by 2 to that the integral is 2*pi. This provides a nice way to make any BRDF--without importance sampling, simply weight each sample by the BRDF(theta), and then scale to ensure that the integral over the hemisphere is 2*pi.

Thanks,
Ian
Edited by Geometrian, 02 August 2012 - 05:56 PM.
#4 Members - Reputation: 1031
Posted 02 August 2012 - 09:00 PM
More progress: you can collapse all that Russian roulette into a simple weighting scheme. This means that, instead of simulating a bunch of rays conditionally stopping, or whatnot, you simulate a single ray, but weight contributions further along geometrically with reflectance. I feel like I tried this before, but for some reason it didn't work.
This self-explanatory OpenCL code works, though. Note that this uses an importance sampled path--one could generate the same result by sampling uniformly from a hemisphere, but weighting each sample by an extra 2.0*cos(theta), as I discovered in my last post.[source lang="c"]HitRecord hits_camera[N];int max_depth = generate_path(ray,N, scene,rvec, hits_camera,NULL,true); //Generate importance sampled pathfloat3 mask = (float3)(1.0f,1.0f,1.0f);for (int i=0;i<N;++i) { const HitRecord* hit = hits_camera + i; accumulated += mask * hit->material->color_emission; float3 f = hit->material->color_diffuse; mask *= f;}[/source]On left, standard path tracing with Russian roulette ray termination. On right, weighting (the above code). Notice that the above code converges more quickly. Intuitively, this is because the weighting scheme needs only one ray to sample all path depths, whereas the Russian roulette needs at least as many rays as there are depths--and the variance for doing this is higher; for weighting, we use the expected value of the reflectance function.

Thanks,
Ian
Edited by Geometrian, 02 August 2012 - 09:03 PM.
#5 Members - Reputation: 269
Posted 04 August 2012 - 04:20 PM
This statement doesn't quite make sense.Russian roulette needs at least as many rays as there are depths
Edited by jameszhao00, 04 August 2012 - 09:02 PM.
#6 Members - Reputation: 1031
Posted 05 August 2012 - 04:19 PM
#7 Members - Reputation: 269
Posted 05 August 2012 - 06:16 PM
Also, a key point of RR is
float3 color = blah blah blah r = 0.3 (or some other ratio) if(rand() < r) color /= r <---- key else terminate next bounce...
Unless I'm missing some context, your weighting scheme is what everyone does, as part of the standard lighting calculating.
Edited by jameszhao00, 05 August 2012 - 06:19 PM.






