I originally wrote a pathtracer that just bounces by the BRDF and each sample is added to a buffer that divides by the current number of frames.

Now I'd like to do next event estimation at each bounce, directly sampling the light along the path. How do I "weight" the samples taken with regular pathtracing along with the direct light samples? Even if I weight the direct light by the solid angle of the light, if I have more than 1 sample taken I can no longer just divide by the frame count right?

  • 2
    $\begingroup$ This doesn't have anything to do with your question but you seem like you probably would be interested to hear about it. You should check out cosine weighted sampling if you haven't heard of it. Instead of multiplying by cos theta, you make your rays be distributed based on cos theta. The easiest way to do this is choose random point on a disk (x/z), and then make y such that it's a normalized vector. You end up sampling more meaningful directions and get faster convergence. $\endgroup$ – Alan Wolfe Nov 19 '16 at 22:08
  • $\begingroup$ It's very difficult to understand what you try to say. Can you clarify your question? Are you talking about progressive path tracing and importance sampling? $\endgroup$ – JarkkoL Nov 21 '16 at 14:44

By "bounces by the BRDF", I assume you mean picking random directions in the hemisphere and weighting by the BRDF, then averaging over those samples. I guess you're accumulating one sample per frame, so then you divide by the current number of frames.

To be theoretically "correct", you should also be weighting those samples by $2\pi$, as that's the solid angle of the hemisphere you're integrating over. That's not too important when you just have a single sampling method, but when you're going to combine multiple ones it's easier to be sure everything's consistent if you have these factors right.

Then, to incorporate explicit direct light sampling, you have to convert from the light-sampling probability density to the solid angle probability density at the receiver point. If the light samples are uniform over the light source's area, then in place of the simple $2\pi$ weight, you'd use this weight factor instead: $$\frac{A}{r^2} (N_\text{light} \cdot -L)$$ where $A$ is the area of the light source, $r$ is the distance between the receiver point (current path point) and the chosen light source point, $N_\text{light}$ is the normal of the light point, and $L$ is the unit vector from the path point, toward the light point.

This factor accounts for how dense the sampled light source points will be in solid angle of the receiver point, varying both with distance and with the angle on the light source's surface (the points will bunch up in areas where the source surface slopes away from the receiver, such as around the edges of a spherical area light).

After weighting by this factor, the direct light samples are in the same solid angle domain as the BRDF samples, so you can just add them together and divide by the total number of samples—which would now be twice the number of frames, if you're doing one BRDF sample and one light sample per frame.

Also, an important thing to get right is not double-counting the light's illumination. Since you're explicitly sampling the lights now, you have to make sure not to include the emissive color if you do happen to randomly hit a light while doing the BRDF samples! Otherwise you'd end up with the lights appearing twice as bright as they should.

A refinement of this is that you may wish to apply explicit light sampling only to the diffuse part of the BRDF, and not the specular part. A narrow specular highlight is better handled through importance-sampling the BRDF instead. This implies that when doing explicit light samples, you would only evaluate the diffuse component of the BRDF, and then if you hit a light source through a specular reflection ray, you would include its emissive color there.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.