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)
This commit is contained in:
2023-08-19 17:12:28 -05:00
parent 601beb10a0
commit fc8f9e0e15
2 changed files with 84 additions and 10 deletions

View File

@@ -7,4 +7,4 @@ edition = "2021"
[dependencies] [dependencies]
rand = { version = "0.8.5", features = ["small_rng"] } rand = { version = "0.8.5", features = ["small_rng"] }
itertools = { version = "0.11.0" }

View File

@@ -18,6 +18,10 @@ use rand::{Rng, SeedableRng};
use rand::rngs::SmallRng; use rand::rngs::SmallRng;
use rand::distributions::Uniform; use rand::distributions::Uniform;
use itertools;
use itertools::Itertools;
use std::ops;
use std::thread; use std::thread;
fn main() { 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 //TODO: Ensure that the compiler hoists the distribution's out as constants
// else, do so manually // else, do so manually
(0..context.image.0).map(|x| { (0..context.image.0).map(|x| {
(0..context.samples_per_pixel).into_iter().fold( sample_pixel(x, y, small_rng, &context, distr)
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)
}
)
}).collect() }).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<Item = (i32, i32)> {
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<i32>, ops::Range<i32>>;
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<Self::Item> {
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<f32> ) -> Vec3 { fn ray_color(r: Ray, world: &Hittable, depth: u32, srng: &mut SmallRng, distrib: Uniform<f32> ) -> Vec3 {
// recursion depth guard // recursion depth guard
if depth == 0 { if depth == 0 {