Created a Renderer type to be in charge of rendering.

This commit is contained in:
Nathan Vegdahl 2016-01-02 22:34:36 -08:00
parent d25f8308a2
commit 470618fa6a
5 changed files with 125 additions and 78 deletions

View File

@ -8,22 +8,22 @@ mod float4;
mod ray; mod ray;
mod bbox; mod bbox;
mod camera; mod camera;
mod data_tree; mod parse;
mod renderer;
mod image; mod image;
mod triangle; mod triangle;
mod bvh; mod bvh;
mod halton; mod halton;
use std::mem; use std::mem;
use std::path::Path;
use docopt::Docopt; use docopt::Docopt;
use image::Image; use math::{Point, Matrix4x4};
use math::{Point, Matrix4x4, fast_logit};
use ray::Ray; use ray::Ray;
use bbox::BBox; use bbox::BBox;
use camera::Camera; 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() { fn main() {
// Parse command line arguments. // Parse command line arguments.
let args: Args = Docopt::new(USAGE.replace("<VERSION>", VERSION)) let args: Args = Docopt::new(USAGE.replace("<VERSION>", VERSION))
@ -125,67 +113,13 @@ fn main() {
vec![20.0], vec![20.0],
vec![1026.0]); vec![1026.0]);
let mut rays = Vec::new(); let r = Renderer {
let mut isects = Vec::new(); output_file: args.arg_imgpath.clone(),
resolution: (512, 512),
// Write output image of ray-traced triangle spp: samples_per_pixel as usize,
let mut img = Image::new(512, 512); camera: cam,
for y in 0..img.height() { scene: scene,
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 r.render();
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));
} }

4
src/parse/mod.rs Normal file
View File

@ -0,0 +1,4 @@
mod data_tree;
mod psy;
pub use self::data_tree::DataTree;

7
src/parse/psy.rs Normal file
View File

@ -0,0 +1,7 @@
// use renderer::Renderer;
//
// use super::DataTree;
// pub fn parse_frame<'a>(tree: &DataTree) -> Renderer<'a> {
// unimplemented!()
// }

102
src/renderer.rs Normal file
View File

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