Attempting to render image in chunks

This commit is contained in:
Ishan Jain 2020-02-15 23:58:23 +05:30
parent edb0b64282
commit fbf41fae22
5 changed files with 121 additions and 44 deletions

View File

@ -7,4 +7,3 @@ edition = "2018"
[dependencies]
sdl2 = "0.33.0"
rand = "0.7.3"

View File

@ -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;
}
}
}

View File

@ -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) {

View File

@ -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;
}
}
}

View File

@ -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;
}
_ => {}
};