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

@ -6,3 +6,4 @@ edition = "2021"
[dependencies]
rand = "0.8.5"
ray-tracing-core = { path = "../ray-tracing-core" }
ray-tracing-material = { path = "../ray-tracing-material" }

View file

@ -1,7 +1,7 @@
use rand::Rng;
use ray_tracing_core::material::DefaultMaterial;
use ray_tracing_core::prelude::*;
use ray_tracing_core::scene::{Intersection, Scene};
use ray_tracing_material::default::DefaultMaterial;
pub struct BasicScene {
pub(crate) spheres: Vec<(Pos3, Float)>,
@ -30,7 +30,8 @@ impl<R: Rng> Scene<R> for BasicScene {
let int = Intersection::new(
d,
((ray.start() + d * ray.dir()) - c).normalize(),
&DefaultMaterial {},
Some(&DefaultMaterial {}),
None,
);
if d >= min && d <= max {
if let Some(i) = intersection.as_ref() {

View file

@ -1,7 +1,2 @@
use rand::Rng;
use ray_tracing_core::material::DefaultMaterial;
use ray_tracing_core::prelude::*;
pub mod basic_scene;
pub mod triangle_bvh;

View file

@ -9,10 +9,15 @@ type Index = u32;
pub struct TriangleBVH<R: Rng> {
vertices: Vec<Pos3>,
triangles: Vec<Triangle>,
materials: Vec<Box<dyn Material<R>>>,
materials: Vec<BVHMaterial<R>>,
bvh: Vec<Node>,
}
struct BVHMaterial<R: Rng> {
material: Option<Box<dyn Material<R>>>,
light: Option<Box<dyn Light<R>>>,
}
#[derive(Debug, Clone, Copy)]
enum Node {
Inner {
@ -53,7 +58,7 @@ fn triangle_intersection(ray: Ray, v: [Pos3; 3]) -> Option<Float> {
let inv_det = 1.0 / det;
let s = ray.start() - v[0];
let u = inv_det * s.dot(ray_cross_e2);
if u < 0.0 || u > 1.0 {
if !(0.0..=1.0).contains(&u) {
return None;
}
@ -82,11 +87,7 @@ fn triangle_normal(v: [Pos3; 3]) -> Dir3 {
}
impl<R: Rng> TriangleBVH<R> {
fn new(
vertices: Vec<Pos3>,
triangles: Vec<Triangle>,
materials: Vec<Box<dyn Material<R>>>,
) -> Self {
fn new(vertices: Vec<Pos3>, triangles: Vec<Triangle>, materials: Vec<BVHMaterial<R>>) -> Self {
Self {
vertices,
bvh: vec![Node::Leaf {
@ -120,7 +121,40 @@ impl<R: Rng> TriangleBVH<R> {
left_aabb,
right,
right_aabb,
} => todo!(),
} => {
let left_intersect = left_aabb.intersect_ray(ray, min, max);
let right_intersect = right_aabb.intersect_ray(ray, min, max);
match (left_intersect, right_intersect) {
(None, None) => None,
(None, Some(_)) => self.intersect_bvh(right, ray, min, max),
(Some(_), None) => self.intersect_bvh(left, ray, min, max),
(Some(l), Some(r)) => {
let close;
let far;
if l < r {
close = left;
far = right;
} else {
close = right;
far = left;
}
if let Some(close_intersect) = self.intersect_bvh(close, ray, min, max) {
if let Some(far_intersect) = self
.intersect_bvh(far, ray, min, Float::min(min, close_intersect.1))
.filter(|far_intersect| far_intersect.1 < close_intersect.1)
{
Some(far_intersect)
} else {
Some(close_intersect)
}
} else {
self.intersect_bvh(far, ray, min, max)
}
}
}
}
Node::Leaf { start, count } => {
let mut intersection = None;
for i in start..(start + count) {
@ -148,19 +182,24 @@ impl<R: Rng> Scene<R> for TriangleBVH<R> {
let (i, t) = self.intersect_bvh(0, ray, min, max)?;
let triangle = self.triangles[i as usize];
let material = self.materials[triangle.material as usize].as_ref();
let material = &self.materials[triangle.material as usize];
let n = triangle_normal(self.get_vertices(i)).normalize();
Some(Intersection::new(t, n, material))
Some(Intersection::new(
t,
n,
material.material.as_deref(),
material.light.as_deref(),
))
}
}
pub mod examples {
use super::{Triangle, TriangleBVH};
use super::{BVHMaterial, Triangle, TriangleBVH};
use rand::Rng;
use ray_tracing_core::material::{AreaLight, DiffuseMaterial};
use ray_tracing_core::prelude::*;
use ray_tracing_core::{light::AreaLight, prelude::*};
use ray_tracing_material::diffuse::DiffuseMaterial;
pub fn cornel<R: Rng>() -> TriangleBVH<R> {
let side_length = 1.5;
@ -196,10 +235,22 @@ pub mod examples {
Triangle::new([11, 9, 10], 3),
],
vec![
Box::new(DiffuseMaterial::new(Color::new(0.8, 0.8, 0.8))),
Box::new(DiffuseMaterial::new(Color::new(0.9, 0.0, 0.0))),
Box::new(DiffuseMaterial::new(Color::new(0.0, 0.9, 0.0))),
Box::new(AreaLight::new(Color::new(5.0, 5.0, 5.0))),
BVHMaterial {
material: Some(Box::new(DiffuseMaterial::new(Color::new(0.8, 0.8, 0.8)))),
light: None,
},
BVHMaterial {
material: Some(Box::new(DiffuseMaterial::new(Color::new(0.9, 0.0, 0.0)))),
light: None,
},
BVHMaterial {
material: Some(Box::new(DiffuseMaterial::new(Color::new(0.0, 0.9, 0.0)))),
light: None,
},
BVHMaterial {
material: None,
light: Some(Box::new(AreaLight::new(Color::white() * 30.0))),
},
],
)
}