Add light as associated type for scene and get something to draw with pbrt materials.

This commit is contained in:
hal8174 2025-08-26 20:27:24 +02:00
parent b54a2b16fe
commit bb2089477e
Signed by: hal8174
SSH key fingerprint: SHA256:NN98ZYwnrreQLSOV/g+amY7C3yL/mS1heD7bi5t6PPw
13 changed files with 286 additions and 87 deletions

1
Cargo.lock generated
View file

@ -2315,6 +2315,7 @@ dependencies = [
"image 0.25.6",
"miette",
"nom 8.0.0",
"rand",
"ray-tracing-core",
"thiserror 2.0.12",
]

View file

@ -5,6 +5,18 @@ pub trait Light<R: Rng>: Send + Sync + Debug {
fn emit(&self, w_in: Dir3, rng: &mut R) -> Color;
}
impl<R: Rng> Light<R> for &'_ dyn Light<R> {
fn emit(&self, w_in: Dir3, rng: &mut R) -> Color {
(*self).emit(w_in, rng)
}
}
impl<R: Rng, L: Light<R>> Light<R> 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,

View file

@ -8,37 +8,43 @@ pub trait Scene<R: Rng> {
Self: 'a,
R: 'a;
type Light<'b>: Light<R>
where
Self: 'b,
R: 'b;
fn intersect(
&self,
ray: Ray,
min: Float,
max: Float,
) -> Option<Intersection<'_, R, Self::Mat<'_>>>;
) -> Option<Intersection<R, Self::Mat<'_>, Self::Light<'_>>>;
fn sample_light<'b>(
&self,
w_in: Dir3,
intersection: &Intersection<'_, R, Self::Mat<'b>>,
intersection: &Intersection<R, Self::Mat<'b>, Self::Light<'b>>,
rng: &mut R,
) -> Option<LightSample<'_, R>>
where
Self: 'b;
}
pub struct Intersection<'sc, R: Rng, M: Material<R> + 'sc> {
pub struct Intersection<R: Rng, M: Material<R>, L: Light<R>> {
t: Float,
normal: Dir3,
material: Option<M>,
light: Option<&'sc dyn Light<R>>,
light: Option<L>,
light_pdf: Float,
r: std::marker::PhantomData<R>,
}
impl<'sc, R: Rng, M: Material<R>> Intersection<'sc, R, M> {
impl<R: Rng, M: Material<R>, L: Light<R>> Intersection<R, M, L> {
pub fn new(
t: Float,
normal: Dir3,
material: Option<M>,
light: Option<&'sc dyn Light<R>>,
light: Option<L>,
light_pdf: Float,
) -> Self {
Self {
@ -47,6 +53,7 @@ impl<'sc, R: Rng, M: Material<R>> Intersection<'sc, R, M> {
material,
light,
light_pdf,
r: std::marker::PhantomData,
}
}
@ -62,8 +69,8 @@ impl<'sc, R: Rng, M: Material<R>> Intersection<'sc, R, M> {
self.material.as_ref()
}
pub fn light(&self) -> Option<&'sc dyn Light<R>> {
self.light
pub fn light(&self) -> Option<&L> {
self.light.as_ref()
}
pub fn light_pdf(&self) -> Float {
@ -120,19 +127,25 @@ impl<T: Scene<R> + ?Sized, R: Rng> Scene<R> for Box<T> {
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<Intersection<'_, R, Self::Mat<'_>>> {
) -> Option<Intersection<R, Self::Mat<'_>, Self::Light<'_>>> {
self.deref().intersect(ray, min, max)
}
fn sample_light<'b>(
&self,
w_in: Dir3,
intersection: &Intersection<'_, R, Self::Mat<'b>>,
intersection: &Intersection<R, Self::Mat<'b>, Self::Light<'b>>,
rng: &mut R,
) -> Option<LightSample<'_, R>>
where

View file

@ -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"] }

View file

@ -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::<SmallRng>(args.filename)?;
// dbg!(t);

View file

@ -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<R> {
AttributeBegin,
AttributeEnd,
WorldBegin,
@ -79,12 +80,12 @@ enum Statement {
Unknown(String, Vec<Token>),
Transform(AffineTransform),
Texture(String, Arc<dyn PbrtTexture>),
Material(Arc<dyn PbrtMaterial>),
MakeNamedMaterial(String, Arc<dyn PbrtMaterial>),
Material(Arc<dyn PbrtMaterial<R>>),
MakeNamedMaterial(String, Arc<dyn PbrtMaterial<R>>),
NamedMaterial(String),
}
fn parse_look_at(iter: &mut Tokenizer) -> Result<Statement> {
fn parse_look_at<R>(iter: &mut Tokenizer) -> Result<Statement<R>> {
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<Statement> {
))
}
fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
fn parse_shape<R>(iter: &mut Tokenizer) -> Result<Statement<R>> {
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<Statement> {
}
}
fn parse_camera(tokenizer: &mut Tokenizer) -> Result<Statement> {
fn parse_camera<R>(tokenizer: &mut Tokenizer) -> Result<Statement<R>> {
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<Statement> {
}
impl Lexer {
fn next(&mut self, context: &PbrtContext) -> Option<Result<Statement>> {
fn next<R: Rng>(&mut self, context: &PbrtContext<R>) -> Option<Result<Statement<R>>> {
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<AffineTransform> {
.ok_or(miette!("Unable to invert transformation"))
}
fn parse_translate(iter: &mut Tokenizer) -> Result<Statement> {
fn parse_translate<R>(iter: &mut Tokenizer) -> Result<Statement<R>> {
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<Statement> {
)))
}
fn parse_scale(iter: &mut Tokenizer) -> Result<Statement> {
fn parse_scale<R>(iter: &mut Tokenizer) -> Result<Statement<R>> {
Ok(Statement::ConcatTransform(AffineTransform::scale(
iter.parse_next()?,
iter.parse_next()?,
@ -497,7 +498,7 @@ fn parse_scale(iter: &mut Tokenizer) -> Result<Statement> {
)))
}
fn parse_rotate(iter: &mut Tokenizer) -> Result<Statement> {
fn parse_rotate<R>(iter: &mut Tokenizer) -> Result<Statement<R>> {
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<Result<Statement>> {
fn next<R: Rng>(&mut self, context: &PbrtContext<R>) -> Option<Result<Statement<R>>> {
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<R: Rng> {
pub settings: PbrtWorldSettings,
pub scene: PbrtScene,
pub scene: PbrtScene<R>,
}
impl Pbrt {
impl<R: Rng> Pbrt<R> {
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<R> {
ctm: Vec<AffineTransform>,
textures: HashMap<String, Arc<dyn PbrtTexture>>,
material: Vec<Arc<dyn PbrtMaterial>>,
materials: HashMap<String, Arc<dyn PbrtMaterial>>,
material: Vec<Arc<dyn PbrtMaterial<R>>>,
materials: HashMap<String, Arc<dyn PbrtMaterial<R>>>,
}
impl PbrtContext {
impl<R> PbrtContext<R> {
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<dyn PbrtMaterial>> {
pub fn get_named_material(&self, name: &String) -> Option<&Arc<dyn PbrtMaterial<R>>> {
self.materials.get(name)
}
pub fn get_material(&self) -> Option<&Arc<dyn PbrtMaterial>> {
pub fn get_material(&self) -> Option<&Arc<dyn PbrtMaterial<R>>> {
self.material.last()
}
@ -656,7 +662,9 @@ impl PbrtContext {
}
}
fn inner_parse_pbrt(path: impl AsRef<Path> + std::fmt::Debug) -> Result<Pbrt> {
fn inner_parse_pbrt<R: Rng + std::fmt::Debug>(
path: impl AsRef<Path> + std::fmt::Debug,
) -> Result<Pbrt<R>> {
// 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<Path> + std::fmt::Debug) -> Result<Pbrt> {
Ok(pbrt)
}
pub fn parse_pbrt_v4(path: impl AsRef<Path> + std::fmt::Debug) -> Result<Pbrt> {
pub fn parse_pbrt_v4<R: Rng + std::fmt::Debug>(
path: impl AsRef<Path> + std::fmt::Debug,
) -> Result<Pbrt<R>> {
inner_parse_pbrt(path)
}

View file

@ -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<R: Rng>: 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<R: Rng>(
input: &mut Tokenizer,
context: &PbrtContext,
) -> Result<(String, Arc<dyn PbrtMaterial>)> {
context: &PbrtContext<R>,
) -> Result<(String, Arc<dyn PbrtMaterial<R>>)> {
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<R: Rng> PbrtMaterial<R> 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<Float, Arc<dyn Pbrt2dFloatTexture>>,
}
impl PbrtMaterial for PbrtDielectricMaterial {}
impl<R: Rng> PbrtMaterial<R> 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<Color, Arc<dyn Pbrt2dSpectrumTexture>>,
}
impl PbrtMaterial for PbrtDiffuseMaterial {}
impl<R: Rng> PbrtMaterial<R> 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<R: Rng>(
input: &mut Tokenizer,
context: &PbrtContext,
context: &PbrtContext<R>,
) -> Result<Arc<dyn Pbrt2dFloatTexture>> {
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<R: Rng>(
input: &mut Tokenizer,
context: &PbrtContext,
context: &PbrtContext<R>,
) -> Result<Arc<dyn Pbrt2dSpectrumTexture>> {
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<R: Rng>(
input: &mut Tokenizer,
context: &PbrtContext,
) -> Result<Arc<dyn PbrtMaterial>> {
context: &PbrtContext<R>,
) -> Result<Arc<dyn PbrtMaterial<R>>> {
let material: String = input.next_string_value()?;
match material.as_str() {

View file

@ -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<Shape>,
pub struct PbrtScene<R: Rng> {
pub(crate) shapes: Vec<Shape<R>>,
pub(crate) infinite_light: Option<PbrtInfiniteLight>,
}
impl<R: Rng> Scene<R> for PbrtScene {
#[derive(Debug)]
pub(crate) struct PbrtInfiniteLight {
pub(crate) color: Color,
}
impl<R: Rng> Light<R> 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<R>,
}
impl<R: Rng + std::fmt::Debug> Material<R> 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<R: Rng + std::fmt::Debug> Scene<R> for PbrtScene<R> {
type Mat<'a>
= &'a dyn Material<R>
= UVMaterial<'a, R>
where
R: 'a;
type Light<'b>
= &'b dyn Light<R>
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<ray_tracing_core::scene::Intersection<'_, R, Self::Mat<'_>>> {
) -> Option<ray_tracing_core::scene::Intersection<R, Self::Mat<'_>, Self::Light<'_>>> {
let mut i = None;
for s in &self.shapes {
if let Some(new_i) = s.intersect::<R>(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<R>),
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<R, Self::Mat<'b>, Self::Light<'b>>,
_rng: &mut R,
) -> Option<ray_tracing_core::scene::LightSample<'_, R>>
where

View file

@ -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<R: Rng> {
pub(crate) ctm: AffineTransform,
pub(crate) material: Arc<dyn PbrtMaterial>,
pub(crate) material: Arc<dyn PbrtMaterial<R>>,
pub(crate) obj: ShapeType,
pub(crate) alpha: ShapeAlpha,
}
@ -158,13 +158,13 @@ fn bilinear_intersection(
.next()
}
impl Shape {
pub(crate) fn intersect<R: Rng>(
impl<R: Rng + std::fmt::Debug> Shape<R> {
pub(crate) fn intersect(
&'_ self,
ray: Ray,
min: Float,
max: Float,
) -> Option<Intersection<'_, R, &'_ dyn Material<R>>> {
) -> Option<Intersection<R, UVMaterial<'_, R>, &'_ dyn Light<R>>> {
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!(),

View file

@ -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<Color> {
Ok(Color::new(t[0], t[1], t[2]))
}
fn parse_float_texture(
fn parse_float_texture<R: Rng>(
input: &mut Tokenizer,
context: &PbrtContext,
context: &PbrtContext<R>,
) -> Result<Arc<dyn PbrtTexture>> {
let texture_class = input.next_string_value()?;
@ -138,9 +141,9 @@ fn parse_float_texture(
}
}
fn parse_spectrum_texture(
fn parse_spectrum_texture<R: Rng>(
input: &mut Tokenizer,
context: &PbrtContext,
context: &PbrtContext<R>,
) -> Result<Arc<dyn PbrtTexture>> {
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<R: Rng>(
input: &mut Tokenizer,
context: &PbrtContext,
context: &PbrtContext<R>,
) -> Result<(String, Arc<dyn PbrtTexture>)> {
let texture_name: String = input.next_string_value()?;
let texture_type: String = input.next_string_value()?;

View file

@ -78,12 +78,19 @@ impl<A: AccelerationStructure<u32>, R: Rng> Scene<R> for AccelerationStructureSc
where
A: 'a,
R: 'a;
type Light<'b>
= &'b dyn Light<R>
where
A: 'b,
R: 'b;
fn intersect(
&self,
ray: Ray,
min: Float,
max: Float,
) -> Option<ray_tracing_core::scene::Intersection<'_, R, Self::Mat<'_>>> {
) -> Option<ray_tracing_core::scene::Intersection<R, Self::Mat<'_>, 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<A: AccelerationStructure<u32>, R: Rng> Scene<R> 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<R, Self::Mat<'b>, Self::Light<'b>>,
rng: &mut R,
) -> Option<ray_tracing_core::scene::LightSample<'_, R>>
where

View file

@ -37,13 +37,19 @@ where
M: 'a,
R: 'a;
type Light<'b>
= &'b dyn Light<R>
where
M: 'b,
R: 'b;
fn intersect(
&self,
ray: Ray,
min: Float,
max: Float,
) -> Option<Intersection<'_, R, Self::Mat<'_>>> {
let mut intersection: Option<Intersection<'_, R, Self::Mat<'_>>> = None;
) -> Option<Intersection<R, Self::Mat<'_>, Self::Light<'_>>> {
let mut intersection: Option<Intersection<R, Self::Mat<'_>, 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<R, Self::Mat<'b>, Self::Light<'b>>,
_rng: &mut R,
) -> Option<ray_tracing_core::scene::LightSample<'_, R>>
where

View file

@ -323,12 +323,17 @@ impl<R: Rng> Scene<R> for TriangleBVH<R> {
where
R: 'a;
type Light<'b>
= &'b dyn Light<R>
where
R: 'b;
fn intersect(
&self,
ray: Ray,
min: Float,
max: Float,
) -> Option<ray_tracing_core::scene::Intersection<'_, R, Self::Mat<'_>>> {
) -> Option<ray_tracing_core::scene::Intersection<R, Self::Mat<'_>, Self::Light<'_>>> {
let (i, t) = self.intersect_bvh(0, ray, min, max)?;
let triangle = self.triangles[i as usize];
@ -350,7 +355,7 @@ impl<R: Rng> Scene<R> for TriangleBVH<R> {
fn sample_light<'b>(
&self,
_w_in: Dir3,
_intersection: &Intersection<'_, R, Self::Mat<'b>>,
_intersection: &Intersection<R, Self::Mat<'b>, Self::Light<'b>>,
rng: &mut R,
) -> Option<ray_tracing_core::scene::LightSample<'_, R>>
where