fere/graphics/gi/probe_volume/
calculation.rs1use 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 coeff[0][count] = 1.0;
36 coeff[1][count] = p[1];
38 coeff[2][count] = p[2];
39 coeff[3][count] = p[0];
40 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 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 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#[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 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 let iproj = Mat4::new_perspective(90.0_f32.to_radians(), 1.0, 0.5, 200.0);
211 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 }