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]] {
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 {

View File

@ -76,7 +76,7 @@ impl Camera {
1.0)
.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 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;
}
}

View File

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