From 2bc5ec93feccfa94f0ff214c0ca372b522d3f5cf Mon Sep 17 00:00:00 2001 From: hal8174 Date: Fri, 22 Aug 2025 21:48:07 +0200 Subject: [PATCH] Change Scene trait to account for material data --- ray-tracing-core/src/material.rs | 28 +++++ ray-tracing-core/src/scene.rs | 54 +++++--- ray-tracing-egui/src/main.rs | 4 +- ray-tracing-egui/src/render.rs | 117 ++++++++++++------ ray-tracing-image/src/main.rs | 10 +- ray-tracing-pbrt-scene/src/scene.rs | 28 +++-- ray-tracing-pbrt-scene/src/shape.rs | 2 +- .../src/acceleration_structure/mod.rs | 16 ++- ray-tracing-scene/src/basic_scene.rs | 32 +++-- .../src/examples/basic_cornell.rs | 9 +- ray-tracing-scene/src/examples/cornell2.rs | 5 +- ray-tracing-scene/src/examples/mis_test.rs | 9 +- ray-tracing-scene/src/examples/mod.rs | 17 ++- .../src/examples/presentation_title_image.rs | 7 +- ray-tracing-scene/src/examples/sphere.rs | 47 +++---- .../src/examples/stanford_dragon.rs | 5 +- .../src/examples/stanford_dragon_as.rs | 7 +- ray-tracing-scene/src/triangle_bvh.rs | 16 ++- ray-tracing-tev/src/main.rs | 17 ++- 19 files changed, 306 insertions(+), 124 deletions(-) diff --git a/ray-tracing-core/src/material.rs b/ray-tracing-core/src/material.rs index 79eae71..f35c32b 100644 --- a/ray-tracing-core/src/material.rs +++ b/ray-tracing-core/src/material.rs @@ -27,6 +27,34 @@ pub trait Material: Send + Sync + Debug { } } +impl Material for &dyn Material { + fn eval(&self, w_in: Dir3, w_out: Dir3, rng: &mut R) -> Color { + (*self).eval(w_in, w_out, rng) + } + + fn sample(&self, w_in: Dir3, rng: &mut R) -> SampleResult { + (*self).sample(w_in, rng) + } + + fn pdf(&self, w_in: Dir3, w_out: Dir3) -> Float { + (*self).pdf(w_in, w_out) + } +} + +impl> Material for &M { + fn eval(&self, w_in: Dir3, w_out: Dir3, rng: &mut R) -> Color { + (*self).eval(w_in, w_out, rng) + } + + fn sample(&self, w_in: Dir3, rng: &mut R) -> SampleResult { + (*self).sample(w_in, rng) + } + + fn pdf(&self, w_in: Dir3, w_out: Dir3) -> Float { + (*self).pdf(w_in, w_out) + } +} + #[derive(Debug)] pub struct SampleResult { w_out: Dir3, diff --git a/ray-tracing-core/src/scene.rs b/ray-tracing-core/src/scene.rs index 661d949..5649060 100644 --- a/ray-tracing-core/src/scene.rs +++ b/ray-tracing-core/src/scene.rs @@ -3,29 +3,41 @@ use std::ops::Deref; use crate::prelude::*; pub trait Scene { - fn intersect(&self, ray: Ray, min: Float, max: Float) -> Option>; + type Mat<'a>: Material + where + Self: 'a, + R: 'a; - fn sample_light( + fn intersect( + &self, + ray: Ray, + min: Float, + max: Float, + ) -> Option>>; + + fn sample_light<'b>( &self, w_in: Dir3, - intersection: &Intersection<'_, R>, + intersection: &Intersection<'_, R, Self::Mat<'b>>, rng: &mut R, - ) -> Option>; + ) -> Option> + where + Self: 'b; } -pub struct Intersection<'sc, R: Rng> { +pub struct Intersection<'sc, R: Rng, M: Material + 'sc> { t: Float, normal: Dir3, - material: Option<&'sc dyn Material>, + material: Option, light: Option<&'sc dyn Light>, light_pdf: Float, } -impl<'sc, R: Rng> Intersection<'sc, R> { +impl<'sc, R: Rng, M: Material> Intersection<'sc, R, M> { pub fn new( t: Float, normal: Dir3, - material: Option<&'sc dyn Material>, + material: Option, light: Option<&'sc dyn Light>, light_pdf: Float, ) -> Self { @@ -46,8 +58,8 @@ impl<'sc, R: Rng> Intersection<'sc, R> { self.normal } - pub fn material(&self) -> Option<&'sc dyn Material> { - self.material + pub fn material(&self) -> Option<&M> { + self.material.as_ref() } pub fn light(&self) -> Option<&'sc dyn Light> { @@ -102,16 +114,30 @@ impl<'sc, R: Rng> LightSample<'sc, R> { } impl + ?Sized, R: Rng> Scene for Box { - fn intersect(&self, ray: Ray, min: Float, max: Float) -> Option> { + type Mat<'a> + = T::Mat<'a> + where + T: 'a, + R: 'a; + + fn intersect( + &self, + ray: Ray, + min: Float, + max: Float, + ) -> Option>> { self.deref().intersect(ray, min, max) } - fn sample_light( + fn sample_light<'b>( &self, w_in: Dir3, - intersection: &Intersection<'_, R>, + intersection: &Intersection<'_, R, Self::Mat<'b>>, rng: &mut R, - ) -> Option> { + ) -> Option> + where + Self: 'b, + { 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 f15175d..f67e5d6 100644 --- a/ray-tracing-egui/src/main.rs +++ b/ray-tracing-egui/src/main.rs @@ -236,9 +236,9 @@ fn main() { }); settings_changed |= egui::ComboBox::from_label("Renderer") - .selected_text(RENDERER[settings.renderer_id].0) + .selected_text(RENDERER[settings.renderer_id]) .show_index(ui, &mut settings.renderer_id, RENDERER.len(), |i| { - RENDERER[i].0 + RENDERER[i] }) .changed(); diff --git a/ray-tracing-egui/src/render.rs b/ray-tracing-egui/src/render.rs index c2ec26a..57f9331 100644 --- a/ray-tracing-egui/src/render.rs +++ b/ray-tracing-egui/src/render.rs @@ -5,7 +5,10 @@ use std::sync::{ use rand::{rngs::SmallRng, SeedableRng}; use ray_tracing_core::{ - camera::BasicCamera, prelude::*, renderer::ClassicalRenderer, scene::Scene, + camera::{BasicCamera, Camera}, + prelude::*, + renderer::ClassicalRenderer, + scene::Scene, }; use ray_tracing_renderer::{ depth_renderer::DepthRenderer, mis::MIS, next_event_estimation::NextEventEstimation, @@ -21,25 +24,6 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter}, }; -type DynRenderer = - dyn ClassicalRenderer + Sync>, BasicCamera> + Sync; -#[allow(clippy::type_complexity)] -pub const RENDERER: [(&str, fn(u32, u32) -> Box); 5] = [ - ("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 - }), - ("MIS", |w, h| Box::new(MIS::new(w, h)) as Box), -]; - #[derive(Debug, Clone)] pub struct RenderSettings { pub width: u32, @@ -59,6 +43,74 @@ pub struct Data { pub buffer: Subbuffer<[f32]>, } +fn render_pass< + R: ClassicalRenderer + std::marker::Sync, + S: Scene + std::marker::Sync, +>( + settings: &RenderSettings, + renderer: &R, + scene: &S, + camera: &BasicCamera, + samples: u32, + buffer: &mut [Float], +) { + buffer.par_chunks_mut(3).enumerate().for_each(|(i, c)| { + let x = (i % settings.width as usize) as u32; + let y = (i / settings.width as usize) as u32; + + let mut rng = SmallRng::seed_from_u64( + (x + y * settings.width) as u64 + + (settings.width as u64 * settings.height as u64 * samples as u64), + ); + let r = renderer.render_pixel(&scene, &camera, x, y, &mut rng); + c[0] += r.r(); + c[1] += r.g(); + c[2] += r.b(); + }); +} + +#[allow(clippy::type_complexity)] +pub const RENDERER: [&str; 5] = [ + "Depth", + "Path tracer", + "Path tracer importance", + "Next event estimation", + "MIS", +]; + +fn render_pass_renderer + Sync>( + settings: &RenderSettings, + scene: &S, + camera: &BasicCamera, + samples: u32, + buffer: &mut [Float], +) { + match settings.renderer_id { + 0 => { + let r = DepthRenderer::new(settings.width, settings.height); + render_pass(settings, &r, scene, camera, samples, buffer); + } + 1 => { + let r = PathTracer::new(settings.width, settings.height); + render_pass(settings, &r, scene, camera, samples, buffer); + } + 2 => { + let r = PathTracerImportance::new(settings.width, settings.height); + render_pass(settings, &r, scene, camera, samples, buffer); + } + 3 => { + let r = NextEventEstimation::new(settings.width, settings.height); + render_pass(settings, &r, scene, camera, samples, buffer); + } + 4 => { + let r = MIS::new(settings.width, settings.height); + render_pass(settings, &r, scene, camera, samples, buffer); + } + + _ => panic!("Unknown renderer"), + } +} + pub fn render_thread( s: RenderSettings, rx: Receiver, @@ -82,8 +134,6 @@ pub fn render_thread( settings.camera_horizontal_fov, ); - let mut renderer = (RENDERER[settings.renderer_id].1)(settings.width, settings.height); - let mut samples = 0; loop { while let Ok(s) = rx.try_recv() { @@ -99,24 +149,17 @@ pub fn render_thread( settings.camera_horizontal_fov, ); buffer = vec![0.0; settings.width as usize * settings.height as usize * 3]; - renderer = (RENDERER[settings.renderer_id].1)(settings.width, settings.height); samples = 0; } - buffer.par_chunks_mut(3).enumerate().for_each(|(i, c)| { - let x = (i % settings.width as usize) as u32; - let y = (i / settings.width as usize) as u32; - - let mut rng = SmallRng::seed_from_u64( - (x + y * settings.width) as u64 - + (settings.width as u64 * settings.height as u64 * samples as u64), - ); - let r = renderer.render_pixel(&scene, &camera, x, y, &mut rng); - c[0] += r.r(); - c[1] += r.g(); - c[2] += r.b(); - }); - + match &scene { + examples::ExampleSceneEnum::AccelerationStructureScene(s) => { + render_pass_renderer(&settings, s, &camera, samples, &mut buffer) + } + examples::ExampleSceneEnum::TriangleBVH(s) => { + render_pass_renderer(&settings, s, &camera, samples, &mut buffer) + } + } samples += 1; let data = Data { diff --git a/ray-tracing-image/src/main.rs b/ray-tracing-image/src/main.rs index 423eba3..416b5ef 100644 --- a/ray-tracing-image/src/main.rs +++ b/ray-tracing-image/src/main.rs @@ -58,5 +58,13 @@ fn main() -> ImageResult<()> { let r = PathTracerImportance::new(400, 400); - render_image(&r, &s.get_scene(), &c, "test.exr", 1048) + let s = s.get_scene(); + match &s { + ray_tracing_scene::examples::ExampleSceneEnum::AccelerationStructureScene(s) => { + render_image(&r, s, &c, "test.exr", 1048) + } + ray_tracing_scene::examples::ExampleSceneEnum::TriangleBVH(s) => { + render_image(&r, s, &c, "test.exr", 1048) + } + } } diff --git a/ray-tracing-pbrt-scene/src/scene.rs b/ray-tracing-pbrt-scene/src/scene.rs index 01c1143..5fe86af 100644 --- a/ray-tracing-pbrt-scene/src/scene.rs +++ b/ray-tracing-pbrt-scene/src/scene.rs @@ -1,4 +1,7 @@ -use ray_tracing_core::{prelude::Rng, scene::Scene}; +use ray_tracing_core::{ + prelude::{Material, Rng}, + scene::Scene, +}; use crate::shape::Shape; @@ -8,19 +11,25 @@ pub struct PbrtScene { } impl Scene for PbrtScene { + type Mat<'a> + = &'a dyn Material + where + R: 'a; + fn intersect( &self, ray: ray_tracing_core::prelude::Ray, min: ray_tracing_core::prelude::Float, max: ray_tracing_core::prelude::Float, - ) -> Option> { + ) -> Option>> { let mut i = None; for s in &self.shapes { if let Some(new_i) = s.intersect::(ray, min, max) - && i.as_ref() - .is_none_or(|i: &ray_tracing_core::scene::Intersection<'_, R>| { + && i.as_ref().is_none_or( + |i: &ray_tracing_core::scene::Intersection<'_, R, Self::Mat<'_>>| { i.t() > new_i.t() - }) + }, + ) { i = Some(new_i); } @@ -29,12 +38,15 @@ impl Scene for PbrtScene { i } - fn sample_light( + fn sample_light<'b>( &self, w_in: ray_tracing_core::prelude::Dir3, - intersection: &ray_tracing_core::scene::Intersection<'_, R>, + intersection: &ray_tracing_core::scene::Intersection<'_, R, Self::Mat<'b>>, rng: &mut R, - ) -> Option> { + ) -> Option> + where + Self: 'b, + { None } } diff --git a/ray-tracing-pbrt-scene/src/shape.rs b/ray-tracing-pbrt-scene/src/shape.rs index 4a5011c..a3c228f 100644 --- a/ray-tracing-pbrt-scene/src/shape.rs +++ b/ray-tracing-pbrt-scene/src/shape.rs @@ -161,7 +161,7 @@ impl Shape { ray: Ray, min: Float, max: Float, - ) -> Option> { + ) -> Option>> { let ray = self.ctm.transform_ray(ray); match &self.obj { diff --git a/ray-tracing-scene/src/acceleration_structure/mod.rs b/ray-tracing-scene/src/acceleration_structure/mod.rs index 9064988..ca8bab9 100644 --- a/ray-tracing-scene/src/acceleration_structure/mod.rs +++ b/ray-tracing-scene/src/acceleration_structure/mod.rs @@ -73,12 +73,17 @@ impl AccelerationStructureScene { } impl, R: Rng> Scene for AccelerationStructureScene { + type Mat<'a> + = &'a dyn Material + where + A: 'a, + R: 'a; fn intersect( &self, ray: Ray, min: Float, max: Float, - ) -> Option> { + ) -> Option>> { let (t, n, i) = self.acceleration_structure.intersect(ray, min, max)?; let material = &self.materials[i as usize]; @@ -98,12 +103,15 @@ impl, R: Rng> Scene for AccelerationStructureSc )) } - fn sample_light( + fn sample_light<'b>( &self, _w_in: Dir3, - _intersection: &ray_tracing_core::scene::Intersection<'_, R>, + _intersection: &ray_tracing_core::scene::Intersection<'_, R, Self::Mat<'b>>, rng: &mut R, - ) -> Option> { + ) -> Option> + where + Self: 'b, + { let t = self.lights.choose(rng); if let Some(&(t, v)) = t { diff --git a/ray-tracing-scene/src/basic_scene.rs b/ray-tracing-scene/src/basic_scene.rs index 4b764d7..51e1465 100644 --- a/ray-tracing-scene/src/basic_scene.rs +++ b/ray-tracing-scene/src/basic_scene.rs @@ -26,9 +26,24 @@ impl Default for BasicScene { } } -impl> Scene for BasicScene { - fn intersect(&self, ray: Ray, min: Float, max: Float) -> Option> { - let mut intersection: Option> = None; +impl Scene for BasicScene +where + R: Rng, + M: Material, +{ + type Mat<'a> + = &'a dyn Material + where + M: 'a, + R: 'a; + + fn intersect( + &self, + ray: Ray, + min: Float, + max: Float, + ) -> Option>> { + let mut intersection: Option>> = None; for &(c, r) in &self.spheres { let offset = ray.start() - c; @@ -41,7 +56,7 @@ impl> Scene for BasicScene { let int = Intersection::new( d, ((ray.start() + d * ray.dir()) - c).normalize(), - Some(&self.material), + Some(&self.material as &dyn Material), None, 0.0, ); @@ -66,12 +81,15 @@ impl> Scene for BasicScene { ))) } - fn sample_light( + fn sample_light<'b>( &self, _w_in: Dir3, - _intersection: &Intersection<'_, R>, + _intersection: &Intersection<'_, R, Self::Mat<'b>>, _rng: &mut R, - ) -> Option> { + ) -> Option> + where + Self: 'b, + { None } } diff --git a/ray-tracing-scene/src/examples/basic_cornell.rs b/ray-tracing-scene/src/examples/basic_cornell.rs index 5d648ba..e2df3eb 100644 --- a/ray-tracing-scene/src/examples/basic_cornell.rs +++ b/ray-tracing-scene/src/examples/basic_cornell.rs @@ -1,6 +1,9 @@ use std::cell::OnceCell; -use crate::triangle_bvh::{BVHMaterial, Triangle, TriangleBVH}; +use crate::{ + examples::ExampleSceneEnum, + triangle_bvh::{BVHMaterial, Triangle, TriangleBVH}, +}; use super::ExampleScene; @@ -26,7 +29,7 @@ impl Default for BasicCornell { } impl ExampleScene for BasicCornell { - fn get_scene(&self) -> Box + Sync> { + fn get_scene(&self) -> ExampleSceneEnum { let s = self.scene.get_or_init(|| { let side_length = 1.5; let light_size = 0.5; @@ -95,7 +98,7 @@ impl ExampleScene for BasicCornell { ) }); - Box::new(s.clone()) as Box + Sync> + ExampleSceneEnum::TriangleBVH(s.clone()) } fn get_camera_pos(&self) -> Pos3 { diff --git a/ray-tracing-scene/src/examples/cornell2.rs b/ray-tracing-scene/src/examples/cornell2.rs index 8145f87..52cdb31 100644 --- a/ray-tracing-scene/src/examples/cornell2.rs +++ b/ray-tracing-scene/src/examples/cornell2.rs @@ -4,6 +4,7 @@ use ray_tracing_material::{diffuse::DiffuseMaterial, mirror::Mirror}; use std::cell::OnceCell; use crate::{ + examples::ExampleSceneEnum, parse_obj::ObjData, triangle_bvh::{BVHMaterial, Triangle, TriangleBVH}, }; @@ -29,7 +30,7 @@ impl Default for Cornell2 { } impl ExampleScene for Cornell2 { - fn get_scene(&self) -> Box + Sync> { + fn get_scene(&self) -> ExampleSceneEnum { let s = self.scene.get_or_init(|| { let obj = ObjData::new("ray-tracing-scene/obj/cornell_box.obj").unwrap(); @@ -61,7 +62,7 @@ impl ExampleScene for Cornell2 { TriangleBVH::new(obj.vertices, triangles, materials) }); - Box::new(s.clone()) + ExampleSceneEnum::TriangleBVH(s.clone()) } fn get_camera_pos(&self) -> Pos3 { diff --git a/ray-tracing-scene/src/examples/mis_test.rs b/ray-tracing-scene/src/examples/mis_test.rs index 1a7aaa2..38a606c 100644 --- a/ray-tracing-scene/src/examples/mis_test.rs +++ b/ray-tracing-scene/src/examples/mis_test.rs @@ -1,5 +1,8 @@ use super::ExampleScene; -use crate::triangle_bvh::{BVHMaterial, Triangle, TriangleBVH}; +use crate::{ + examples::ExampleSceneEnum, + triangle_bvh::{BVHMaterial, Triangle, TriangleBVH}, +}; use ray_tracing_core::{light::AreaLight, prelude::*, scene::Scene}; use ray_tracing_material::{ microfacet::{BeckmannDistribution, Microfacet}, @@ -70,7 +73,7 @@ impl Default for MISTest { } impl ExampleScene for MISTest { - fn get_scene(&self) -> Box + Sync> { + fn get_scene(&self) -> ExampleSceneEnum { let s = self.scene.get_or_init(move || { let mut vertices = Vec::new(); let mut triangles = Vec::new(); @@ -155,7 +158,7 @@ impl ExampleScene for MISTest { TriangleBVH::new(vertices, triangles, materials) }); - Box::new(s.clone()) as Box + Sync> + ExampleSceneEnum::TriangleBVH(s.clone()) } fn get_camera_pos(&self) -> Pos3 { diff --git a/ray-tracing-scene/src/examples/mod.rs b/ray-tracing-scene/src/examples/mod.rs index de7b5ed..d4f7c46 100644 --- a/ray-tracing-scene/src/examples/mod.rs +++ b/ray-tracing-scene/src/examples/mod.rs @@ -5,8 +5,17 @@ use ray_tracing_material::mirror::Mirror; use std::collections::HashMap; use std::fmt::Debug; -pub trait ExampleScene { - fn get_scene(&self) -> Box + Sync>; +use crate::acceleration_structure::triangle_bvh::TriangleBVH; +use crate::acceleration_structure::AccelerationStructureScene; +use crate::basic_scene::BasicScene; + +pub enum ExampleSceneEnum { + AccelerationStructureScene(AccelerationStructureScene, R>), + TriangleBVH(crate::triangle_bvh::TriangleBVH), +} + +pub trait ExampleScene { + fn get_scene(&self) -> ExampleSceneEnum; fn get_camera_pos(&self) -> Pos3; @@ -50,8 +59,8 @@ pub fn example_scenes() -> HashMap<&'static str, Box Presentation { } impl ExampleScene for Presentation { - fn get_scene(&self) -> Box + Sync> { + fn get_scene(&self) -> ExampleSceneEnum { let s = self.scene.get_or_init(|| { let obj = ObjData::new("ray-tracing-scene/obj/stanford_dragon.obj").unwrap(); @@ -129,7 +130,7 @@ impl ExampleScene for Presentation { TriangleBVH::new(vertices, triangles, materials) }); - Box::new(s.clone()) + ExampleSceneEnum::TriangleBVH(s.clone()) } fn get_camera_pos(&self) -> Pos3 { diff --git a/ray-tracing-scene/src/examples/sphere.rs b/ray-tracing-scene/src/examples/sphere.rs index 4ce2d6a..8971c46 100644 --- a/ray-tracing-scene/src/examples/sphere.rs +++ b/ray-tracing-scene/src/examples/sphere.rs @@ -1,5 +1,5 @@ use super::ExampleScene; -use crate::basic_scene::BasicScene; +use crate::{basic_scene::BasicScene, examples::ExampleSceneEnum}; use ray_tracing_core::prelude::*; use std::cell::{Cell, OnceCell}; @@ -17,28 +17,33 @@ impl SphereScene { } } -impl + Clone + 'static> ExampleScene for SphereScene { - fn get_scene(&self) -> Box + Sync> { - let s = self - .scene - .get_or_init(|| BasicScene::new(self.material.take().unwrap())); +// impl ExampleScene for SphereScene +// where +// R: Rng + 'static, +// M: Material + Clone + 'static, +// M: Send + Sync, +// { +// fn get_scene(&self) -> ExampleSceneEnum { +// let s = self +// .scene +// .get_or_init(|| BasicScene::new(self.material.take().unwrap())); - Box::new(s.clone()) - } +// ExampleSceneEnum::BasicScene(s.clone()) +// } - fn get_camera_pos(&self) -> Pos3 { - Pos3::new(5.0, 1.0, 0.0) - } +// fn get_camera_pos(&self) -> Pos3 { +// Pos3::new(5.0, 1.0, 0.0) +// } - fn get_camera_look_at(&self) -> Pos3 { - Pos3::new(0.0, 0.0, 0.0) - } +// fn get_camera_look_at(&self) -> Pos3 { +// Pos3::new(0.0, 0.0, 0.0) +// } - fn get_camera_up(&self) -> Dir3 { - Dir3::up() - } +// fn get_camera_up(&self) -> Dir3 { +// Dir3::up() +// } - fn get_horizontal_fov(&self) -> Float { - Float::to_radians(90.0) - } -} +// fn get_horizontal_fov(&self) -> Float { +// Float::to_radians(90.0) +// } +// } diff --git a/ray-tracing-scene/src/examples/stanford_dragon.rs b/ray-tracing-scene/src/examples/stanford_dragon.rs index ccc14a8..6bae783 100644 --- a/ray-tracing-scene/src/examples/stanford_dragon.rs +++ b/ray-tracing-scene/src/examples/stanford_dragon.rs @@ -1,4 +1,5 @@ use crate::{ + examples::ExampleSceneEnum, parse_obj::ObjData, triangle_bvh::{BVHMaterial, Triangle, TriangleBVH}, }; @@ -24,7 +25,7 @@ impl> StanfordDragon { } impl + 'static> ExampleScene for StanfordDragon { - fn get_scene(&self) -> Box + Sync> { + fn get_scene(&self) -> ExampleSceneEnum { let s = self.scene.get_or_init(|| { let obj = ObjData::new("ray-tracing-scene/obj/stanford_dragon.obj").unwrap(); @@ -83,7 +84,7 @@ impl + 'static> ExampleScene for StanfordDra TriangleBVH::new(vertices, triangles, materials) }); - Box::new(s.clone()) + ExampleSceneEnum::TriangleBVH(s.clone()) } fn get_camera_pos(&self) -> Pos3 { diff --git a/ray-tracing-scene/src/examples/stanford_dragon_as.rs b/ray-tracing-scene/src/examples/stanford_dragon_as.rs index 7be3517..447f2c5 100644 --- a/ray-tracing-scene/src/examples/stanford_dragon_as.rs +++ b/ray-tracing-scene/src/examples/stanford_dragon_as.rs @@ -11,6 +11,7 @@ use crate::{ triangle_bvh::{Triangle, TriangleBVH}, ASMaterial, AccelerationStructureScene, }, + examples::ExampleSceneEnum, parse_obj::ObjData, }; @@ -34,8 +35,8 @@ impl Default for StanfordDragon { } } -impl ExampleScene for StanfordDragon { - fn get_scene(&self) -> Box + Sync> { +impl ExampleScene for StanfordDragon { + fn get_scene(&self) -> ExampleSceneEnum { let s = self.scene.get_or_init(|| { let obj = ObjData::new("ray-tracing-scene/obj/stanford_dragon.obj").unwrap(); @@ -111,7 +112,7 @@ impl ExampleScene for StanfordDragon { }); let n: AccelerationStructureScene<_, _> = s.clone(); - Box::new(n) + ExampleSceneEnum::AccelerationStructureScene(n) } fn get_camera_pos(&self) -> Pos3 { diff --git a/ray-tracing-scene/src/triangle_bvh.rs b/ray-tracing-scene/src/triangle_bvh.rs index 3b61f30..3d59290 100644 --- a/ray-tracing-scene/src/triangle_bvh.rs +++ b/ray-tracing-scene/src/triangle_bvh.rs @@ -318,12 +318,17 @@ impl TriangleBVH { } impl Scene for TriangleBVH { + type Mat<'a> + = &'a dyn Material + where + R: 'a; + fn intersect( &self, ray: Ray, min: Float, max: Float, - ) -> Option> { + ) -> Option>> { let (i, t) = self.intersect_bvh(0, ray, min, max)?; let triangle = self.triangles[i as usize]; @@ -342,12 +347,15 @@ impl Scene for TriangleBVH { )) } - fn sample_light( + fn sample_light<'b>( &self, _w_in: Dir3, - _intersection: &Intersection<'_, R>, + _intersection: &Intersection<'_, R, Self::Mat<'b>>, rng: &mut R, - ) -> Option> { + ) -> Option> + where + Self: 'b, + { let t = self.lights.choose(rng); if let Some(t) = t { diff --git a/ray-tracing-tev/src/main.rs b/ray-tracing-tev/src/main.rs index aa96c11..9d46110 100644 --- a/ray-tracing-tev/src/main.rs +++ b/ray-tracing-tev/src/main.rs @@ -36,13 +36,14 @@ struct Args { } fn render_image< + 'sc, R: ClassicalRenderer + Sync, S: Scene + Sync, C: Camera + Sync, >( name: impl AsRef, renderer: &R, - scene: &S, + scene: &'sc S, camera: &C, samples_per_pixel: usize, tev: &mut TevClient, @@ -108,7 +109,7 @@ fn render_image< Ok(()) } -fn choose_renderer(args: &Args, scene: &str, s: &S, c: &C, tev: &mut TevClient) +fn choose_renderer<'sc, S, C>(args: &Args, scene: &str, s: &'sc S, c: &C, tev: &mut TevClient) where S: Scene + Sync, C: Camera + Sync, @@ -183,7 +184,7 @@ fn main() { let mut client = TevClient::wrap(TcpStream::connect(&args.tev).unwrap()); - let map = example_scenes(); + let map = example_scenes::(); let scenes: Vec<&str> = if args.pbrt_filename.is_none() { if args.scenes.is_empty() { @@ -208,8 +209,14 @@ fn main() { f.get_camera_up(), f.get_horizontal_fov(), ); - - choose_renderer(&args, scene, &s, &c, &mut client); + match &s { + ray_tracing_scene::examples::ExampleSceneEnum::AccelerationStructureScene(s) => { + choose_renderer(&args, scene, s, &c, &mut client); + } + ray_tracing_scene::examples::ExampleSceneEnum::TriangleBVH(s) => { + choose_renderer(&args, scene, s, &c, &mut client); + } + } } if let Some(pbrt_filename) = &args.pbrt_filename {