mmp / pbrt-v3

Source code for pbrt, the renderer described in the third edition of "Physically Based Rendering: From Theory To Implementation", by Matt Pharr, Wenzel Jakob, and Greg Humphreys.
http://pbrt.org
BSD 2-Clause "Simplified" License
4.86k stars 1.18k forks source link

Mathematical confusion of Global sampler array samples #334

Open longpractice opened 4 months ago

longpractice commented 4 months ago

I read through the implementation of the GlobalSampler with the low discrepency digital sequences.

One thing confuses me most is that for 1D and 2D array samples, the sample and dimension seems to have a miss match:

Let's say we use

  1. Halton sequence.
  2. We request 3 samples per pixel.
  3. For each pixel, we request one 1d array with 5 elements.

Now from the implementation of GlobalSample::StartPixel

void GlobalSampler::StartPixel(const Point2i &p) {
    ProfilePhase _(Prof::StartPixel);
    Sampler::StartPixel(p);
    dimension = 0;
    intervalSampleIndex = GetIndexForSample(0);
    // Compute _arrayEndDim_ for dimensions used for array samples
    arrayEndDim =
        arrayStartDim + sampleArray1D.size() + 2 * sampleArray2D.size();

    // Compute 1D array samples for _GlobalSampler_
    for (size_t i = 0; i < samples1DArraySizes.size(); ++i) {
        int nSamples = samples1DArraySizes[i] * samplesPerPixel;
        for (int j = 0; j < nSamples; ++j) {
            int64_t index = GetIndexForSample(j);
            sampleArray1D[i][j] = SampleDimension(index, arrayStartDim + i);
        }
    }

    // Compute 2D array samples for _GlobalSampler_
    int dim = arrayStartDim + samples1DArraySizes.size();
    for (size_t i = 0; i < samples2DArraySizes.size(); ++i) {
        int nSamples = samples2DArraySizes[i] * samplesPerPixel;
        for (int j = 0; j < nSamples; ++j) {
            int64_t idx = GetIndexForSample(j);
            sampleArray2D[i][j].x = SampleDimension(idx, dim);
            sampleArray2D[i][j].y = SampleDimension(idx, dim + 1);
        }
        dim += 2;
    }
    CHECK_EQ(arrayEndDim, dim);
}

For our first sample, the 5 elements of the requested 1D array comes from the Halton sequence samples:

GetIndexForSample(0), 
GetIndexForSample(1),
GetIndexForSample(2),
GetIndexForSample(3),
GetIndexForSample(4)

, while other non-array values come from the GetIndexForSample(0) Halton sequence sample.

For our second sample, the 5 elements of the requested single 1D array comes from the Halton sequence samples:

GetIndexForSample(5), 
GetIndexForSample(6),
GetIndexForSample(7),
GetIndexForSample(8),
GetIndexForSample(9)

, while the other non-array values come from the GetIndexForSample(1) Halton sequence sample.

This seems breaks the simple explanation/definition of the low discrepency sequence. The 1D/2D arrays from a sample in our sampler comes from different samples of low discrepency digital sequences. I wonder if there is any mathematical explanation of this?