rust_pathtracer/
buffer.rs

1use crate::prelude::*;
2use rayon::{slice::ParallelSliceMut, iter::{IndexedParallelIterator, ParallelIterator}};
3
4/// A color buffer holding an array of either f32 or f64 pixels (as defined by PTF).
5#[derive(PartialEq, Debug, Clone)]
6pub struct ColorBuffer {
7
8    pub width               : usize,
9    pub height              : usize,
10
11    pub pixels              : Vec<F>,
12
13    pub frames              : usize,
14}
15
16impl ColorBuffer {
17
18    pub fn new(width: usize, height: usize) -> Self {
19        Self {
20            width,
21            height,
22
23            pixels      : vec![0.0; width * height * 4],
24            frames      : 0,
25        }
26    }
27
28    #[inline(always)]
29    pub fn at(&self, x: usize, y: usize) -> [F;4] {
30        let i = y * self.width * 4 + x * 4;
31        [self.pixels[i], self.pixels[i + 1], self.pixels[i + 2], self.pixels[i + 3]]
32    }
33
34    // TODO: Multithread the conversion routines
35
36    /// Convert the frame to an u8 vec
37    pub fn to_u8_vec(&self) -> Vec<u8> {
38
39        let source = &self.pixels[..];
40        let mut out : Vec<u8> = vec![0; self.width * self.height * 4];
41
42        for y in 0..self.height {
43            for x in 0..self.width {
44                let d = x * 4 + y * self.width * 4;
45                //let c = [(source[d] * 255.0) as u8, (source[d+1] * 255.0) as u8,  (source[d+2] * 255.0) as u8,  (source[d+3] * 255.0) as u8];
46                let c = [(source[d].powf(0.4545) * 255.0) as u8, (source[d+1].powf(0.4545) * 255.0) as u8, (source[d+2].powf(0.4545) * 255.0) as u8, (source[d+3] * 255.0) as u8];
47                out[d..d + 4].copy_from_slice(&c);
48            }
49        }
50
51        out
52    }
53
54    /// Convert the pixel buffer to an Vec<u8> and converts gamma the colors from linear into gamma space.
55    pub fn convert_to_u8(&self, frame: &mut [u8]) {
56        for y in 0..self.height {
57            for x in 0..self.width {
58                let o = x * 4 + y * self.width * 4;
59                let c = [(self.pixels[o].powf(0.4545) * 255.0) as u8, (self.pixels[o+1].powf(0.4545) * 255.0) as u8, (self.pixels[o+2].powf(0.4545) * 255.0) as u8, (self.pixels[o+3] * 255.0) as u8];
60                // let c = [(self.pixels[o]* 255.0) as u8, (self.pixels[o+1] * 255.0) as u8, (self.pixels[o+2]* 255.0) as u8, (self.pixels[o+3] * 255.0) as u8];
61                frame[o..o + 4].copy_from_slice(&c);
62            }
63        }
64    }
65
66    /// Convert the pixel buffer to an Vec<u8> and converts the colors from linear into gamma space.
67    pub fn convert_to_u8_at(&self, frame: &mut [u8], at: (usize, usize, usize, usize)) {
68
69        let width = at.2;
70        let height = at.3;
71
72        frame
73            .par_rchunks_exact_mut(width * 4)
74            .enumerate()
75            .for_each(|(j, line)| {
76                for (i, pixel) in line.chunks_exact_mut(4).enumerate() {
77                    let i = j * width + i;
78
79                    let x = i % width;
80                    let y = height - (i / width);
81
82                    if x > at.0 && x < at.0 + self.width {
83                        if y > at.1 && y < at.1 + self.height {
84                            let o = (x - at.0) * 4 + (y - at.1) * self.width * 4;
85                            let c = [(self.pixels[o] * 255.0) as u8, (self.pixels[o+1] * 255.0) as u8, (self.pixels[o+2] * 255.0) as u8, (self.pixels[o+3] * 255.0) as u8];
86                            pixel.copy_from_slice(&c);
87                        }
88                    }
89                }
90            });
91
92
93        /*
94        for y in 0..self.height {
95            for x in 0..self.width {
96                let o = x * 4 + y * self.width * 4;
97                let d = (x+at.0) * 4 + (y+at.1) * stride * 4;
98                let c = [(self.pixels[o].powf(0.4545) * 255.0) as u8, (self.pixels[o+1].powf(0.4545) * 255.0) as u8, (self.pixels[o+2].powf(0.4545) * 255.0) as u8, (self.pixels[o+3] * 255.0) as u8];
99                frame[d..d + 4].copy_from_slice(&c);
100            }
101        }*/
102    }
103}