Move Material to new module && TriangleBVH intersect && Seperate light and material

This commit is contained in:
hal8174 2024-09-30 21:13:50 +02:00
parent 50d3874467
commit b3fdef8837
18 changed files with 180 additions and 90 deletions

View file

@ -43,7 +43,7 @@ impl AABB {
&& pos.z <= self.max.z
}
pub fn intersect_ray(self, ray: Ray) -> Option<Float> {
pub fn intersect_ray(self, ray: Ray, min: Float, max: Float) -> Option<Float> {
todo!()
}
}

View file

@ -1,6 +1,7 @@
pub mod aabb;
pub mod camera;
pub mod color;
pub mod light;
pub mod material;
pub mod math;
pub mod ray;
@ -11,6 +12,7 @@ pub mod prelude {
pub type Float = f32;
pub use crate::aabb::AABB;
pub use crate::color::Color;
pub use crate::light::Light;
pub use crate::material::Material;
pub use crate::math::*;
pub use crate::ray::Ray;

View file

@ -0,0 +1,26 @@
use crate::prelude::*;
use rand::Rng;
pub trait Light<R: Rng>: Sync {
fn emit(&self, w_in: Dir3, rng: &mut R) -> Color;
}
pub struct AreaLight {
pub(crate) color: Color,
}
impl AreaLight {
pub fn new(color: Color) -> Self {
Self { color }
}
}
impl<R: Rng> Light<R> for AreaLight {
fn emit(&self, w_in: Dir3, _rng: &mut R) -> Color {
if w_in.y() > 0.0 {
self.color
} else {
Color::black()
}
}
}

View file

@ -3,52 +3,5 @@ use rand::Rng;
/// All calculations for the material are done a tangent space of the intersection.
pub trait Material<R: Rng>: Sync {
fn eval(&self, w_in: Dir3, w_out: Dir3, rng: &mut R) -> Option<Color> {
None
}
fn emit(&self, w_in: Dir3, rng: &mut R) -> Option<Color> {
None
}
}
pub struct DefaultMaterial {}
impl<R: Rng> Material<R> for DefaultMaterial {
// evaluates the bsdf
fn eval(&self, _w_in: Dir3, _w_out: Dir3, _rng: &mut R) -> Option<Color> {
None
}
}
pub struct DiffuseMaterial {
color: Color,
}
impl DiffuseMaterial {
pub fn new(color: Color) -> Self {
Self { color }
}
}
impl<R: Rng> Material<R> for DiffuseMaterial {
fn eval(&self, _w_in: Dir3, _w_out: Dir3, _rng: &mut R) -> Option<Color> {
Some(self.color)
}
}
pub struct AreaLight {
color: Color,
}
impl AreaLight {
pub fn new(color: Color) -> Self {
Self { color }
}
}
impl<R: Rng> Material<R> for AreaLight {
fn emit(&self, _w_in: Dir3, _rng: &mut R) -> Option<Color> {
Some(self.color)
}
fn eval(&self, w_in: Dir3, w_out: Dir3, rng: &mut R) -> Color;
}

View file

@ -39,7 +39,9 @@ mod test {
dbg!(f);
dbg!(f.to_world(Dir3::new(0.0, 1.0, 0.0)));
let t = dbg!(f.to_world(Dir3::new(1.0, 1.0, 1.0)));
dbg!(f.to_frame(t));
panic!()
}

View file

@ -50,27 +50,25 @@ where
let mut count = 0;
while let Some(i) = self.scene.intersect(r, 0.001, Float::INFINITY) {
if count > 4 {
break;
}
let frame = i.tangent_frame();
let w_in = frame.to_frame(-r.dir());
let w_out = Dir3::generate_uniform_hemisphere(rng);
let mat = i.material();
if let Some(c) = mat.emit(w_in, rng) {
sum += alpha * c * w_out.y();
if let Some(light) = i.light() {
sum += alpha * light.emit(w_in, rng) * w_out.y();
}
if let Some(c) = mat.eval(w_in, w_out, rng) {
alpha *= c;
if let Some(material) = i.material() {
alpha *= material.eval(w_in, w_out, rng) * w_out.y();
} else {
return sum;
}
r = Ray::new(r.at(i.t()), frame.to_world(w_out), r.time());
count += 1;
if count > 4 {
break;
}
}
sum

View file

@ -8,15 +8,22 @@ pub trait Scene<R: Rng> {
pub struct Intersection<'sc, R: Rng> {
t: Float,
normal: Dir3,
material: &'sc dyn Material<R>,
material: Option<&'sc dyn Material<R>>,
light: Option<&'sc dyn Light<R>>,
}
impl<'sc, R: Rng> Intersection<'sc, R> {
pub fn new(t: Float, normal: Dir3, material: &'sc dyn Material<R>) -> Self {
pub fn new(
t: Float,
normal: Dir3,
material: Option<&'sc dyn Material<R>>,
light: Option<&'sc dyn Light<R>>,
) -> Self {
Self {
t,
normal,
material,
light,
}
}
@ -28,10 +35,14 @@ impl<'sc, R: Rng> Intersection<'sc, R> {
self.normal
}
pub fn material(&self) -> &'sc dyn Material<R> {
pub fn material(&self) -> Option<&'sc dyn Material<R>> {
self.material
}
pub fn light(&self) -> Option<&'sc dyn Light<R>> {
self.light
}
pub fn tangent_frame(&self) -> Frame {
Frame::from_normal(self.normal)
}