diff --git a/pathtracer/examples/cornell-box.yaml b/pathtracer/examples/cornell-box.yaml index d6fa9bb..e6b0f46 100644 --- a/pathtracer/examples/cornell-box.yaml +++ b/pathtracer/examples/cornell-box.yaml @@ -1,4 +1,5 @@ reflection_limit: 5 +shot_rays: 50 camera: origin: [0.0, 1.0, 0.0] diff --git a/pathtracer/src/render/pathtrace/pathtracer.rs b/pathtracer/src/render/pathtrace/pathtracer.rs index a4363be..dec5700 100644 --- a/pathtracer/src/render/pathtrace/pathtracer.rs +++ b/pathtracer/src/render/pathtrace/pathtracer.rs @@ -1,4 +1,6 @@ -use super::super::utils::{buffer_to_image, prepare_buffer, sample_hemisphere}; +use rayon::prelude::*; + +use super::super::utils::{buffer_to_image, sample_hemisphere}; use super::super::Renderer; use crate::{ core::LinearColor, @@ -35,29 +37,44 @@ impl Pathtracer { self.scene.camera.film().height(), ); let total = width * height; - let mut buffer = prepare_buffer(total); - // (total passes, film) - // FIXME: use MultiProgress because of rendering issues - let (pa, pb) = super::super::progress::get_multiple_progress(total, self.scene.shot_rays); + let p = super::super::progress::get_progressbar(self.scene.shot_rays as u64); // Ensure at least one round of shots - for _ in 0..self.scene.shot_rays.max(1) { - pb.reset(); // We're rendering the whole film again, reset the pixel counter - for y in 0..self.scene.camera.film().height() { - for x in 0..self.scene.camera.film().width() { - let i = x + y * self.scene.camera.film().width(); - buffer[i as usize] += self.pixel_ray(x as f32, y as f32); - pb.inc(1); + let img_buf = (0..self.scene.shot_rays.max(1)) + .into_par_iter() + .map(|_| { + let mut buffer: Vec = Vec::new(); + buffer.resize_with(total as usize, LinearColor::black); + + for y in 0..self.scene.camera.film().height() { + for x in 0..self.scene.camera.film().width() { + let i = x + y * self.scene.camera.film().width(); + buffer[i as usize] += self.pixel_ray(x as f32, y as f32); + } } - } - pa.inc(1); // Increment the number of passes - } + p.inc(1); // Increment the number of passes - pa.finish(); - pb.finish_and_clear(); + buffer + }) + .reduce( + || { + let mut vec = Vec::new(); + vec.resize_with(total as usize, LinearColor::black); + vec + }, + |mut acc, buf| { + for (i, pixel) in buf.into_iter().enumerate() { + acc[i] += pixel; + } - buffer_to_image(buffer, self.scene.shot_rays, width, height) + acc + }, + ); + + p.finish(); + + buffer_to_image(img_buf, self.scene.shot_rays, width, height) } fn pixel_ray(&self, x: f32, y: f32) -> LinearColor { diff --git a/pathtracer/src/render/progress.rs b/pathtracer/src/render/progress.rs index 15d5851..4d2c398 100644 --- a/pathtracer/src/render/progress.rs +++ b/pathtracer/src/render/progress.rs @@ -8,12 +8,3 @@ pub fn get_progressbar(total: u64) -> ProgressBar { )); pb } - -pub fn get_multiple_progress(total: u32, passes: u32) -> (ProgressBar, ProgressBar) { - let pb = ProgressBar::new(passes as u64); - pb.set_draw_delta((passes as u64 / 100).max(1)); - pb.set_style(indicatif::ProgressStyle::default_bar().template( - "{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {percent:>3}%: {pos}/{len} passes (ETA: {eta})", - )); - (pb, get_progressbar(total as u64)) -} diff --git a/pathtracer/src/render/utils.rs b/pathtracer/src/render/utils.rs index 4ed4c3a..086a31e 100644 --- a/pathtracer/src/render/utils.rs +++ b/pathtracer/src/render/utils.rs @@ -104,14 +104,6 @@ pub fn sample_hemisphere(normal: Unit) -> (Unit, f32) { (scattered, 1. / scattered.dot(&normal)) } -pub fn prepare_buffer(total: u32) -> Vec { - let mut ans = Vec::with_capacity(total as usize); - for _ in 0..total { - ans.push(LinearColor::black()); - } - ans -} - pub fn buffer_to_image(buffer: Vec, passes: u32, width: u32, height: u32) -> RgbImage { let mut image = RgbImage::new(width, height);