aboutsummaryrefslogtreecommitdiff
path: root/src/display/image.rs
blob: 4b25cb2cad10f30711defe08c7fe8cf23aaa89a9 (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
use std::io::Write;

use crate::display::{Display, Pixel};
use crate::vec3::Color;

pub struct Image {
    width: usize,
    height: usize,
    data: Vec<Pixel>,
}

impl Image {
    pub fn new(width: usize, height: usize) -> Image {
        let data = vec![
            Pixel {
                color: Color {
                    x: 0.0,
                    y: 0.0,
                    z: 0.0
                },
                sample_count: 0
            };
            width * height
        ];
        Image {
            width,
            height,
            data,
        }
    }
}

impl Display for Image {
    fn add_sample(&mut self, x: usize, y: usize, color: Color) {
        self.data
            .get_mut((y * self.width) + x)
            .unwrap()
            .update(color);
    }

    fn maybe_write(&self, output: &mut impl Write) {
        output
            .write_fmt(format_args!("P3\n{} {}\n255\n", self.width, self.height))
            .unwrap();
        for y in (0..self.height).rev() {
            for x in 0..self.width {
                let pixel = self.data.get((y * self.width) + x).unwrap();
                let mut r = pixel.color.x;
                let mut g = pixel.color.y;
                let mut b = pixel.color.z;

                // Divide by the number of samples and perform gamma correction for gamma 2
                let scale = 1.0 / pixel.sample_count as f64;
                r = (r * scale).sqrt();
                g = (g * scale).sqrt();
                b = (b * scale).sqrt();

                output
                    .write_fmt(format_args!(
                        "{} {} {}\n",
                        (256.0 * r.clamp(0.0, 0.999)) as u32,
                        (256.0 * g.clamp(0.0, 0.999)) as u32,
                        (256.0 * b.clamp(0.0, 0.999)) as u32,
                    ))
                    .unwrap();
            }
        }
    }
    fn maybe_update(&mut self) {}
}