pbrt/src/samplers/halton.rs
2026-01-22 14:18:57 +00:00

101 lines
2.9 KiB
Rust

use crate::Arena;
use crate::core::sampler::CreateSampler;
use crate::utils::{FileLoc, ParameterDictionary};
use anyhow::{Result, anyhow};
use shared::core::geometry::Point2i;
use shared::core::options::get_options;
use shared::core::sampler::{HaltonSampler, RandomizeStrategy};
pub trait CreateHaltonSampler {
fn new(
samples_per_pixel: i32,
full_res: Point2i,
randomize: RandomizeStrategy,
seed: u64,
) -> Self;
}
impl CreateHaltonSampler for HaltonSampler {
fn new(
samples_per_pixel: i32,
full_res: Point2i,
randomize: RandomizeStrategy,
seed: u64,
) -> Self {
let digit_permutations = compute_radical_inverse_permutations(seed);
let mut base_scales = [0u64; 2];
let mut base_exponents = [0u64; 2];
let bases = [2, 3];
let res_coords = [full_res.x(), full_res.y()];
for i in 0..2 {
let base = bases[i] as u64;
let mut scale = 1u64;
let mut exp = 0u64;
let limit = std::cmp::min(res_coords[i], MAX_HALTON_RESOLUTION) as u64;
while scale < limit {
scale *= base;
exp += 1;
}
base_scales[i] = scale;
base_exponents[i] = exp;
}
let mut mult_inverse = [0u64; 2];
mult_inverse[0] =
Self::multiplicative_inverse(base_scales[0] as i64, base_scales[0] as i64);
mult_inverse[1] =
Self::multiplicative_inverse(base_scales[1] as i64, base_scales[1] as i64);
Self {
samples_per_pixel,
randomize,
digit_permutations,
base_scales,
base_exponents,
mult_inverse,
halton_index: 0,
dim: 0,
}
}
}
impl CreateSampler for HaltonSampler {
fn create(
params: &ParameterDictionary,
full_res: Point2i,
_loc: &FileLoc,
_arena: &mut Arena,
) -> Result<Self> {
let options = get_options();
let nsamp = options
.quick_render
.then_some(1)
.or(options.pixel_samples)
.unwrap_or_else(|| params.get_one_int("pixelsamples", 16));
let seed = params.get_one_int("seed", options.seed);
let s = match params
.get_one_string("randomization", "permutedigits")
.as_str()
{
"none" => RandomizeStrategy::None,
"permutedigits" => RandomizeStrategy::PermuteDigits,
"fastowen" => RandomizeStrategy::FastOwen,
"owen" => RandomizeStrategy::Owen,
_ => {
return Err(anyhow!(
"{}: Unknown randomization strategy for Halton",
loc
));
}
};
let sampler = HaltonSampler::new(nsamp, full_res, s, seed as u64);
// arena.alloc(sampler);
Ok(sampler)
}
}