Use BoundingVolumeHierarchy to accelerate rendering
This commit is contained in:
parent
2b8794c884
commit
ad2b9247b8
31
src/main.rs
31
src/main.rs
|
|
@ -19,7 +19,7 @@ use vanrijn::colour::{ColourRgbF, NamedColour};
|
||||||
use vanrijn::image::{ClampingToneMapper, ImageRgbU8, ToneMapper};
|
use vanrijn::image::{ClampingToneMapper, ImageRgbU8, ToneMapper};
|
||||||
use vanrijn::materials::{LambertianMaterial, PhongMaterial, ReflectiveMaterial};
|
use vanrijn::materials::{LambertianMaterial, PhongMaterial, ReflectiveMaterial};
|
||||||
use vanrijn::mesh::load_obj;
|
use vanrijn::mesh::load_obj;
|
||||||
use vanrijn::raycasting::{Plane, Primitive, Sphere};
|
use vanrijn::raycasting::{BoundingVolumeHierarchy, Plane, Primitive, Sphere};
|
||||||
use vanrijn::scene::Scene;
|
use vanrijn::scene::Scene;
|
||||||
use vanrijn::util::{Tile, TileIterator};
|
use vanrijn::util::{Tile, TileIterator};
|
||||||
|
|
||||||
|
|
@ -70,18 +70,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
let scene = Arc::new(Scene {
|
let scene = Arc::new(Scene {
|
||||||
camera_location: Point3::new(-2.0, 1.0, -5.0),
|
camera_location: Point3::new(-2.0, 1.0, -5.0),
|
||||||
objects: load_obj(
|
objects: vec![
|
||||||
Path::new("/home/matthew/Downloads/bunny.obj"),
|
|
||||||
Arc::new(ReflectiveMaterial {
|
|
||||||
colour: ColourRgbF::from_named(NamedColour::Yellow),
|
|
||||||
diffuse_strength: 0.05,
|
|
||||||
reflection_strength: 0.9,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
.into_iter()
|
|
||||||
.map(|triangle| Arc::new(triangle) as Arc<dyn Primitive<f64>>)
|
|
||||||
.chain(vec![
|
|
||||||
Arc::new(Plane::new(
|
Arc::new(Plane::new(
|
||||||
Vector3::new(0.0, 1.0, 0.0),
|
Vector3::new(0.0, 1.0, 0.0),
|
||||||
-2.0,
|
-2.0,
|
||||||
|
|
@ -117,8 +106,18 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
specular_strength: 1.0,
|
specular_strength: 1.0,
|
||||||
}),
|
}),
|
||||||
)),
|
)),
|
||||||
])
|
Arc::new(BoundingVolumeHierarchy::build(
|
||||||
.collect(),
|
&load_obj(
|
||||||
|
Path::new("/home/matthew/Downloads/bunny.obj"),
|
||||||
|
Arc::new(ReflectiveMaterial {
|
||||||
|
colour: ColourRgbF::from_named(NamedColour::Yellow),
|
||||||
|
diffuse_strength: 0.05,
|
||||||
|
reflection_strength: 0.9,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
)),
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut event_pump = sdl_context.event_pump()?;
|
let mut event_pump = sdl_context.event_pump()?;
|
||||||
|
|
@ -127,7 +126,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut tile_rx = Some(tile_rx);
|
let mut tile_rx = Some(tile_rx);
|
||||||
|
|
||||||
let worker_boss = std::thread::spawn(move || {
|
let worker_boss = std::thread::spawn(move || {
|
||||||
TileIterator::new(image_width as usize, image_height as usize, 8)
|
TileIterator::new(image_width as usize, image_height as usize, 32)
|
||||||
.map(move |tile| (tile, tile_tx.clone()))
|
.map(move |tile| (tile, tile_tx.clone()))
|
||||||
.par_bridge()
|
.par_bridge()
|
||||||
.try_for_each(|(tile, tx)| {
|
.try_for_each(|(tile, tx)| {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ mod wavefront_obj {
|
||||||
use crate::materials::Material;
|
use crate::materials::Material;
|
||||||
use crate::Real;
|
use crate::Real;
|
||||||
|
|
||||||
use crate::raycasting::Triangle;
|
use crate::raycasting::{Primitive, Triangle};
|
||||||
|
|
||||||
use alga::general::SupersetOf;
|
use alga::general::SupersetOf;
|
||||||
use nalgebra::{convert, Point3, Vector3};
|
use nalgebra::{convert, Point3, Vector3};
|
||||||
|
|
@ -67,7 +67,7 @@ mod wavefront_obj {
|
||||||
pub fn load_obj<T: Real>(
|
pub fn load_obj<T: Real>(
|
||||||
filename: &Path,
|
filename: &Path,
|
||||||
material: Arc<dyn Material<T>>,
|
material: Arc<dyn Material<T>>,
|
||||||
) -> Result<Vec<Triangle<T>>>
|
) -> Result<Vec<Arc<dyn Primitive<T>>>>
|
||||||
where
|
where
|
||||||
T: SupersetOf<f32>,
|
T: SupersetOf<f32>,
|
||||||
{
|
{
|
||||||
|
|
@ -79,6 +79,7 @@ mod wavefront_obj {
|
||||||
.flat_map(|object| object.groups.iter())
|
.flat_map(|object| object.groups.iter())
|
||||||
.flat_map(|group| group.polys.iter())
|
.flat_map(|group| group.polys.iter())
|
||||||
.flat_map(|poly| get_triangles(poly, &obj.position, &obj.normal, material.clone()))
|
.flat_map(|poly| get_triangles(poly, &obj.position, &obj.normal, material.clone()))
|
||||||
|
.map(|triangle| Arc::new(triangle) as Arc<dyn Primitive<T>>)
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{BoundingBox, Primitive};
|
use super::{BoundingBox, HasBoundingBox, Intersect, IntersectP, IntersectionInfo, Primitive, Ray};
|
||||||
|
|
||||||
use crate::util::morton::morton_order_value_3d;
|
use crate::util::morton::morton_order_value_3d;
|
||||||
use crate::util::normalizer::Point3Normalizer;
|
use crate::util::normalizer::Point3Normalizer;
|
||||||
|
|
@ -111,6 +111,55 @@ impl<T: Real> BoundingVolumeHierarchy<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn closest_intersection<T: Real>(
|
||||||
|
a: Option<IntersectionInfo<T>>,
|
||||||
|
b: Option<IntersectionInfo<T>>,
|
||||||
|
) -> Option<IntersectionInfo<T>> {
|
||||||
|
match (a, b) {
|
||||||
|
(Some(a), Some(b)) => {
|
||||||
|
if a.distance < b.distance {
|
||||||
|
Some(a)
|
||||||
|
} else {
|
||||||
|
Some(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Some(a), None) => Some(a),
|
||||||
|
(None, Some(b)) => Some(b),
|
||||||
|
(None, None) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Real> Intersect<T> for BoundingVolumeHierarchy<T> {
|
||||||
|
fn intersect<'a>(&'a self, ray: &Ray<T>) -> Option<IntersectionInfo<T>> {
|
||||||
|
match self {
|
||||||
|
Self::Node {
|
||||||
|
bounds,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
} => {
|
||||||
|
if bounds.intersect(ray) {
|
||||||
|
closest_intersection(left.intersect(ray), right.intersect(ray))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::Leaf {
|
||||||
|
bounds: _,
|
||||||
|
primitive,
|
||||||
|
} => primitive.intersect(ray),
|
||||||
|
Self::None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Real> HasBoundingBox<T> for BoundingVolumeHierarchy<T> {
|
||||||
|
fn bounding_box(&self) -> BoundingBox<T> {
|
||||||
|
self.get_bounds()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Real> Primitive<T> for BoundingVolumeHierarchy<T> {}
|
||||||
|
|
||||||
pub struct FilterIterator<'a, T: Real> {
|
pub struct FilterIterator<'a, T: Real> {
|
||||||
unsearched_subtrees: Vec<&'a BoundingVolumeHierarchy<T>>,
|
unsearched_subtrees: Vec<&'a BoundingVolumeHierarchy<T>>,
|
||||||
predicate: Box<dyn Fn(&BoundingBox<T>) -> bool>,
|
predicate: Box<dyn Fn(&BoundingBox<T>) -> bool>,
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ pub mod axis_aligned_bounding_box;
|
||||||
pub use axis_aligned_bounding_box::BoundingBox;
|
pub use axis_aligned_bounding_box::BoundingBox;
|
||||||
|
|
||||||
pub mod bounding_volume_hierarchy;
|
pub mod bounding_volume_hierarchy;
|
||||||
|
pub use bounding_volume_hierarchy::BoundingVolumeHierarchy;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Ray<T: Real> {
|
pub struct Ray<T: Real> {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue