diff --git a/Cargo.toml b/Cargo.toml index 217bdc0..0bb6862 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,3 @@ edition = "2018" [dependencies] sdl2 = "0.33.0" rand = "0.7.3" - diff --git a/src/demos/linear_gradient_rectangle.rs b/src/demos/linear_gradient_rectangle.rs index 239fe94..ed94e90 100644 --- a/src/demos/linear_gradient_rectangle.rs +++ b/src/demos/linear_gradient_rectangle.rs @@ -2,7 +2,8 @@ pub struct LinearGradientRectangle; use crate::{ types::{Ray, Vec3}, - Demo, + HORIZONTAL_PARTITION, VERTICAL_PARTITION, + {demos::Chunk, Demo}, }; impl Demo for LinearGradientRectangle { @@ -11,8 +12,35 @@ impl Demo for LinearGradientRectangle { } fn render(&self, buf: &mut [u8], width: usize, height: usize, _samples: u8) { - let mut offset = 0; + let nx = width / VERTICAL_PARTITION; + let ny = height / HORIZONTAL_PARTITION; + for j in 0..VERTICAL_PARTITION { + for i in 0..HORIZONTAL_PARTITION { + let start_y = j * ny; + let start_x = i * nx; + let chunk = Chunk { + x: width, + y: height, + nx, + ny, + start_x, + start_y, + }; + + self.render_chunk(buf, chunk); + } + } + } + fn render_chunk(&self, buf: &mut [u8], meta: Chunk) { + let Chunk { + x, + y, + nx, + ny, + start_x, + start_y, + } = meta; // -2.0 and 4.0 in lower_left_corner and horizontal respectively // because our canvas is in 2:1 ratio let lower_left_corner = Vec3::new(-2.0, -1.0, -1.0); @@ -20,18 +48,18 @@ impl Demo for LinearGradientRectangle { let vertical = Vec3::new(0.0, 2.0, 0.0); let origin = Vec3::new(0.0, 0.0, 0.0); - for j in (0..height).rev() { - for i in 0..width { - let u = i as f64 / width as f64; - let v = j as f64 / height as f64; + for j in start_y..start_y + ny { + for i in start_x..start_x + nx { + let u = i as f64 / x as f64; + let v = j as f64 / y as f64; let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v); let c = color(ray); + let offset = (j * x + i) * 4; buf[offset] = (255.99 * c.r()) as u8; buf[offset + 1] = (255.99 * c.g()) as u8; buf[offset + 2] = (255.99 * c.b()) as u8; - offset += 4; } } } diff --git a/src/demos/mod.rs b/src/demos/mod.rs index b84e88c..f8d4407 100644 --- a/src/demos/mod.rs +++ b/src/demos/mod.rs @@ -1,25 +1,38 @@ -mod diffuse_materials; -mod hitable_sphere; +//mod diffuse_materials; +//mod hitable_sphere; mod linear_gradient_rectangle; -mod materials; -mod simple_antialiasing; +//mod materials; +//mod simple_antialiasing; mod simple_rectangle; -mod simple_sphere; -mod surface_normal_sphere; +//mod simple_sphere; +//mod surface_normal_sphere; -pub use diffuse_materials::DiffuseMaterials; -pub use hitable_sphere::HitableSphere; +//pub use diffuse_materials::DiffuseMaterials; +//pub use hitable_sphere::HitableSphere; pub use linear_gradient_rectangle::LinearGradientRectangle; -pub use materials::Materials; -pub use simple_antialiasing::SimpleAntialiasing; +//pub use materials::Materials; +//pub use simple_antialiasing::SimpleAntialiasing; pub use simple_rectangle::SimpleRectangle; -pub use simple_sphere::SimpleSphere; -pub use surface_normal_sphere::SurfaceNormalSphere; +//pub use simple_sphere::SimpleSphere; +//pub use surface_normal_sphere::SurfaceNormalSphere; use std::{fs::File, io::Write}; +#[derive(Debug)] +pub struct Chunk { + x: usize, + y: usize, + nx: usize, + ny: usize, + start_x: usize, + start_y: usize, +} + pub trait Demo { fn render(&self, buf: &mut [u8], width: usize, height: usize, samples: u8); + + fn render_chunk(&self, buf: &mut [u8], meta: Chunk); + fn name(&self) -> &'static str; fn save_as_ppm(&self, buf: &[u8], width: usize, height: usize) { diff --git a/src/demos/simple_rectangle.rs b/src/demos/simple_rectangle.rs index a4740d6..f15e366 100644 --- a/src/demos/simple_rectangle.rs +++ b/src/demos/simple_rectangle.rs @@ -1,4 +1,8 @@ -use crate::{demos::Demo, types::Vec3}; +use crate::{ + demos::{Chunk, Demo}, + types::Vec3, + HORIZONTAL_PARTITION, VERTICAL_PARTITION, +}; pub struct SimpleRectangle; @@ -8,16 +12,45 @@ impl Demo for SimpleRectangle { } fn render(&self, buf: &mut [u8], width: usize, height: usize, _samples: u8) { - let mut offset = 0; - for j in (0..height).rev() { - for i in 0..width { - let color = Vec3::new(i as f64 / width as f64, j as f64 / width as f64, 0.2); + let nx = width / VERTICAL_PARTITION; + let ny = height / HORIZONTAL_PARTITION; - buf[offset] = (255.99 * color.r()) as u8; - buf[offset + 1] = (255.99 * color.g()) as u8; - buf[offset + 2] = (255.99 * color.b()) as u8; + for j in 0..VERTICAL_PARTITION { + for i in 0..HORIZONTAL_PARTITION { + let start_y = j * ny; + let start_x = i * nx; + let chunk = Chunk { + x: width, + y: height, + nx, + ny, + start_x, + start_y, + }; - offset += 4; + self.render_chunk(buf, chunk); + } + } + } + + fn render_chunk(&self, buf: &mut [u8], meta: Chunk) { + let Chunk { + x, + y, + nx, + ny, + start_x, + start_y, + } = meta; + + for j in start_y..start_y + ny { + for i in start_x..start_x + nx { + let color = [i as f64 / x as f64, j as f64 / y as f64, 0.2]; + let offset = (j * x + i) * 4; + + buf[offset] = (255.99 * color[0]) as u8; + buf[offset + 1] = (255.99 * color[1]) as u8; + buf[offset + 2] = (255.99 * color[2]) as u8; } } } diff --git a/src/main.rs b/src/main.rs index 90a8910..ed70228 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,13 +15,16 @@ use { }, }; -const NUM_SAMPLES: u8 = 20; +const NUM_SAMPLES: u8 = 100; + +const VERTICAL_PARTITION: usize = 8; +const HORIZONTAL_PARTITION: usize = 8; fn main() -> Result<(), String> { let sdl_ctx = sdl2::init()?; let video_subsys = sdl_ctx.video()?; - let (mut width, mut height) = (1280, 640); + let (width, height) = (1280usize, 640usize); let window = video_subsys .window("Ray tracing in a weekend", width as u32, height as u32) @@ -53,6 +56,7 @@ fn main() -> Result<(), String> { // TODO: Maybe consider using condition variable to make loop {} not run at full // speed at all times pinning a core at 100% let mut should_update = true; + loop { for event in event_pump.poll_iter() { match event { @@ -68,12 +72,12 @@ fn main() -> Result<(), String> { Some(Keycode::Num2) => { active_demo = Box::new(demos::LinearGradientRectangle) } - Some(Keycode::Num3) => active_demo = Box::new(demos::SimpleSphere), - Some(Keycode::Num4) => active_demo = Box::new(demos::SurfaceNormalSphere), - Some(Keycode::Num5) => active_demo = Box::new(demos::HitableSphere), - Some(Keycode::Num6) => active_demo = Box::new(demos::SimpleAntialiasing), - Some(Keycode::Num7) => active_demo = Box::new(demos::DiffuseMaterials), - Some(Keycode::Num8) => active_demo = Box::new(demos::Materials), + //Some(Keycode::Num3) => active_demo = Box::new(demos::SimpleSphere), + //Some(Keycode::Num4) => active_demo = Box::new(demos::SurfaceNormalSphere), + //Some(Keycode::Num5) => active_demo = Box::new(demos::HitableSphere), + //Some(Keycode::Num6) => active_demo = Box::new(demos::SimpleAntialiasing), + //Some(Keycode::Num7) => active_demo = Box::new(demos::DiffuseMaterials), + //Some(Keycode::Num8) => active_demo = Box::new(demos::Materials), None => unreachable!(), _ => (), }; @@ -83,13 +87,13 @@ fn main() -> Result<(), String> { win_event: WindowEvent::Resized(w, h), .. } => { - width = w as usize; - height = h as usize; - buffer.resize(width * height * 4, 0); - texture = texture_creator - .create_texture_static(PixelFormatEnum::BGR888, width as u32, height as u32) - .expect("error in resizing texture"); - should_update = true; + //width = w as usize; + //height = h as usize; + //buffer.resize(width * height * 4, 0); + //texture = texture_creator + // .create_texture_static(PixelFormatEnum::BGR888, width as u32, height as u32) + // .expect("error in resizing texture"); + //should_update = true; } _ => {} };