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

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