wip: parallelization

This commit is contained in:
djaidjai committed 2026-05-03 14:58:56 +02:00
1 parent eb90c36ae8
commit 10f9c0984d
23 files changed
+294 -211

No files matched your search

+96
View File
@@ -0,0 +1,96 @@
use image::{ExtendedColorType, ImageEncoder, codecs::png::PngEncoder};
use log::{error, info};
use rayon::iter::IntoParallelIterator;
use rayon::prelude::*;
use std::{fs::File, sync::Arc};
use crate::{
objects::{hit::Hit, traits::Hittable},
ray::Ray,
scenes::scene::Scene,
vec3::Colour,
};
pub fn write_image(filename: &str, pixels: &[u8], width: u32, height: u32) {
match File::create(filename) {
Ok(out) => {
let enc = PngEncoder::new(out);
if let Err(e) = enc.write_image(pixels, width, height, ExtendedColorType::Rgb8) {
error!("Failed writing image: {}", e);
}
}
Err(e) => error!("Failed to create image file: {} ", e),
}
}
pub fn render(scene: &mut Scene) {
let camera = &mut scene.camera;
camera.init(scene.image_width as f32, scene.image_height as f32);
// TODO: currently splits per vertical line, but could be more granular (per chunk)
let mut pixels = vec![0 as u8; (scene.image_width * scene.image_height * 3) as usize];
let scanlines: Vec<(usize, &mut [u8])> = pixels
.chunks_mut(scene.image_width as usize * 3)
.enumerate()
.collect();
scanlines.into_par_iter().for_each(|(i, chunk)| {
render_chunk(chunk, scene, i as u32);
});
info!("Writing image file...");
write_image(
&scene.filename,
&pixels,
scene.image_width,
scene.image_height,
);
}
pub fn render_chunk(chunk: &mut [u8], scene: &Scene, y: u32) {
let camera = &scene.camera;
for i in 0..scene.image_width {
let pixel_tl = camera.pixel00_loc + (i * camera.pixel_delta_u) + (y * camera.pixel_delta_v);
// THOUGHT: the above seems more efficient (esp for larger aa rates) but can test for a
// get_ray_no_tl() function and compare performance.
let mut pixel_colour = Colour::default();
for y in 1..(camera.anti_alias_rate + 1) {
for x in 1..(camera.anti_alias_rate + 1) {
let r = camera.get_ray(pixel_tl, x, y);
pixel_colour += ray_colour(&scene.objects, &r, scene.max_depth);
}
}
let (r, g, b) =
(pixel_colour / (camera.anti_alias_rate * camera.anti_alias_rate) as f32).output();
chunk[(i * 3) as usize] = r;
chunk[(i * 3) as usize + 1] = g;
chunk[(i * 3) as usize + 2] = b;
}
info!("Line {} finished.", y);
}
pub fn ray_colour(hittables: &Vec<Arc<dyn Hittable>>, r: &Ray, depth: u32) -> Colour {
if depth == 0 {
return Colour::default();
}
let closest = Hit::hit_list(hittables, r);
if let Some(hit) = closest {
if let Some((scattered, att)) = hit.mat().scatter(&hit, r) {
if let Some(ray) = scattered {
return att * ray_colour(hittables, &ray, depth - 1);
}
return att;
}
return Colour::default();
}
// background
let unit_dir = r.dir().get_unit();
let a = 0.5 * (unit_dir.y() + 1.);
(1.0 - a) * Colour::new(1., 1., 1.) + a * Colour::new(0.5, 0.7, 1.0)
}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.