More improvements to Sobol sampling.
- Added an additional scramble round to the Owen scrambling, with new optimized constants. - Reordered the dimensions of the direction numbers to improve 2d projections between adjecent dimensions. Only did this for dimensions under ~40.
This commit is contained in:
parent
de5a643a2a
commit
9e14e164e7
|
@ -709,10 +709,7 @@ fn get_sample(dimension: u32, i: u32, pixel_co: (u32, u32), seed: u32) -> f32 {
|
||||||
n if (n - 1) < sobol::MAX_DIMENSION as u32 => {
|
n if (n - 1) < sobol::MAX_DIMENSION as u32 => {
|
||||||
let dim = n - 1;
|
let dim = n - 1;
|
||||||
// Sobol sampling.
|
// Sobol sampling.
|
||||||
// We skip the first 32 samples because doing so reduces noise
|
sobol::sample_owen_cranley(dim, i, hash_u32(dim, scramble))
|
||||||
// in some areas when rendering at 64 spp. Not sure why, but it
|
|
||||||
// works.
|
|
||||||
sobol::sample_owen_cranley(dim, i + 32, hash_u32(dim, scramble))
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Random sampling.
|
// Random sampling.
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::{env, fs::File, io::Write, path::Path};
|
||||||
const NUM_DIMENSIONS: usize = 256;
|
const NUM_DIMENSIONS: usize = 256;
|
||||||
|
|
||||||
/// What file to generate the numbers from.
|
/// What file to generate the numbers from.
|
||||||
const DIRECTION_NUMBERS_TEXT: &str = include_str!("direction_numbers/joe-kuo-other-3.1024.txt");
|
const DIRECTION_NUMBERS_TEXT: &str = include_str!("direction_numbers/joe-kuo-cessen-3.1024.txt");
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let out_dir = env::var("OUT_DIR").unwrap();
|
let out_dir = env::var("OUT_DIR").unwrap();
|
||||||
|
@ -143,7 +143,9 @@ pub fn generate_direction_vectors(dimensions: usize) -> Vec<[u32; SOBOL_BITS]> {
|
||||||
/// text file. Returns the `a` and `m` parts.
|
/// text file. Returns the `a` and `m` parts.
|
||||||
fn parse_direction_numbers(text: &str) -> Result<(u32, Vec<u32>), Box<dyn std::error::Error>> {
|
fn parse_direction_numbers(text: &str) -> Result<(u32, Vec<u32>), Box<dyn std::error::Error>> {
|
||||||
let mut numbers = text.split_whitespace();
|
let mut numbers = text.split_whitespace();
|
||||||
assert!(numbers.clone().count() >= 4);
|
if numbers.clone().count() < 4 || text.starts_with("#") {
|
||||||
|
return Err(Box::new(ParseError(())));
|
||||||
|
}
|
||||||
|
|
||||||
// Skip the first two numbers, which are just the dimension and the count
|
// Skip the first two numbers, which are just the dimension and the count
|
||||||
// of direction numbers for this dimension.
|
// of direction numbers for this dimension.
|
||||||
|
@ -159,3 +161,12 @@ fn parse_direction_numbers(text: &str) -> Result<(u32, Vec<u32>), Box<dyn std::e
|
||||||
|
|
||||||
Ok((a, m))
|
Ok((a, m))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
struct ParseError(());
|
||||||
|
impl std::error::Error for ParseError {}
|
||||||
|
impl std::fmt::Display for ParseError {
|
||||||
|
fn fmt(&self, _f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
1029
sub_crates/sobol/direction_numbers/joe-kuo-cessen-3.1024.txt
Normal file
1029
sub_crates/sobol/direction_numbers/joe-kuo-cessen-3.1024.txt
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -125,7 +125,7 @@ fn owen_scramble_u32(mut n: u32, scramble: u32) -> u32 {
|
||||||
|
|
||||||
n = n.reverse_bits();
|
n = n.reverse_bits();
|
||||||
n ^= scramble;
|
n ^= scramble;
|
||||||
let perms = [0x7ed7a4b4, 0xcb95fcb6, 0x4ea13ebc];
|
let perms = [0xa56bb1c6, 0xef577134, 0xd0e5e808, 0x200bd50a];
|
||||||
for p in perms.iter() {
|
for p in perms.iter() {
|
||||||
n ^= n.wrapping_mul(*p);
|
n ^= n.wrapping_mul(*p);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user