From bb2089477ee1cbd7adee11967ae597209b2b1f33 Mon Sep 17 00:00:00 2001 From: hal8174 Date: Tue, 26 Aug 2025 20:27:24 +0200 Subject: [PATCH] Add light as associated type for scene and get something to draw with pbrt materials. --- Cargo.lock | 1 + ray-tracing-core/src/light.rs | 12 +++ ray-tracing-core/src/scene.rs | 33 +++++-- ray-tracing-pbrt-scene/Cargo.toml | 1 + ray-tracing-pbrt-scene/examples/pbrt-test.rs | 3 +- ray-tracing-pbrt-scene/src/lib.rs | 58 ++++++----- ray-tracing-pbrt-scene/src/material.rs | 84 +++++++++++++--- ray-tracing-pbrt-scene/src/scene.rs | 95 ++++++++++++++++--- ray-tracing-pbrt-scene/src/shape.rs | 37 ++++++-- ray-tracing-pbrt-scene/src/texture.rs | 17 ++-- .../src/acceleration_structure/mod.rs | 11 ++- ray-tracing-scene/src/basic_scene.rs | 12 ++- ray-tracing-scene/src/triangle_bvh.rs | 9 +- 13 files changed, 286 insertions(+), 87 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4386486..d846c6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2315,6 +2315,7 @@ dependencies = [ "image 0.25.6", "miette", "nom 8.0.0", + "rand", "ray-tracing-core", "thiserror 2.0.12", ] diff --git a/ray-tracing-core/src/light.rs b/ray-tracing-core/src/light.rs index 9201fc0..36e75d1 100644 --- a/ray-tracing-core/src/light.rs +++ b/ray-tracing-core/src/light.rs @@ -5,6 +5,18 @@ pub trait Light: Send + Sync + Debug { fn emit(&self, w_in: Dir3, rng: &mut R) -> Color; } +impl Light for &'_ dyn Light { + fn emit(&self, w_in: Dir3, rng: &mut R) -> Color { + (*self).emit(w_in, rng) + } +} + +impl> Light for &L { + fn emit(&self, w_in: Dir3, rng: &mut R) -> Color { + (*self).emit(w_in, rng) + } +} + #[derive(Clone, Debug)] pub struct AreaLight { pub(crate) color: Color, diff --git a/ray-tracing-core/src/scene.rs b/ray-tracing-core/src/scene.rs index 5649060..f3a9c03 100644 --- a/ray-tracing-core/src/scene.rs +++ b/ray-tracing-core/src/scene.rs @@ -8,37 +8,43 @@ pub trait Scene { Self: 'a, R: 'a; + type Light<'b>: Light + where + Self: 'b, + R: 'b; + fn intersect( &self, ray: Ray, min: Float, max: Float, - ) -> Option>>; + ) -> Option, Self::Light<'_>>>; fn sample_light<'b>( &self, w_in: Dir3, - intersection: &Intersection<'_, R, Self::Mat<'b>>, + intersection: &Intersection, Self::Light<'b>>, rng: &mut R, ) -> Option> where Self: 'b; } -pub struct Intersection<'sc, R: Rng, M: Material + 'sc> { +pub struct Intersection, L: Light> { t: Float, normal: Dir3, material: Option, - light: Option<&'sc dyn Light>, + light: Option, light_pdf: Float, + r: std::marker::PhantomData, } -impl<'sc, R: Rng, M: Material> Intersection<'sc, R, M> { +impl, L: Light> Intersection { pub fn new( t: Float, normal: Dir3, material: Option, - light: Option<&'sc dyn Light>, + light: Option, light_pdf: Float, ) -> Self { Self { @@ -47,6 +53,7 @@ impl<'sc, R: Rng, M: Material> Intersection<'sc, R, M> { material, light, light_pdf, + r: std::marker::PhantomData, } } @@ -62,8 +69,8 @@ impl<'sc, R: Rng, M: Material> Intersection<'sc, R, M> { self.material.as_ref() } - pub fn light(&self) -> Option<&'sc dyn Light> { - self.light + pub fn light(&self) -> Option<&L> { + self.light.as_ref() } pub fn light_pdf(&self) -> Float { @@ -120,19 +127,25 @@ impl + ?Sized, R: Rng> Scene for Box { T: 'a, R: 'a; + type Light<'b> + = T::Light<'b> + where + T: 'b, + R: 'b; + fn intersect( &self, ray: Ray, min: Float, max: Float, - ) -> Option>> { + ) -> Option, Self::Light<'_>>> { self.deref().intersect(ray, min, max) } fn sample_light<'b>( &self, w_in: Dir3, - intersection: &Intersection<'_, R, Self::Mat<'b>>, + intersection: &Intersection, Self::Light<'b>>, rng: &mut R, ) -> Option> where diff --git a/ray-tracing-pbrt-scene/Cargo.toml b/ray-tracing-pbrt-scene/Cargo.toml index 0fe2c6c..27409e8 100644 --- a/ray-tracing-pbrt-scene/Cargo.toml +++ b/ray-tracing-pbrt-scene/Cargo.toml @@ -11,3 +11,4 @@ nom = "8.0.0" thiserror = "2.0.12" image = "0.25.6" const_format = "0.2.34" +rand = { version = "0.8.5", features = ["small_rng"] } diff --git a/ray-tracing-pbrt-scene/examples/pbrt-test.rs b/ray-tracing-pbrt-scene/examples/pbrt-test.rs index ac9d964..754d8a2 100644 --- a/ray-tracing-pbrt-scene/examples/pbrt-test.rs +++ b/ray-tracing-pbrt-scene/examples/pbrt-test.rs @@ -1,4 +1,5 @@ use clap::Parser; +use rand::rngs::SmallRng; use ray_tracing_pbrt_scene::parse_pbrt_v4; use std::path::PathBuf; @@ -10,7 +11,7 @@ struct Args { fn main() -> Result<(), miette::Error> { let args = Args::parse(); - let _t = parse_pbrt_v4(args.filename)?; + let _t = parse_pbrt_v4::(args.filename)?; // dbg!(t); diff --git a/ray-tracing-pbrt-scene/src/lib.rs b/ray-tracing-pbrt-scene/src/lib.rs index f6a3751..3196f9a 100644 --- a/ray-tracing-pbrt-scene/src/lib.rs +++ b/ray-tracing-pbrt-scene/src/lib.rs @@ -7,8 +7,9 @@ use material::PbrtMaterial; use miette::{IntoDiagnostic, Result, bail, miette}; use ray_tracing_core::{ affine_transform::AffineTransform, + color::Color, math::{Dir3, Pos3}, - prelude::Float, + prelude::{Float, Rng}, }; use std::{ collections::HashMap, @@ -66,7 +67,7 @@ struct PbrtCamera { } #[derive(Debug)] -enum Statement { +enum Statement { AttributeBegin, AttributeEnd, WorldBegin, @@ -79,12 +80,12 @@ enum Statement { Unknown(String, Vec), Transform(AffineTransform), Texture(String, Arc), - Material(Arc), - MakeNamedMaterial(String, Arc), + Material(Arc>), + MakeNamedMaterial(String, Arc>), NamedMaterial(String), } -fn parse_look_at(iter: &mut Tokenizer) -> Result { +fn parse_look_at(iter: &mut Tokenizer) -> Result> { let eye = Pos3::new(iter.parse_next()?, iter.parse_next()?, iter.parse_next()?); let look_at = Pos3::new(iter.parse_next()?, iter.parse_next()?, iter.parse_next()?); let up = Dir3::new(iter.parse_next()?, iter.parse_next()?, iter.parse_next()?); @@ -95,7 +96,7 @@ fn parse_look_at(iter: &mut Tokenizer) -> Result { )) } -fn parse_shape(iter: &mut Tokenizer) -> Result { +fn parse_shape(iter: &mut Tokenizer) -> Result> { let shape_type = iter .next_if_string_value() .ok_or(miette!("unable to get shape type"))??; @@ -312,7 +313,7 @@ fn parse_shape(iter: &mut Tokenizer) -> Result { } } -fn parse_camera(tokenizer: &mut Tokenizer) -> Result { +fn parse_camera(tokenizer: &mut Tokenizer) -> Result> { let camera_type = tokenizer .next_if_string_value() .ok_or(miette!("unable to get shape type"))??; @@ -382,7 +383,7 @@ fn parse_camera(tokenizer: &mut Tokenizer) -> Result { } impl Lexer { - fn next(&mut self, context: &PbrtContext) -> Option> { + fn next(&mut self, context: &PbrtContext) -> Option>> { match self.input.next() { Some(Ok(Token::Identifier(s))) => match s.as_str() { "AttributeBegin" => Some(Ok(Statement::AttributeBegin)), @@ -481,7 +482,7 @@ fn parse_transform(input: &mut Tokenizer) -> Result { .ok_or(miette!("Unable to invert transformation")) } -fn parse_translate(iter: &mut Tokenizer) -> Result { +fn parse_translate(iter: &mut Tokenizer) -> Result> { let pos = Pos3::new(iter.parse_next()?, iter.parse_next()?, iter.parse_next()?); Ok(Statement::ConcatTransform(AffineTransform::translation( @@ -489,7 +490,7 @@ fn parse_translate(iter: &mut Tokenizer) -> Result { ))) } -fn parse_scale(iter: &mut Tokenizer) -> Result { +fn parse_scale(iter: &mut Tokenizer) -> Result> { Ok(Statement::ConcatTransform(AffineTransform::scale( iter.parse_next()?, iter.parse_next()?, @@ -497,7 +498,7 @@ fn parse_scale(iter: &mut Tokenizer) -> Result { ))) } -fn parse_rotate(iter: &mut Tokenizer) -> Result { +fn parse_rotate(iter: &mut Tokenizer) -> Result> { let angle = iter.parse_parameter()?; let dir = Dir3::new( iter.parse_parameter()?, @@ -557,7 +558,7 @@ impl Parser { } impl Parser { - fn next(&mut self, context: &PbrtContext) -> Option> { + fn next(&mut self, context: &PbrtContext) -> Option>> { if let Some(iter) = &mut self.inner { if let Some(statement) = iter.next(context) { return Some(statement); @@ -579,16 +580,21 @@ impl Parser { } #[derive(Debug)] -pub struct Pbrt { +pub struct Pbrt { pub settings: PbrtWorldSettings, - pub scene: PbrtScene, + pub scene: PbrtScene, } -impl Pbrt { +impl Pbrt { fn new(settings: PbrtWorldSettings) -> Self { Self { settings, - scene: PbrtScene { shapes: Vec::new() }, + scene: PbrtScene { + shapes: Vec::new(), + infinite_light: Some(scene::PbrtInfiniteLight { + color: Color::white(), + }), + }, } } } @@ -601,14 +607,14 @@ pub struct PbrtWorldSettings { } #[derive(Debug)] -pub struct PbrtContext { +pub struct PbrtContext { ctm: Vec, textures: HashMap>, - material: Vec>, - materials: HashMap>, + material: Vec>>, + materials: HashMap>>, } -impl PbrtContext { +impl PbrtContext { fn new() -> Self { Self { ctm: vec![AffineTransform::identity()], @@ -626,11 +632,11 @@ impl PbrtContext { self.textures.get(name) } - pub fn get_named_material(&self, name: &String) -> Option<&Arc> { + pub fn get_named_material(&self, name: &String) -> Option<&Arc>> { self.materials.get(name) } - pub fn get_material(&self) -> Option<&Arc> { + pub fn get_material(&self) -> Option<&Arc>> { self.material.last() } @@ -656,7 +662,9 @@ impl PbrtContext { } } -fn inner_parse_pbrt(path: impl AsRef + std::fmt::Debug) -> Result { +fn inner_parse_pbrt( + path: impl AsRef + std::fmt::Debug, +) -> Result> { // unwrap on context.last() ok because context is never empty let mut context = PbrtContext::new(); @@ -792,6 +800,8 @@ fn inner_parse_pbrt(path: impl AsRef + std::fmt::Debug) -> Result { Ok(pbrt) } -pub fn parse_pbrt_v4(path: impl AsRef + std::fmt::Debug) -> Result { +pub fn parse_pbrt_v4( + path: impl AsRef + std::fmt::Debug, +) -> Result> { inner_parse_pbrt(path) } diff --git a/ray-tracing-pbrt-scene/src/material.rs b/ray-tracing-pbrt-scene/src/material.rs index dfc4649..a050559 100644 --- a/ray-tracing-pbrt-scene/src/material.rs +++ b/ray-tracing-pbrt-scene/src/material.rs @@ -1,4 +1,4 @@ -use ray_tracing_core::color::Color; +use ray_tracing_core::{color::Color, material::SampleResult, prelude::*}; use crate::{ either::Either, @@ -7,12 +7,35 @@ use crate::{ use super::*; -pub trait PbrtMaterial: std::fmt::Debug + Send + Sync {} +pub trait PbrtMaterial: std::fmt::Debug + Send + Sync { + /// evaluate f(w_in, w_out) + fn eval(&self, u: Float, v: Float, w_in: Dir3, w_out: Dir3, rng: &mut R) -> Color; -pub fn parse_make_named_material( + /// sample w_out and return: + /// f(w_in, w_out) * cos(theta) / pdf + fn sample(&self, u: Float, v: Float, w_in: Dir3, rng: &mut R) -> SampleResult { + let w_out = Dir3::sample_cosine_hemisphere(rng); + + SampleResult::new( + w_out, + self.eval(u, v, w_in, w_out, rng) * FloatConsts::PI, + false, + ) + } + + /// returns the pdf for (w_in, w_out) + fn pdf(&self, u: Float, v: Float, w_in: Dir3, w_out: Dir3) -> Float { + let _ = v; + let _ = u; + let _ = w_out; + FloatConsts::FRAC_1_PI * Float::max(w_in.y(), 0.0) + } +} + +pub fn parse_make_named_material( input: &mut Tokenizer, - context: &PbrtContext, -) -> Result<(String, Arc)> { + context: &PbrtContext, +) -> Result<(String, Arc>)> { let name = input.next_string_value()?; if input.next_string_value()?.as_str() != "string type" { @@ -42,7 +65,16 @@ struct PbrtCoatedDiffuseMaterial { >, } -impl PbrtMaterial for PbrtCoatedDiffuseMaterial {} +impl PbrtMaterial for PbrtCoatedDiffuseMaterial { + fn eval(&self, u: Float, v: Float, w_in: Dir3, w_out: Dir3, rng: &mut R) -> Color { + let _ = rng; + let _ = w_out; + let _ = w_in; + let _ = u; + let _ = v; + Color::black() + } +} #[derive(Debug)] #[allow(dead_code)] @@ -57,7 +89,16 @@ struct PbrtDielectricMaterial { vroughness: Either>, } -impl PbrtMaterial for PbrtDielectricMaterial {} +impl PbrtMaterial for PbrtDielectricMaterial { + fn eval(&self, u: Float, v: Float, w_in: Dir3, w_out: Dir3, rng: &mut R) -> Color { + let _ = rng; + let _ = w_out; + let _ = w_in; + let _ = v; + let _ = u; + Color::black() + } +} #[derive(Debug)] #[allow(dead_code)] @@ -65,11 +106,24 @@ struct PbrtDiffuseMaterial { reflectance: Either>, } -impl PbrtMaterial for PbrtDiffuseMaterial {} +impl PbrtMaterial for PbrtDiffuseMaterial { + fn eval(&self, u: Float, v: Float, w_in: Dir3, w_out: Dir3, rng: &mut R) -> Color { + let _ = rng; + let _ = w_in; + if w_out.y() >= 0.0 { + match &self.reflectance { + Either::A(v) => *v, + Either::B(t) => t.get(u, v), + } + } else { + Color::black() + } + } +} -fn parse_2d_float_texture( +fn parse_2d_float_texture( input: &mut Tokenizer, - context: &PbrtContext, + context: &PbrtContext, ) -> Result> { let n = input.next_string_value()?; @@ -79,9 +133,9 @@ fn parse_2d_float_texture( .and_then(|t| Arc::clone(t).get_2d_float_texture()) } -fn parse_2d_spectrum_texture( +fn parse_2d_spectrum_texture( input: &mut Tokenizer, - context: &PbrtContext, + context: &PbrtContext, ) -> Result> { let n = input.next_string_value()?; @@ -91,10 +145,10 @@ fn parse_2d_spectrum_texture( .and_then(|t| Arc::clone(t).get_2d_spectrum_texture()) } -pub fn parse_material( +pub fn parse_material( input: &mut Tokenizer, - context: &PbrtContext, -) -> Result> { + context: &PbrtContext, +) -> Result>> { let material: String = input.next_string_value()?; match material.as_str() { diff --git a/ray-tracing-pbrt-scene/src/scene.rs b/ray-tracing-pbrt-scene/src/scene.rs index 7a95e4a..5550882 100644 --- a/ray-tracing-pbrt-scene/src/scene.rs +++ b/ray-tracing-pbrt-scene/src/scene.rs @@ -1,47 +1,114 @@ use ray_tracing_core::{ - prelude::{Material, Rng}, - scene::Scene, + color::Color, + light::Light, + prelude::{Float, Material, Rng}, + scene::{Intersection, Scene}, }; -use crate::shape::Shape; +use crate::{material::PbrtMaterial, shape::Shape}; #[derive(Debug)] -pub struct PbrtScene { - pub(crate) shapes: Vec, +pub struct PbrtScene { + pub(crate) shapes: Vec>, + pub(crate) infinite_light: Option, } -impl Scene for PbrtScene { +#[derive(Debug)] +pub(crate) struct PbrtInfiniteLight { + pub(crate) color: Color, +} + +impl Light for PbrtInfiniteLight { + fn emit(&self, w_in: ray_tracing_core::prelude::Dir3, rng: &mut R) -> Color { + let _ = rng; + let _ = w_in; + self.color + } +} + +#[derive(Debug)] +pub struct UVMaterial<'a, R: Rng + std::fmt::Debug> { + pub(crate) u: Float, + pub(crate) v: Float, + pub(crate) material: &'a dyn PbrtMaterial, +} + +impl Material for UVMaterial<'_, R> { + fn eval( + &self, + w_in: ray_tracing_core::prelude::Dir3, + w_out: ray_tracing_core::prelude::Dir3, + rng: &mut R, + ) -> Color { + self.material.eval(self.u, self.v, w_in, w_out, rng) + } + + fn sample( + &self, + w_in: ray_tracing_core::prelude::Dir3, + rng: &mut R, + ) -> ray_tracing_core::material::SampleResult { + self.material.sample(self.u, self.v, w_in, rng) + } + + fn pdf( + &self, + w_in: ray_tracing_core::prelude::Dir3, + w_out: ray_tracing_core::prelude::Dir3, + ) -> Float { + self.material.pdf(self.u, self.v, w_in, w_out) + } +} + +impl Scene for PbrtScene { type Mat<'a> - = &'a dyn Material + = UVMaterial<'a, R> where R: 'a; + type Light<'b> + = &'b dyn Light + where + R: 'b; + fn intersect( &'_ self, ray: ray_tracing_core::prelude::Ray, min: ray_tracing_core::prelude::Float, max: ray_tracing_core::prelude::Float, - ) -> Option>> { + ) -> Option, Self::Light<'_>>> { let mut i = None; for s in &self.shapes { - if let Some(new_i) = s.intersect::(ray, min, max) + if let Some(new_i) = s.intersect(ray, min, max) && i.as_ref().is_none_or( - |i: &ray_tracing_core::scene::Intersection<'_, R, Self::Mat<'_>>| { - i.t() > new_i.t() - }, + |i: &ray_tracing_core::scene::Intersection< + R, + Self::Mat<'_>, + Self::Light<'_>, + >| { i.t() > new_i.t() }, ) { i = Some(new_i); } } - i + i.or_else(|| { + self.infinite_light.as_ref().map(|l| { + Intersection::new( + Float::INFINITY, + -ray.dir(), + None, + Some(l as &dyn Light), + 0.0, + ) + }) + }) } fn sample_light<'b>( &self, _w_in: ray_tracing_core::prelude::Dir3, - _intersection: &ray_tracing_core::scene::Intersection<'_, R, Self::Mat<'b>>, + _intersection: &ray_tracing_core::scene::Intersection, Self::Light<'b>>, _rng: &mut R, ) -> Option> where diff --git a/ray-tracing-pbrt-scene/src/shape.rs b/ray-tracing-pbrt-scene/src/shape.rs index c6630ff..7992705 100644 --- a/ray-tracing-pbrt-scene/src/shape.rs +++ b/ray-tracing-pbrt-scene/src/shape.rs @@ -2,13 +2,13 @@ use std::sync::Arc; use ray_tracing_core::{affine_transform::AffineTransform, prelude::*, scene::Intersection}; -use crate::material::PbrtMaterial; +use crate::{material::PbrtMaterial, scene::UVMaterial}; #[derive(Debug)] #[allow(dead_code)] -pub(crate) struct Shape { +pub(crate) struct Shape { pub(crate) ctm: AffineTransform, - pub(crate) material: Arc, + pub(crate) material: Arc>, pub(crate) obj: ShapeType, pub(crate) alpha: ShapeAlpha, } @@ -158,13 +158,13 @@ fn bilinear_intersection( .next() } -impl Shape { - pub(crate) fn intersect( +impl Shape { + pub(crate) fn intersect( &'_ self, ray: Ray, min: Float, max: Float, - ) -> Option>> { + ) -> Option, &'_ dyn Light>> { let ray = self.ctm.transform_ray(ray); match &self.obj { @@ -213,10 +213,19 @@ impl Shape { } false }) { + let p = ray.at(t0); + let mut phi = Float::atan2(p.y(), p.x()); + if phi < 0.0 { + phi += 2.0 * FloatConsts::PI; + } return Some(Intersection::new( t, (ray.at(t) - Pos3::zero()).normalize(), - None, + Some(UVMaterial { + u: phi, + v: Float::acos(p.z() / radius), + material: self.material.as_ref(), + }), None, 0.0, )); @@ -231,10 +240,20 @@ impl Shape { uv: _, } => { if indices.is_empty() - && let Some((t, _u, _v)) = + && let Some((t, u, v)) = bilinear_intersection(ray, min, max, [p[0], p[1], p[2], p[3]]) { - return Some(Intersection::new(t, Dir3::up(), None, None, 0.0)); + return Some(Intersection::new( + t, + Dir3::up(), + Some(UVMaterial { + u, + v, + material: self.material.as_ref(), + }), + None, + 0.0, + )); } } ShapeType::LoopSubDiv { .. } => todo!(), diff --git a/ray-tracing-pbrt-scene/src/texture.rs b/ray-tracing-pbrt-scene/src/texture.rs index 8549f6d..7e760ca 100644 --- a/ray-tracing-pbrt-scene/src/texture.rs +++ b/ray-tracing-pbrt-scene/src/texture.rs @@ -1,7 +1,10 @@ use crate::{PbrtContext, either::Either, tokenizer::Tokenizer}; use imagemap::{ImageMapEncoding, ImageMapWrap, SpectrumImageMapTexture}; use miette::{Result, miette}; -use ray_tracing_core::{color::Color, prelude::Float}; +use ray_tracing_core::{ + color::Color, + prelude::{Float, Rng}, +}; use scale::SpectrumScaleTexture2d; use std::sync::Arc; @@ -65,9 +68,9 @@ pub fn parse_rgb(input: &mut Tokenizer) -> Result { Ok(Color::new(t[0], t[1], t[2])) } -fn parse_float_texture( +fn parse_float_texture( input: &mut Tokenizer, - context: &PbrtContext, + context: &PbrtContext, ) -> Result> { let texture_class = input.next_string_value()?; @@ -138,9 +141,9 @@ fn parse_float_texture( } } -fn parse_spectrum_texture( +fn parse_spectrum_texture( input: &mut Tokenizer, - context: &PbrtContext, + context: &PbrtContext, ) -> Result> { let texture_class = input.next_string_value()?; match texture_class.as_str() { @@ -284,9 +287,9 @@ fn parse_spectrum_texture( } } -pub fn parse_texture( +pub fn parse_texture( input: &mut Tokenizer, - context: &PbrtContext, + context: &PbrtContext, ) -> Result<(String, Arc)> { let texture_name: String = input.next_string_value()?; let texture_type: String = input.next_string_value()?; diff --git a/ray-tracing-scene/src/acceleration_structure/mod.rs b/ray-tracing-scene/src/acceleration_structure/mod.rs index ca8bab9..2dc4f8f 100644 --- a/ray-tracing-scene/src/acceleration_structure/mod.rs +++ b/ray-tracing-scene/src/acceleration_structure/mod.rs @@ -78,12 +78,19 @@ impl, R: Rng> Scene for AccelerationStructureSc where A: 'a, R: 'a; + + type Light<'b> + = &'b dyn Light + where + A: 'b, + R: 'b; + fn intersect( &self, ray: Ray, min: Float, max: Float, - ) -> Option>> { + ) -> Option, Self::Light<'_>>> { let (t, n, i) = self.acceleration_structure.intersect(ray, min, max)?; let material = &self.materials[i as usize]; @@ -106,7 +113,7 @@ impl, R: Rng> Scene for AccelerationStructureSc fn sample_light<'b>( &self, _w_in: Dir3, - _intersection: &ray_tracing_core::scene::Intersection<'_, R, Self::Mat<'b>>, + _intersection: &ray_tracing_core::scene::Intersection, Self::Light<'b>>, rng: &mut R, ) -> Option> where diff --git a/ray-tracing-scene/src/basic_scene.rs b/ray-tracing-scene/src/basic_scene.rs index 51e1465..6be1972 100644 --- a/ray-tracing-scene/src/basic_scene.rs +++ b/ray-tracing-scene/src/basic_scene.rs @@ -37,13 +37,19 @@ where M: 'a, R: 'a; + type Light<'b> + = &'b dyn Light + where + M: 'b, + R: 'b; + fn intersect( &self, ray: Ray, min: Float, max: Float, - ) -> Option>> { - let mut intersection: Option>> = None; + ) -> Option, Self::Light<'_>>> { + let mut intersection: Option, Self::Light<'_>>> = None; for &(c, r) in &self.spheres { let offset = ray.start() - c; @@ -84,7 +90,7 @@ where fn sample_light<'b>( &self, _w_in: Dir3, - _intersection: &Intersection<'_, R, Self::Mat<'b>>, + _intersection: &Intersection, Self::Light<'b>>, _rng: &mut R, ) -> Option> where diff --git a/ray-tracing-scene/src/triangle_bvh.rs b/ray-tracing-scene/src/triangle_bvh.rs index 3d59290..7c4f562 100644 --- a/ray-tracing-scene/src/triangle_bvh.rs +++ b/ray-tracing-scene/src/triangle_bvh.rs @@ -323,12 +323,17 @@ impl Scene for TriangleBVH { where R: 'a; + type Light<'b> + = &'b dyn Light + where + R: 'b; + fn intersect( &self, ray: Ray, min: Float, max: Float, - ) -> Option>> { + ) -> Option, Self::Light<'_>>> { let (i, t) = self.intersect_bvh(0, ray, min, max)?; let triangle = self.triangles[i as usize]; @@ -350,7 +355,7 @@ impl Scene for TriangleBVH { fn sample_light<'b>( &self, _w_in: Dir3, - _intersection: &Intersection<'_, R, Self::Mat<'b>>, + _intersection: &Intersection, Self::Light<'b>>, rng: &mut R, ) -> Option> where