diff --git a/assignment-1d/.gitignore b/assignment-1d/.gitignore index 38a241f..59b392f 100644 --- a/assignment-1d/.gitignore +++ b/assignment-1d/.gitignore @@ -8,3 +8,4 @@ perf.data* flamegraph.svg showcase.png +/out.log diff --git a/assignment-1d/src/scene/illumination.rs b/assignment-1d/src/scene/illumination.rs index fc8bfcf..7972b68 100644 --- a/assignment-1d/src/scene/illumination.rs +++ b/assignment-1d/src/scene/illumination.rs @@ -18,9 +18,14 @@ use super::{ // TODO: Is this a good constant? const JITTER_CONST: f64 = 0.05; - const ZERO_COLOR: Color = Color::new(0.0, 0.0, 0.0); +// Soft shadows: jitter some rays here to somewhere close to the +// actual location as well, and measure the proportion +// of them that intersect any objects +const SOFT_SHADOW_JITTER_RADIUS: f64 = 1.0; +const JITTER_RAYS: usize = 75; + impl Scene { /// Determine the color that should be used to fill this pixel. /// @@ -218,6 +223,12 @@ impl Scene { .enumerate() .filter(|(i, _)| *i != obj_idx); + #[derive(Clone, Copy)] + struct ShadowResult { + transparent_coefficient: f64, + opacity: f64, + } + // Get the list of intersections with all the other objects in the scene // This list will be a set of opacities let intersections = other_objects @@ -243,7 +254,13 @@ impl Scene { } else { let soft_shadow_coefficient = self.compute_soft_shadow_coefficient(location, point, object); - Some(soft_shadow_coefficient) + + let material = &self.materials[object.material_idx]; + + Some(ShadowResult { + transparent_coefficient: 1.0 - material.alpha, + opacity: soft_shadow_coefficient, + }) } } @@ -253,7 +270,10 @@ impl Scene { if intersection_time <= 0.0 { None } else { - Some(0.0) // complete obstruction + Some(ShadowResult { + transparent_coefficient: 1.0, + opacity: 0.0, + }) // complete obstruction } } } @@ -263,9 +283,15 @@ impl Scene { match intersections.is_empty() { true => 1.0, false => { - let average = intersections.iter().cloned().sum::() + let average = intersections.iter().map(|s| s.opacity).sum::() / intersections.len() as f64; - average + + let transparency = intersections + .iter() + .map(|s| s.transparent_coefficient) + .product::(); + + average * transparency } } } @@ -276,22 +302,17 @@ impl Scene { original_intersection_point: Point, object: &Object, ) -> f64 { - // Soft shadows: jitter some rays here to somewhere close to the - // actual location as well, and measure the proportion - // of them that intersect any objects - const JITTER_RADIUS: f64 = 1.0; - const JITTER_RAYS: usize = 75; - let mut rng = rand::thread_rng(); let locations = iter::repeat_with(|| { - let x = rng.gen_range(0.0..JITTER_RADIUS); - let y = rng.gen_range(0.0..JITTER_RADIUS); - let z = rng.gen_range(0.0..JITTER_RADIUS); + let x = rng.gen_range(0.0..SOFT_SHADOW_JITTER_RADIUS); + let y = rng.gen_range(0.0..SOFT_SHADOW_JITTER_RADIUS); + let z = rng.gen_range(0.0..SOFT_SHADOW_JITTER_RADIUS); let delta = Vector::new(x, y, z); light_location + delta }) .take(JITTER_RAYS) .collect::>(); + let num_obstructed_rays = locations .into_par_iter() .filter(|location| { @@ -431,14 +452,14 @@ impl Scene { let t_lambda = self.trace_single_ray(ray, depth + 1)?; let value = (1.0 - fresnel_coefficient) * (1.0 - material.alpha) * t_lambda; - debug!( + /* debug!( depth, fresnel_coefficient, alpha = material.alpha, ?t_lambda, ?value, "computing final value" - ); + ); */ Ok(value) } diff --git a/assignment-1d/src/scene/sphere.rs b/assignment-1d/src/scene/sphere.rs index 7805e8f..e828840 100644 --- a/assignment-1d/src/scene/sphere.rs +++ b/assignment-1d/src/scene/sphere.rs @@ -81,7 +81,7 @@ impl Sphere { let dy = ray.origin.y - self.center.y; let dz = ray.origin.z - self.center.z; - dx.powi(2) + dy.powi(2) + dz.powi(2) < self.radius.powi(2) + dx.powi(2) + dy.powi(2) + dz.powi(2) <= self.radius.powi(2) }; /* let normal = match exiting {