From eaeec4c207b86d35ed3d3fbcbc8ed851e35845cd Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Thu, 31 Dec 2015 13:12:15 -0800 Subject: [PATCH] BVH now works on slices of Rays, taking a breadth-first approach. --- src/bvh.rs | 27 +++++++++++++++++---------- src/main.rs | 41 +++++++++++++++++++++++++---------------- src/ray.rs | 4 ++++ 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/src/bvh.rs b/src/bvh.rs index 584bc22..a8d62b8 100644 --- a/src/bvh.rs +++ b/src/bvh.rs @@ -1,6 +1,7 @@ #![allow(dead_code)] use std::marker; +use std::slice; use bbox::BBox; use ray::Ray; @@ -131,33 +132,40 @@ impl<'a, T> BVH<'a, T> { pub struct BVHTraverser<'a, T: 'a> { bvh: &'a BVH<'a, T>, - ray: *mut Ray, - _ray_marker: marker::PhantomData<&'a mut Ray>, + rays: (*mut Ray, usize), + _ray_marker: marker::PhantomData<&'a mut [Ray]>, i_stack: [usize; 65], + ray_i_stack: [usize; 65], stack_ptr: usize, } impl<'a, T> BVHTraverser<'a, T> { - pub fn from_bvh_and_ray(bvh: &'a BVH<'a, T>, ray: &'a mut Ray) -> BVHTraverser<'a, T> { + pub fn from_bvh_and_ray(bvh: &'a BVH<'a, T>, rays: &'a mut [Ray]) -> BVHTraverser<'a, T> { BVHTraverser { bvh: bvh, - ray: ray as *mut Ray, + rays: (&mut rays[0] as *mut Ray, rays.len()), _ray_marker: marker::PhantomData, i_stack: [0; 65], + ray_i_stack: [rays.len(); 65], stack_ptr: 1, } } } impl<'a, T> Iterator for BVHTraverser<'a, T> { - type Item = (&'a T, &'a mut Ray); - fn next(&mut self) -> Option<(&'a T, &'a mut Ray)> { + type Item = (&'a T, &'a mut [Ray]); + fn next(&mut self) -> Option<(&'a T, &'a mut [Ray])> { + let rays = unsafe { slice::from_raw_parts_mut(self.rays.0, self.rays.1) }; while self.stack_ptr > 0 { match self.bvh.nodes[self.i_stack[self.stack_ptr]] { BVHNode::Internal { bounds, second_child_index } => { - if bounds.intersect_ray(&(unsafe { *self.ray })) { + let part = partition(&mut rays[..self.ray_i_stack[self.stack_ptr]], + |r| bounds.intersect_ray(r)); + if part > 0 { self.i_stack[self.stack_ptr] += 1; self.i_stack[self.stack_ptr + 1] = second_child_index; + self.ray_i_stack[self.stack_ptr] = part; + self.ray_i_stack[self.stack_ptr + 1] = part; self.stack_ptr += 1; } else { self.stack_ptr -= 1; @@ -166,9 +174,8 @@ impl<'a, T> Iterator for BVHTraverser<'a, T> { BVHNode::Leaf { bounds: _, object_index } => { self.stack_ptr -= 1; - unsafe { - return Some((&self.bvh.objects[object_index], &mut (*self.ray))); - } + return Some((&self.bvh.objects[object_index], + &mut rays[..self.ray_i_stack[self.stack_ptr + 1]])); } } } diff --git a/src/main.rs b/src/main.rs index b6f3735..c1ca8aa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ mod triangle; mod bvh; mod halton; +use std::mem; use std::path::Path; use docopt::Docopt; @@ -72,6 +73,8 @@ fn main() { return; } + println!("Ray size: {} bytes", mem::size_of::()); + // Generate a scene of triangles let mut triangles = { let mut triangles = Vec::new(); @@ -103,17 +106,20 @@ fn main() { }); println!("Scene built."); + let mut rays = Vec::new(); + let mut isects = Vec::new(); + // 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 mut r = 0.0; - let mut g = 0.0; - let mut b = 0.0; let offset = hash_u32(((x as u32) << 16) ^ (y as u32), 0); const SAMPLES: usize = 16; + + // Generate rays + rays.clear(); + isects.clear(); for si in 0..SAMPLES { - // Generate ray let mut ray = Ray::new(Point::new(x as f32 + fast_logit(halton::sample(0, offset + si as u32), @@ -124,40 +130,43 @@ fn main() { 1.5), 0.0), Vector::new(0.0, 0.0, 1.0)); + ray.id = si as u32; + rays.push(ray); + isects.push((false, 0.0, 0.0)); + } - // Test ray against scene - let (mut u, mut v) = (0.0, 0.0); - let mut hit = false; - for (tri, r) in bvh::BVHTraverser::from_bvh_and_ray(&scene, &mut ray) { + // Test ray against scene + for (tri, rs) in bvh::BVHTraverser::from_bvh_and_ray(&scene, &mut rays[..]) { + for r in rs.iter_mut() { if let Some((t, tri_u, tri_v)) = triangle::intersect_ray(r, *tri) { if t < r.max_t { - hit = true; + isects[r.id as usize] = (true, tri_u, tri_v); r.max_t = t; - u = tri_u; - v = tri_v; } } } + } - // Update color based on ray hit + // 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); - // r += 1.0; - // g += 1.0; - // b += 1.0; } else { r += 0.1; g += 0.1; b += 0.1; } } - r *= 255.0 / SAMPLES as f32; g *= 255.0 / SAMPLES as f32; b *= 255.0 / SAMPLES as f32; + // Set pixel color img.set(x, y, (r as u8, g as u8, b as u8)); } } diff --git a/src/ray.rs b/src/ray.rs index 2767330..d44d822 100644 --- a/src/ray.rs +++ b/src/ray.rs @@ -12,6 +12,8 @@ pub struct Ray { pub dir_inv: Vector, pub max_t: f32, pub time: f32, + pub id: u32, + pub flags: u32, } impl Ray { @@ -22,6 +24,8 @@ impl Ray { dir_inv: Vector { co: Float4::new(1.0, 1.0, 1.0, 1.0) / dir.co }, max_t: std::f32::INFINITY, time: 0.0, + id: 0, + flags: 0, } }