# Sampling Sun And Sky

In this post I will briefly cover how I implemented sampling of external light sources in a path tracing framework, concluding with an observation about sampling multiple external light sources that are non-zero over very different solid angles. I’m going to assume the reader is familiar with path tracing in the Veach framework.

My definition of an *external* light source, which I’ve also seen called an “infinite” light source since they are considered to be infinitely far away (and infinitely bright as a result), is as follows:

- Radiance always originates from outside of the scene bounds
- Radiance is a function of world space direction only (not sample position)

A simple example would be a cube map considered to be always centered at the sample point.

## Single Emitter

The way I represent external lighting is as a sum of *external emitters*.
A single external emitter is defined as follows:

- Provides a function that takes a world space direction and returns emitted radiance from that direction
- Provides a function to generate a world space direction and emitted radiance given 2 uniform random variables

Both of these functions also compute the probability density of the direction with respect to solid angle.

There are two techniques in a path tracer that would include radiance from an external emitter:

- Sample the BSDF and evaluate the emitter if there is no geometry in that ray direction
- Sample the emitter and evaluate the BSDF if there is no geometry in that ray direction

Here’s a diagram of this for an external emitter that is only non-zero for a small solid angle (where the dotted line is solid):

In this example, BRDF sampling is unlikely to generate samples that hit the non-zero region, so it is essential to use multiple importance sampling between these two techniques to avoid excessive noise. This should all be very familiar to anyone that has implemented such a “next event estimation” path tracer, so let’s move on.

## Multiple Emitters

It is common to require more than one external emitter to be active at the same time. For example, I implement the daylight model by Preetham et al as the sum of 2 external emitters:

- A constant emission function for some solid angle in the sun direction (i.e. sunlight)
- A variable emission function over the hemisphere in the “up” direction (i.e. skylight)

A first strategy to handle multiple emission functions might be to pick a single emitter for each sample (using some random variable), adjust the pdf accordingly, and rely on multiple samples to cover all the functions. However, this is quite wasteful of our intersection tests considering that these emission functions should be completely additive for a given direction, we can do better by using all functions and multiple importance sampling between them. Note this is a separate application of MIS, used in addition to the MIS between path tracing techniques we already apply during the path tracing algorithm.

So let us consider a new type of external emitter that is simply an array of N external emitters, and consider how to sample it. We define each emitter as a function of direction as:

Each emitter has probability density with respect to solid angle of:

We also define our discrete probabilities for choosing one of these N emitters as:

We can then define the value and probability density of our combined emitter as:

Our sampling function is constructed from the sampling functions for each emitter as follows:

- Pick an emitter according to the probabilities
`$s_i$`

- Sample a world space direction using the sampling function of the chosen emitter
- Compute the radiance and combined pdf using the equations above

This multiple importance sampling step nicely handles the fact that sunlight and skylight are non-zero over very different solid angles: even if we choose the sky emitter and happen to lie within the solid angle of the sun (producing a very large radiance value), the combined pdf will take into account the density of all emitters resulting in a low-variance estimate.

A sensible approach for choosing the discrete probabilities `$s_i$`

is to use the proportion of the total power provided by each emitter.

## Multiple Emitters With Restricted Sampling

What I hadn’t realised before is that it’s perfectly valid to make the discrete probability for one or more of the emitters 0. This can of course result in the combined radiance function (as defined above) being non-zero when the combined pdf is zero. When this situation is detected by calling code while the emitters are being evaluated for some direction, it should be treated as “this direction can only be sampled by BSDF sampling”, setting the multiple importance sampling weight to 1 (since there is only one technique for this direction).

This gives us a way to only multiple importance sample between BSDF sampling and emitter sampling for *some components* of the external lighting, with the remaining components (that have 0 discrete probability) sampled *only* using BSDF sampling.

Somewhat counter-intuitively, I get lower variance when using this approach with sunlight and skylight. I produced a reference image for this scene using 1024spp, then looked at the convergence speed for discrete probabilities that correspond to the following ratios:

^{50}⁄_{50}sunlight/skylight^{90}⁄_{10}sunlight/skylight^{100}⁄_{0}sunlight/skylight (i.e. only the sun emitter can be sampled explicitly)

Here’s the reference image, sorry for the lack of shading normals on the Stanford bunny:

Here’s a log/log graph of the results for each of the 3 sampling strategies for the external emitters. The x axis is the base-2 logarithm of the sample count, so the data points are at from 1,2,4 etc up to 256 samples. The y axis is the base-10 logarithm of RMSE, so lower is better. (At some point I need to implement a perceptual metric, but RMSE will have to do for now.)

The technique with the lowest noise is the technique that doesn’t explicitly sample skylight at all, relying only on BSDF sampling to find skylight not within the solid angle of the sun. I think this works out because:

- By always sampling sunlight, we removed a random variable from the system.
- Since BSDF sampling only for skylight is already a good technique, the net effect of removing a random variable is less overall noise.