From 0d189f763db2dc8c5c4a69cef6dd17e967c16cdf Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Sun, 21 Aug 2016 15:27:15 -0700 Subject: [PATCH] Changed LightTree traversal to be a bit better in its choices. After some experimentation, it's pretty clear that the LightTree performs a lot better with a model of spherical _volume_ light sources. This makes sense considering that generally they represent a distribution of other lights in space. This is a quick hack to make it behave a bit more like that. But the long-term solution will be to adjust how estimate_eval_over_solid_angle() of surface closures is implemented. --- src/light_accel/light_tree.rs | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/light_accel/light_tree.rs b/src/light_accel/light_tree.rs index 97dd2c1..8d864dd 100644 --- a/src/light_accel/light_tree.rs +++ b/src/light_accel/light_tree.rs @@ -141,19 +141,30 @@ impl LightAccel for LightTree { let d = bbox.center() - pos; let dist2 = d.length2(); let r = bbox.diagonal() * 0.5; - let r2 = r * r; - let inv_surface_area = 1.0 / r2; - - let cos_theta_max = if dist2 <= r2 { - -1.0 - } else { - let sin_theta_max2 = (r2 / dist2).min(1.0); - (1.0 - sin_theta_max2).sqrt() - }; + let inv_surface_area = 1.0 / (r * r); // Get the approximate amount of light contribution from the // composite light source. - let approx_contrib = sc.estimate_eval_over_solid_angle(inc, d, nor, cos_theta_max); + let approx_contrib = { + let mut approx_contrib = 0.0; + let steps = 2; + let fstep = 1.0 / (steps as f32); + for i in 0..steps { + let r2 = { + let step = fstep * (i + 1) as f32; + let r = r * step; + r * r + }; + let cos_theta_max = if dist2 <= r2 { + -1.0 + } else { + let sin_theta_max2 = (r2 / dist2).min(1.0); + (1.0 - sin_theta_max2).sqrt() + }; + approx_contrib += sc.estimate_eval_over_solid_angle(inc, d, nor, cos_theta_max); + } + approx_contrib * fstep + }; node_ref.energy * inv_surface_area * approx_contrib };