Compare commits

..

No commits in common. "6ccd4e306daae68a6bd85d37f6694ffd7645d10d" and "608fe8bda196a84fe22cae583d3a0b81fbfacf88" have entirely different histories.

4 changed files with 318 additions and 491 deletions

View File

@ -1,2 +0,0 @@
#!/bin/sh
RUSTFLAGS="-C target-cpu=native" cargo build --release

View File

@ -52,6 +52,7 @@ use crate::{
accel::BVH4Node, accel::BVH4Node,
bbox::BBox, bbox::BBox,
parse::{parse_scene, DataTree}, parse::{parse_scene, DataTree},
renderer::LightPath,
surface::SurfaceIntersection, surface::SurfaceIntersection,
timer::Timer, timer::Timer,
}; };
@ -163,6 +164,7 @@ fn main() {
"SurfaceIntersection size: {} bytes", "SurfaceIntersection size: {} bytes",
mem::size_of::<SurfaceIntersection>() mem::size_of::<SurfaceIntersection>()
); );
println!("LightPath size: {} bytes", mem::size_of::<LightPath>());
println!("BBox size: {} bytes", mem::size_of::<BBox>()); println!("BBox size: {} bytes", mem::size_of::<BBox>());
// println!("BVHNode size: {} bytes", mem::size_of::<BVHNode>()); // println!("BVHNode size: {} bytes", mem::size_of::<BVHNode>());
println!("BVH4Node size: {} bytes", mem::size_of::<BVH4Node>()); println!("BVH4Node size: {} bytes", mem::size_of::<BVH4Node>());

View File

