ReSTIR

This is my ReSTIR implementation, developed on top of Microsoft’s DirectX 12 Raytracing Samples.

A Gentle Introduction to ReSTIR: Path Reuse in Real-time.

Resampled Importance Sampling (RIS)

Proof: is to estimate

We begin by computing the expectation of over the samples , conditioning on :

Using linearity of expectation:

Since each :

Therefore:

Proof: is an Unbiased Contribution Weight

Based on Course Notes, Equation 3.1.

Let be i.i.d. samples from a probability distribution .
We define:

Our goal is to show that is an unbiased contribution weight, meaning it satisfies:

Compute

Since , we get:

We are interested in evaluating:

Given that resampling selects with probability:

We have:

Therefore:

Simplifying:

Now:

Since each , we know:

So:

Conclusion

We have successfully proven:

This shows that is indeed an unbiased contribution weight, as stated in Equation 3.1 of the ReSTIR course notes.

Weighted Reservoir Sampling

Reservoir Sampling

Reservoir Sampling is a class of algorithms used to randomly select elements from a stream of data (or from a set where is very large and cannot be stored entirely). The value of is usually small, and is typically large, meaning the entire dataset may not be stored in memory.

Basic Algorithm

Given a sequence of size , or when the total size is unknown and data is being streamed, you need to sample elements.

  1. Initialization:

    • Create an array that can hold elements.
    • Populate this array with the first elements from the stream.
  2. Subsequent Elements:

    • Starting from element , for each new element in the stream, decide with a probability of (where is the total number of elements seen so far) whether the element should replace one of the elements in the array.
    • The probability of replacement for any element in the reservoir is equal across the array.
  3. Final Result:

    • Once all elements have been processed, the array will contain elements, which are the required samples.

Derivation of the Probability

For each element in the reservoir, the probability of it being retained is derived as follows:

  • Before any new elements are encountered, all elements in the reservoir have a probability of 1 of being retained.

  • At step , the probability that an element in the reservoir is replaced by the -th element is:

    Therefore, the probability of not being replaced is:

  • At step , the probability of not being replaced is:

  • This process continues, and after elements have been processed, the probability of an element being retained in the reservoir is:

Hence, every element has an equal probability of of being retained in the final sample.

When the total number of elements, , is unknown, this probability becomes at any point during the sampling process.

Weighted Reservoir Sampling

Weighted Reservoir Sampling extends the basic algorithm by allowing each element to have an associated weight , which determines its likelihood of being included in the sample.

Pseudocode for Weighted Reservoir Sampling

# Reservoir Sampling Algorithm with Weights
 
class Reservoir:
    y = 0                # Output sample
    w_sum = 0            # Sum of weights
    M = 0                # Number of samples seen so far
 
    function update(x_i, w_i):
        w_sum = w_sum + w_i
        M = M + 1
        if rand() < (w_i / w_sum):
            y = x_i
 
function reservoirSampling(S):
    Reservoir r
    for i = 1 to M:
        r.update(S[i], weight(S[i]))
    return r

Derivation of the Probability

To understand why the probability of the last element being selected in Weighted Reservoir Sampling is , let’s break it down step by step.

Definitions

  • : A sequence of elements.
  • : Weight associated with element .
  • : Total weight of elements processed up to .
  • : Current reservoir sample.

Key Idea

Each element has a weight , which determines the probability it gets selected into the reservoir at the time it is processed. For to remain in the reservoir, it must survive the updates from all subsequent elements .

Selection Probability for

  1. Initial Selection
    When is processed, it has a probability of being selected as :

    Here, is the sum of weights of the elements processed up to .

  2. Survival Probability
    After is selected, it must survive replacement by . At each subsequent step , is replaced with probability:

    where is the cumulative weight after including .

    The probability that survives step is:

  3. Combined Survival Probability
    For to remain the final reservoir sample, it must survive all replacements from to . The overall survival probability is:

  4. Final Probability for
    Combining the probability of being selected at step with the probability of surviving subsequent steps, we have:

    Substituting the expressions:

Simplification Using Recursion

The term can be rewritten as:

This reflects the fact that removing the weight leaves the cumulative weight of the previous step. Substituting this into the product:

This is a telescoping product, where intermediate terms cancel out, leaving:

Substituting Back

Substituting this result into the original formula:

The terms cancel, leaving:

Since , we conclude:

Combining Weighted Reservoir Sampling with RIS

The following steps illustrate how this combination works:

  1. Generate a sample stream for each pixel, neighboring pixels, and time-reusable pixels in the image.
  2. Update the reservoir with the sample, weight, and the total count of samples each time.
  3. After updating, use the RIS unbiased estimator to perform the final sampling.

References

Understanding The Math Behind ReSTIR DI

ReSTIR GI

UE5.4 Lumen ReSTIR Gather

UE5.4 Lumen ReSTIR Gather

ReSTIR DI