Working on chunk based rendering system
This commit is contained in:
parent
cae95b0bf0
commit
c52d148451
|
@ -14,15 +14,14 @@ impl Demo for DiffuseMaterials {
|
|||
"Diffuse Materials"
|
||||
}
|
||||
|
||||
fn render_chunk(&self, buf: &mut [u8], meta: Chunk, samples: u8) {
|
||||
let Chunk {
|
||||
x,
|
||||
y,
|
||||
nx,
|
||||
ny,
|
||||
start_x,
|
||||
start_y,
|
||||
} = meta;
|
||||
fn render_chunk(&self, chunk: &mut Chunk, samples: u8) {
|
||||
let x = chunk.x;
|
||||
let y = chunk.y;
|
||||
let nx = chunk.nx;
|
||||
let ny = chunk.ny;
|
||||
let start_x = chunk.start_x;
|
||||
let start_y = chunk.start_y;
|
||||
let buffer = &mut chunk.buffer;
|
||||
|
||||
let world = HitableList {
|
||||
list: vec![
|
||||
|
@ -33,7 +32,7 @@ impl Demo for DiffuseMaterials {
|
|||
|
||||
let camera: Camera = Default::default();
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let mut offset = 0;
|
||||
for j in start_y..start_y + ny {
|
||||
for i in start_x..start_x + nx {
|
||||
let mut color = Vec3::new(0.0, 0.0, 0.0);
|
||||
|
@ -41,13 +40,11 @@ impl Demo for DiffuseMaterials {
|
|||
for _s in 0..samples {
|
||||
let u = (i as f64 + rng.gen::<f64>()) / x as f64;
|
||||
let v = (j as f64 + rng.gen::<f64>()) / y as f64;
|
||||
|
||||
let r = camera.get_ray(u, v);
|
||||
color += calc_color(r, &world, &mut rng);
|
||||
}
|
||||
|
||||
color /= samples as f64;
|
||||
let offset = ((y - j - 1) * x + i) * 4;
|
||||
|
||||
// Without taking square root of each color, we get a picture that
|
||||
// is quite dark
|
||||
|
@ -55,9 +52,10 @@ impl Demo for DiffuseMaterials {
|
|||
// So, IRL, It *should* look a bit lighter in color
|
||||
// To do that, We apply gamma correction by a factor of 2
|
||||
// which means multiple rgb values by 1/gamma aka 1/2
|
||||
buf[offset] = (255.99 * color.r().sqrt()) as u8;
|
||||
buf[offset + 1] = (255.99 * color.g().sqrt()) as u8;
|
||||
buf[offset + 2] = (255.99 * color.b().sqrt()) as u8;
|
||||
buffer[offset] = (255.99 * color.r().sqrt()) as u8;
|
||||
buffer[offset + 1] = (255.99 * color.g().sqrt()) as u8;
|
||||
buffer[offset + 2] = (255.99 * color.b().sqrt()) as u8;
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,15 +9,14 @@ impl Demo for HitableSphere {
|
|||
"Sphere using Hit table"
|
||||
}
|
||||
|
||||
fn render_chunk(&self, buf: &mut [u8], meta: Chunk, _samples: u8) {
|
||||
let Chunk {
|
||||
x,
|
||||
y,
|
||||
nx,
|
||||
ny,
|
||||
start_x,
|
||||
start_y,
|
||||
} = meta;
|
||||
fn render_chunk(&self, chunk: &mut Chunk, _samples: u8) {
|
||||
let x = chunk.x;
|
||||
let y = chunk.y;
|
||||
let nx = chunk.nx;
|
||||
let ny = chunk.ny;
|
||||
let start_x = chunk.start_x;
|
||||
let start_y = chunk.start_y;
|
||||
let buffer = &mut chunk.buffer;
|
||||
|
||||
let lower_left_corner = Vec3::new(-2.0, -1.0, -1.0);
|
||||
let horizontal = Vec3::new(4.0, 0.0, 0.0);
|
||||
|
@ -30,7 +29,7 @@ impl Demo for HitableSphere {
|
|||
Box::new(Sphere::new(Vec3::new(0.0, -100.5, -1.0), 100.0)),
|
||||
],
|
||||
};
|
||||
|
||||
let mut offset = 0;
|
||||
for j in start_y..start_y + ny {
|
||||
for i in start_x..start_x + nx {
|
||||
let u = i as f64 / x as f64;
|
||||
|
@ -38,10 +37,10 @@ impl Demo for HitableSphere {
|
|||
let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
|
||||
let color = calc_color(ray, &world);
|
||||
|
||||
let offset = ((y - j - 1) * x + i) * 4;
|
||||
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;
|
||||
buffer[offset] = (255.99 * color.r()) as u8;
|
||||
buffer[offset + 1] = (255.99 * color.g()) as u8;
|
||||
buffer[offset + 2] = (255.99 * color.b()) as u8;
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,15 +10,15 @@ impl Demo for LinearGradientRectangle {
|
|||
"Linear Gradient Rectangle"
|
||||
}
|
||||
|
||||
fn render_chunk(&self, buf: &mut [u8], meta: Chunk, _samples: u8) {
|
||||
let Chunk {
|
||||
x,
|
||||
y,
|
||||
nx,
|
||||
ny,
|
||||
start_x,
|
||||
start_y,
|
||||
} = meta;
|
||||
fn render_chunk(&self, chunk: &mut Chunk, _samples: u8) {
|
||||
let x = chunk.x;
|
||||
let y = chunk.y;
|
||||
let nx = chunk.nx;
|
||||
let ny = chunk.ny;
|
||||
let start_x = chunk.start_x;
|
||||
let start_y = chunk.start_y;
|
||||
let buffer = &mut chunk.buffer;
|
||||
|
||||
// -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);
|
||||
|
@ -26,6 +26,7 @@ impl Demo for LinearGradientRectangle {
|
|||
let vertical = Vec3::new(0.0, 2.0, 0.0);
|
||||
let origin = Vec3::new(0.0, 0.0, 0.0);
|
||||
|
||||
let mut offset = 0;
|
||||
for j in start_y..start_y + ny {
|
||||
for i in start_x..start_x + nx {
|
||||
let u = i as f64 / x as f64;
|
||||
|
@ -33,10 +34,10 @@ impl Demo for LinearGradientRectangle {
|
|||
let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
|
||||
|
||||
let c = color(ray);
|
||||
let offset = ((y - j - 1) * 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;
|
||||
buffer[offset] = (255.99 * c.r()) as u8;
|
||||
buffer[offset + 1] = (255.99 * c.g()) as u8;
|
||||
buffer[offset + 2] = (255.99 * c.b()) as u8;
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,15 +14,14 @@ impl Demo for Materials {
|
|||
"Metal Material"
|
||||
}
|
||||
|
||||
fn render_chunk(&self, buf: &mut [u8], meta: Chunk, samples: u8) {
|
||||
let Chunk {
|
||||
x,
|
||||
y,
|
||||
nx,
|
||||
ny,
|
||||
start_x,
|
||||
start_y,
|
||||
} = meta;
|
||||
fn render_chunk(&self, chunk: &mut Chunk, samples: u8) {
|
||||
let x = chunk.x;
|
||||
let y = chunk.y;
|
||||
let nx = chunk.nx;
|
||||
let ny = chunk.ny;
|
||||
let start_x = chunk.start_x;
|
||||
let start_y = chunk.start_y;
|
||||
let buffer = &mut chunk.buffer;
|
||||
|
||||
let world = HitableList {
|
||||
list: vec![
|
||||
|
@ -51,6 +50,7 @@ impl Demo for Materials {
|
|||
|
||||
let camera: Camera = Default::default();
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut offset = 0;
|
||||
|
||||
for j in start_y..start_y + ny {
|
||||
for i in start_x..start_x + nx {
|
||||
|
@ -64,12 +64,12 @@ impl Demo for Materials {
|
|||
}
|
||||
|
||||
color /= samples as f64;
|
||||
let offset = ((y - j - 1) * x + i) * 4;
|
||||
|
||||
// gamma 2 corrected
|
||||
buf[offset] = (255.99 * color.r().sqrt()) as u8;
|
||||
buf[offset + 1] = (255.99 * color.g().sqrt()) as u8;
|
||||
buf[offset + 2] = (255.99 * color.b().sqrt()) as u8;
|
||||
buffer[offset] = (255.99 * color.r().sqrt()) as u8;
|
||||
buffer[offset + 1] = (255.99 * color.g().sqrt()) as u8;
|
||||
buffer[offset + 2] = (255.99 * color.b().sqrt()) as u8;
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,16 +30,17 @@ pub struct Chunk {
|
|||
ny: usize,
|
||||
start_x: usize,
|
||||
start_y: usize,
|
||||
buffer: Vec<u8>,
|
||||
}
|
||||
|
||||
pub trait Demo {
|
||||
pub trait Demo: std::marker::Sync {
|
||||
fn render(&self, buf: &mut [u8], width: usize, height: usize, samples: u8) {
|
||||
let nx = width / VERTICAL_PARTITION;
|
||||
let ny = height / HORIZONTAL_PARTITION;
|
||||
|
||||
let v = (0..VERTICAL_PARTITION).collect::<Vec<usize>>();
|
||||
let mut chunks: Vec<Chunk> = Vec::with_capacity(HORIZONTAL_PARTITION * VERTICAL_PARTITION);
|
||||
|
||||
for j in v {
|
||||
for j in 0..VERTICAL_PARTITION {
|
||||
for i in 0..HORIZONTAL_PARTITION {
|
||||
let start_y = j * ny;
|
||||
let start_x = i * nx;
|
||||
|
@ -50,14 +51,20 @@ pub trait Demo {
|
|||
ny,
|
||||
start_x,
|
||||
start_y,
|
||||
buffer: vec![0; nx * ny * 4],
|
||||
};
|
||||
|
||||
self.render_chunk(buf, chunk, samples);
|
||||
chunks.push(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
chunks
|
||||
.par_iter_mut()
|
||||
.for_each(|mut chunk| self.render_chunk(&mut chunk, samples));
|
||||
|
||||
// ((y - j - 1) * x + i) * 4
|
||||
}
|
||||
|
||||
fn render_chunk(&self, buf: &mut [u8], meta: Chunk, samples: u8);
|
||||
fn render_chunk(&self, chunk: &mut Chunk, samples: u8);
|
||||
|
||||
fn name(&self) -> &'static str;
|
||||
|
||||
|
|
|
@ -12,15 +12,14 @@ impl Demo for SimpleAntialiasing {
|
|||
fn name(&self) -> &'static str {
|
||||
"A simple antialiasing implementation"
|
||||
}
|
||||
fn render_chunk(&self, buf: &mut [u8], meta: Chunk, samples: u8) {
|
||||
let Chunk {
|
||||
x,
|
||||
y,
|
||||
nx,
|
||||
ny,
|
||||
start_x,
|
||||
start_y,
|
||||
} = meta;
|
||||
fn render_chunk(&self, chunk: &mut Chunk, samples: u8) {
|
||||
let x = chunk.x;
|
||||
let y = chunk.y;
|
||||
let nx = chunk.nx;
|
||||
let ny = chunk.ny;
|
||||
let start_x = chunk.start_x;
|
||||
let start_y = chunk.start_y;
|
||||
let buffer = &mut chunk.buffer;
|
||||
|
||||
let world = HitableList {
|
||||
list: vec![
|
||||
|
@ -31,6 +30,7 @@ impl Demo for SimpleAntialiasing {
|
|||
|
||||
let camera: Camera = Default::default();
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut offset = 0;
|
||||
|
||||
for j in start_y..start_y + ny {
|
||||
for i in start_x..start_x + nx {
|
||||
|
@ -43,10 +43,10 @@ impl Demo for SimpleAntialiasing {
|
|||
color += calc_color(r, &world);
|
||||
}
|
||||
color /= samples as f64;
|
||||
let offset = ((y - j - 1) * x + i) * 4;
|
||||
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;
|
||||
buffer[offset] = (255.99 * color.r()) as u8;
|
||||
buffer[offset + 1] = (255.99 * color.g()) as u8;
|
||||
buffer[offset + 2] = (255.99 * color.b()) as u8;
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
use crate::{
|
||||
demos::{Chunk, Demo},
|
||||
HORIZONTAL_PARTITION, VERTICAL_PARTITION,
|
||||
};
|
||||
use crate::demos::{Chunk, Demo};
|
||||
|
||||
pub struct SimpleRectangle;
|
||||
|
||||
|
@ -10,46 +7,24 @@ impl Demo for SimpleRectangle {
|
|||
"simple_rectangle"
|
||||
}
|
||||
|
||||
fn render(&self, buf: &mut [u8], width: usize, height: usize, samples: u8) {
|
||||
let nx = width / VERTICAL_PARTITION;
|
||||
let ny = height / HORIZONTAL_PARTITION;
|
||||
fn render_chunk(&self, chunk: &mut Chunk, samples: u8) {
|
||||
let x = chunk.x;
|
||||
let y = chunk.y;
|
||||
let nx = chunk.nx;
|
||||
let ny = chunk.ny;
|
||||
let start_x = chunk.start_x;
|
||||
let start_y = chunk.start_y;
|
||||
let buffer = &mut chunk.buffer;
|
||||
|
||||
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, samples);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render_chunk(&self, buf: &mut [u8], meta: Chunk, _samples: u8) {
|
||||
let Chunk {
|
||||
x,
|
||||
y,
|
||||
nx,
|
||||
ny,
|
||||
start_x,
|
||||
start_y,
|
||||
} = meta;
|
||||
let mut offset = 0;
|
||||
|
||||
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 = ((y - j - 1) * 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;
|
||||
buffer[offset] = (255.99 * color[0]) as u8;
|
||||
buffer[offset + 1] = (255.99 * color[1]) as u8;
|
||||
buffer[offset + 2] = (255.99 * color[2]) as u8;
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,15 @@ impl Demo for SimpleSphere {
|
|||
"simple_sphere"
|
||||
}
|
||||
|
||||
fn render_chunk(&self, buf: &mut [u8], meta: Chunk, _ns: u8) {
|
||||
fn render_chunk(&self, chunk: &mut Chunk, _samples: u8) {
|
||||
let x = chunk.x;
|
||||
let y = chunk.y;
|
||||
let nx = chunk.nx;
|
||||
let ny = chunk.ny;
|
||||
let start_x = chunk.start_x;
|
||||
let start_y = chunk.start_y;
|
||||
let buffer = &mut chunk.buffer;
|
||||
|
||||
// Usually, lower_left_corner should've been -1.0,-1.0,-1.0 and
|
||||
// horizontal should've been 2.0,0.0,0.0
|
||||
// but we are working with a canvas that is 2:1 in size.
|
||||
|
@ -23,20 +31,14 @@ impl Demo for SimpleSphere {
|
|||
// stretched horizontally.
|
||||
// To prevent this from happening, Since our dimensions are in 2:1 ratio,
|
||||
// We adjust the lower_left_corner and horizontal values to scale
|
||||
let Chunk {
|
||||
x,
|
||||
y,
|
||||
nx,
|
||||
ny,
|
||||
start_x,
|
||||
start_y,
|
||||
} = meta;
|
||||
let lower_left_corner = Vec3::new(-2.0, -1.0, -1.0);
|
||||
let horizontal = Vec3::new(4.0, 0.0, 0.0);
|
||||
let vertical = Vec3::new(0.0, 2.0, 0.0);
|
||||
// Observer's position
|
||||
let origin = Vec3::new(0.0, 0.0, 0.0);
|
||||
|
||||
let mut offset = 0;
|
||||
|
||||
for j in start_y..start_y + ny {
|
||||
for i in start_x..start_x + nx {
|
||||
// relative offsets
|
||||
|
@ -46,11 +48,10 @@ impl Demo for SimpleSphere {
|
|||
|
||||
let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
|
||||
let color = calc_color(ray);
|
||||
|
||||
let offset = ((y - j - 1) * x + i) * 4;
|
||||
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;
|
||||
buffer[offset] = (255.99 * color.r()) as u8;
|
||||
buffer[offset + 1] = (255.99 * color.g()) as u8;
|
||||
buffer[offset + 2] = (255.99 * color.b()) as u8;
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,15 @@ impl Demo for SurfaceNormalSphere {
|
|||
"surface_normal_sphere"
|
||||
}
|
||||
|
||||
fn render_chunk(&self, buf: &mut [u8], meta: Chunk, _samples: u8) {
|
||||
fn render_chunk(&self, chunk: &mut Chunk, _samples: u8) {
|
||||
let x = chunk.x;
|
||||
let y = chunk.y;
|
||||
let nx = chunk.nx;
|
||||
let ny = chunk.ny;
|
||||
let start_x = chunk.start_x;
|
||||
let start_y = chunk.start_y;
|
||||
let buffer = &mut chunk.buffer;
|
||||
|
||||
// Usually, lower_left_corner should've been -1.0,-1.0,-1.0 and
|
||||
// horizontal should've been 2.0,0.0,0.0
|
||||
// but we are working with a canvas that is 2:1 in size.
|
||||
|
@ -22,21 +30,14 @@ impl Demo for SurfaceNormalSphere {
|
|||
// stretched horizontally.
|
||||
// To prevent this from happening, Since our dimensions are in 2:1 ratio,
|
||||
// We adjust the lower_left_corner and horizontal values to scale
|
||||
let Chunk {
|
||||
x,
|
||||
y,
|
||||
nx,
|
||||
ny,
|
||||
start_x,
|
||||
start_y,
|
||||
} = meta;
|
||||
|
||||
let lower_left_corner = Vec3::new(-2.0, -1.0, -1.0);
|
||||
let horizontal = Vec3::new(4.0, 0.0, 0.0);
|
||||
let vertical = Vec3::new(0.0, 2.0, 0.0);
|
||||
// Observer position
|
||||
let origin = Vec3::new(0.0, 0.0, 0.0);
|
||||
|
||||
let mut offset = 0;
|
||||
|
||||
for j in start_y..start_y + ny {
|
||||
for i in start_x..start_x + nx {
|
||||
let u = i as f64 / x as f64;
|
||||
|
@ -48,10 +49,10 @@ impl Demo for SurfaceNormalSphere {
|
|||
let ig = (255.99 * color.g()) as u8;
|
||||
let ib = (255.99 * color.b()) as u8;
|
||||
|
||||
let offset = ((y - j - 1) * x + i) * 4;
|
||||
buf[offset] = ir;
|
||||
buf[offset + 1] = ig;
|
||||
buf[offset + 2] = ib;
|
||||
buffer[offset] = ir;
|
||||
buffer[offset + 1] = ig;
|
||||
buffer[offset + 2] = ib;
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user