From aab1fa0a5edf0a8b27818004c00308e0d858c8fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20R=C3=B6ger?= Date: Wed, 20 Nov 2024 00:27:55 +0100 Subject: [PATCH] feat(scene): make render loop parallelized --- Cargo.lock | 1 + Cargo.toml | 1 + rust-toolchain.toml | 2 +- src/bin/rt_demo.rs | 9 +++++---- src/raytracer/camera.rs | 40 +++++++++++++++++++++++----------------- src/raytracer/scene.rs | 5 +++-- 6 files changed, 34 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1340793..d70ee79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -513,6 +513,7 @@ dependencies = [ "image", "nalgebra", "nix", + "rayon", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index d2c4c78..564f5e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,3 +24,4 @@ futures = "0.3.30" image = "0.25.5" nalgebra = "0.33.2" nix = "0.29.0" +rayon = "1.10.0" diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 5d41bff..58e81e8 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly" +channel = "1.80.1" components = [ "rustfmt", "rustc-dev", "rust-analyzer", "rust-src"] diff --git a/src/bin/rt_demo.rs b/src/bin/rt_demo.rs index d8c66e4..a20574d 100644 --- a/src/bin/rt_demo.rs +++ b/src/bin/rt_demo.rs @@ -6,6 +6,7 @@ use lispers::raytracer::{ types::{Color, Light, Material, Point3, Vector3}, }; extern crate nalgebra as na; +use std::sync::Arc; fn main() { let mut scene = Scene::new(); @@ -21,7 +22,7 @@ fn main() { color: Color::new(1.0, 1.0, 1.0), }); - scene.add_object(Box::new(Plane::new( + scene.add_object(Arc::new(Plane::new( Point3::new(0.0, -1.0, 0.0), Vector3::new(0.0, 1.0, 0.0), Material::new( @@ -33,7 +34,7 @@ fn main() { ), ))); - scene.add_object(Box::new(Sphere::new( + scene.add_object(Arc::new(Sphere::new( Point3::new(-2.0, 0.0, 1.0), 1.0, Material::new( @@ -45,7 +46,7 @@ fn main() { ), ))); - scene.add_object(Box::new(Sphere::new( + scene.add_object(Arc::new(Sphere::new( Point3::new(0.2, -0.5, -0.2), 0.5, Material::new( @@ -57,7 +58,7 @@ fn main() { ), ))); - scene.add_object(Box::new(Sphere::new( + scene.add_object(Arc::new(Sphere::new( Point3::new(-0.5, 0.5, -2.0), 1.5, Material::new( diff --git a/src/raytracer/camera.rs b/src/raytracer/camera.rs index b85e46f..092f33d 100644 --- a/src/raytracer/camera.rs +++ b/src/raytracer/camera.rs @@ -3,6 +3,7 @@ use super::{ types::{Color, Point3, Ray, Scalar, Vector3}, }; use image::RgbImage; +use rayon::prelude::*; /// A camera that can render a scene. pub struct Camera { @@ -77,26 +78,31 @@ impl Camera { /// - `subp` is the number of subpixels to use for antialiasing. pub fn render(&self, scene: &Scene, depth: u32, subp: u32) -> RgbImage { let dx = 1.0 / self.width as Scalar; - let dy = 1.0 / self.width as Scalar; + let dy = 1.0 / self.height as Scalar; let dsx = dx / subp as Scalar; let dsy = dy / subp as Scalar; - RgbImage::from_fn(self.width as u32, self.height as u32, |x, y| { - let x = x as Scalar * dx; - let y = y as Scalar * dy; - let mut color = Color::new(0.0, 0.0, 0.0); - for sx in 0..subp { - for sy in 0..subp { - color += scene.trace( - &self.ray_at_relative( - x + sx as Scalar * dsx, - 1.0 - (y + sy as Scalar * dsy), - ), - depth, - ); + let mut img = RgbImage::new(self.width as u32, self.height as u32); + + img.enumerate_rows_mut().par_bridge().for_each(|(_, row)| { + for (x, y, pixel) in row { + let y = y as Scalar * dy; + let x = x as Scalar * dx; + let mut color = Color::new(0.0, 0.0, 0.0); + for sx in 0..subp { + for sy in 0..subp { + color += scene.trace( + &self.ray_at_relative( + x + sx as Scalar * dsx, + 1.0 - (y + sy as Scalar * dsy), + ), + depth, + ); + } } + color *= 255.0 / (subp * subp) as Scalar; + *pixel = [color.x as u8, color.y as u8, color.z as u8].into(); } - color *= 255.0 / (subp * subp) as Scalar; - [color.x as u8, color.y as u8, color.z as u8].into() - }) + }); + img } } diff --git a/src/raytracer/scene.rs b/src/raytracer/scene.rs index 3cfe543..1c4a79b 100644 --- a/src/raytracer/scene.rs +++ b/src/raytracer/scene.rs @@ -7,6 +7,7 @@ use super::types::Ray; use super::types::Vector3; use super::vec::mirror; use super::vec::reflect; +use std::sync::Arc; extern crate nalgebra as na; /// A scene is a collection of objects and lights, and provides a method to trace a ray through the scene. @@ -14,7 +15,7 @@ pub struct Scene { /// The ambient light of the scene ambient: Color, /// The objects in the scene - objects: Vec>, + objects: Vec>, /// The lights in the scene lights: Vec, } @@ -35,7 +36,7 @@ impl Scene { } /// Add an object to the scene - pub fn add_object(&mut self, obj: Box) { + pub fn add_object(&mut self, obj: Arc) { self.objects.push(obj); }