Ste*_*ini 7 algorithm raytracing
我正在实现一个光线跟踪器,我正在实现采样器.采样器是方形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]
}
Run Code Online (Sandbox Code Playgroud)
其中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
Run Code Online (Sandbox Code Playgroud)
这是微不足道的,并且工作正常.
第二个需要是改变指数,这就是我的问题所在.该书修改了如下代码
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]]
}
Run Code Online (Sandbox Code Playgroud)
其中,混洗索引是一个如下计算的数组
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]);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是一种非常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
Run Code Online (Sandbox Code Playgroud)
我还可以实现一个迭代集合的随机迭代器,保存列表副本,但这不是重点.我的问题来自书中的以下短语:
... [除去相关性]的另一种可能性是在每组的样本上使用最终的随机播放,但这会破坏n-rooks条件[...].最好的方法是随机混洗
sample_unit_square
每个集合中使用的索引,但保证使用所有样本.
我不明白的是:为什么它说每套样品的最后洗牌打破了n-rooks?关键是他正在使用间接索引到点数组中.这个间接索引是在从1到集合的所有索引的混洗中创建的,但这相当于每个集合中所有样本的混洗.作为恕我直言,我不明白为什么第一个配方应该打破n-rooks,为什么第二个配方不会.
据记载,这本书由凯文·萨弗恩(Kevin Suffern)撰写的"雷从头开始追踪".
在我看来就像
...对每组样本进行最后的洗牌..
建议在洗牌后将每组独立洗牌。
def __iter__(self):
while True:
for sample_set in random.choice(self._samples_sets):
for sample in random.choice(sample_set):
yield sample
Run Code Online (Sandbox Code Playgroud)
就像这样。我不是 Python 专家,所以请原谅任何代码错误。这会破坏 n-rooks,尽管这可能只是一个坏主意。这取决于你的目的。