summaryrefslogtreecommitdiff
path: root/src/common.rs
blob: 918c59c645c2765bd043f03ac83451e58cfd3a0c (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
use crate::calculus::calculus::Point3;
use crate::interval::Interval;

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

pub const VIEWPORT_HEIGHT: f32 = 2.0;
pub const FOCAL_LENGTH: f32 = 1.0;
pub const CAMERA_CENTER: Point3 = Point3 { x: 0f32, y: 0f32, z: 0f32 };

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

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,
}

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

    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];