1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
//! Provides the Sampler trait which is implemented by the various samplers //! to provide stratified, low-discrepancy, adaptive sampling methods and so //! on through a simple trait interface use rand::StdRng; use film::ImageSample; pub use self::uniform::Uniform; pub use self::ld::LowDiscrepancy; pub use self::adaptive::Adaptive; pub use self::block_queue::BlockQueue; pub mod morton; pub mod uniform; pub mod ld; pub mod adaptive; pub mod block_queue; /// Provides the interface for all samplers to implement. Defines functions for /// getting samples from the sampler and checking the sampler has finished sampling /// the region pub trait Sampler { /// Fill the vector with 2D pixel coordinate samples for a single pixel /// in the region being sampled. If the sampler doesn't have any more samples /// for the region the vector will be empty /// Samplers that use randomness to compute samples will use the thread rng fn get_samples(&mut self, samples: &mut Vec<(f32, f32)>, rng: &mut StdRng); /// Fill the slice with 2D samples from the sampler fn get_samples_2d(&mut self, samples: &mut [(f32, f32)], rng: &mut StdRng); /// Fill the slice with 1D samples from the sampler fn get_samples_1d(&mut self, samples: &mut [f32], rng: &mut StdRng); /// Get the max number of samples this sampler will take per pixel fn max_spp(&self) -> usize; /// Check if the sampler has more samples for the region being sampled fn has_samples(&self) -> bool; /// Get the dimensions of the region being sampled in pixels fn dimensions(&self) -> (u32, u32); /// Move to a new block of the image to sample with this sampler by specifying /// the starting `(x, y)` block index for the new block. The block starting /// position will be calculated as `dimensions * start` fn select_block(&mut self, start: (u32, u32)); /// Get the region being samples fn get_region(&self) -> &Region; /// Let the sampler inspect the results of sampling the pixel so it can /// determine if more samples should be taken. Returns true if these samples /// are ok to use, false if more need to be taken. The default implementation /// just returns true. fn report_results(&mut self, _samples: &[ImageSample]) -> bool { true } } /// Provides a simple way to pass around a 3 component sample consisting of one 2D and /// one 1D sample #[derive(Debug)] pub struct Sample { /// The 2D sample pub two_d: (f32, f32), /// The 1D sample pub one_d: f32, } impl Sample { /// Create a new sample taking the 2D sample values from the slice pub fn new(two_d: &(f32, f32), one_d: f32) -> Sample { Sample { two_d: *two_d, one_d: one_d } } } /// Defines a region of the image being sampled in pixel coordinates #[derive(Clone, Copy, Debug)] pub struct Region { /// Current coordinates of the pixel to sample (x, y) pub current: (u32, u32), /// Coordinates of the start of region being sampled (x, y) pub start: (u32, u32), /// Coordinates of the end of the region being sampled (x, y) pub end: (u32, u32), /// Dimensions of the region being sampled pub dim: (u32, u32), } impl Region { /// Create a new region starting at `start` with dimension `dim` pub fn new(start: (u32, u32), dim: (u32, u32)) -> Region { Region { current: start, start: start, end: (start.0 + dim.0, start.1 + dim.1), dim: dim } } /// Select a new region starting at region indices `start` with the same dimensions /// eg. with blocks of width 8 the 2nd region along x is at 16 so to get /// this block you'd set start.0 = 2 pub fn select_region(&mut self, start: (u32, u32)) { self.start.0 = start.0 * self.dim.0; self.start.1 = start.1 * self.dim.1; self.end.0 = self.start.0 + self.dim.0; self.end.1 = self.start.1 + self.dim.1; self.current.0 = self.start.0; self.current.1 = self.start.1; } }