Implemented occlusion rays.

This is prep for lighting support: occlusion rays are useful for
speedier shadow tests.
This commit is contained in:
Nathan Vegdahl 2016-06-27 21:01:18 -07:00
parent 6f6807009b
commit 3b85b60a62
4 changed files with 52 additions and 16 deletions

View File

@ -192,6 +192,7 @@ impl BVH {
match self.nodes[i_stack[stack_ptr]] { match self.nodes[i_stack[stack_ptr]] {
BVHNode::Internal { bounds_range: br, second_child_index, split_axis } => { BVHNode::Internal { bounds_range: br, second_child_index, split_axis } => {
let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| { 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) lerp_slice(&self.bounds[br.0..br.1], r.time).intersect_accel_ray(r)
}); });
if part > 0 { if part > 0 {
@ -210,6 +211,7 @@ impl BVH {
BVHNode::Leaf { bounds_range: br, object_range } => { BVHNode::Leaf { bounds_range: br, object_range } => {
let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| { 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) lerp_slice(&self.bounds[br.0..br.1], r.time).intersect_accel_ray(r)
}); });
if part > 0 { if part > 0 {

View File

@ -76,7 +76,7 @@ impl Camera {
1.0) 1.0)
.normalized(); .normalized();
Ray::new(orig * transform, dir * transform, time) Ray::new(orig * transform, dir * transform, time, false)
} }
} }

View File

@ -5,6 +5,9 @@ use std;
use float4::Float4; use float4::Float4;
use math::{Vector, Point, Matrix4x4}; use math::{Vector, Point, Matrix4x4};
const OCCLUSION_FLAG: u32 = 1;
const DONE_FLAG: u32 = 1 << 1;
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Ray { pub struct Ray {
pub orig: Point, pub orig: Point,
@ -15,13 +18,23 @@ pub struct Ray {
} }
impl Ray { impl Ray {
pub fn new(orig: Point, dir: Vector, time: f32) -> Ray { pub fn new(orig: Point, dir: Vector, time: f32, is_occ: bool) -> Ray {
Ray { if !is_occ {
orig: orig, Ray {
dir: dir, orig: orig,
max_t: std::f32::INFINITY, dir: dir,
time: time, max_t: std::f32::INFINITY,
flags: 0, 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.orig = self.orig * *mat;
self.dir = self.dir * *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.orig = wr.orig * *mat;
self.dir_inv = Vector { co: Float4::new(1.0, 1.0, 1.0, 1.0) / (wr.dir * *mat).co }; 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;
}
} }

View File

@ -78,14 +78,19 @@ impl Surface for TriangleMesh {
let tri = (tri.0 * mat_inv, tri.1 * mat_inv, tri.2 * mat_inv); 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 let Some((t, tri_u, tri_v)) = triangle::intersect_ray(wr, tri) {
if t < r.max_t { if t < r.max_t {
isects[r.id as usize] = SurfaceIntersection::Hit { if r.is_occlusion() {
t: t, isects[r.id as usize] = SurfaceIntersection::Occlude;
pos: wr.orig + (wr.dir * t), r.mark_done();
nor: Normal::new(0.0, 0.0, 0.0), // TODO } else {
local_space: mat_space, isects[r.id as usize] = SurfaceIntersection::Hit {
uv: (tri_u, tri_v), t: t,
}; pos: wr.orig + (wr.dir * t),
r.max_t = t; nor: Normal::new(0.0, 0.0, 0.0), // TODO
local_space: mat_space,
uv: (tri_u, tri_v),
};
r.max_t = t;
}
} }
} }
} }