diff --git a/pathtracer-gui/src/main.rs b/pathtracer-gui/src/main.rs index 503b9fd6..4ba5f5da 100644 --- a/pathtracer-gui/src/main.rs +++ b/pathtracer-gui/src/main.rs @@ -1,11 +1,9 @@ use clap::Parser; use kdtree::{build::build_kdtree, build_sah::SahKdTreeBuilder}; -use scene::{camera::Pinhole, Scene}; +use scene::Scene; use stage::Stage; use tracing::pathtracer::Pathtracer; -use crate::worker::Worker; - mod stage; mod worker; @@ -49,11 +47,8 @@ fn main() { kdtree, }; - let camera = pathtracer.scene.cameras[0].clone(); - let pinhole = Pinhole::new(camera.clone(), 128, 128); - let worker = Worker::spawn(pathtracer, pinhole); - miniquad::start(Default::default(), move || { - Box::new(Stage::new(worker, camera)) + let camera = pathtracer.scene.cameras[0].clone(); + Box::new(Stage::new(pathtracer, camera)) }); } diff --git a/pathtracer-gui/src/stage.rs b/pathtracer-gui/src/stage.rs index 665af805..07793c49 100644 --- a/pathtracer-gui/src/stage.rs +++ b/pathtracer-gui/src/stage.rs @@ -2,11 +2,12 @@ use std::time::Instant; use glam::{Mat3, Vec3}; use miniquad::{ - window, Bindings, BufferLayout, BufferSource, BufferType, BufferUsage, EventHandler, KeyCode, - Pipeline, PipelineParams, RenderingBackend, ShaderSource, TextureId, VertexAttribute, + Bindings, BufferLayout, BufferSource, BufferType, BufferUsage, EventHandler, GlContext, + KeyCode, Pipeline, PipelineParams, RenderingBackend, ShaderSource, TextureId, VertexAttribute, VertexFormat, }; use scene::camera::{Camera, Pinhole}; +use tracing::pathtracer::Pathtracer; use crate::worker::Worker; @@ -49,7 +50,7 @@ impl Default for InputState { } pub(crate) struct Stage { - ctx: Box, + ctx: Box, pipeline: Pipeline, bindings: Bindings, @@ -57,15 +58,21 @@ pub(crate) struct Stage { worker: Option, + target_size: (u32, u32), camera: Camera, + waiting_for_first_result: bool, last_update: Instant, input: InputState, } impl Stage { - pub fn new(worker: Worker, camera: Camera) -> Stage { - let mut ctx: Box = window::new_rendering_backend(); + pub fn new(pathtracer: Pathtracer, camera: Camera) -> Stage { + let target_size = (128, 128); + let pinhole = Pinhole::new(camera.clone(), target_size.0, target_size.1); + let worker = Worker::spawn(pathtracer, pinhole); + + let mut ctx = Box::new(GlContext::new()); #[rustfmt::skip] let full_screen_quad: [Vertex; 4] = [ @@ -90,7 +97,12 @@ impl Stage { let texture = ctx.new_texture( miniquad::TextureAccess::Static, miniquad::TextureSource::Empty, - Default::default(), + miniquad::TextureParams { + format: miniquad::TextureFormat::RGB8, + width: 0, + height: 0, + ..Default::default() + }, ); let bindings = Bindings { @@ -125,7 +137,9 @@ impl Stage { bindings, texture, worker: Some(worker), + target_size, camera, + waiting_for_first_result: false, last_update: Instant::now(), input: InputState::default(), } @@ -165,7 +179,9 @@ impl EventHandler for Stage { fn resize_event(&mut self, width: f32, height: f32) { if !cfg!(debug_assertions) { if let Some(worker) = &self.worker { - let pinhole = Pinhole::new(self.camera.clone(), width as u32, height as u32); + self.target_size = (width as u32, height as u32); + let pinhole = + Pinhole::new(self.camera.clone(), self.target_size.0, self.target_size.1); worker.send(pinhole); } } @@ -176,19 +192,21 @@ impl EventHandler for Stage { let delta = (now - self.last_update).as_secs_f32(); if let Some(worker) = &self.worker { let translation = self.input.translation(); - if translation != Vec3::ZERO { + if translation != Vec3::ZERO && !self.waiting_for_first_result { const TRANSLATION_SPEED: f32 = 2.0; let distance = delta * TRANSLATION_SPEED; let translation_matrix = Mat3::from_cols(self.camera.right, self.camera.up, self.camera.direction); let position = self.camera.position + translation_matrix * translation * distance; self.camera = self.camera.with_position(position); - let texture_size = self.ctx.texture_size(self.texture); - let pinhole = Pinhole::new(self.camera.clone(), texture_size.0, texture_size.1); + let pinhole = + Pinhole::new(self.camera.clone(), self.target_size.0, self.target_size.1); worker.send(pinhole); + self.waiting_for_first_result = true; } - if let Some(result) = worker.try_receive() { + while let Some(result) = worker.try_receive() { + self.waiting_for_first_result = false; eprintln!( "Received {:?} @ {} rendered in {:?}.", [result.buffer.width, result.buffer.height], @@ -197,6 +215,12 @@ impl EventHandler for Stage { ); let texture_size = self.ctx.texture_size(self.texture); if result.buffer.size() != texture_size { + eprintln!( + "Reallocating texture {:?} {:?} to {:?}.", + self.texture, + texture_size, + result.buffer.size() + ); self.ctx.delete_texture(self.texture); let width = result.buffer.width; let height = result.buffer.height; @@ -211,6 +235,10 @@ impl EventHandler for Stage { ); self.bindings.images = vec![self.texture]; } else { + eprintln!( + "Updating existing texture {:?} {:?}.", + self.texture, texture_size + ); self.ctx .texture_update(self.texture, &result.buffer.to_rgb8(result.iterations)) } diff --git a/pathtracer-gui/src/worker.rs b/pathtracer-gui/src/worker.rs index 50a3a4fa..6e3826a3 100644 --- a/pathtracer-gui/src/worker.rs +++ b/pathtracer-gui/src/worker.rs @@ -38,12 +38,6 @@ impl RenderResult { fn render_subdivided(pathtracer: &Pathtracer, pinhole: &Pinhole, sub_size: UVec2) -> ImageBuffer { let count_x = pinhole.width / sub_size.x; let count_y = pinhole.height / sub_size.y; - eprintln!( - "Rendering size={:?} sub_size={:?} count={:?}", - pinhole.size(), - sub_size, - [count_x, count_y] - ); (0..count_x * count_y) .into_par_iter() .fold( @@ -108,12 +102,14 @@ fn worker_loop( 64, 64 * pinhole.height / pinhole.width, ); + eprintln!("Rendering scaled down size={:?}", pinhole_small.size()); let (duration, buffer) = measure(|| { render_subdivided(&pathtracer, &pinhole_small, pinhole_small.size() / 3) }); let _ = tx.send(RenderResult::new(1, duration, buffer)); } + eprintln!("Rendering size={:?}", pinhole.size()); let (duration, buffer) = measure(|| render_subdivided(&pathtracer, &pinhole, pinhole.size() / 4)); combined_buffer += buffer; @@ -152,7 +148,16 @@ impl Worker { } pub fn try_receive(&self) -> Option { - self.result_rx.try_recv().ok() + let mut previous = self.result_rx.try_recv(); + while previous.is_ok() { + let result = self.result_rx.try_recv(); + if result.is_ok() { + previous = result; + } else { + return previous.ok(); + } + } + None } pub fn join(self) {