color.rs (3604B)
1 use std::ops::{Add, AddAssign, Div, Mul}; 2 3 use crate::random::RandomNumberGenerator; 4 5 #[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)] 6 pub struct GammaColor { 7 red: f64, 8 green: f64, 9 blue: f64, 10 } 11 12 impl GammaColor { 13 pub const fn red(&self) -> f64 { 14 self.red 15 } 16 17 pub const fn green(&self) -> f64 { 18 self.green 19 } 20 21 pub const fn blue(&self) -> f64 { 22 self.blue 23 } 24 } 25 26 #[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)] 27 pub struct LinearColor { 28 red: f64, 29 green: f64, 30 blue: f64, 31 } 32 33 impl LinearColor { 34 const MIN: f64 = 0.; 35 const MAX: f64 = 1.; 36 37 pub const fn new(red: f64, green: f64, blue: f64) -> Self { 38 LinearColor { 39 red: red.clamp(LinearColor::MIN, LinearColor::MAX), 40 green: green.clamp(LinearColor::MIN, LinearColor::MAX), 41 blue: blue.clamp(LinearColor::MIN, LinearColor::MAX), 42 } 43 } 44 45 pub fn as_gamma(&self) -> GammaColor { 46 GammaColor { 47 red: if self.red > 0. { self.red.sqrt() } else { 0. }, 48 green: if self.green > 0. { 49 self.green.sqrt() 50 } else { 51 0. 52 }, 53 blue: if self.blue > 0. { self.blue.sqrt() } else { 0. }, 54 } 55 } 56 57 pub const fn red(&self) -> f64 { 58 self.red 59 } 60 61 pub const fn green(&self) -> f64 { 62 self.green 63 } 64 65 pub const fn blue(&self) -> f64 { 66 self.blue 67 } 68 69 pub fn random(rng: &mut RandomNumberGenerator) -> Self { 70 LinearColor::new(rng.next_f64(), rng.next_f64(), rng.next_f64()) 71 } 72 73 pub fn random_in_range(min: f64, max: f64, rng: &mut RandomNumberGenerator) -> Self { 74 LinearColor { 75 red: rng.next_f64_in_range(min, max), 76 green: rng.next_f64_in_range(min, max), 77 blue: rng.next_f64_in_range(min, max), 78 } 79 } 80 } 81 82 impl Add<LinearColor> for LinearColor { 83 type Output = LinearColor; 84 85 fn add(self, rhs: LinearColor) -> Self::Output { 86 LinearColor { 87 red: (self.red + rhs.red).clamp(LinearColor::MIN, LinearColor::MAX), 88 green: (self.green + rhs.green).clamp(LinearColor::MIN, LinearColor::MAX), 89 blue: (self.blue + rhs.blue).clamp(LinearColor::MIN, LinearColor::MAX), 90 } 91 } 92 } 93 94 impl AddAssign<LinearColor> for LinearColor { 95 fn add_assign(&mut self, rhs: LinearColor) { 96 self.red += rhs.red; 97 self.green += rhs.green; 98 self.blue += rhs.blue; 99 } 100 } 101 102 impl Mul<f64> for LinearColor { 103 type Output = LinearColor; 104 105 fn mul(self, rhs: f64) -> Self::Output { 106 LinearColor { 107 red: (self.red * rhs).clamp(LinearColor::MIN, LinearColor::MAX), 108 green: (self.green * rhs).clamp(LinearColor::MIN, LinearColor::MAX), 109 blue: (self.blue * rhs).clamp(LinearColor::MIN, LinearColor::MAX), 110 } 111 } 112 } 113 114 impl Mul<LinearColor> for f64 { 115 type Output = LinearColor; 116 117 fn mul(self, rhs: LinearColor) -> Self::Output { 118 rhs * self 119 } 120 } 121 122 impl Mul<LinearColor> for LinearColor { 123 type Output = LinearColor; 124 125 fn mul(self, rhs: LinearColor) -> Self::Output { 126 LinearColor { 127 red: (self.red * rhs.red).clamp(LinearColor::MIN, LinearColor::MAX), 128 green: (self.green * rhs.green).clamp(LinearColor::MIN, LinearColor::MAX), 129 blue: (self.blue * rhs.blue).clamp(LinearColor::MIN, LinearColor::MAX), 130 } 131 } 132 } 133 134 impl Div<f64> for LinearColor { 135 type Output = LinearColor; 136 137 fn div(self, rhs: f64) -> Self::Output { 138 self * (1. / rhs) 139 } 140 }