libredr/light_source/
functional.rs1use nalgebra as na;
2use ndarray::{Axis, Array4};
3use anyhow::{Result, ensure};
4
5pub fn functional_envmap<F>(resolution: usize, mut f: F) -> Result<Array4<f32>>
12 where F: FnMut(na::Vector3<f32>) -> na::Vector3<f32> {
13 let mut envmap = Array4::zeros((3, 6, resolution, resolution));
14 for (face_id, mut envmap) in envmap.axis_iter_mut(Axis(1)).enumerate() {
15 for (i_row, mut envmap) in envmap.axis_iter_mut(Axis(1)).enumerate() {
16 for (i_col, mut envmap) in envmap.axis_iter_mut(Axis(1)).enumerate() {
17 let i_row = ((resolution - 1 - i_row) as f32 + 0.5) / resolution as f32 * 2. - 1.;
18 let i_col = (i_col as f32 + 0.5) / resolution as f32 * 2. - 1.;
19 let mut axis_xyz = na::Vector3::zeros();
20 axis_xyz[face_id / 2] = if face_id % 2 == 0 { 1. } else { -1. };
21 match face_id / 2 {
22 0 => (axis_xyz[2], axis_xyz[1]) = (i_row, i_col),
23 1 => (axis_xyz[2], axis_xyz[0]) = (i_row, i_col),
24 2 => (axis_xyz[1], axis_xyz[0]) = (i_row, i_col),
25 _ => unreachable!(),
26 }
27 let intensity = f(axis_xyz.normalize());
28 for (intensity, envmap) in intensity.into_iter().zip(envmap.iter_mut()) {
29 ensure!(*intensity >= 0.,
30 "light_source::functional_envmap: negative `intensity` at {face_id} {i_row} {i_col}");
31 ensure!(intensity.is_finite(),
32 "light_source::functional_envmap: infinite nor NaN `intensity` at {face_id} {i_row} {i_col}");
33 *envmap = *intensity;
34 }
35 }
36 }
37 }
38 Ok(envmap)
39}