@ -20,6 +20,7 @@ use crate::{
scene::{Scene, SceneLightSample}, scene::{Scene, SceneLightSample},
scramble::owen4, scramble::owen4,
space_fill::{hilbert, morton}, space_fill::{hilbert, morton},
surface,
timer::Timer, timer::Timer,
tracer::Tracer, tracer::Tracer,
}; };
@ -242,7 +243,7 @@ impl<'a> Renderer<'a> {
let (d1, d2, d3, d4) = get_sample_4d(si, 0, self.seed); let (d1, d2, d3, d4) = get_sample_4d(si, 0, self.seed);
let (d5, _, _, _) = get_sample_4d(si, 1, self.seed); let (d5, _, _, _) = get_sample_4d(si, 1, self.seed);
// Calculate the values we need to generate a camera ray. // Calculate image plane x and y coordinates
let (img_x, img_y) = { let (img_x, img_y) = {
let filter_x = probit(d4, 2.0 / 6.0) + 0.5; let filter_x = probit(d4, 2.0 / 6.0) + 0.5;
let filter_y = probit(d5, 2.0 / 6.0) + 0.5; let filter_y = probit(d5, 2.0 / 6.0) + 0.5;
@ -250,19 +251,31 @@ impl<'a> Renderer<'a> {
let samp_y = (filter_y + y as f32) * cmpy; let samp_y = (filter_y + y as f32) * cmpy;
((samp_x - 0.5) * x_extent, (0.5 - samp_y) * y_extent) ((samp_x - 0.5) * x_extent, (0.5 - samp_y) * y_extent)
}; };
let wavelength = map_0_1_to_wavelength(d0);
let time = d1;
let lens_uv = (d2, d3);
// Trace light path starting from a camera ray. // Create the light path and initial ray for this sample.
let ray = self let (mut path, mut ray) = LightPath::new(
.scene &self.scene,
.camera self.seed,
.generate_ray(img_x, img_y, time, wavelength, lens_uv.0, lens_uv.1); (x, y),
let path_col = (img_x, img_y),
trace_camera_light_path(&mut tracer, &self.scene, ray, si, self.seed); (d2, d3),
d1,
map_0_1_to_wavelength(d0),
si as u32,
);
// Trace light path.
let mut isect;
loop {
isect = surface::SurfaceIntersection::Miss;
tracer.trace(&mut ray, &mut isect);
if !path.next(&self.scene, &isect, &mut ray) {
break;
}
}
// Accummulate light path color to pixel. // Accummulate light path color to pixel.
let path_col = SpectralSample::from_parts(path.color, path.wavelength);
let mut col = img_bucket.get(x, y); let mut col = img_bucket.get(x, y);
col += XYZ::from_spectral_sample(&path_col) / self.spp as f32; col += XYZ::from_spectral_sample(&path_col) / self.spp as f32;
img_bucket.set(x, y, col); img_bucket.set(x, y, col);
@ -321,511 +334,328 @@ impl<'a> Renderer<'a> {
} }
} }
fn trace_camera_light_path( #[derive(Debug)]
tracer: &mut Tracer, enum LightPathEvent {
scene: &Scene, CameraRay,
camera_ray: Ray, BounceRay,
sample_index: u32, ShadowRay,
seed: u32, }
) -> SpectralSample {
use crate::shading::surface_closure::SurfaceClosure;
use crate::surface::SurfaceIntersection;
const BOUNCE_COUNT: usize = 3; #[derive(Debug)]
pub struct LightPath {
event: LightPathEvent,
bounce_count: u32,
let mut ray = camera_ray; sampling_seed: u32,
let mut ray_pdf = 1.0; // PDF from generating the ray. pixel_co: (u32, u32),
let mut acc_color = Float4::splat(0.0); // Accumulated color. sample_number: u32, // Which sample in the LDS sequence this is.
let mut attenuation = Float4::splat(1.0); // Color attenuation along the path so far. dim_offset: u32,
let mut sampling_seed = seed + 1; time: f32,
wavelength: f32,
for _ in 0..BOUNCE_COUNT { next_bounce_ray: Option<Ray>,
let isect = tracer.trace(&mut ray); next_attenuation_fac: Float4,
if let SurfaceIntersection::Hit {
intersection_data: idata,
closure,
} = &isect
{
// Hit something! Do the stuff
// If it's an emission closure, handle specially: closure_sample_pdf: f32,
// - Collect light from the emission. light_attenuation: Float4,
// - Terminate the path. pending_color_addition: Float4,
if let SurfaceClosure::Emit(color) = *closure { color: Float4,
let mis_pdf = power_heuristic(ray_pdf, idata.sample_pdf); }
acc_color += color.to_spectral_sample(ray.wavelength).e * attenuation / mis_pdf;
break; #[allow(clippy::new_ret_no_self)]
} impl LightPath {
fn new(
scene: &Scene,
sampling_seed: u32,
pixel_co: (u32, u32),
image_plane_co: (f32, f32),
lens_uv: (f32, f32),
time: f32,
wavelength: f32,
sample_number: u32,
) -> (LightPath, Ray) {
(
LightPath {
event: LightPathEvent::CameraRay,
bounce_count: 0,
// Roll the previous closure pdf into the attenauation sampling_seed: sampling_seed ^ 0x40d4682b,
attenuation /= ray_pdf; pixel_co: pixel_co,
sample_number: sample_number,
dim_offset: 0,
time: time,
wavelength: wavelength,
//------------------------------------------------- next_bounce_ray: None,
// Sample light sources. next_attenuation_fac: Float4::splat(1.0),
sampling_seed = sampling_seed.wrapping_add(1); closure_sample_pdf: 1.0,
let (light_n, d2, d3, d4) = get_sample_4d(sample_index, 0, sampling_seed); light_attenuation: Float4::splat(1.0),
pending_color_addition: Float4::splat(0.0),
color: Float4::splat(0.0),
},
scene.camera.generate_ray(
image_plane_co.0,
image_plane_co.1,
time,
wavelength,
lens_uv.0,
lens_uv.1,
),
)
}
let light_uvw = (d2, d3, d4); fn next_lds_sequence(&mut self) {
let light_info = scene.sample_lights( self.dim_offset = 0;
light_n, self.sampling_seed += 1;
light_uvw, }
ray.wavelength,
ray.time,
&XformFull::identity(),
&isect,
);
if !light_info.is_none() && light_info.pdf() > 0.0 && light_info.selection_pdf() > 0.0 {
let light_pdf = light_info.pdf();
let light_sel_pdf = light_info.selection_pdf();
// Calculate the shadow ray and surface closure stuff. fn next_lds_samp(&mut self) -> (f32, f32, f32, f32) {
let (light_attenuation, closure_pdf, mut shadow_ray) = match light_info { let dimension = self.dim_offset;
SceneLightSample::None => unreachable!(), self.dim_offset += 1;
get_sample_4d(self.sample_number, dimension, self.sampling_seed)
}
// Distant light fn next(&mut self, scene: &Scene, isect: &surface::SurfaceIntersection, ray: &mut Ray) -> bool {
SceneLightSample::Distant { direction, .. } => { match self.event {
let (light_attenuation, closure_pdf) = closure.evaluate( //--------------------------------------------------------------------
ray.dir, // Result of Camera or bounce ray, prepare next bounce and light rays
direction, LightPathEvent::CameraRay | LightPathEvent::BounceRay => {
idata.nor, if let surface::SurfaceIntersection::Hit {
idata.nor_g, intersection_data: ref idata,
ray.wavelength, ref closure,
); } = *isect
let shadow_ray = { {
// Calculate the shadow ray for testing if the light is // Hit something! Do the stuff
// in shadow or not.
let offset_pos = robust_ray_origin( // If it's an emission closure, handle specially:
idata.pos, // - Collect light from the emission.
idata.pos_err, // - Terminate the path.
idata.nor_g.normalized(), use crate::shading::surface_closure::SurfaceClosure;
direction, if let SurfaceClosure::Emit(color) = *closure {
); let color = color.to_spectral_sample(self.wavelength).e;
Ray::new( if let LightPathEvent::CameraRay = self.event {
offset_pos, self.color += color;
direction, } else {
ray.time, let mis_pdf =
ray.wavelength, power_heuristic(self.closure_sample_pdf, idata.sample_pdf);
std::f32::INFINITY, self.color += color * self.light_attenuation / mis_pdf;
true,
)
}; };
(light_attenuation, closure_pdf, shadow_ray)
return false;
} }
// Surface light // Roll the previous closure pdf into the attenauation
SceneLightSample::Surface { sample_geo, .. } => { self.light_attenuation /= self.closure_sample_pdf;
let dir = sample_geo.0 - idata.pos;
let (light_attenuation, closure_pdf) = // Prepare light ray
closure.evaluate(ray.dir, dir, idata.nor, idata.nor_g, ray.wavelength); self.next_lds_sequence();
let shadow_ray = { let (light_n, d2, d3, d4) = self.next_lds_samp();
// Calculate the shadow ray for testing if the light is let light_uvw = (d2, d3, d4);
// in shadow or not. let light_info = scene.sample_lights(
light_n,
light_uvw,
self.wavelength,
self.time,
&XformFull::identity(),
isect,
);
let found_light = if light_info.is_none()
|| light_info.pdf() <= 0.0
|| light_info.selection_pdf() <= 0.0
{
false
} else {
let light_pdf = light_info.pdf();
let light_sel_pdf = light_info.selection_pdf();
// Calculate the shadow ray and surface closure stuff
let (attenuation, closure_pdf, shadow_ray) = match light_info {
SceneLightSample::None => unreachable!(),
// Distant light
SceneLightSample::Distant { direction, .. } => {
let (attenuation, closure_pdf) = closure.evaluate(
ray.dir,
direction,
idata.nor,
idata.nor_g,
self.wavelength,
);
let shadow_ray = {
// Calculate the shadow ray for testing if the light is
// in shadow or not.
let offset_pos = robust_ray_origin(
idata.pos,
idata.pos_err,
idata.nor_g.normalized(),
direction,
);
Ray::new(
offset_pos,
direction,
self.time,
self.wavelength,
std::f32::INFINITY,
true,
)
};
(attenuation, closure_pdf, shadow_ray)
}
// Surface light
SceneLightSample::Surface { sample_geo, .. } => {
let dir = sample_geo.0 - idata.pos;
let (attenuation, closure_pdf) = closure.evaluate(
ray.dir,
dir,
idata.nor,
idata.nor_g,
self.wavelength,
);
let shadow_ray = {
// Calculate the shadow ray for testing if the light is
// in shadow or not.
let offset_pos = robust_ray_origin(
idata.pos,
idata.pos_err,
idata.nor_g.normalized(),
dir,
);
let offset_end = robust_ray_origin(
sample_geo.0,
sample_geo.2,
sample_geo.1.normalized(),
-dir,
);
Ray::new(
offset_pos,
offset_end - offset_pos,
self.time,
self.wavelength,
1.0,
true,
)
};
(attenuation, closure_pdf, shadow_ray)
}
};
// If there's any possible contribution, set up for a
// light ray.
if attenuation.e.max_element() <= 0.0 {
false
} else {
// Calculate and store the light that will be contributed
// to the film plane if the light is not in shadow.
let light_mis_pdf = power_heuristic(light_pdf, closure_pdf);
self.pending_color_addition =
light_info.color().e * attenuation.e * self.light_attenuation
/ (light_mis_pdf * light_sel_pdf);
*ray = shadow_ray;
true
}
};
// Prepare bounce ray
let do_bounce = if self.bounce_count < 2 {
self.bounce_count += 1;
// Sample closure
let (dir, filter, pdf) = {
self.next_lds_sequence();
let (u, v, _, _) = self.next_lds_samp();
closure.sample(
idata.incoming,
idata.nor,
idata.nor_g,
(u, v),
self.wavelength,
)
};
// Check if pdf is zero, to avoid NaN's.
if (pdf > 0.0) && (filter.e.max_element() > 0.0) {
// Account for the additional light attenuation from
// this bounce
self.next_attenuation_fac = filter.e;
self.closure_sample_pdf = pdf;
// Calculate the ray for this bounce
let offset_pos = robust_ray_origin( let offset_pos = robust_ray_origin(
idata.pos, idata.pos,
idata.pos_err, idata.pos_err,
idata.nor_g.normalized(), idata.nor_g.normalized(),
dir, dir,
); );
let offset_end = robust_ray_origin( self.next_bounce_ray = Some(Ray::new(
sample_geo.0,
sample_geo.2,
sample_geo.1.normalized(),
-dir,
);
Ray::new(
offset_pos, offset_pos,
offset_end - offset_pos, dir,
ray.time, self.time,
ray.wavelength, self.wavelength,
1.0, std::f32::INFINITY,
true, false,
) ));
};
(light_attenuation, closure_pdf, shadow_ray)
}
};
// If there's any possible contribution, shoot a shadow true
// ray to see if we can reach it. } else {
if light_attenuation.e.max_element() > 0.0 { false
if let SurfaceIntersection::Occlude = tracer.trace(&mut shadow_ray) { }
// Calculate and store the light that will be contributed } else {
// to the film plane if the light is not in shadow. self.next_bounce_ray = None;
let light_mis_pdf = power_heuristic(light_pdf, closure_pdf); false
acc_color += light_info.color().e * light_attenuation.e * attenuation };
/ (light_mis_pdf * light_sel_pdf);
// Book keeping for next event
if found_light {
self.event = LightPathEvent::ShadowRay;
return true;
} else if do_bounce {
*ray = self.next_bounce_ray.unwrap();
self.event = LightPathEvent::BounceRay;
self.light_attenuation *= self.next_attenuation_fac;
return true;
} else {
return false;
} }
} else {
// Didn't hit anything, so background color
self.color += scene
.world
.background_color
.to_spectral_sample(self.wavelength)
.e
* self.light_attenuation
/ self.closure_sample_pdf;
return false;
} }
} }
//------------------------------------------------- //--------------------------------------------------------------------
// Prepare next bounce ray. // Result of shadow ray from sampling a light
LightPathEvent::ShadowRay => {
// If the light was not in shadow, add it's light to the film
// plane.
if let surface::SurfaceIntersection::Miss = *isect {
self.color += self.pending_color_addition;
}
// Sample closure // Set up for the next bounce, if any
let (dir, filter, pdf) = { if let Some(ref nbr) = self.next_bounce_ray {
sampling_seed = sampling_seed.wrapping_add(1); *ray = *nbr;
let (u, v, _, _) = get_sample_4d(sample_index, 0, sampling_seed); self.light_attenuation *= self.next_attenuation_fac;
self.event = LightPathEvent::BounceRay;
closure.sample( return true;
idata.incoming, } else {
idata.nor, return false;
idata.nor_g, }
(u, v),
ray.wavelength,
)
};
// Check if pdf is zero, to avoid NaN's.
if (pdf > 0.0) && (filter.e.max_element() > 0.0) {
// Account for the additional light attenuation from
// this bounce
attenuation *= filter.e;
ray_pdf = pdf;
// Calculate the ray for this bounce
let offset_pos =
robust_ray_origin(idata.pos, idata.pos_err, idata.nor_g.normalized(), dir);
ray = Ray::new(
offset_pos,
dir,
ray.time,
ray.wavelength,
std::f32::INFINITY,
false,
);
} else {
break;
} }
} }
} }
SpectralSample::from_parts(acc_color, ray.wavelength)
} }
// #[derive(Debug)]
// enum LightPathEvent {
// CameraRay,
// BounceRay,
// ShadowRay,
// }
// #[derive(Debug)]
// pub struct LightPath {
// event: LightPathEvent,
// bounce_count: u32,
// sampling_seed: u32,
// pixel_co: (u32, u32),
// sample_number: u32, // Which sample in the LDS sequence this is.
// dim_offset: u32,
// time: f32,
// wavelength: f32,
// next_bounce_ray: Option<Ray>,
// next_attenuation_fac: Float4,
// closure_sample_pdf: f32,
// light_attenuation: Float4,
// pending_color_addition: Float4,
// color: Float4,
// }
// #[allow(clippy::new_ret_no_self)]
// impl LightPath {
// fn new(
// scene: &Scene,
// sampling_seed: u32,
// pixel_co: (u32, u32),
// image_plane_co: (f32, f32),
// lens_uv: (f32, f32),
// time: f32,
// wavelength: f32,
// sample_number: u32,
// ) -> (LightPath, Ray) {
// (
// LightPath {
// event: LightPathEvent::CameraRay,
// bounce_count: 0,
// sampling_seed: sampling_seed ^ 0x40d4682b,
// pixel_co: pixel_co,
// sample_number: sample_number,
// dim_offset: 0,
// time: time,
// wavelength: wavelength,
// next_bounce_ray: None,
// next_attenuation_fac: Float4::splat(1.0),
// closure_sample_pdf: 1.0,
// light_attenuation: Float4::splat(1.0),
// pending_color_addition: Float4::splat(0.0),
// color: Float4::splat(0.0),
// },
// scene.camera.generate_ray(
// image_plane_co.0,
// image_plane_co.1,
// time,
// wavelength,
// lens_uv.0,
// lens_uv.1,
// ),
// )
// }
// fn next_lds_sequence(&mut self) {
// self.dim_offset = 0;
// self.sampling_seed += 1;
// }
// fn next_lds_samp(&mut self) -> (f32, f32, f32, f32) {
// let dimension = self.dim_offset;
// self.dim_offset += 1;
// get_sample_4d(self.sample_number, dimension, self.sampling_seed)
// }
// fn next(&mut self, scene: &Scene, isect: &surface::SurfaceIntersection, ray: &mut Ray) -> bool {
// match self.event {
// //--------------------------------------------------------------------
// // Result of Camera or bounce ray, prepare next bounce and light rays
// LightPathEvent::CameraRay | LightPathEvent::BounceRay => {
// if let surface::SurfaceIntersection::Hit {
// intersection_data: ref idata,
// ref closure,
// } = *isect
// {
// // Hit something! Do the stuff
// // If it's an emission closure, handle specially:
// // - Collect light from the emission.
// // - Terminate the path.
// use crate::shading::surface_closure::SurfaceClosure;
// if let SurfaceClosure::Emit(color) = *closure {
// let color = color.to_spectral_sample(self.wavelength).e;
// if let LightPathEvent::CameraRay = self.event {
// self.color += color;
// } else {
// let mis_pdf =
// power_heuristic(self.closure_sample_pdf, idata.sample_pdf);
// self.color += color * self.light_attenuation / mis_pdf;
// };
// return false;
// }
// // Roll the previous closure pdf into the attenauation
// self.light_attenuation /= self.closure_sample_pdf;
// // Prepare light ray
// self.next_lds_sequence();
// let (light_n, d2, d3, d4) = self.next_lds_samp();
// let light_uvw = (d2, d3, d4);
// let light_info = scene.sample_lights(
// light_n,
// light_uvw,
// self.wavelength,
// self.time,
// &XformFull::identity(),
// isect,
// );
// let found_light = if light_info.is_none()
// || light_info.pdf() <= 0.0
// || light_info.selection_pdf() <= 0.0
// {
// false
// } else {
// let light_pdf = light_info.pdf();
// let light_sel_pdf = light_info.selection_pdf();
// // Calculate the shadow ray and surface closure stuff
// let (attenuation, closure_pdf, shadow_ray) = match light_info {
// SceneLightSample::None => unreachable!(),
// // Distant light
// SceneLightSample::Distant { direction, .. } => {
// let (attenuation, closure_pdf) = closure.evaluate(
// ray.dir,
// direction,
// idata.nor,
// idata.nor_g,
// self.wavelength,
// );
// let shadow_ray = {
// // Calculate the shadow ray for testing if the light is
// // in shadow or not.
// let offset_pos = robust_ray_origin(
// idata.pos,
// idata.pos_err,
// idata.nor_g.normalized(),
// direction,
// );
// Ray::new(
// offset_pos,
// direction,
// self.time,
// self.wavelength,
// std::f32::INFINITY,
// true,
// )
// };
// (attenuation, closure_pdf, shadow_ray)
// }
// // Surface light
// SceneLightSample::Surface { sample_geo, .. } => {
// let dir = sample_geo.0 - idata.pos;
// let (attenuation, closure_pdf) = closure.evaluate(
// ray.dir,
// dir,
// idata.nor,
// idata.nor_g,
// self.wavelength,
// );
// let shadow_ray = {
// // Calculate the shadow ray for testing if the light is
// // in shadow or not.
// let offset_pos = robust_ray_origin(
// idata.pos,
// idata.pos_err,
// idata.nor_g.normalized(),
// dir,
// );
// let offset_end = robust_ray_origin(
// sample_geo.0,
// sample_geo.2,
// sample_geo.1.normalized(),
// -dir,
// );
// Ray::new(
// offset_pos,
// offset_end - offset_pos,
// self.time,
// self.wavelength,
// 1.0,
// true,
// )
// };
// (attenuation, closure_pdf, shadow_ray)
// }
// };
// // If there's any possible contribution, set up for a
// // light ray.
// if attenuation.e.max_element() <= 0.0 {
// false
// } else {
// // Calculate and store the light that will be contributed
// // to the film plane if the light is not in shadow.
// let light_mis_pdf = power_heuristic(light_pdf, closure_pdf);
// self.pending_color_addition =
// light_info.color().e * attenuation.e * self.light_attenuation
// / (light_mis_pdf * light_sel_pdf);
// *ray = shadow_ray;
// true
// }
// };
// // Prepare bounce ray
// let do_bounce = if self.bounce_count < 2 {
// self.bounce_count += 1;
// // Sample closure
// let (dir, filter, pdf) = {
// self.next_lds_sequence();
// let (u, v, _, _) = self.next_lds_samp();
// closure.sample(
// idata.incoming,
// idata.nor,
// idata.nor_g,
// (u, v),
// self.wavelength,
// )
// };
// // Check if pdf is zero, to avoid NaN's.
// if (pdf > 0.0) && (filter.e.max_element() > 0.0) {
// // Account for the additional light attenuation from
// // this bounce
// self.next_attenuation_fac = filter.e;
// self.closure_sample_pdf = pdf;
// // Calculate the ray for this bounce
// let offset_pos = robust_ray_origin(
// idata.pos,
// idata.pos_err,
// idata.nor_g.normalized(),
// dir,
// );
// self.next_bounce_ray = Some(Ray::new(
// offset_pos,
// dir,
// self.time,
// self.wavelength,
// std::f32::INFINITY,
// false,
// ));
// true
// } else {
// false
// }
// } else {
// self.next_bounce_ray = None;
// false
// };
// // Book keeping for next event
// if found_light {
// self.event = LightPathEvent::ShadowRay;
// return true;
// } else if do_bounce {
// *ray = self.next_bounce_ray.unwrap();
// self.event = LightPathEvent::BounceRay;
// self.light_attenuation *= self.next_attenuation_fac;
// return true;
// } else {
// return false;
// }
// } else {
// // Didn't hit anything, so background color
// self.color += scene
// .world
// .background_color
// .to_spectral_sample(self.wavelength)
// .e
// * self.light_attenuation
// / self.closure_sample_pdf;
// return false;
// }
// }
// //--------------------------------------------------------------------
// // Result of shadow ray from sampling a light
// LightPathEvent::ShadowRay => {
// // If the light was not in shadow, add it's light to the film
// // plane.
// if let surface::SurfaceIntersection::Miss = *isect {
// self.color += self.pending_color_addition;
// }
// // Set up for the next bounce, if any
// if let Some(ref nbr) = self.next_bounce_ray {
// *ray = *nbr;
// self.light_attenuation *= self.next_attenuation_fac;
// self.event = LightPathEvent::BounceRay;
// return true;
// } else {
// return false;
// }
// }
// }
// }
// }
/// Gets a sample, using LDS samples for lower dimensions, /// Gets a sample, using LDS samples for lower dimensions,
/// and switching to random samples at higher dimensions where /// and switching to random samples at higher dimensions where
/// LDS samples aren't available. /// LDS samples aren't available.

View File

@ -25,16 +25,13 @@ impl<'a> Tracer<'a> {
self.ray_trace_count self.ray_trace_count
} }
pub fn trace(&mut self, ray: &mut Ray) -> SurfaceIntersection { pub fn trace(&mut self, ray: &mut Ray, isect: &mut SurfaceIntersection) {
self.ray_trace_count += 1; self.ray_trace_count += 1;
let local_ray = ray.to_local(); let local_ray = ray.to_local();
let space = XformFull::identity(); let space = XformFull::identity();
let mut isect = SurfaceIntersection::Miss;
self.trace_assembly(self.root, ray, &local_ray, &space, &mut isect); self.trace_assembly(self.root, ray, &local_ray, &space, isect);
isect
} }
fn trace_assembly( fn trace_assembly(