改组和NRooks约束保存

时间:2011-06-22 20:46:45

标签: algorithm raytracing

我正在实施光线跟踪器,我正在实施采样器。采样器是方形x = 0:1,y = 0:1上的随机点的生成器。每个采样器保存多组“随机”样本,每组包含给定数量的样本。

现在,其中一个采样器是NRooks。它将表面划分为n x n块,沿对角线选择块,在每个对角线块中提取一个随机点,最后先将x混合在一起,然后再移动y

enter image description here

这一切都很干净。然而,当提取点数时,我正在遵循的书提出了这些额外的要求,以打破后续像素和采样之间的相关性。 第一个要求是每次设置耗尽时,随机选取一个新的样本集。实现此目的的代码如下:

 Point2D Sampler::sample_unit_square(void) { 
    if (count % num_samples == 0) jump = (rand_int() % num_sets) * num_samples;
    return (samples[jump + count++ % num_samples]
 }

其中samples是Point2D的大小为num_samples*num_sets的向量(它是线性化的)。每次完成一个像素(计数可被num_samples整除)时,将提取一个新的跳转并用于指示线性阵列以开始新的一组。

由于我使用的是python,我的策略是使用迭代器:

def __iter__(self):

    while True:
        for sample_set in random.choice(self._samples_sets):
            for sample in sample_set:
                yield sample

这很简单,工作正常。

第二个需要是改变指数,这就是我的问题所在。该书修改了以下代码

 Point2D Sampler::sample_unit_square(void) { 
    if (count % num_samples == 0) jump = (rand_int() % num_sets) * num_samples;
    return (samples[jump + shuffled_indices[ jump + count++ % num_samples]]
 }

其中,混洗索引是一个如下计算的数组

 void Sampler::setup_shuffled_indices(void) {
     shuffled_indices.reserve(num_samples*num_sets);
     vector<int> indices;

     for (int j=0; j<num_samples; j++) indices.push_back(j);

     for (int p=0; p<num_sets; p++) {
          random_shuffle(indices.begin(), indices.end());
          for (int j=0; j<num_samples; j++) {
              shuffled_indices.push_back(indices[j]);
          }
     }
 }

这是一种非常C ++的方法,可以从1到n中取一个数字列表并对它们进行混洗。我想在python中实现以下代码

def __iter__(self):

    while True:
        sample_set = random.choice(self._samples_sets):
        shuffled_set = sample_set[:]
        random.shuffle(shuffled_set)
        for sample in shuffled_set:
            yield sample

我还可以实现一个迭代集合的随机迭代器,保存列表副本,但这不是重点。我的问题来自书中的以下短语:

  

...... [除去相关性]的另一种可能性是在每组的样本上使用最终的随机播放,但这会破坏n-rooks条件[...]。最好的方法是随机改组sample_unit_square中使用的索引,但保证所有样本都被使用。

我不明白的是:为什么说每套样品的最后一次洗牌打破了n-rooks?关键是他正在使用间接索引到点数组中。这个间接索引是在从1到集合的所有索引的混洗中创建的,但这相当于每个集合中所有样本的混洗。由于恕我直言,我不明白为什么第一个配方应该打破n-rooks,为什么第二个配方不会。

这本书的记录是凯文·萨弗恩(Kevin Suffern)的“从头开始追踪”。

1 个答案:

答案 0 :(得分:1)

在我看来像是

  

...对样本进行最后的洗牌   每一套..

建议在集合被洗牌后独立地对每个集合进行洗牌。

def __iter__(self):

    while True:
        for sample_set in random.choice(self._samples_sets):
            for sample in random.choice(sample_set):
                yield sample
像这样。我不是Python专家所以请原谅任何代码错误。这会打破n-rooks,虽然这可能只是一个坏主意。这取决于你的目标。