From 3b85b60a62f6d2788c3c4a54f65c0aee2850eef1 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Mon, 27 Jun 2016 21:01:18 -0700 Subject: [PATCH] Implemented occlusion rays. This is prep for lighting support: occlusion rays are useful for speedier shadow tests. --- src/bvh.rs | 2 ++ src/camera.rs | 2 +- src/ray.rs | 43 ++++++++++++++++++++++++++++++------ src/surface/triangle_mesh.rs | 21 +++++++++++------- 4 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/bvh.rs b/src/bvh.rs index 6a6c32a..443e787 100644 --- a/src/bvh.rs +++ b/src/bvh.rs @@ -192,6 +192,7 @@ impl BVH { match self.nodes[i_stack[stack_ptr]] { BVHNode::Internal { bounds_range: br, second_child_index, split_axis } => { let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| { + (!r.is_done()) && lerp_slice(&self.bounds[br.0..br.1], r.time).intersect_accel_ray(r) }); if part > 0 { @@ -210,6 +211,7 @@ impl BVH { BVHNode::Leaf { bounds_range: br, object_range } => { let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| { + (!r.is_done()) && lerp_slice(&self.bounds[br.0..br.1], r.time).intersect_accel_ray(r) }); if part > 0 { diff --git a/src/camera.rs b/src/camera.rs index 35100c9..a5cd4b6 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -76,7 +76,7 @@ impl Camera { 1.0) .normalized(); - Ray::new(orig * transform, dir * transform, time) + Ray::new(orig * transform, dir * transform, time, false) } } diff --git a/src/ray.rs b/src/ray.rs index 108b142..e4f905f 100644 --- a/src/ray.rs +++ b/src/ray.rs @@ -5,6 +5,9 @@ use std; use float4::Float4; use math::{Vector, Point, Matrix4x4}; +const OCCLUSION_FLAG: u32 = 1; +const DONE_FLAG: u32 = 1 << 1; + #[derive(Debug, Copy, Clone)] pub struct Ray { pub orig: Point, @@ -15,13 +18,23 @@ pub struct Ray { } impl Ray { - pub fn new(orig: Point, dir: Vector, time: f32) -> Ray { - Ray { - orig: orig, - dir: dir, - max_t: std::f32::INFINITY, - time: time, - flags: 0, + pub fn new(orig: Point, dir: Vector, time: f32, is_occ: bool) -> Ray { + if !is_occ { + Ray { + orig: orig, + dir: dir, + max_t: std::f32::INFINITY, + time: time, + flags: 0, + } + } else { + Ray { + orig: orig, + dir: dir, + max_t: 1.0, + time: time, + flags: OCCLUSION_FLAG, + } } } @@ -29,6 +42,10 @@ impl Ray { self.orig = self.orig * *mat; self.dir = self.dir * *mat; } + + pub fn is_occlusion(&self) -> bool { + (self.flags & OCCLUSION_FLAG) != 0 + } } @@ -63,4 +80,16 @@ impl AccelRay { self.orig = wr.orig * *mat; self.dir_inv = Vector { co: Float4::new(1.0, 1.0, 1.0, 1.0) / (wr.dir * *mat).co }; } + + pub fn is_occlusion(&self) -> bool { + (self.flags & OCCLUSION_FLAG) != 0 + } + + pub fn is_done(&self) -> bool { + (self.flags & DONE_FLAG) != 0 + } + + pub fn mark_done(&mut self) { + self.flags |= DONE_FLAG; + } } diff --git a/src/surface/triangle_mesh.rs b/src/surface/triangle_mesh.rs index a302b8b..50dceaf 100644 --- a/src/surface/triangle_mesh.rs +++ b/src/surface/triangle_mesh.rs @@ -78,14 +78,19 @@ impl Surface for TriangleMesh { let tri = (tri.0 * mat_inv, tri.1 * mat_inv, tri.2 * mat_inv); if let Some((t, tri_u, tri_v)) = triangle::intersect_ray(wr, tri) { if t < r.max_t { - isects[r.id as usize] = SurfaceIntersection::Hit { - t: t, - pos: wr.orig + (wr.dir * t), - nor: Normal::new(0.0, 0.0, 0.0), // TODO - local_space: mat_space, - uv: (tri_u, tri_v), - }; - r.max_t = t; + if r.is_occlusion() { + isects[r.id as usize] = SurfaceIntersection::Occlude; + r.mark_done(); + } else { + isects[r.id as usize] = SurfaceIntersection::Hit { + t: t, + pos: wr.orig + (wr.dir * t), + nor: Normal::new(0.0, 0.0, 0.0), // TODO + local_space: mat_space, + uv: (tri_u, tri_v), + }; + r.max_t = t; + } } } }