opendefocus_shared/
internal_settings.rs1use crate::math::{ceilf, get_points_for_ring};
2
3use bitflags::bitflags;
4use bytemuck::{Pod, Zeroable};
5use core::f32::consts::PI;
6use glam::{IVec4, UVec2, Vec2};
7const LARGEST_WEIGHT: f32 = 1.0 / (PI * 0.5);
8
9bitflags! {
10 #[derive(Debug, Clone, Copy, Zeroable, Pod, PartialEq)]
12 #[repr(C)]
13 pub struct GlobalFlags: u32 {
14 const IS_2D = 0b00000001;
16 const SIMPLE_DISC = 0b00000010;
18 const HIGH_RESOLUTION_INTERPOLATION = 0b00000100;
20 const USE_NON_UNIFORM = 0b00001000;
22 const INVERSE_FOREGROUND_BOKEH_SHAPE = 0b00010000;
24 const AXIAL_ABERRATION_ENABLE = 0b00100000;
26 const INVERSE_Y = 0b01000000;
28
29 }
30
31 #[derive(Debug, Clone, Copy, Zeroable, Pod, PartialEq)]
33 #[repr(C)]
34 pub struct NonUniformFlags: u32 {
35 const CATSEYE_ENABLED = 0b00000001;
37 const CATSEYE_INVERSE = 0b00000010;
39 const CATSEYE_INVERSE_FOREGROUND = 0b00000100;
41 const CATSEYE_SCREEN_RELATIVE = 0b00001000;
43 const ASTIGMATISM_ENABLED = 0b00010000;
45 const BARNDOORS_ENABLED = 0b00100000;
47 const BARNDOORS_INVERSE = 0b01000000;
49 const BARNDOORS_INVERSE_FOREGROUND = 0b10000000;
51 }
52
53}
54
55pub struct AxialAberration {
58 pub enable: bool,
60 pub amount: f32,
62 pub color_type: AxialAberrationType,
64}
65
66#[repr(u32)]
67pub enum AxialAberrationType {
68 RedBlue = 1,
70 BlueYellow = 2,
72 GreenPurple = 3,
74}
75
76#[derive(Copy, Clone, Debug, Pod, Zeroable)]
78#[repr(C, align(16))]
79pub struct ConvolveSettings {
80 pub process_region: IVec4,
82 pub full_region: IVec4,
84 pub resolution: UVec2,
86 pub filter_resolution: UVec2,
88 pub center: Vec2,
90 pub flags: u32,
92 pub non_uniform_flags: u32,
94 pub samples: u32,
96 pub pixel_aspect: f32,
98 pub size: f32,
100 pub max_size: f32,
102 pub catseye_amount: f32,
104 pub catseye_gamma: f32,
106 pub catseye_softness: f32,
108 pub astigmatism_amount: f32,
110 pub astigmatism_gamma: f32,
112 pub barndoors_amount: f32,
114 pub barndoors_gamma: f32,
116 pub barndoors_top: f32,
118 pub barndoors_bottom: f32,
120 pub barndoors_left: f32,
122 pub barndoors_right: f32,
124 pub filter_aspect_ratio_normalizer: f32,
126 pub image_elements: u32,
128 pub ring_distance: f32,
130 pub filter_aspect_ratio: f32,
132 pub pixel_aspect_normalizer: f32,
134 pub render_scale: u32,
136 pub axial_aberration_amount: f32,
138 pub axial_aberration_type: i32,
139
140 pub _padding: u32,
141}
142impl ConvolveSettings {
143 pub fn compute_sample_weight(&self, coc: f32) -> f32 {
144 let mut total_points = 1;
145 let mut ring_id = 0;
146 let mut remaining_coc = coc;
147
148 while remaining_coc > 0.0 {
149 total_points += get_points_for_ring(ring_id, self.samples, true);
150 remaining_coc -= self.ring_distance;
151 ring_id += 1;
152 }
153 (1.0 / (total_points as f32)).min(LARGEST_WEIGHT)
154 }
155
156 pub fn get_sample_weights(&self) -> [f32; 2048] {
157 let mut weights = [0.0; 2048];
158 for coc in 0..ceilf(self.max_size) as i32 + 1 {
159 weights[coc as usize] = self.compute_sample_weight(coc as f32)
160 }
161 weights
162 }
163
164 pub fn get_image_resolution(&self) -> UVec2 {
165 UVec2::new(
166 (self.full_region.z - self.full_region.x) as u32,
167 (self.full_region.w - self.full_region.y) as u32,
168 )
169 }
170
171 pub fn get_real_coordinates(&self, coordinates: UVec2) -> UVec2 {
173 UVec2::new(
174 (self.full_region.x as u32) + coordinates.x,
175 (self.full_region.y as u32) + coordinates.y,
176 )
177 }
178
179 pub fn get_axial_aberration_settings(&self) -> AxialAberration {
180 AxialAberration {
181 enable: NonUniformFlags::from_bits_retain(self.non_uniform_flags)
182 .contains(NonUniformFlags::BARNDOORS_ENABLED),
183 amount: self.axial_aberration_amount,
184 color_type: match self.axial_aberration_type {
185 1 => AxialAberrationType::RedBlue,
186 2 => AxialAberrationType::BlueYellow,
187 3 => AxialAberrationType::GreenPurple,
188 _ => AxialAberrationType::RedBlue,
189 },
190 }
191 }
192}
193
194#[cfg(test)]
195mod tests {
196 use super::*;
197
198 #[test]
200 fn test_struct_size() {
201 assert_eq!(core::mem::size_of::<ConvolveSettings>(), 160)
202 }
203}