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:
Nathan Vegdahl 2020-03-18 12:05:42 +09:00
parent de5a643a2a
commit 9e14e164e7
4 changed files with 1044 additions and 7 deletions

View File

@ -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 => {
let dim = n - 1;
// Sobol sampling.
// We skip the first 32 samples because doing so reduces noise
// 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))
sobol::sample_owen_cranley(dim, i, hash_u32(dim, scramble))
}
_ => {
// Random sampling.

View File

@ -7,7 +7,7 @@ use std::{env, fs::File, io::Write, path::Path};
const NUM_DIMENSIONS: usize = 256;
/// 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() {
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.
fn parse_direction_numbers(text: &str) -> Result<(u32, Vec<u32>), Box<dyn std::error::Error>> {
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
// 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))
}
#[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(())
}
}

File diff suppressed because it is too large Load Diff

View File

@ -125,7 +125,7 @@ fn owen_scramble_u32(mut n: u32, scramble: u32) -> u32 {
n = n.reverse_bits();
n ^= scramble;
let perms = [0x7ed7a4b4, 0xcb95fcb6, 0x4ea13ebc];
let perms = [0xa56bb1c6, 0xef577134, 0xd0e5e808, 0x200bd50a];
for p in perms.iter() {
n ^= n.wrapping_mul(*p);
}