From fc8f9e0e1595f30266be2351a62f27e0385794ce Mon Sep 17 00:00:00 2001 From: Robert Garrett Date: Sat, 19 Aug 2023 17:12:28 -0500 Subject: [PATCH] Starting to get a hold of the Tile struct Iterators are turning my brain to mush. I'm trying far too hard to leverage existing iterator tooling. The closures all over the place make saying the type names basically impossible. For chaining in the middle of a function, this is fine. But I need to stick it in a `struct Tile{}` and move it between threads. This commit is a save point for my own sanity, more than anything else. The tile struct exists and compiles. The only changed part is the extraction of the pixel sampling loop into a named function (instead of an nameless closuuuruurreeee) --- Cargo.toml | 2 +- src/main.rs | 92 +++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 84 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c91eba2..952a559 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] rand = { version = "0.8.5", features = ["small_rng"] } - +itertools = { version = "0.11.0" } diff --git a/src/main.rs b/src/main.rs index 1c912b2..8625dd1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,10 @@ use rand::{Rng, SeedableRng}; use rand::rngs::SmallRng; use rand::distributions::Uniform; +use itertools; +use itertools::Itertools; +use std::ops; + use std::thread; fn main() { @@ -165,18 +169,88 @@ fn render_line(y: i32, small_rng: &mut SmallRng, context: RenderContext, distr: //TODO: Ensure that the compiler hoists the distribution's out as constants // else, do so manually (0..context.image.0).map(|x| { - (0..context.samples_per_pixel).into_iter().fold( - Vec3::zero(), - |color, _sample| { - let u = ((x as f32) + small_rng.sample(distr.distrib_zero_one)) / ((context.image.0 - 1) as f32); - let v = ((y as f32) + small_rng.sample(distr.distrib_zero_one)) / ((context.image.1 - 1) as f32); - let ray = context.camera.get_ray(u, v, small_rng); - color + ray_color(ray, &context.world, context.max_depth, small_rng, distr.distrib_plusminus_one) - } - ) + sample_pixel(x, y, small_rng, &context, distr) }).collect() } +fn sample_pixel(x: i32, y: i32, small_rng: &mut SmallRng, context: &RenderContext, distr: &DistributionContianer) -> Vec3{ + (0..context.samples_per_pixel).into_iter().fold( + Vec3::zero(), + |color, _sample| { + let u = ((x as f32) + small_rng.sample(distr.distrib_zero_one)) / ((context.image.0 - 1) as f32); + let v = ((y as f32) + small_rng.sample(distr.distrib_zero_one)) / ((context.image.1 - 1) as f32); + let ray = context.camera.get_ray(u, v, small_rng); + color + ray_color(ray, &context.world, context.max_depth, small_rng, distr.distrib_plusminus_one) + } + ) +} + +fn range2d(bounds: (i32, i32, i32, i32)) -> impl Iterator { + let rheight = bounds.1..(bounds.1+bounds.3); + rheight.flat_map(move |y| { + let rwidth = bounds.0..(bounds.0+bounds.2); + rwidth.map( move |x| { + (x, y) + }) + }) +} + +#[derive (Copy, Clone)] +struct Rect { + x: i32, + y: i32, + w: i32, + h: i32, +} + +/* Iterable that produces pixels left-to-right, top-to-bottom. + * `Tile`s represent the render space, not the finished image. + * There is no internal pixel buffer + */ + +type TileCursorIter = itertools::Product, ops::Range>; + +struct Tile { + bounds: Rect, + context: RenderContext, + small_rng: SmallRng, + rand_distr: DistributionContianer, + cursor: TileCursorIter, +} + +impl Tile{ + fn new( + bounds: Rect, + context: RenderContext, + small_rng: SmallRng, + rand_distr: DistributionContianer + ) -> Self + { + Tile { bounds, context, small_rng, rand_distr, + cursor: (bounds.x..(bounds.x + bounds.w)) + .cartesian_product(bounds.y..(bounds.y + bounds.h) + ) + } + + } +} + +impl Iterator for Tile { + type Item = Vec3; + fn next(&mut self) -> Option { + if let Some((x, y)) = self.cursor.next(){ + Some(sample_pixel( + x, y, + &mut self.small_rng, + &self.context, + &self.rand_distr, + )) + } else { + None + } + } +} + fn ray_color(r: Ray, world: &Hittable, depth: u32, srng: &mut SmallRng, distrib: Uniform ) -> Vec3 { // recursion depth guard if depth == 0 {