From 58720ce44ec38ac9a98300697a39ef2965ca259c Mon Sep 17 00:00:00 2001 From: waridh Date: Sun, 8 Sep 2024 17:53:35 -0400 Subject: [PATCH] added parallel processing using rayon --- Cargo.toml | 2 +- src/camera.rs | 48 +++++++++++++++++++++++++++--------------------- src/color.rs | 23 ++++++++++++++++++++++- 3 files changed, 50 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b9c62e7..9dd8580 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" [dependencies] anyhow = "1.0.86" -indicatif = "0.17.8" +indicatif = { version = "*", features = ["rayon"] } rand = "0.8.5" rayon = "1.10.0" diff --git a/src/camera.rs b/src/camera.rs index 6fbcbf1..c711a47 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -4,7 +4,7 @@ use crate::{ ray::{self}, vec3::{self, Point3, Vec3}, }; -use indicatif::{ProgressBar, ProgressStyle}; +use indicatif::{ParallelProgressIterator, ProgressBar, ProgressIterator, ProgressStyle}; use rand::{self, Rng}; use rayon::prelude::*; use std::f32::INFINITY; @@ -127,24 +127,35 @@ impl Camera { println!("P3\n{} {}\n255", self.image_width, self.image_height); - for j in 0..self.image_height { - for i in 0..self.image_width { - let mut pixel = Color::black(); - for _ in 0..self.samples_per_pixel { - let r = self.get_ray(i, j); - pixel += Camera::ray_color(r, self.reflection_depth, world); - } - - println!("{}", pixel * self.pixel_sample_scale); - } - bar.inc(1); - } - bar.finish(); + let pixels = (0..self.image_height) + .into_par_iter() + .progress_with(bar) + .flat_map(|j| { + (0..self.image_width) + .map(|i| { + (0..self.samples_per_pixel) + .map(|_| { + let r = self.get_ray(i, j); + Camera::ray_color(r, self.reflection_depth, world) + }) + .sum::() + }) + .collect::>() + }) + .collect::>(); + + let spinner = ProgressBar::new_spinner(); + spinner.enable_steady_tick(std::time::Duration::from_millis(100)); + + pixels + .iter() + .progress_with(spinner) + .for_each(|e| println!("{}", self.pixel_sample_scale * e)); } /// Create a ray from the defocus lens in the camera center, and direct /// it at the pixel square - fn get_ray(&mut self, i: usize, j: usize) -> ray::Ray { + fn get_ray(&self, i: usize, j: usize) -> ray::Ray { let offset = self.sample_square(); let pixel_center = self.pixel00 + (self.pixel_delta_u * ((i as f32) + offset[0])) @@ -161,7 +172,7 @@ impl Camera { ray::Ray::new(raydir, ray_orig) } - fn sample_square(&mut self) -> vec3::Vec3 { + fn sample_square(&self) -> vec3::Vec3 { let mut rng = rand::thread_rng(); vec3::Vec3(rng.gen_range(-0.5..0.5), rng.gen_range(-0.5..0.5), 0.) } @@ -187,8 +198,3 @@ impl Camera { } } } - -#[cfg(test)] -mod test { - use super::*; -} diff --git a/src/color.rs b/src/color.rs index 99451bf..db2751b 100644 --- a/src/color.rs +++ b/src/color.rs @@ -1,5 +1,5 @@ use crate::vec3; -use std::{fmt, ops}; +use std::{fmt, iter, ops}; pub fn linear_to_gamma(linear: f32) -> f32 { match linear { @@ -35,6 +35,12 @@ impl From<(f32, f32, f32)> for Color { } } +impl iter::Sum for Color { + fn sum>(iter: I) -> Self { + iter.fold(Color::new(0., 0., 0.), |a, e| a + e) + } +} + /// Used to clamp the color output fn clamp(legal_range: &ops::Range, val: f32) -> f32 { match val { @@ -82,6 +88,14 @@ impl ops::Mul for Color { } } +impl ops::Mul for &Color { + type Output = Color; + fn mul(self, rhs: f32) -> Self::Output { + let new_val = (self[0] * rhs, self[1] * rhs, self[2] * rhs); + Color::from(new_val) + } +} + impl ops::Mul for f32 { type Output = Color; fn mul(self, rhs: Color) -> Self::Output { @@ -89,6 +103,13 @@ impl ops::Mul for f32 { } } +impl ops::Mul<&Color> for f32 { + type Output = Color; + fn mul(self, rhs: &Color) -> Self::Output { + rhs * self + } +} + impl ops::Mul for Color { type Output = Color; fn mul(self, rhs: Color) -> Self::Output {