summaryrefslogtreecommitdiff
path: root/src/common.rs
blob: 92b820336cf764f79ba59a48b71b2181fe68f3d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use crate::calculus::calculus::{Point3, Vec3};
use crate::interval::Interval;

// "Ideal" aspect ratio, allowing fraction
pub const ASPECT_RATIO: f32 = 16.0 / 9.0;
pub const IMG_WIDTH: usize = 400;
pub const IMG_HEIGHT: usize = get_image_height(IMG_WIDTH, ASPECT_RATIO);

pub const SAMPLES_PER_PIXEL: usize = 100;
pub const MAX_DEPTH: usize = 50;

pub const VFOV: f32 = 30.0;
pub const LOOK_FROM: Point3 = Point3 { x: -2.0, y: 2.0, z: 1.0 };
pub const LOOK_AT: Point3 = Point3 { x: 0.0, y: 0.0, z: -1.0 };
pub const VUP: Vec3 = Vec3 { x: 0.0, y: 1.0, z: 0.0 };

pub const DEFOCUS_ANGLE: f32 = 0.0;
pub const FOCUS_DIST: f32 = 4.0;

pub const fn get_image_height(image_width: usize, aspect_ratio: f32) -> usize {
    let image_height = (image_width as f32 / aspect_ratio) as usize;
    if image_width < 1 { 1 } else { image_height }
}

#[derive(Debug, Clone)]
pub struct Color {
    pub r: f32,
    pub g: f32,
    pub b: f32,
}

#[allow(unused)]
pub enum ColorName {
    Black,
    White,
    Red,
    Lime,
    Blue,
    Yellow,
    Cyan,
    Magenta,
    Silver,
    Gray,
    Maroon,
    Olive,
    Green,
    Purple,
    Teal,
    Navy,
}

impl Color {
    pub fn new(r: f32, g: f32, b: f32) -> Self {
        Self { r, g, b }
    }

    pub fn from_name(name: ColorName) -> Self {
        match name {
            ColorName::Black => { Self::new(0.0, 0.0, 0.0) }
            ColorName::White => { Self::new(1.0, 1.0, 1.0) }
            ColorName::Red => { Self::new(1.0, 0.0, 0.0) }
            ColorName::Lime => { Self::new(0.0, 1.0, 0.0) }
            ColorName::Blue => { Self::new(0.0, 0.0, 1.0) }
            ColorName::Yellow => { Self::new(1.0, 1.0, 0.0) }
            ColorName::Cyan => { Self::new(0.0, 1.0, 1.0) }
            ColorName::Magenta => { Self::new(1.0, 0.0, 1.0) }
            ColorName::Silver => { Self::new(0.75, 0.75, 0.75) }
            ColorName::Gray => { Self::new(0.5, 0.5, 0.5) }
            ColorName::Maroon => { Self::new(0.5, 0.0, 0.0) }
            ColorName::Olive => { Self::new(0.5, 0.5, 0.0)}
            ColorName::Green => { Self::new(0.0, 0.5, 0.0) }
            ColorName::Purple => { Self::new(0.5, 0.0, 0.5) }
            ColorName::Teal => { Self::new(0.0, 0.5, 0.5) }
            ColorName::Navy => { Self::new(0.0, 0.0, 0.5) }
        }
    }

    pub fn mul_scalar(&self, scalar: f32) -> Color {
        Self {
            r: self.r * scalar,
            g: self.g * scalar,
            b: self.b * scalar,
        }
    }

    pub fn add(&self, other: &Self) -> Color {
        Self {
            r: self.r + other.r,
            g: self.g + other.g,
            b: self.b + other.b
        }
    }

    pub fn elem_prod(&self, other: &Self) -> Self {
        Self {
            r: self.r * other.r,
            g: self.g * other.g,
            b: self.b * other.b,
        }
    }

    fn _linear_to_gamma(linear_comp: f32) -> f32 {
        if linear_comp > 0.0 { linear_comp.sqrt() } else { 0.0 }
    }

    pub fn linear_to_gamma(&mut self) {
        self.r = Self::_linear_to_gamma(self.r);
        self.g = Self::_linear_to_gamma(self.g);
        self.b = Self::_linear_to_gamma(self.b);
    }
}


#[derive(Debug, Copy, Clone)]
pub struct Pixel {
    pub r: u8,
    pub g: u8,
    pub b: u8,
}

impl Pixel {
    pub fn from_frac(r: f32, g: f32, b: f32) -> Self {
        let intensity = Interval::new(0.0, 0.999);
        Self {
            r: (256.0 * intensity.clamp(r)) as u8,
            g: (256.0 * intensity.clamp(g)) as u8,
            b: (256.0 * intensity.clamp(b)) as u8,
        }
    }

    pub fn from_color(color: &Color) -> Self {
        let mut clone = color.clone();
        clone.linear_to_gamma();
        let (r, g, b) = (color.r, color.g, color.b);
        Self::from_frac(r, g, b)
    }
}

impl Default for Pixel {
    fn default() -> Self {
        Pixel { r:0, g:0, b:0 }
    }
}

pub type DisplayBuffer = [[Pixel; IMG_WIDTH]; IMG_HEIGHT];