Implement multithreading
This commit is contained in:
62
src/main.rs
62
src/main.rs
@ -1,9 +1,13 @@
|
||||
use std::sync::Mutex;
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::camera::Camera;
|
||||
use crate::hittable::{Hittable, Sphere};
|
||||
use crate::output::{Output, P3};
|
||||
use crate::ray::Ray;
|
||||
use crate::vec3::{Color, Point3, Vec3};
|
||||
use rand::distributions::{Distribution, Uniform};
|
||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||
use crate::material::{Dielectric, Lambertian, Material, Metal};
|
||||
|
||||
mod vec3;
|
||||
@ -13,8 +17,8 @@ mod material;
|
||||
mod camera;
|
||||
mod output;
|
||||
|
||||
fn random_scene() -> Vec<Box<dyn Hittable>> {
|
||||
let mut world:Vec<Box<dyn Hittable>> = Vec::new();
|
||||
fn random_scene() -> Vec<Box<dyn Hittable + Sync>> {
|
||||
let mut world:Vec<Box<dyn Hittable + Sync>> = Vec::new();
|
||||
|
||||
let material_ground = Material::Lambertian(Lambertian::new(Color::new(0.5, 0.5, 0.5)));
|
||||
let ground = Sphere {
|
||||
@ -82,8 +86,9 @@ fn main() {
|
||||
const ASPECT_RATIO: f64 = 3.0 / 2.0;
|
||||
const IMAGE_WIDTH: usize = 1200;
|
||||
const IMAGE_HEIGHT: usize = (IMAGE_WIDTH as f64 / ASPECT_RATIO) as usize;
|
||||
const SAMPLES_PER_PIXEL: i32 = 100;
|
||||
const SAMPLES_PER_PIXEL: i32 = 500;
|
||||
const MAX_DEPTH: i32 = 50;
|
||||
let hh = IMAGE_HEIGHT;
|
||||
|
||||
let look_from = Point3::new(13.0, 2.0, 3.0);
|
||||
let look_at = Point3::new(0.0, 0.0, 0.0);
|
||||
@ -101,27 +106,38 @@ fn main() {
|
||||
// World
|
||||
let world= random_scene();
|
||||
|
||||
//println!("P3\n{} {}\n255", IMAGE_WIDTH, IMAGE_HEIGHT);
|
||||
|
||||
let between = Uniform::from(0.0..1.0);
|
||||
let mut pixels = Vec::<u8>::new();
|
||||
let mut rng = rand::thread_rng();
|
||||
for j in (0..IMAGE_HEIGHT).rev() {
|
||||
eprint!("\rScanlines remaining: {} ", j);
|
||||
for i in 0..IMAGE_WIDTH {
|
||||
let mut color = Color::default();
|
||||
(0..SAMPLES_PER_PIXEL).for_each(|_s| {
|
||||
let random_number = between.sample(&mut rng);
|
||||
let u = (i as f64 + random_number) / (IMAGE_WIDTH - 1) as f64;
|
||||
let v = (j as f64 + random_number) / (IMAGE_HEIGHT - 1) as f64;
|
||||
let ray = cam.get_ray(u, v);
|
||||
color += ray.pixel_color(&world, MAX_DEPTH);
|
||||
});
|
||||
pixels.append(&mut color.into_bytes(SAMPLES_PER_PIXEL));
|
||||
|
||||
//color.write_color(SAMPLES_PER_PIXEL);
|
||||
let start = Instant::now();
|
||||
let mut pixels = vec![0; IMAGE_WIDTH * IMAGE_HEIGHT * 3];
|
||||
let bands: Vec<(usize, &mut [u8])> = pixels.chunks_mut(3).enumerate().collect();
|
||||
let count = Mutex::new(0);
|
||||
bands.into_par_iter().for_each(|(i, pixel)| {
|
||||
let row = IMAGE_HEIGHT - (i / IMAGE_WIDTH) - 1;
|
||||
let col = i % IMAGE_WIDTH;
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut color = Color::default();
|
||||
(0..SAMPLES_PER_PIXEL).for_each(|_s| {
|
||||
let random_number = between.sample(&mut rng);
|
||||
let u = (col as f64 + random_number) / (IMAGE_WIDTH - 1) as f64;
|
||||
let v = (row as f64 + random_number) / (IMAGE_HEIGHT - 1) as f64;
|
||||
let ray = cam.get_ray(u, v);
|
||||
color += ray.pixel_color(&world, MAX_DEPTH);
|
||||
});
|
||||
let bytes = color.into_bytes(SAMPLES_PER_PIXEL);
|
||||
pixel[0] = bytes[0];
|
||||
pixel[1] = bytes[1];
|
||||
pixel[2] = bytes[2];
|
||||
if i % 100 == 0 {
|
||||
let mut rem = count.lock().unwrap();
|
||||
let percent_done_before = 100 * *rem / (IMAGE_WIDTH * IMAGE_HEIGHT);
|
||||
*rem += 100;
|
||||
let percent_done_after = 100 * *rem / (IMAGE_WIDTH * IMAGE_HEIGHT);
|
||||
if percent_done_before != percent_done_after {
|
||||
eprint!("\rProgress: {}% ", percent_done_after);
|
||||
}
|
||||
}
|
||||
}
|
||||
P3::write("i.ppm", &pixels, IMAGE_WIDTH, IMAGE_HEIGHT).expect("Error writing image: {}");
|
||||
eprintln!("\nDone");
|
||||
});
|
||||
P3::write("imc.ppm", &pixels, IMAGE_WIDTH, IMAGE_HEIGHT).expect("Error writing image: {}");
|
||||
eprintln!("\nDone. Time: {}ms", start.elapsed().as_millis());
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ impl Ray {
|
||||
}
|
||||
pub fn direction(&self) -> Vec3 { self.direction }
|
||||
pub fn origin(&self) -> Point3 { self.origin }
|
||||
pub fn pixel_color(&self, world: &Vec<Box<dyn Hittable>>, depth: i32) -> Color {
|
||||
pub fn pixel_color(&self, world: &Vec<Box<dyn Hittable + Sync>>, depth: i32) -> Color {
|
||||
if depth <= 0 {
|
||||
return Color::default();
|
||||
}
|
||||
@ -50,7 +50,7 @@ impl Ray {
|
||||
}
|
||||
fn hit_world<'material>(
|
||||
&self,
|
||||
world: &'material Vec<Box<dyn Hittable>>,
|
||||
world: &'material Vec<Box<dyn Hittable + Sync>>,
|
||||
t_min: f64,
|
||||
t_max: f64,
|
||||
) -> Option<HitRecord<'material>> {
|
||||
|
Reference in New Issue
Block a user