From 470618fa6ad0d8d756a591768ae918dea6f77880 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Sat, 2 Jan 2016 22:34:36 -0800 Subject: [PATCH] Created a Renderer type to be in charge of rendering. --- src/main.rs | 90 +++++-------------------------- src/{ => parse}/data_tree.rs | 0 src/parse/mod.rs | 4 ++ src/parse/psy.rs | 7 +++ src/renderer.rs | 102 +++++++++++++++++++++++++++++++++++ 5 files changed, 125 insertions(+), 78 deletions(-) rename src/{ => parse}/data_tree.rs (100%) create mode 100644 src/parse/mod.rs create mode 100644 src/parse/psy.rs create mode 100644 src/renderer.rs diff --git a/src/main.rs b/src/main.rs index b52d641..8bd783d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,22 +8,22 @@ mod float4; mod ray; mod bbox; mod camera; -mod data_tree; +mod parse; +mod renderer; mod image; mod triangle; mod bvh; mod halton; use std::mem; -use std::path::Path; use docopt::Docopt; -use image::Image; -use math::{Point, Matrix4x4, fast_logit}; +use math::{Point, Matrix4x4}; use ray::Ray; use bbox::BBox; use camera::Camera; +use renderer::Renderer; // ---------------------------------------------------------------- @@ -55,18 +55,6 @@ struct Args { // ---------------------------------------------------------------- -fn hash_u32(n: u32, seed: u32) -> u32 { - let mut hash = n; - - for _ in 0..3 { - hash = hash.wrapping_mul(1936502639); - hash ^= hash.wrapping_shr(16); - hash = hash.wrapping_add(seed); - } - - return hash; -} - fn main() { // Parse command line arguments. let args: Args = Docopt::new(USAGE.replace("", VERSION)) @@ -125,67 +113,13 @@ fn main() { vec![20.0], vec![1026.0]); - let mut rays = Vec::new(); - let mut isects = Vec::new(); + let r = Renderer { + output_file: args.arg_imgpath.clone(), + resolution: (512, 512), + spp: samples_per_pixel as usize, + camera: cam, + scene: scene, + }; - // Write output image of ray-traced triangle - let mut img = Image::new(512, 512); - for y in 0..img.height() { - for x in 0..img.width() { - let offset = hash_u32(((x as u32) << 16) ^ (y as u32), 0); - - // Generate rays - rays.clear(); - isects.clear(); - for si in 0..samples_per_pixel { - let mut ray = { - let filter_x = fast_logit(halton::sample(3, offset + si as u32), 1.5); - let filter_y = fast_logit(halton::sample(4, offset + si as u32), 1.5); - cam.generate_ray((x as f32 + filter_x) / 512.0 - 0.5, - (y as f32 + filter_y) / 512.0 - 0.5, - halton::sample(0, offset + si as u32), - halton::sample(1, offset + si as u32), - halton::sample(2, offset + si as u32)) - }; - ray.id = si as u32; - rays.push(ray); - isects.push((false, 0.0, 0.0)); - } - - // Test rays against scene - scene.traverse(&mut rays, |tri, rs| { - for r in rs { - if let Some((t, tri_u, tri_v)) = triangle::intersect_ray(r, *tri) { - if t < r.max_t { - isects[r.id as usize] = (true, tri_u, tri_v); - r.max_t = t; - } - } - } - }); - - // Calculate color based on ray hits - let mut r = 0.0; - let mut g = 0.0; - let mut b = 0.0; - for &(hit, u, v) in isects.iter() { - if hit { - r += u; - g += v; - b += (1.0 - u - v).max(0.0); - } else { - r += 0.1; - g += 0.1; - b += 0.1; - } - } - r *= 255.0 / samples_per_pixel as f32; - g *= 255.0 / samples_per_pixel as f32; - b *= 255.0 / samples_per_pixel as f32; - - // Set pixel color - img.set(x, y, (r as u8, g as u8, b as u8)); - } - } - let _ = img.write_binary_ppm(Path::new(&args.arg_imgpath)); + r.render(); } diff --git a/src/data_tree.rs b/src/parse/data_tree.rs similarity index 100% rename from src/data_tree.rs rename to src/parse/data_tree.rs diff --git a/src/parse/mod.rs b/src/parse/mod.rs new file mode 100644 index 0000000..b704633 --- /dev/null +++ b/src/parse/mod.rs @@ -0,0 +1,4 @@ +mod data_tree; +mod psy; + +pub use self::data_tree::DataTree; diff --git a/src/parse/psy.rs b/src/parse/psy.rs new file mode 100644 index 0000000..b1f7224 --- /dev/null +++ b/src/parse/psy.rs @@ -0,0 +1,7 @@ +// use renderer::Renderer; +// +// use super::DataTree; + +// pub fn parse_frame<'a>(tree: &DataTree) -> Renderer<'a> { +// unimplemented!() +// } diff --git a/src/renderer.rs b/src/renderer.rs new file mode 100644 index 0000000..fff0ee1 --- /dev/null +++ b/src/renderer.rs @@ -0,0 +1,102 @@ +use std::path::Path; + +use camera::Camera; +use halton; +use math::{Point, fast_logit}; +use image::Image; +use bvh::BVH; +use triangle; + +pub struct Renderer<'a> { + pub output_file: String, + pub resolution: (usize, usize), + pub spp: usize, + pub camera: Camera, + pub scene: BVH<'a, (Point, Point, Point)>, +} + +impl<'a> Renderer<'a> { + pub fn render(&self) { + let mut rays = Vec::new(); + let mut isects = Vec::new(); + let mut img = Image::new(self.resolution.0, self.resolution.1); + + // Render image of ray-traced triangle + let cmpx = 1.0 / self.resolution.0 as f32; + let cmpy = 1.0 / self.resolution.1 as f32; + + for y in 0..img.height() { + for x in 0..img.width() { + let offset = hash_u32(((x as u32) << 16) ^ (y as u32), 0); + + // Generate rays + rays.clear(); + isects.clear(); + for si in 0..self.spp { + let mut ray = { + let filter_x = fast_logit(halton::sample(3, offset + si as u32), 1.5); + let filter_y = fast_logit(halton::sample(4, offset + si as u32), 1.5); + self.camera.generate_ray((x as f32 + filter_x) * cmpx - 0.5, + (y as f32 + filter_y) * cmpy - 0.5, + halton::sample(0, offset + si as u32), + halton::sample(1, offset + si as u32), + halton::sample(2, offset + si as u32)) + }; + ray.id = si as u32; + rays.push(ray); + isects.push((false, 0.0, 0.0)); + } + + // Test rays against scene + self.scene.traverse(&mut rays, |tri, rs| { + for r in rs { + if let Some((t, tri_u, tri_v)) = triangle::intersect_ray(r, *tri) { + if t < r.max_t { + isects[r.id as usize] = (true, tri_u, tri_v); + r.max_t = t; + } + } + } + }); + + // Calculate color based on ray hits + let mut r = 0.0; + let mut g = 0.0; + let mut b = 0.0; + for &(hit, u, v) in isects.iter() { + if hit { + r += u; + g += v; + b += (1.0 - u - v).max(0.0); + } else { + r += 0.1; + g += 0.1; + b += 0.1; + } + } + r *= 255.0 / self.spp as f32; + g *= 255.0 / self.spp as f32; + b *= 255.0 / self.spp as f32; + + // Set pixel color + img.set(x, y, (r as u8, g as u8, b as u8)); + } + } + + // Write rendered image to disk + let _ = img.write_binary_ppm(Path::new(&self.output_file)); + } +} + + +fn hash_u32(n: u32, seed: u32) -> u32 { + let mut hash = n; + + for _ in 0..3 { + hash = hash.wrapping_mul(1936502639); + hash ^= hash.wrapping_shr(16); + hash = hash.wrapping_add(seed); + } + + return hash; +}