embedded_3dgfx/draw/
effects.rs1use core::fmt::Debug;
4use embedded_graphics_core::pixelcolor::{Rgb565, RgbColor};
5
6#[derive(Debug, Clone, Copy)]
8pub struct FogConfig {
9 pub color: Rgb565,
11 pub near: u32,
13 pub far: u32,
15}
16
17impl FogConfig {
18 pub fn new(color: Rgb565, near: f32, far: f32) -> Self {
20 Self {
21 color,
22 near: (near * 65536.0) as u32,
23 far: (far * 65536.0) as u32,
24 }
25 }
26
27 #[inline]
29 pub fn apply(&self, base_color: Rgb565, depth: u32) -> Rgb565 {
30 let fog_factor = if depth <= self.near {
31 0u32
32 } else if depth >= self.far {
33 65536u32
34 } else {
35 let numerator = (depth - self.near) as u64;
36 let denominator = (self.far - self.near) as u64;
37 ((numerator * 65536) / denominator) as u32
38 };
39
40 let base_r = base_color.r() as u32;
41 let base_g = base_color.g() as u32;
42 let base_b = base_color.b() as u32;
43
44 let fog_r = self.color.r() as u32;
45 let fog_g = self.color.g() as u32;
46 let fog_b = self.color.b() as u32;
47
48 let r = ((base_r * (65536 - fog_factor) + fog_r * fog_factor) / 65536) as u8;
49 let g = ((base_g * (65536 - fog_factor) + fog_g * fog_factor) / 65536) as u8;
50 let b = ((base_b * (65536 - fog_factor) + fog_b * fog_factor) / 65536) as u8;
51
52 Rgb565::new(r, g, b)
53 }
54}
55
56#[derive(Debug, Clone, Copy)]
58pub struct DitherConfig {
59 pub intensity: u8,
61}
62
63impl DitherConfig {
64 const BAYER_MATRIX: [[u8; 4]; 4] =
66 [[0, 8, 2, 10], [12, 4, 14, 6], [3, 11, 1, 9], [15, 7, 13, 5]];
67
68 pub fn new(intensity: u8) -> Self {
70 Self { intensity }
71 }
72
73 #[inline]
75 pub fn apply(&self, color: Rgb565, x: i32, y: i32) -> Rgb565 {
76 if self.intensity == 0 {
77 return color;
78 }
79
80 let matrix_x = (x & 3) as usize;
81 let matrix_y = (y & 3) as usize;
82 let threshold = Self::BAYER_MATRIX[matrix_y][matrix_x];
83
84 let scaled_threshold = ((threshold as u16 * self.intensity as u16) / 15) as u8;
85
86 let r = color.r();
87 let g = color.g();
88 let b = color.b();
89
90 let r = if r > scaled_threshold {
91 r.saturating_sub(scaled_threshold / 2)
92 } else {
93 r.saturating_add(scaled_threshold / 2)
94 };
95
96 let g = if g > scaled_threshold {
97 g.saturating_sub(scaled_threshold / 2)
98 } else {
99 g.saturating_add(scaled_threshold / 2)
100 };
101
102 let b = if b > scaled_threshold {
103 b.saturating_sub(scaled_threshold / 2)
104 } else {
105 b.saturating_add(scaled_threshold / 2)
106 };
107
108 Rgb565::new(r, g, b)
109 }
110}