Skip to content

Commit

Permalink
Add sobol sampler
Browse files Browse the repository at this point in the history
I think I eventually got it working correctly (at least the images look less noisy). But using it currently triggers asserts in a couple of places that imply either numerical errors or bugs in sampling algorithms somewhere, so it's not currently being used.

Separately, since I'm using a trait to do polymorphism, it's hard to make the sampler configurable via scene files. I'll probably have to switch over to an enum, or rip out all but one implementations.
  • Loading branch information
banga committed Jan 25, 2024
1 parent 54d43a0 commit 6b15599
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 5 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ minifb = "0.25.0"
num_cpus = "1.13.1"
rand = { version = "0.8.5", features = ["small_rng"] }
rand_distr = "0.4.3"
sobol_burley = "0.5.0"
tobj = { version = "4.0.0", features = ["use_f64"] }

[[bin]]
Expand Down
3 changes: 2 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ TODO
- [ ] Textures
- [ ] Film
- [ ] Thin lens camera
- [ ] Samplers
- [x] Samplers
- [ ] Fix cosine_sample_hemisphere assert failing with SobolSampler
- [ ] Spectrum
16 changes: 12 additions & 4 deletions src/bin/sampling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use craytracer::{
geometry::{normal::Normal, point::Point, vector::Vector},
n, p,
sampling::{
samplers::{IndependentSampler, Sampler, UniformSampler},
samplers::{IndependentSampler, Sampler, SobolSampler, UniformSampler},
sampling_fns::sample_disk,
sampling_fns::sample_hemisphere,
sampling_fns::sample_triangle,
Expand Down Expand Up @@ -190,6 +190,7 @@ fn main() {

let width = 10;
let height = 10;
let seed = 0;
let spp = spp_x * spp_y;

match test.as_str() {
Expand All @@ -198,8 +199,14 @@ fn main() {
"uniform" => {
test_sampler_quality(&mut UniformSampler::new(spp_x, spp_y), width, height, spp)
}
"independent" => {
test_sampler_quality(&mut IndependentSampler::new(0, spp), width, height, spp)
"independent" => test_sampler_quality(
&mut IndependentSampler::new(seed, spp),
width,
height,
spp,
),
"sobol" => {
test_sampler_quality(&mut SobolSampler::new(seed, spp), width, height, spp)
}
_ => panic!("Unknown sampler: {}", sampler),
};
Expand All @@ -210,8 +217,9 @@ fn main() {
visualize_samples(sample_fn.as_str(), &mut UniformSampler::new(spp_x, spp_y))
}
"independent" => {
visualize_samples(sample_fn.as_str(), &mut IndependentSampler::new(0, spp))
visualize_samples(sample_fn.as_str(), &mut IndependentSampler::new(seed, spp))
}
"sobol" => visualize_samples(sample_fn.as_str(), &mut SobolSampler::new(seed, spp)),
_ => panic!("Unknown sampler: {}", sampler),
};
}
Expand Down
54 changes: 54 additions & 0 deletions src/sampling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub mod sampling_fns {
let (x, y) = sample_disk(sample);
let z = (1.0 - x * x - y * y).max(0.0).sqrt();
let a = tangent * x + bitangent * y + normal * z;
// TODO: This fails when using SobolSampler
assert!(a.dot(&normal) >= 0.0);
a
}
Expand Down Expand Up @@ -193,4 +194,57 @@ pub mod samplers {
Sample2d(sample_x, sample_y)
}
}

#[derive(Clone)]
pub struct SobolSampler {
seed: usize,
num_samples: usize,

hash: u32,
sample_index: u32,
dimension: u32,
}

impl SobolSampler {
pub fn new(seed: usize, num_samples: usize) -> Self {
SobolSampler {
seed,
num_samples,
hash: 0,
sample_index: 0,
dimension: 0,
}
}
}

impl Sampler for SobolSampler {
fn num_samples(&self) -> usize {
self.num_samples
}

fn start_pixel(&mut self, x: usize, y: usize, sample_index: usize) {
let mut hasher = DefaultHasher::new();
self.seed.hash(&mut hasher);
x.hash(&mut hasher);
y.hash(&mut hasher);
self.hash = hasher.finish() as u32;

self.sample_index = sample_index as u32;
self.dimension = 0;
}

fn sample_1d(&mut self) -> Sample1d {
let sample = sobol_burley::sample(self.sample_index, self.dimension, self.hash);
self.dimension += 1;
Sample1d(sample as f64)
}

fn sample_2d(&mut self) -> Sample2d {
let sample_x = sobol_burley::sample(self.sample_index, self.dimension, self.hash);
self.dimension += 1;
let sample_y = sobol_burley::sample(self.sample_index, self.dimension, self.hash);
self.dimension += 1;
Sample2d(sample_x as f64, sample_y as f64)
}
}
}

0 comments on commit 6b15599

Please sign in to comment.