diff options
author | lamp | 2024-01-21 13:44:51 +0000 |
---|---|---|
committer | lamp | 2024-01-21 13:44:51 +0000 |
commit | c0fc3926e06acddcc02ef086fbda688d4709e5ba (patch) | |
tree | e9f752758a49bedf1936003a7a2cd883e7d8e3cf | |
parent | 78ddaff5855bf8446adef9e18eb0d7b7ddcee52a (diff) |
refactor display backends, add pixelflut backend
-rw-r--r-- | src/display/image.rs (renamed from src/image.rs) | 21 | ||||
-rw-r--r-- | src/display/mod.rs | 17 | ||||
-rw-r--r-- | src/display/pixel.rs | 14 | ||||
-rw-r--r-- | src/display/pixelflut.rs | 69 | ||||
-rw-r--r-- | src/main.rs | 14 |
5 files changed, 115 insertions, 20 deletions
diff --git a/src/image.rs b/src/display/image.rs index e24c14b..77d8c83 100644 --- a/src/image.rs +++ b/src/display/image.rs @@ -1,6 +1,7 @@ use std::io::Write; use crate::vec3::Color; +use crate::display::{Display, Pixel}; pub struct Image { width: usize, @@ -8,12 +9,6 @@ pub struct Image { data: Vec<Pixel>, } -#[derive(Clone)] -struct Pixel { - color: Color, - sample_count: u32, -} - impl Image { pub fn new(width: usize, height: usize) -> Image { let data = vec![ @@ -33,15 +28,17 @@ impl Image { data, } } +} - pub fn add_sample(&mut self, x: usize, y: usize, color: Color) { +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); } - pub fn write(&self, output: &mut impl Write) { + 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 { @@ -67,11 +64,5 @@ impl Image { } } } -} - -impl Pixel { - pub fn update(&mut self, color: Color) { - self.color += color; - self.sample_count += 1; - } + fn maybe_update(&mut self) {} } diff --git a/src/display/mod.rs b/src/display/mod.rs new file mode 100644 index 0000000..0a18e48 --- /dev/null +++ b/src/display/mod.rs @@ -0,0 +1,17 @@ +mod image; +pub use image::Image; +mod pixelflut; +pub use pixelflut::Pixelflut; + +mod pixel; +use pixel::Pixel; + +use std::io::Write; + +use crate::vec3::Color; + +pub trait Display { + fn add_sample(&mut self, x: usize, y: usize, color: Color); + fn maybe_write(&self, output: &mut impl Write); + fn maybe_update(&mut self); +} diff --git a/src/display/pixel.rs b/src/display/pixel.rs new file mode 100644 index 0000000..c9113d9 --- /dev/null +++ b/src/display/pixel.rs @@ -0,0 +1,14 @@ +use crate::vec3::Color; + +#[derive(Clone)] +pub struct Pixel { + pub color: Color, + pub sample_count: u32, +} + +impl Pixel { + pub fn update(&mut self, color: Color) { + self.color += color; + self.sample_count += 1; + } +} diff --git a/src/display/pixelflut.rs b/src/display/pixelflut.rs new file mode 100644 index 0000000..3a62f8d --- /dev/null +++ b/src/display/pixelflut.rs @@ -0,0 +1,69 @@ +use std::io::Write; +use std::net::{TcpStream}; + +use crate::vec3::Color; +use crate::display::{Display, Pixel}; + +pub struct Pixelflut { + socket: TcpStream, + x: usize, + y: usize, + width: usize, + height: usize, + data: Vec<Pixel>, +} + +impl Pixelflut { + pub fn new(addr: &str, x: usize, y: usize, width: usize, height: usize) -> Self { + let data = vec![ + Pixel { + color: Color { + x: 0.0, + y: 0.0, + z: 0.0 + }, + sample_count: 0 + }; + width * height + ]; + let mut ret = Self { + socket: TcpStream::connect(addr).expect("Could not connect to Pixelflut!"), + x, + y, + width, + height, + data, + }; + ret.maybe_update(); + ret + } +} + +impl Display for Pixelflut { + fn add_sample(&mut self, x: usize, y: usize, color: crate::vec3::Color) { + self.data + .get_mut((y * self.width) + x) + .unwrap() + .update(color); + } + + fn maybe_write(&self, _: &mut impl std::io::prelude::Write) {} + + fn maybe_update(&mut self) { + for y in 0..self.height { + for x in 0..self.width { + let pixel = self.data.get((y * self.width) + x).unwrap(); + let scale = 1.0 / pixel.sample_count as f64; + let mut r = (pixel.color.x * scale).sqrt(); + let mut g = (pixel.color.y * scale).sqrt(); + let mut b = (pixel.color.z * scale).sqrt(); + self.socket.write(format!("PX {} {} {:02x}{:02x}{:02x}\n", + self.x + x, + self.y + self.height - y, + (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).as_bytes()); + } + } + } +} diff --git a/src/main.rs b/src/main.rs index 7ec82e6..c99ca58 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ mod material; mod ray; mod util; mod vec3; -mod image; +mod display; mod texture; mod scenes; @@ -12,7 +12,7 @@ use std::{sync::{Arc, mpsc}, thread}; use camera::Camera; use hittable::Hittable; -use image::Image; +use display::{Display, Image, Pixelflut}; use ray::Ray; use vec3::{Vec3, Color}; use scenes::get_scene; @@ -70,7 +70,7 @@ fn main() { //const ASPECT_RATIO: f64 = 1.0; const IMAGE_WIDTH: u32 = 600; const IMAGE_HEIGHT: u32 = (IMAGE_WIDTH as f64 / ASPECT_RATIO) as u32; - const SAMPLES_PER_PIXEL: u32 = 30; + const SAMPLES_PER_PIXEL: u32 = 500; const MAX_DEPTH: u32 = 50; const THREAD_COUNT: u32 = 8; const TIME_START: f64 = 0.0; @@ -83,7 +83,8 @@ fn main() { let dist_to_focus = 10.0; let cam = Arc::new(Camera::new(lookfrom, lookat, vup, vfov, ASPECT_RATIO, aperture, dist_to_focus, TIME_START, TIME_END)); // Render - let mut final_image = Image::new(IMAGE_WIDTH as usize, IMAGE_HEIGHT as usize); + // let mut final_image = Image::new(IMAGE_WIDTH as usize, IMAGE_HEIGHT as usize); + let mut final_image = Pixelflut::new("192.168.0.38:1337", 0, 0, IMAGE_WIDTH as usize, IMAGE_HEIGHT as usize); let (tx, rx) = mpsc::channel::<PixelUpdate>(); for _ in 0..THREAD_COUNT { let sender = tx.clone(); @@ -96,12 +97,14 @@ fn main() { } let expected_updates: u64 = (SAMPLES_PER_PIXEL / THREAD_COUNT) as u64 * THREAD_COUNT as u64 * IMAGE_HEIGHT as u64 * IMAGE_WIDTH as u64; let print_frequency: u64 = (SAMPLES_PER_PIXEL / THREAD_COUNT) as u64 * THREAD_COUNT as u64 * IMAGE_WIDTH as u64; + let print_frequency = print_frequency * 3; let mut update_count: u64 = 0; loop { if let Ok(update) = rx.try_recv() { update_count += 1; final_image.add_sample(update.x, update.y, update.color); if update_count % print_frequency == 0 { + final_image.maybe_update(); eprint!("\rCurrent completion: {:.2}%", (update_count as f64 / expected_updates as f64) * 100.0) } } else { @@ -110,6 +113,7 @@ fn main() { } } } - final_image.write(&mut std::io::stdout()); + final_image.maybe_update(); + final_image.maybe_write(&mut std::io::stdout()); eprintln!("\nDone."); } |