Change Scene trait to account for material data

This commit is contained in:
hal8174 2025-08-22 21:48:07 +02:00
parent 76448ed442
commit 2bc5ec93fe
Signed by: hal8174
SSH key fingerprint: SHA256:NN98ZYwnrreQLSOV/g+amY7C3yL/mS1heD7bi5t6PPw
19 changed files with 306 additions and 124 deletions

View file

@ -27,6 +27,34 @@ pub trait Material<R: Rng>: Send + Sync + Debug {
}
}
impl<R: Rng> Material<R> for &dyn Material<R> {
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<R: Rng, M: Material<R>> Material<R> 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,

View file

@ -3,29 +3,41 @@ use std::ops::Deref;
use crate::prelude::*;
pub trait Scene<R: Rng> {
fn intersect(&self, ray: Ray, min: Float, max: Float) -> Option<Intersection<'_, R>>;
type Mat<'a>: Material<R>
where
Self: 'a,
R: 'a;
fn sample_light(
fn intersect(
&self,
ray: Ray,
min: Float,
max: Float,
) -> Option<Intersection<'_, R, Self::Mat<'_>>>;
fn sample_light<'b>(
&self,
w_in: Dir3,
intersection: &Intersection<'_, R>,
intersection: &Intersection<'_, R, Self::Mat<'b>>,
rng: &mut R,
) -> Option<LightSample<'_, R>>;
) -> Option<LightSample<'_, R>>
where
Self: 'b;
}
pub struct Intersection<'sc, R: Rng> {
pub struct Intersection<'sc, R: Rng, M: Material<R> + 'sc> {
t: Float,
normal: Dir3,
material: Option<&'sc dyn Material<R>>,
material: Option<M>,
light: Option<&'sc dyn Light<R>>,
light_pdf: Float,
}
impl<'sc, R: Rng> Intersection<'sc, R> {
impl<'sc, R: Rng, M: Material<R>> Intersection<'sc, R, M> {
pub fn new(
t: Float,
normal: Dir3,
material: Option<&'sc dyn Material<R>>,
material: Option<M>,
light: Option<&'sc dyn Light<R>>,
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<R>> {
self.material
pub fn material(&self) -> Option<&M> {
self.material.as_ref()
}
pub fn light(&self) -> Option<&'sc dyn Light<R>> {
@ -102,16 +114,30 @@ impl<'sc, R: Rng> LightSample<'sc, R> {
}
impl<T: Scene<R> + ?Sized, R: Rng> Scene<R> for Box<T> {
fn intersect(&self, ray: Ray, min: Float, max: Float) -> Option<Intersection<'_, R>> {
type Mat<'a>
= T::Mat<'a>
where
T: 'a,
R: 'a;
fn intersect(
&self,
ray: Ray,
min: Float,
max: Float,
) -> Option<Intersection<'_, R, Self::Mat<'_>>> {
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<LightSample<'_, R>> {
) -> Option<LightSample<'_, R>>
where
Self: 'b,
{
self.deref().sample_light(w_in, intersection, rng)
}
}