diff --git a/src/material.rs b/src/material.rs index c7d0efb..4ce924c 100644 --- a/src/material.rs +++ b/src/material.rs @@ -9,7 +9,7 @@ pub struct Scatter { pub ray: Ray, } -pub trait Material { +pub trait Material: Send + Sync { fn scatter(&self, r_in: &Ray, rec: &HitRecord, rng: &mut ThreadRng) -> Option; } diff --git a/src/object.rs b/src/object.rs index c465e72..3eea3ff 100644 --- a/src/object.rs +++ b/src/object.rs @@ -5,7 +5,7 @@ use rand::prelude::*; use std::sync::Arc; -pub trait Hittable { +pub trait Hittable: Send + Sync{ fn hit(&self, ray: Ray, interval:Interval) -> Option; } diff --git a/src/render.rs b/src/render.rs index a13581f..91763e3 100644 --- a/src/render.rs +++ b/src/render.rs @@ -2,6 +2,7 @@ use crate::object::{HitRecord, Hittable}; use crate::vec3::{Interval, Ray, Vec3, Point3}; use crate::image::Image; use std::sync::Arc; +use std::thread; use rand::prelude::*; @@ -70,29 +71,53 @@ impl Camera { pub fn render(&mut self, world: &World){ - let mut rng:ThreadRng = rand::rng(); - for y in 0..self.img.height { - for x in 0..self.img.width { - let (mut r,mut g,mut b) = (0.0,0.0,0.0); - let num_samples=10.0; - let depth=10; - for _ in 0..num_samples as i32{ - let ray = self.get_ray(x,y,&mut rng); - let (tr,tg,tb)= trace(ray, &world,depth,&mut rng); - r+= tr; - g+= tg; - b+= tb; - } - r /= num_samples; - g /= num_samples; - b /= num_samples; + let thread_count = thread::available_parallelism().unwrap().get() as i32; + let height = self.img.height; + let width = self.img.width; + let total_pixels = height*width; + let num_samples = 5; - r = r.clamp(0.0,1.0).sqrt(); - g = g.clamp(0.0,1.0).sqrt(); - b = b.clamp(0.0,1.0).sqrt(); - if let Some(px) = self.img.get_pixel(x,y){ - px.set_color(r,g,b); - } else{/*ignore*/} + //cast to const ref + let const_self = &*self; + + let threads:Vec> = thread::scope(|s|{ + (0..thread_count).map(|i|{ + s.spawn(move ||{ + let mut rng:ThreadRng = rand::rng(); + let start = (i*total_pixels)/thread_count; + let end = ((i+1)*total_pixels)/thread_count; + (start..end).map(|i|{ + let x = i%width; + let y = i/width; + let (mut r,mut g,mut b) = (0.0,0.0,0.0); + let ray = const_self.get_ray(x,y,&mut rng); + for _ in 0..num_samples{ + let (tr,tg,tb) = trace(ray, &world,10,&mut rng); + r+=tr; + g+=tg; + b+=tb; + } + + r/=num_samples as f64; + g/=num_samples as f64; + b/=num_samples as f64; + + r = r.clamp(0.0,1.0).sqrt(); + g = g.clamp(0.0,1.0).sqrt(); + b = b.clamp(0.0,1.0).sqrt(); + + ((x,y),(r,g,b)) + }).collect::>() + }) + }).collect::>().into_iter().map(|t|{t.join().unwrap()}).collect() + }); + + for t in threads { + for c in t { + let ((x,y),rgb) = c; + let px = self.img.get_pixel(x,y).unwrap(); + let (r,g,b)= rgb; + px.set_color(r,g,b); } } self.img.save("./foo.ppm").unwrap();