我正在实施光线跟踪器,我正在实施采样器。采样器是方形x = 0:1,y = 0:1上的随机点的生成器。每个采样器保存多组“随机”样本,每组包含给定数量的样本。
现在,其中一个采样器是NRooks。它将表面划分为n x n
块,沿对角线选择块,在每个对角线块中提取一个随机点,最后先将x
混合在一起,然后再移动y
。
这一切都很干净。然而,当提取点数时,我正在遵循的书提出了这些额外的要求,以打破后续像素和采样之间的相关性。 第一个要求是每次设置耗尽时,随机选取一个新的样本集。实现此目的的代码如下:
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)的“从头开始追踪”。
答案 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,虽然这可能只是一个坏主意。这取决于你的目标。