From 1bfef16afa07f3f3f6f6ee6a362af1c39261dad1 Mon Sep 17 00:00:00 2001 From: hal8174 Date: Thu, 28 Nov 2024 17:59:46 +0100 Subject: [PATCH] Add scene and renderer selection to egui --- ray-tracing-core/src/renderer.rs | 18 +++ ray-tracing-core/src/scene.rs | 17 +++ ray-tracing-egui/src/main.rs | 31 ++++- ray-tracing-egui/src/render.rs | 38 +++++- ray-tracing-scene/src/examples.rs | 194 ++++++++++++++++-------------- ray-tracing-tev/src/main.rs | 2 +- 6 files changed, 200 insertions(+), 100 deletions(-) diff --git a/ray-tracing-core/src/renderer.rs b/ray-tracing-core/src/renderer.rs index d85a73b..a7fa7dd 100644 --- a/ray-tracing-core/src/renderer.rs +++ b/ray-tracing-core/src/renderer.rs @@ -1,3 +1,5 @@ +use std::ops::Deref; + use crate::{camera::Camera, prelude::*, scene::Scene}; pub trait ClassicalRenderer, C: Camera> { @@ -5,3 +7,19 @@ pub trait ClassicalRenderer, C: Camera> { fn width(&self) -> u32; fn height(&self) -> u32; } + +impl, C: Camera, T: ClassicalRenderer + ?Sized> + ClassicalRenderer for Box +{ + fn render_pixel(&self, scene: &S, camera: &C, x: u32, y: u32, rng: &mut R) -> Color { + self.deref().render_pixel(scene, camera, x, y, rng) + } + + fn width(&self) -> u32 { + self.deref().width() + } + + fn height(&self) -> u32 { + self.deref().height() + } +} diff --git a/ray-tracing-core/src/scene.rs b/ray-tracing-core/src/scene.rs index 975f522..61fa0d1 100644 --- a/ray-tracing-core/src/scene.rs +++ b/ray-tracing-core/src/scene.rs @@ -1,3 +1,5 @@ +use std::ops::Deref; + use crate::prelude::*; pub trait Scene { @@ -91,3 +93,18 @@ impl<'sc, R: Rng> LightSample<'sc, R> { Frame::from_normal(self.normal) } } + +impl + ?Sized, R: Rng> Scene for Box { + fn intersect(&self, ray: Ray, min: Float, max: Float) -> Option> { + self.deref().intersect(ray, min, max) + } + + fn sample_light( + &self, + w_in: Dir3, + intersection: &Intersection<'_, R>, + rng: &mut R, + ) -> Option> { + self.deref().sample_light(w_in, intersection, rng) + } +} diff --git a/ray-tracing-egui/src/main.rs b/ray-tracing-egui/src/main.rs index 009397e..e5b75f2 100644 --- a/ray-tracing-egui/src/main.rs +++ b/ray-tracing-egui/src/main.rs @@ -1,5 +1,6 @@ use egui_winit_vulkano::{Gui, GuiConfig}; -use render::render_thread; +use ray_tracing_scene::examples::example_scenes; +use render::{render_thread, RENDERER}; use setup::{get_compute_pipeline, get_framebuffers}; use std::sync::Arc; use vulkano::{ @@ -87,9 +88,13 @@ fn main() { let (control_tx, control_rx) = std::sync::mpsc::channel(); let (data_tx, data_rx) = std::sync::mpsc::channel(); + let scenes = example_scenes::(); + let mut settings = render::RenderSettings { width: window.inner_size().width, height: window.inner_size().height, + scene: scenes.keys().next().unwrap(), + renderer_id: 0, }; let send_settings = settings.clone(); @@ -163,10 +168,28 @@ fn main() { pipeline = get_compute_pipeline(device.clone(), cs.clone()); } + let mut settings_changed = false; gui.immediate_ui(|gui| { let ctx = gui.context(); egui::Window::new("panel").show(&ctx, |ui| { - ui.heading("fdjkslf"); + ui.collapsing("Scene Settings:", |ui| { + egui::ComboBox::from_label("Scene") + .selected_text(settings.scene) + .show_ui(ui, |ui| { + for &label in scenes.keys() { + settings_changed |= ui + .selectable_value(&mut settings.scene, label, label) + .changed(); + } + }); + }); + + settings_changed |= egui::ComboBox::from_label("Renderer") + .selected_text(RENDERER[settings.renderer_id].0) + .show_index(ui, &mut settings.renderer_id, RENDERER.len(), |i| { + RENDERER[i].0 + }) + .changed(); ui.collapsing("Render Settings:", |ui| { ui.label(format!("{:#?}", &settings)); @@ -174,6 +197,10 @@ fn main() { }); }); + if settings_changed { + let _ = control_tx.send(settings.clone()); + } + let (image_i, suboptimal, acquire_future) = match swapchain::acquire_next_image(swapchain.clone(), None) .map_err(Validated::unwrap) diff --git a/ray-tracing-egui/src/render.rs b/ray-tracing-egui/src/render.rs index 031673f..d5a602f 100644 --- a/ray-tracing-egui/src/render.rs +++ b/ray-tracing-egui/src/render.rs @@ -4,8 +4,11 @@ use std::sync::{ }; use rand::{rngs::SmallRng, SeedableRng}; -use ray_tracing_core::{camera::BasicCamera, renderer::ClassicalRenderer}; -use ray_tracing_renderer::path_tracer_importance::PathTracerImportance; +use ray_tracing_core::{camera::BasicCamera, renderer::ClassicalRenderer, scene::Scene}; +use ray_tracing_renderer::{ + depth_renderer::DepthRenderer, next_event_estimation::NextEventEstimation, + path_tracer::PathTracer, path_tracer_importance::PathTracerImportance, +}; use ray_tracing_scene::examples::{self, example_scenes, ExampleScene}; use rayon::{ iter::{IndexedParallelIterator, ParallelIterator}, @@ -19,10 +22,29 @@ use vulkano::{ }, }; +type DynRenderer = + dyn ClassicalRenderer + Sync>, BasicCamera> + Sync; +pub const RENDERER: [(&str, fn(u32, u32) -> Box); 4] = [ + ("Depth", |w, h| { + Box::new(DepthRenderer::new(w, h)) as Box + }), + ("Path tracer", |w, h| { + Box::new(PathTracer::new(w, h)) as Box + }), + ("Path tracer importance", |w, h| { + Box::new(PathTracerImportance::new(w, h)) as Box + }), + ("Next event estimation", |w, h| { + Box::new(NextEventEstimation::new(w, h)) as Box + }), +]; + #[derive(Debug, Clone)] pub struct RenderSettings { pub width: u32, pub height: u32, + pub scene: &'static str, + pub renderer_id: usize, } pub enum ControlMessages { @@ -46,9 +68,10 @@ pub fn render_thread( let mut buffer = vec![0.0; settings.width as usize * settings.height as usize * 3]; - let e = examples::cornell2(); + let example_scenes = examples::example_scenes::(); - let scene = e.scene; + let e = example_scenes[settings.scene](); + let mut scene = (e.scene)(); let mut camera = BasicCamera::new( settings.width, @@ -59,12 +82,15 @@ pub fn render_thread( e.horizontal_fov, ); - let mut renderer = PathTracerImportance::new(settings.width, settings.height); + let mut renderer = (RENDERER[settings.renderer_id].1)(settings.width, settings.height); let mut samples = 0; loop { while let Ok(s) = rx.try_recv() { + println!("Settings changed."); settings = s; + let e = example_scenes[settings.scene](); + scene = (e.scene)(); camera = BasicCamera::new( settings.width, settings.height, @@ -74,7 +100,7 @@ pub fn render_thread( e.horizontal_fov, ); buffer = vec![0.0; settings.width as usize * settings.height as usize * 3]; - renderer = PathTracerImportance::new(settings.width, settings.height); + renderer = (RENDERER[settings.renderer_id].1)(settings.width, settings.height); samples = 0; } diff --git a/ray-tracing-scene/src/examples.rs b/ray-tracing-scene/src/examples.rs index bf04306..d2777f0 100644 --- a/ray-tracing-scene/src/examples.rs +++ b/ray-tracing-scene/src/examples.rs @@ -2,52 +2,60 @@ use crate::{ parse_obj::ObjData, triangle_bvh::{BVHMaterial, Triangle, TriangleBVH}, }; -use ray_tracing_core::{light::AreaLight, prelude::*}; +use ray_tracing_core::{light::AreaLight, prelude::*, scene::Scene}; use ray_tracing_material::{diffuse::DiffuseMaterial, mirror::Mirror}; use std::collections::HashMap; use std::fmt::Debug; pub struct ExampleScene { - pub scene: TriangleBVH, + pub scene: fn() -> Box + Sync>, pub camera_pos: Pos3, pub camera_dir: Dir3, pub camera_up: Dir3, pub horizontal_fov: Float, } -pub fn example_scenes() -> HashMap<&'static str, fn() -> ExampleScene> { +pub fn example_scenes() -> HashMap<&'static str, fn() -> ExampleScene> +{ let mut map: HashMap<&str, fn() -> ExampleScene> = HashMap::new(); map.insert("basic_cornel", basic_cornell::); map.insert("cornel2", cornell2::); map } -pub fn cornell2() -> ExampleScene { - let obj = ObjData::new("ray-tracing-scene/obj/cornell_box.obj").unwrap(); +pub fn cornell2() -> ExampleScene { + let f = || { + let obj = ObjData::new("ray-tracing-scene/obj/cornell_box.obj").unwrap(); - let triangles = obj - .triangle_faces() - .map(|t| Triangle::new(t.v, t.mat.unwrap())) - .collect(); + let triangles = obj + .triangle_faces() + .map(|t| Triangle::new(t.v, t.mat.unwrap())) + .collect(); - let materials = obj - .materials() - .iter() - .map(|m| match m.name.as_str() { - "white" => BVHMaterial::new_material(DiffuseMaterial::new(Color::white())), - "light" => BVHMaterial::new_light(AreaLight::new(Color::white() * 100.0)), - "blue" => BVHMaterial::new_material(DiffuseMaterial::new(Color::new(0.0, 0.0, 1.0))), - "red" => BVHMaterial::new_material(DiffuseMaterial::new(Color::new(1.0, 0.0, 0.0))), - "green" => BVHMaterial::new_material(DiffuseMaterial::new(Color::new(0.0, 1.0, 0.0))), - "mirror" => BVHMaterial::new_material(Mirror::new(Color::white())), - _ => unreachable!(), - }) - .collect(); + let materials = obj + .materials() + .iter() + .map(|m| match m.name.as_str() { + "white" => BVHMaterial::new_material(DiffuseMaterial::new(Color::white())), + "light" => BVHMaterial::new_light(AreaLight::new(Color::white() * 100.0)), + "blue" => { + BVHMaterial::new_material(DiffuseMaterial::new(Color::new(0.0, 0.0, 1.0))) + } + "red" => BVHMaterial::new_material(DiffuseMaterial::new(Color::new(1.0, 0.0, 0.0))), + "green" => { + BVHMaterial::new_material(DiffuseMaterial::new(Color::new(0.0, 1.0, 0.0))) + } + "mirror" => BVHMaterial::new_material(Mirror::new(Color::white())), + _ => unreachable!(), + }) + .collect(); - let scene = TriangleBVH::new(obj.vertices, triangles, materials); + let scene = TriangleBVH::new(obj.vertices, triangles, materials); + Box::new(scene) as Box + Sync> + }; ExampleScene { - scene, + scene: f, camera_pos: Pos3::new(275.0, 275.0, -800.0), camera_dir: Dir3::new(0.0, 0.0, 1.0), camera_up: Dir3::up(), @@ -55,75 +63,79 @@ pub fn cornell2() -> ExampleScene { } } -pub fn basic_cornell() -> ExampleScene { - let side_length = 1.5; - let light_size = 0.5; - let light_offset = 0.01; - let box_size = 0.3; - let scene = TriangleBVH::new( - vec![ - Pos3::new(side_length, side_length, side_length), - Pos3::new(side_length, side_length, -side_length), - Pos3::new(side_length, -side_length, side_length), - Pos3::new(side_length, -side_length, -side_length), - Pos3::new(-side_length, side_length, side_length), - Pos3::new(-side_length, side_length, -side_length), - Pos3::new(-side_length, -side_length, side_length), - Pos3::new(-side_length, -side_length, -side_length), - Pos3::new(light_size, side_length - light_offset, light_size), - Pos3::new(light_size, side_length - light_offset, -light_size), - Pos3::new(-light_size, side_length - light_offset, light_size), - Pos3::new(-light_size, side_length - light_offset, -light_size), - Pos3::new(box_size, -side_length, 0.0), - Pos3::new(0.0, -side_length, -box_size), - Pos3::new(-box_size, -side_length, 0.0), - Pos3::new(0.0, -side_length, box_size), - Pos3::new(0.0, box_size - side_length, 0.0), - ], - vec![ - Triangle::new([0, 1, 2], 0), - Triangle::new([1, 3, 2], 0), - Triangle::new([0, 4, 1], 0), - Triangle::new([1, 4, 5], 0), - Triangle::new([2, 3, 6], 0), - Triangle::new([3, 7, 6], 0), - Triangle::new([0, 2, 4], 1), - Triangle::new([6, 4, 2], 1), - Triangle::new([1, 5, 3], 2), - Triangle::new([7, 3, 5], 2), - Triangle::new([8, 10, 9], 3), - Triangle::new([11, 9, 10], 3), - Triangle::new([12, 13, 16], 4), - Triangle::new([13, 14, 16], 4), - Triangle::new([14, 15, 16], 4), - Triangle::new([15, 12, 16], 4), - ], - vec![ - BVHMaterial { - material: Some(Box::new(DiffuseMaterial::new(Color::new(0.8, 0.8, 0.8)))), - light: None, - }, - BVHMaterial { - material: Some(Box::new(DiffuseMaterial::new(Color::new(0.9, 0.0, 0.0)))), - light: None, - }, - BVHMaterial { - material: Some(Box::new(DiffuseMaterial::new(Color::new(0.0, 0.9, 0.0)))), - light: None, - }, - BVHMaterial { - material: None, - light: Some(Box::new(AreaLight::new(Color::white() * 30.0))), - }, - BVHMaterial { - material: Some(Box::new(Mirror::new(Color::new(1.0, 1.0, 1.0)))), - light: None, - }, - ], - ); +pub fn basic_cornell() -> ExampleScene { + let f = || { + let side_length = 1.5; + let light_size = 0.5; + let light_offset = 0.01; + let box_size = 0.3; + let scene = TriangleBVH::new( + vec![ + Pos3::new(side_length, side_length, side_length), + Pos3::new(side_length, side_length, -side_length), + Pos3::new(side_length, -side_length, side_length), + Pos3::new(side_length, -side_length, -side_length), + Pos3::new(-side_length, side_length, side_length), + Pos3::new(-side_length, side_length, -side_length), + Pos3::new(-side_length, -side_length, side_length), + Pos3::new(-side_length, -side_length, -side_length), + Pos3::new(light_size, side_length - light_offset, light_size), + Pos3::new(light_size, side_length - light_offset, -light_size), + Pos3::new(-light_size, side_length - light_offset, light_size), + Pos3::new(-light_size, side_length - light_offset, -light_size), + Pos3::new(box_size, -side_length, 0.0), + Pos3::new(0.0, -side_length, -box_size), + Pos3::new(-box_size, -side_length, 0.0), + Pos3::new(0.0, -side_length, box_size), + Pos3::new(0.0, box_size - side_length, 0.0), + ], + vec![ + Triangle::new([0, 1, 2], 0), + Triangle::new([1, 3, 2], 0), + Triangle::new([0, 4, 1], 0), + Triangle::new([1, 4, 5], 0), + Triangle::new([2, 3, 6], 0), + Triangle::new([3, 7, 6], 0), + Triangle::new([0, 2, 4], 1), + Triangle::new([6, 4, 2], 1), + Triangle::new([1, 5, 3], 2), + Triangle::new([7, 3, 5], 2), + Triangle::new([8, 10, 9], 3), + Triangle::new([11, 9, 10], 3), + Triangle::new([12, 13, 16], 4), + Triangle::new([13, 14, 16], 4), + Triangle::new([14, 15, 16], 4), + Triangle::new([15, 12, 16], 4), + ], + vec![ + BVHMaterial { + material: Some(Box::new(DiffuseMaterial::new(Color::new(0.8, 0.8, 0.8)))), + light: None, + }, + BVHMaterial { + material: Some(Box::new(DiffuseMaterial::new(Color::new(0.9, 0.0, 0.0)))), + light: None, + }, + BVHMaterial { + material: Some(Box::new(DiffuseMaterial::new(Color::new(0.0, 0.9, 0.0)))), + light: None, + }, + BVHMaterial { + material: None, + light: Some(Box::new(AreaLight::new(Color::white() * 30.0))), + }, + BVHMaterial { + material: Some(Box::new(Mirror::new(Color::new(1.0, 1.0, 1.0)))), + light: None, + }, + ], + ); + + Box::new(scene) as Box + Sync> + }; ExampleScene { - scene, + scene: f, camera_pos: Pos3::new(-6.0, 0.0, 0.0), camera_dir: Dir3::new(1.0, 0.0, 0.0), camera_up: Dir3::up(), diff --git a/ray-tracing-tev/src/main.rs b/ray-tracing-tev/src/main.rs index 9fcb5be..eda26b8 100644 --- a/ray-tracing-tev/src/main.rs +++ b/ray-tracing-tev/src/main.rs @@ -107,7 +107,7 @@ fn main() { e.camera_up, e.horizontal_fov, ); - let s = e.scene; + let s = (e.scene)(); let r = DepthRenderer::new(args.width, args.height); render_image(