Finished light tree arity configurability.
Turns out going higher arity makes a huge positive difference is sampling quality. Currently have 32-arity set as the default, as it seems to be worth it for the better sampling.
This commit is contained in:
parent
47c2bf4ed9
commit
e48bff3011
|
@ -9,8 +9,8 @@ use shading::surface_closure::SurfaceClosure;
|
||||||
use super::LightAccel;
|
use super::LightAccel;
|
||||||
use super::objects_split::sah_split;
|
use super::objects_split::sah_split;
|
||||||
|
|
||||||
const LEVEL_COLLAPSE: usize = 1; // Number of levels of the binary tree to
|
const LEVEL_COLLAPSE: usize = 5; // Number of levels of the binary tree to
|
||||||
// collapse together (1 = no collapsing)
|
// collapse together (1 = no collapsing, leave as binary tree)
|
||||||
const ARITY: usize = 1 << LEVEL_COLLAPSE; // Arity of the final tree
|
const ARITY: usize = 1 << LEVEL_COLLAPSE; // Arity of the final tree
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,24 +152,14 @@ impl<'a> LightAccel for LightTree<'a> {
|
||||||
// Get the approximate amount of light contribution from the
|
// Get the approximate amount of light contribution from the
|
||||||
// composite light source.
|
// composite light source.
|
||||||
let approx_contrib = {
|
let approx_contrib = {
|
||||||
let mut approx_contrib = 0.0;
|
let r2 = r * r;
|
||||||
let steps = 2;
|
let cos_theta_max = if dist2 <= r2 {
|
||||||
let fstep = 1.0 / (steps as f32);
|
-1.0
|
||||||
for i in 0..steps {
|
} else {
|
||||||
let r2 = {
|
let sin_theta_max2 = (r2 / dist2).min(1.0);
|
||||||
let step = fstep * (i + 1) as f32;
|
(1.0 - sin_theta_max2).sqrt()
|
||||||
let r = r * step;
|
};
|
||||||
r * r
|
sc.estimate_eval_over_solid_angle(inc, d, nor, cos_theta_max)
|
||||||
};
|
|
||||||
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
|
node_ref.energy() * inv_surface_area * approx_contrib
|
||||||
|
@ -192,11 +182,11 @@ impl<'a> LightAccel for LightTree<'a> {
|
||||||
}
|
}
|
||||||
if total <= 0.0 {
|
if total <= 0.0 {
|
||||||
let p = 1.0 / children.len() as f32;
|
let p = 1.0 / children.len() as f32;
|
||||||
for prob in &mut ps {
|
for prob in &mut ps[..] {
|
||||||
*prob = p;
|
*prob = p;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for prob in &mut ps {
|
for prob in &mut ps[..] {
|
||||||
*prob = *prob / total;
|
*prob = *prob / total;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,7 +254,7 @@ impl LightTreeBuilder {
|
||||||
// Returns the number of children of this node, assuming a collapse
|
// Returns the number of children of this node, assuming a collapse
|
||||||
// number of `LEVEL_COLLAPSE`.
|
// number of `LEVEL_COLLAPSE`.
|
||||||
pub fn node_child_count(&self, node_index: usize) -> usize {
|
pub fn node_child_count(&self, node_index: usize) -> usize {
|
||||||
self.node_child_count_recurse(LEVEL_COLLAPSE, node_index).0
|
self.node_child_count_recurse(LEVEL_COLLAPSE, node_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the index of the nth child, assuming a collapse
|
// Returns the index of the nth child, assuming a collapse
|
||||||
|
@ -276,12 +266,21 @@ impl LightTreeBuilder {
|
||||||
|
|
||||||
// Returns the number of children of this node, assuming a collapse
|
// Returns the number of children of this node, assuming a collapse
|
||||||
// number of `level_collapse`.
|
// number of `level_collapse`.
|
||||||
pub fn node_child_count_recurse(
|
pub fn node_child_count_recurse(&self, level_collapse: usize, node_index: usize) -> usize {
|
||||||
&self,
|
if level_collapse > 0 {
|
||||||
level_collapse: usize,
|
if self.nodes[node_index].is_leaf {
|
||||||
node_index: usize,
|
return 1;
|
||||||
) -> (usize, usize) {
|
} else {
|
||||||
(2, 0)
|
let a = self.node_child_count_recurse(level_collapse - 1, node_index + 1);
|
||||||
|
let b = self.node_child_count_recurse(
|
||||||
|
level_collapse - 1,
|
||||||
|
self.nodes[node_index].child_index,
|
||||||
|
);
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the index of the nth child, assuming a collapse
|
// Returns the index of the nth child, assuming a collapse
|
||||||
|
@ -292,10 +291,19 @@ impl LightTreeBuilder {
|
||||||
node_index: usize,
|
node_index: usize,
|
||||||
child_n: usize,
|
child_n: usize,
|
||||||
) -> (usize, usize) {
|
) -> (usize, usize) {
|
||||||
match child_n {
|
if level_collapse > 0 && !self.nodes[node_index].is_leaf {
|
||||||
0 => (node_index + 1, 0),
|
let (index, rem) =
|
||||||
1 => (self.nodes[node_index].child_index, 0),
|
self.node_nth_child_index_recurse(level_collapse - 1, node_index + 1, child_n);
|
||||||
_ => unreachable!(),
|
if rem == 0 {
|
||||||
|
return (index, 0);
|
||||||
|
}
|
||||||
|
return self.node_nth_child_index_recurse(
|
||||||
|
level_collapse - 1,
|
||||||
|
self.nodes[node_index].child_index,
|
||||||
|
rem - 1,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (node_index, child_n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user