layout: default title: (Task 6) Direct Lighting permalink: /pathtracer/direct_lighting parent: "A3: Pathtracer" usemathjax: true

(Task 6) Direct Lighting

After tasks 4 and 5, Pathtracer::sample_direct_lighting is no different than the indirect case: it simply samples a ray from the BSDF scattering function and traces it into the scene to gather direct lighting. In this task, you will modify the sampling algorithm by splitting samples between BSDF scatters and the surface of area lights, a procedure commonly known as next event estimation.

First consider why sampling lights is useful. Currently, we are only importance sampling the BSDF term of the rendering equation (in which we have included the cosine term). However, each sample we take will also be multiplied by incoming radiance. If we could somehow sample the full product, our monte carlo estimator would exhibit far lower variance. Sampling lights is one way to importance sample incoming radiance, but there are some caveats.

How do we do it?

It's tempting to simply compute an estimate of direct lighting from BSDF samples, another from sampling the surface of lights, and average the results. However, variance is additive: averaging two high-variance estimators does not give back a low-variance one. Instead, we can create a single new distribution that has the average PDF of the two inputs.

To do so, simply uniformly randomly choose which strategy to use before sampling from it as usual. Any given sample could then have been generated from either distribution, so the PDF at the sample is the average over each individual strategy's PDF. This is called mixture sampling, or more properly single-sample multiple importance sampling.

Why is this helpful?

Intuitively, consider that the average of multiple PDFs is itself a PDF: it is non-negative and integrates to one. The average PDF will assign higher weight to any region that one of its components did, producing a distribution following the strengths of each. We can then use the improved distribution to sample and accumulate monte carlo estimates as usual.

Previously, if we chose a low-weight BSDF sample that just happened to hit a bright light, we would get a huge (high-variance) result after dividing (large) incoming light by the (small) PDF. Now, regardless of whether that sample came from BSDF::scatter or Pathtracer::sample_area_lights, the PDF of the sample cannot be small, because its Pathtracer::area_lights_pdf component is not small.

For a more rigorous explanation of multiple importance sampling, refer to Physically Based Rendering chapters 13.10 and 14.3.

Lastly, note that when the true light distribution heavily favors only one strategy (e.g. a highly specular but still continuous BSDF, or an intense but small area light), we will end up wasting time on samples we got from the wrong strategy. Ideally, we could adaptively choose how much contribution we take from each option, which is known as multi-sample multiple importance sampling (see Extra Credit).

Finally, let's upgrade Pathtracer::sample_direct_lighting. Start by reading the following functions:


Reference Results

You will now be able to render scenes featuring area lights using far fewer samples and still get good results. The effect will be particularly pronounced when small and/or intense area lights are used with Lambertian materials (e.g. see task 7, grace.exr).

Here are cbox.dae and cbox_lambertian.dae without (left) and with (right) area light sampling (32 samples, max depth = 8):

Extra Credit

Table of Content