fere/graphics/gi/probe_volume/
calculation.rs

1use super::{Probe, ProbeVolume};
2use fere_common::{
3    geo::{six_sides, SixDir},
4    vec::GridAccessor3,
5    *,
6};
7
8pub fn calculate_sh_cache(fb_size: usize, param: usize) -> [Vec<Vec<f32>>; 6] {
9    let mut result: [Vec<Vec<f32>>; 6] = Default::default();
10    for i in 0..6 {
11        result[i].resize(param, Default::default());
12        for v in result[i].iter_mut() {
13            v.resize(fb_size * fb_size, 0.0);
14        }
15        let coeff = &mut result[i];
16        let mut count = 0;
17
18        for x in 0..fb_size {
19            for y in 0..fb_size {
20                let q = Vec4::new(
21                    x as f32 + 0.5 - fb_size as f32 / 2.0,
22                    y as f32 + 0.5 - fb_size as f32 / 2.0,
23                    -(fb_size as f32) / 2.0,
24                    1.0,
25                );
26                let p = normalize(&(six_sides(i as SixDir) * q).xyz());
27                let mut table = Mat3::from_element(0.0);
28                for m in 0..3 {
29                    for n in 0..3 {
30                        *table.get_mut((m, n)).unwrap() = p[m] * p[n];
31                    }
32                }
33
34                // l = 0
35                coeff[0][count] = 1.0;
36                // l = 1
37                coeff[1][count] = p[1];
38                coeff[2][count] = p[2];
39                coeff[3][count] = p[0];
40                // l = 2
41                coeff[4][count] = table[(0, 1)];
42                coeff[5][count] = table[(1, 2)];
43                coeff[6][count] = 3.0 * table[(2, 2)] - 1.0;
44                coeff[7][count] = table[(0, 2)];
45                coeff[8][count] = table[(0, 0)] - table[(1, 1)];
46                // l = 4
47                coeff[9][count] = table[(0, 1)] * (table[(0, 0)] - table[(1, 1)]);
48                coeff[10][count] = table[(1, 2)] * (3.0 * table[(0, 0)] - table[(1, 1)]);
49                coeff[11][count] = table[(0, 1)] * (7.0 * table[(2, 2)] - 1.0);
50                coeff[12][count] = table[(1, 2)] * (7.0 * table[(2, 2)] - 3.0);
51                coeff[13][count] = table[(2, 2)] * (35.0 * table[(2, 2)] - 30.0) + 3.0;
52                coeff[14][count] = table[(0, 2)] * (7.0 * table[(2, 2)] - 3.0);
53                coeff[15][count] = (table[(0, 0)] - table[(1, 1)]) * (7.0 * table[(2, 2)] - 1.0);
54                coeff[16][count] = table[(0, 2)] * (table[(0, 0)] - 3.0 * table[(1, 1)]);
55                coeff[17][count] = table[(0, 0)] * (table[(0, 0)] - 3.0 * table[(1, 1)])
56                    - table[(1, 1)] * (3.0 * table[(0, 0)] - table[(1, 1)]);
57                /*
58                for h in 1..18 {
59                    coeff[h][count] = 0.0;
60                }*/
61
62                count += 1;
63            }
64        }
65    }
66    result
67}
68
69trait Accessor {
70    fn acc(x: &mut (Vec3, Vec3, f32), dim: usize) -> &mut f32;
71}
72
73struct AccDiffuse;
74impl Accessor for AccDiffuse {
75    fn acc(x: &mut (Vec3, Vec3, f32), dim: usize) -> &mut f32 {
76        &mut x.0[dim]
77    }
78}
79struct AccIllum;
80impl Accessor for AccIllum {
81    fn acc(x: &mut (Vec3, Vec3, f32), dim: usize) -> &mut f32 {
82        &mut x.1[dim]
83    }
84}
85struct AccDepth;
86impl Accessor for AccDepth {
87    fn acc(x: &mut (Vec3, Vec3, f32), _dim: usize) -> &mut f32 {
88        &mut x.2
89    }
90}
91
92/// TODO: replace various subscribtion [] to unchecked get
93/// TODO: Parallel execution
94#[allow(clippy::approx_constant)]
95fn update_sub<T: Accessor>(
96    probe: &mut Probe,
97    dc: &[f32; 4],
98    max_depth: f32,
99    param: usize,
100    sh_cache: &[Vec<Vec<f32>>; 6],
101    size: usize,
102    dim: usize,
103    buffer: &[*const f32],
104) {
105    for i in 0..6 {
106        let mut count = 0;
107        let coeff = &sh_cache[i];
108
109        if dim == 1 {
110            for x in 0..size {
111                for _ in 0..size {
112                    for d in 0..dim {
113                        let mut value = unsafe { *buffer[i].add(count + d) };
114                        // TODO: calculate this in shader?
115                        value = -(dc[3] * value - dc[1]) / (dc[0] - dc[2] * value + 0.001);
116                        value *= x as f32 / size as f32;
117                        value = max_depth.min(value);
118                        value /= max_depth;
119
120                        let sh = &mut probe.sh;
121                        for c in 0..param {
122                            *T::acc(&mut sh[c], d) += value * coeff[c][count / dim];
123                        }
124                    }
125                    count += dim;
126                }
127            }
128        } else {
129            for _ in 0..size {
130                for _ in 0..size {
131                    for d in 0..dim {
132                        let value = unsafe { *buffer[i].add(count + d) };
133                        let sh = &mut probe.sh;
134                        for c in 0..param {
135                            *T::acc(&mut sh[c], d) += value * coeff[c][count / dim];
136                        }
137                    }
138                    count += dim;
139                }
140            }
141        }
142    }
143
144    let k = (size * size * 6) as f64 / (2.0 * std::f64::consts::PI.powi(2)) * 20.0;
145    let k = k as f32;
146    for d in 0..dim {
147        let sh = &mut probe.sh;
148        let mut c;
149        let mut a;
150
151        a = 3.141593;
152        c = 0.282095;
153        *T::acc(&mut sh[0], d) *= c * a / k;
154
155        a = 2.094395;
156        c = 0.488603;
157        *T::acc(&mut sh[1], d) *= c * a / k;
158        *T::acc(&mut sh[2], d) *= c * a / k;
159        *T::acc(&mut sh[3], d) *= c * a / k;
160
161        a = 0.785298;
162        c = 1.092548;
163        *T::acc(&mut sh[4], d) *= c * a / k;
164        *T::acc(&mut sh[5], d) *= c * a / k;
165        c = 0.315392;
166        *T::acc(&mut sh[6], d) *= c * a / k;
167        c = 1.092548;
168        *T::acc(&mut sh[7], d) *= c * a / k;
169        c = 0.546274;
170        *T::acc(&mut sh[8], d) *= c * a / k;
171
172        a = -0.130900;
173        c = 2.503342;
174        *T::acc(&mut sh[9], d) *= c * a / k;
175        c = 1.77013;
176        *T::acc(&mut sh[10], d) *= c * a / k;
177        c = 0.946174;
178        *T::acc(&mut sh[11], d) *= c * a / k;
179        c = 0.669046;
180        *T::acc(&mut sh[12], d) *= c * a / k;
181        c = 0.105785;
182        *T::acc(&mut sh[13], d) *= c * a / k;
183        c = 0.669046;
184        *T::acc(&mut sh[14], d) *= c * a / k;
185        c = 0.473087;
186        *T::acc(&mut sh[15], d) *= c * a / k;
187        c = 1.77013;
188        *T::acc(&mut sh[16], d) *= c * a / k;
189        c = 0.625835;
190        *T::acc(&mut sh[17], d) *= c * a / k;
191    }
192}
193
194pub fn update_probe(
195    volume: &mut ProbeVolume,
196    index: IVec3,
197    size: usize,
198    cube_diffuse: &[Vec<Vec3>; 6],
199    cube_illumination: &[Vec<Vec3>; 6],
200    cube_depth: &[Vec<f32>; 6],
201) {
202    let ga = GridAccessor3(volume.number);
203    let probe = &mut volume.probes[ga.get(&index)];
204
205    for p in 0..volume.param {
206        probe.sh[p] = (Vec3::from_element(0.0), Vec3::from_element(0.0), 0.0);
207    }
208
209    // TODO: sync this
210    let iproj = Mat4::new_perspective(90.0_f32.to_radians(), 1.0, 0.5, 200.0);
211    //for simplicity, we assume x = 0 and y = 0 for the original coord (afterh view trans)
212    let dc = [iproj[(2, 2)], iproj[(3, 2)], iproj[(2, 3)], iproj[(3, 3)]];
213
214    let max_depth = 100.0;
215
216    let mut cube_diffuse_unwrap: Vec<*const f32> = Vec::new();
217    let mut cube_illumination_unwrap: Vec<*const f32> = Vec::new();
218    let mut cube_depth_unwrap: Vec<*const f32> = Vec::new();
219
220    for i in 0..6 {
221        cube_diffuse_unwrap.push(cube_diffuse[i][0].as_ptr());
222        cube_illumination_unwrap.push(cube_illumination[i][0].as_ptr());
223        cube_depth_unwrap.push(cube_depth[i].as_ptr());
224    }
225
226    update_sub::<AccDiffuse>(
227        probe,
228        &dc,
229        max_depth,
230        volume.param,
231        &volume.sh_cache,
232        size,
233        3,
234        &cube_diffuse_unwrap,
235    );
236    update_sub::<AccIllum>(
237        probe,
238        &dc,
239        max_depth,
240        volume.param,
241        &volume.sh_cache,
242        size,
243        3,
244        &cube_illumination_unwrap,
245    );
246    update_sub::<AccDepth>(
247        probe,
248        &dc,
249        max_depth,
250        volume.param,
251        &volume.sh_cache,
252        size,
253        1,
254        &cube_depth_unwrap,
255    );
256
257    let _q: Vec<f32> = probe.sh.iter().map(|x| x.0.x).collect();
258    //println!("{:?}", q);
259}