concinnity_core/gfx/
ssao.rs1use crate::gfx::camera::view_ray_scale;
8
9use crate::gfx::render_types::SsaoParams;
10
11const MAX_INTENSITY: f32 = 4.0;
14
15const MIN_RADIUS: f32 = 1.0e-3;
18
19#[derive(Debug, Clone, Copy, PartialEq)]
22pub struct SsaoSettings {
23 pub radius: f32,
25 pub intensity: f32,
27}
28
29impl SsaoSettings {
30 pub fn resolve(radius: f32, intensity: f32) -> Self {
32 Self {
33 radius: radius.max(MIN_RADIUS),
34 intensity: intensity.clamp(0.0, MAX_INTENSITY),
35 }
36 }
37
38 pub fn params(&self, fov_y_radians: f32, aspect: f32) -> SsaoParams {
43 let (tan_half_fov_y, aspect) = view_ray_scale(fov_y_radians, aspect);
44 SsaoParams {
45 radius: self.radius,
46 intensity: self.intensity,
47 tan_half_fov_y,
48 aspect,
49 }
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn resolve_floors_radius_and_clamps_intensity() {
59 let s = SsaoSettings::resolve(-1.0, 100.0);
60 assert!(s.radius >= MIN_RADIUS);
61 assert_eq!(s.intensity, MAX_INTENSITY);
62
63 let s = SsaoSettings::resolve(0.75, -2.0);
64 assert_eq!(s.radius, 0.75);
65 assert_eq!(s.intensity, 0.0);
66 }
67
68 #[test]
69 fn resolve_passes_through_in_range_values() {
70 let s = SsaoSettings::resolve(0.5, 1.0);
71 assert_eq!(s.radius, 0.5);
72 assert_eq!(s.intensity, 1.0);
73 }
74
75 #[test]
76 fn params_compute_tan_half_fov() {
77 let s = SsaoSettings::resolve(0.5, 1.0);
78 let p = s.params(core::f32::consts::FRAC_PI_2, 1.6);
80 assert!((p.tan_half_fov_y - 1.0).abs() < 1.0e-5);
81 assert_eq!(p.aspect, 1.6);
82 assert_eq!(p.radius, 0.5);
83 assert_eq!(p.intensity, 1.0);
84 }
85
86 #[test]
87 fn params_floor_a_degenerate_aspect() {
88 let s = SsaoSettings::resolve(0.5, 1.0);
89 let p = s.params(core::f32::consts::FRAC_PI_2, 0.0);
90 assert!(p.aspect >= MIN_RADIUS);
91 }
92}