So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation.
The problem is without MIS I get images like,
This is obtained by setting
light_sample *= 1/light_pdf; // Note no mis_weight
and just returning this sample alone. No BRDF sampling.
Where as with MIS as defined above I get darker images like,
The reason is surely the mis_weight
factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a mis_weight
. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in light_pdf = 0
. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by mis_weight
when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?
Imo, mis_weight
factor in light_sample
should only be used when BRDF sampling also results in a light ray that intersects the light source.
Can anybody explain if these results are ok or there is something wrong with the code?
EDIT:- There is another case which is a little confusing. I am currently using a heuristic (basically power/distance) to choose 1 light out of multiple lights. What if Light sampling and BRDF sampling choose different light sources. Is MIS still valid then? Since the PDF would change resulting the weights not being able to sum to 1 anymore
EDIT2:- So Stefan pointed out a mistake here, that I was clamping radiance. And this solved that issue and changed the results I'm getting for MIS. I have double checked PBRT's implementation and it is similar to mine. I'm still getting darker images using MIS however now I'm getting more fireflies and I think I read that MIS reduces fireflies? Updated the images. It seems fireflies are less in MIS however, the reflection seems harder to converge.
Note the reflection is harder to converge. Both images are 1000 spp. Top is without MIS.
I'm removing the snippet and adding a link to github for the whole kernel. The core functions are evaluateDirectLighting
, shading
, sampleLights
. Link to code is "here"
--Found a mistake. I was using the direct lighting equation when calculating the brdf sample. (multiplying by $\cos(\theta^{\prime})$ and dividing by $r^2$). Removed it since we initially sampled through BSDF which is integral over solid angle not area. The image got a little brighter. Still don't know if MIS is working as intended. See answer.
EDIT3:- Added a release as well. So if anybody wants, they can try changing the code in "*.cl" file and run the program to see the results. (You must have an OpenCL 1.1 supported GPU or CPU)
EDIT4:- Here's an overview of what I'm doing now.
First I choose a single light source out of multiple using simple heuristic scheme like the distance, intensity, area and the cosine falloff angles. I appropriately set the weights for the light like this
$light\_pdf = weight/area$
where weight is in range 0-1.
Next I trace the ray to see if light source is visible. If it is I calculate the $light\_sample$ using the direct lighting equation (integral over Area).
Then I calculate the BRDF PDF for this given ray. However I use Lafortune's algorithm for it. If a random number falls under the specular color I sample through the modfied Phong PDF else through Cosine.
The weights are computed using power heuristic, $ weight = light\_pdf^2/(light\_pdf^2+brdf\_pdf^2)$
The MIS estimator is then calculated as
$light\_sample = light\_sample * weight/light\_pdf$
After that I come to BRDF sampling. I again sample through either Phong/Cosine based on what I did earlier during light sample calculation. If the sampled ray doesn't hit any light source or not the same one. I set the $brdf\_sample$ to zero. If it hits, I set the $light\_pdf$ to same value as before. Calculate the weights like mentioned above and calculate brdf sample using the original equation (integral over solid angle).
EDIT5:- After lightxbulb suggestions, I think the problem has resolved.
Note the images might look a whole lot different but that's cause I implemented Tonemapping + Gamma Correction in the meantime :)
With MIS 700spp
brdf_pdf
. $\endgroup$cos(theta)/pi
$\endgroup$mis_weight
times darker/brighter. Because as I said as soon as i remove mis_wieght and just divide bylight_pdf
I get the brighter image. $\endgroup$