Change testscene interface

This commit is contained in:
hal8174 2025-01-02 23:17:17 +01:00
parent 829476c602
commit 0b3daf9441
12 changed files with 313 additions and 223 deletions

View file

@ -1,3 +1,5 @@
use std::cell::OnceCell;
use crate::triangle_bvh::{BVHMaterial, Triangle, TriangleBVH};
use super::ExampleScene;
@ -5,82 +7,104 @@ use super::ExampleScene;
use ray_tracing_core::{light::AreaLight, prelude::*, scene::Scene};
use ray_tracing_material::{diffuse::DiffuseMaterial, mirror::Mirror};
pub fn scene<R: Rng + 'static>() -> ExampleScene<R> {
let f = || {
let side_length = 1.5;
let light_size = 0.5;
let light_offset = 0.01;
let box_size = 0.3;
let scene = TriangleBVH::new(
vec![
Pos3::new(side_length, side_length, side_length),
Pos3::new(side_length, side_length, -side_length),
Pos3::new(side_length, -side_length, side_length),
Pos3::new(side_length, -side_length, -side_length),
Pos3::new(-side_length, side_length, side_length),
Pos3::new(-side_length, side_length, -side_length),
Pos3::new(-side_length, -side_length, side_length),
Pos3::new(-side_length, -side_length, -side_length),
Pos3::new(light_size, side_length - light_offset, light_size),
Pos3::new(light_size, side_length - light_offset, -light_size),
Pos3::new(-light_size, side_length - light_offset, light_size),
Pos3::new(-light_size, side_length - light_offset, -light_size),
Pos3::new(box_size, -side_length, 0.0),
Pos3::new(0.0, -side_length, -box_size),
Pos3::new(-box_size, -side_length, 0.0),
Pos3::new(0.0, -side_length, box_size),
Pos3::new(0.0, box_size - side_length, 0.0),
],
vec![
Triangle::new([0, 1, 2], 0),
Triangle::new([1, 3, 2], 0),
Triangle::new([0, 4, 1], 0),
Triangle::new([1, 4, 5], 0),
Triangle::new([2, 3, 6], 0),
Triangle::new([3, 7, 6], 0),
Triangle::new([0, 2, 4], 1),
Triangle::new([6, 4, 2], 1),
Triangle::new([1, 5, 3], 2),
Triangle::new([7, 3, 5], 2),
Triangle::new([8, 10, 9], 3),
Triangle::new([11, 9, 10], 3),
Triangle::new([12, 13, 16], 4),
Triangle::new([13, 14, 16], 4),
Triangle::new([14, 15, 16], 4),
Triangle::new([15, 12, 16], 4),
],
vec![
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() * 18.0))),
},
BVHMaterial {
material: Some(Box::new(Mirror::new(Color::new(1.0, 1.0, 1.0)))),
light: None,
},
],
);
pub struct BasicCornell<R: Rng> {
scene: OnceCell<TriangleBVH<R>>,
}
Box::new(scene) as Box<dyn Scene<R> + Sync>
};
ExampleScene {
scene: f,
camera_pos: Pos3::new(-6.0, 0.0, 0.0),
camera_look_at: Pos3::new(0.0, 0.0, 0.0),
camera_up: Dir3::up(),
horizontal_fov: Float::to_radians(90.0),
impl<R: Rng> BasicCornell<R> {
pub fn new() -> Self {
BasicCornell {
scene: OnceCell::new(),
}
}
}
impl<R: Rng + 'static> ExampleScene<R> for BasicCornell<R> {
fn get_scene(&self) -> Box<dyn Scene<R> + Sync> {
let s = self.scene.get_or_init(|| {
let side_length = 1.5;
let light_size = 0.5;
let light_offset = 0.01;
let box_size = 0.3;
TriangleBVH::new(
vec![
Pos3::new(side_length, side_length, side_length),
Pos3::new(side_length, side_length, -side_length),
Pos3::new(side_length, -side_length, side_length),
Pos3::new(side_length, -side_length, -side_length),
Pos3::new(-side_length, side_length, side_length),
Pos3::new(-side_length, side_length, -side_length),
Pos3::new(-side_length, -side_length, side_length),
Pos3::new(-side_length, -side_length, -side_length),
Pos3::new(light_size, side_length - light_offset, light_size),
Pos3::new(light_size, side_length - light_offset, -light_size),
Pos3::new(-light_size, side_length - light_offset, light_size),
Pos3::new(-light_size, side_length - light_offset, -light_size),
Pos3::new(box_size, -side_length, 0.0),
Pos3::new(0.0, -side_length, -box_size),
Pos3::new(-box_size, -side_length, 0.0),
Pos3::new(0.0, -side_length, box_size),
Pos3::new(0.0, box_size - side_length, 0.0),
],
vec![
Triangle::new([0, 1, 2], 0),
Triangle::new([1, 3, 2], 0),
Triangle::new([0, 4, 1], 0),
Triangle::new([1, 4, 5], 0),
Triangle::new([2, 3, 6], 0),
Triangle::new([3, 7, 6], 0),
Triangle::new([0, 2, 4], 1),
Triangle::new([6, 4, 2], 1),
Triangle::new([1, 5, 3], 2),
Triangle::new([7, 3, 5], 2),
Triangle::new([8, 10, 9], 3),
Triangle::new([11, 9, 10], 3),
Triangle::new([12, 13, 16], 4),
Triangle::new([13, 14, 16], 4),
Triangle::new([14, 15, 16], 4),
Triangle::new([15, 12, 16], 4),
],
vec![
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() * 18.0))),
},
BVHMaterial {
material: Some(Box::new(Mirror::new(Color::new(1.0, 1.0, 1.0)))),
light: None,
},
],
)
});
Box::new(s.clone()) as Box<dyn Scene<R> + Sync>
}
fn get_camera_pos(&self) -> Pos3 {
Pos3::new(-6.0, 0.0, 0.0)
}
fn get_camera_look_at(&self) -> Pos3 {
Pos3::new(0.0, 0.0, 0.0)
}
fn get_camera_up(&self) -> Dir3 {
Dir3::up()
}
fn get_horizontal_fov(&self) -> Float {
Float::to_radians(90.0)
}
}

View file

@ -1,7 +1,7 @@
use rand::Rng;
use ray_tracing_core::{light::AreaLight, prelude::*, scene::Scene};
use ray_tracing_material::{diffuse::DiffuseMaterial, mirror::Mirror};
use std::fmt::Debug;
use std::{cell::OnceCell, fmt::Debug};
use crate::{
parse_obj::ObjData,
@ -10,42 +10,67 @@ use crate::{
use super::ExampleScene;
pub fn scene<R: Rng + Debug + 'static>() -> ExampleScene<R> {
let f = || {
let obj = ObjData::new("ray-tracing-scene/obj/cornell_box.obj").unwrap();
pub struct Cornell2<R: Rng> {
scene: OnceCell<TriangleBVH<R>>,
}
let triangles = obj
.triangle_faces()
.map(|t| Triangle::new(t.v, t.mat.unwrap()))
.collect();
let materials = obj
.materials()
.iter()
.map(|m| match m.name.as_str() {
"white" => BVHMaterial::new_material(DiffuseMaterial::new(Color::white())),
"light" => BVHMaterial::new_light(AreaLight::new(Color::white() * 30.0)),
"blue" => {
BVHMaterial::new_material(DiffuseMaterial::new(Color::new(0.0, 0.0, 1.0)))
}
"red" => BVHMaterial::new_material(DiffuseMaterial::new(Color::new(1.0, 0.0, 0.0))),
"green" => {
BVHMaterial::new_material(DiffuseMaterial::new(Color::new(0.0, 1.0, 0.0)))
}
"mirror" => BVHMaterial::new_material(Mirror::new(Color::white())),
_ => unreachable!(),
})
.collect();
let scene = TriangleBVH::new(obj.vertices, triangles, materials);
Box::new(scene) as Box<dyn Scene<R> + Sync>
};
ExampleScene {
scene: f,
camera_pos: Pos3::new(275.0, 275.0, -800.0),
camera_look_at: Pos3::new(275.0, 275.0, 275.0),
camera_up: Dir3::up(),
horizontal_fov: 90.0_f32.to_radians(),
impl<R: Rng> Cornell2<R> {
pub fn new() -> Self {
Self {
scene: OnceCell::new(),
}
}
}
impl<R: Rng + 'static> ExampleScene<R> for Cornell2<R> {
fn get_scene(&self) -> Box<dyn Scene<R> + Sync> {
let s = self.scene.get_or_init(|| {
let obj = ObjData::new("ray-tracing-scene/obj/cornell_box.obj").unwrap();
let triangles = obj
.triangle_faces()
.map(|t| Triangle::new(t.v, t.mat.unwrap()))
.collect();
let materials = obj
.materials()
.iter()
.map(|m| match m.name.as_str() {
"white" => BVHMaterial::new_material(DiffuseMaterial::new(Color::white())),
"light" => BVHMaterial::new_light(AreaLight::new(Color::white() * 30.0)),
"blue" => {
BVHMaterial::new_material(DiffuseMaterial::new(Color::new(0.0, 0.0, 1.0)))
}
"red" => {
BVHMaterial::new_material(DiffuseMaterial::new(Color::new(1.0, 0.0, 0.0)))
}
"green" => {
BVHMaterial::new_material(DiffuseMaterial::new(Color::new(0.0, 1.0, 0.0)))
}
"mirror" => BVHMaterial::new_material(Mirror::new(Color::white())),
_ => unreachable!(),
})
.collect();
TriangleBVH::new(obj.vertices, triangles, materials)
});
Box::new(s.clone())
}
fn get_camera_pos(&self) -> Pos3 {
Pos3::new(275.0, 275.0, -800.0)
}
fn get_camera_look_at(&self) -> Pos3 {
Pos3::new(275.0, 275.0, 275.0)
}
fn get_camera_up(&self) -> Dir3 {
Dir3::up()
}
fn get_horizontal_fov(&self) -> Float {
Float::to_radians(90.0)
}
}

View file

@ -2,20 +2,27 @@ use ray_tracing_core::{prelude::*, scene::Scene};
use std::collections::HashMap;
use std::fmt::Debug;
pub struct ExampleScene<R: Rng> {
pub scene: fn() -> Box<dyn Scene<R> + Sync>,
pub camera_pos: Pos3,
pub camera_look_at: Pos3,
pub camera_up: Dir3,
pub horizontal_fov: Float,
pub trait ExampleScene<R: Rng + 'static> {
fn get_scene(&self) -> Box<dyn Scene<R> + Sync>;
fn get_camera_pos(&self) -> Pos3;
fn get_camera_look_at(&self) -> Pos3;
fn get_camera_up(&self) -> Dir3;
fn get_horizontal_fov(&self) -> Float;
}
pub fn example_scenes<R: Rng + Debug + 'static>() -> HashMap<&'static str, fn() -> ExampleScene<R>>
pub fn example_scenes<R: Rng + Debug + 'static>() -> HashMap<&'static str, Box<dyn ExampleScene<R>>>
{
let mut map: HashMap<&str, fn() -> ExampleScene<R>> = HashMap::new();
map.insert("basic_cornel", basic_cornell::scene::<R>);
map.insert("cornel2", cornell2::scene::<R>);
map.insert("stanford_dragon", stanford_dragon::scene::<R>);
let mut map: HashMap<&str, Box<dyn ExampleScene<R>>> = HashMap::new();
map.insert("basic_cornel", Box::new(basic_cornell::BasicCornell::new()));
map.insert("cornel2", Box::new(cornell2::Cornell2::new()));
map.insert(
"stanford_dragon",
Box::new(stanford_dragon::StanfordDragon::new()),
);
map
}

View file

@ -1,11 +1,10 @@
use rand::Rng;
use ray_tracing_core::{light::AreaLight, prelude::*, scene::Scene};
use ray_tracing_material::{
diffuse::DiffuseMaterial,
microfacet::{BeckmannDistribution, Microfacet},
oren_nayar::OrenNayar,
};
use std::fmt::Debug;
use std::cell::OnceCell;
use crate::{
parse_obj::ObjData,
@ -14,72 +13,95 @@ use crate::{
use super::ExampleScene;
pub fn scene<R: Rng + Debug + 'static>() -> ExampleScene<R> {
let f = || {
let obj = ObjData::new("ray-tracing-scene/obj/stanford_dragon.obj").unwrap();
pub struct StanfordDragon<R: Rng> {
scene: OnceCell<TriangleBVH<R>>,
}
let mut triangles = obj
.triangle_faces()
.map(|t| Triangle::new(t.v, 0))
.collect::<Vec<_>>();
let color = Color::new(0.2, 0.2, 0.9);
let materials = vec![
BVHMaterial::new_material(Microfacet::new(BeckmannDistribution::new(0.01), color)),
BVHMaterial::new_material(OrenNayar::new(0.5, Color::new(0.8, 0.8, 0.8))),
BVHMaterial::new_material(OrenNayar::new(0.5, Color::new(0.9, 0.0, 0.0))),
BVHMaterial::new_material(OrenNayar::new(0.5, Color::new(0.0, 0.9, 0.0))),
BVHMaterial::new_light(AreaLight::new(Color::white() * 30.0)),
];
let mut vertices = obj.vertices;
for v in &mut vertices {
*v = Pos3::new(v.x(), v.z() + 60.0, -v.y());
impl<R: Rng> StanfordDragon<R> {
pub fn new() -> Self {
Self {
scene: OnceCell::new(),
}
let side_length = 400.0;
let light_size = 150.0;
let light_offset = 0.01;
let offset = vertices.len() as u32;
vertices.extend_from_slice(&[
Pos3::new(side_length, 2.0 * side_length, side_length),
Pos3::new(side_length, 2.0 * side_length, -side_length),
Pos3::new(side_length, 0.0, side_length),
Pos3::new(side_length, 0.0, -side_length),
Pos3::new(-side_length, 2.0 * side_length, side_length),
Pos3::new(-side_length, 2.0 * side_length, -side_length),
Pos3::new(-side_length, 0.0, side_length),
Pos3::new(-side_length, 0.0, -side_length),
Pos3::new(light_size, 2.0 * side_length - light_offset, light_size),
Pos3::new(light_size, 2.0 * side_length - light_offset, -light_size),
Pos3::new(-light_size, 2.0 * side_length - light_offset, light_size),
Pos3::new(-light_size, 2.0 * side_length - light_offset, -light_size),
]);
triangles.extend_from_slice(&[
Triangle::new([offset, 1 + offset, 2 + offset], 1),
Triangle::new([1 + offset, 3 + offset, 2 + offset], 1),
Triangle::new([offset, 4 + offset, 1 + offset], 1),
Triangle::new([1 + offset, 4 + offset, 5 + offset], 1),
Triangle::new([2 + offset, 3 + offset, 6 + offset], 1),
Triangle::new([3 + offset, 7 + offset, 6 + offset], 1),
Triangle::new([offset, 2 + offset, 4 + offset], 2),
Triangle::new([6 + offset, 4 + offset, 2 + offset], 2),
Triangle::new([1 + offset, 5 + offset, 3 + offset], 3),
Triangle::new([7 + offset, 3 + offset, 5 + offset], 3),
Triangle::new([8 + offset, 10 + offset, 9 + offset], 4),
Triangle::new([11 + offset, 9 + offset, 10 + offset], 4),
]);
let scene = TriangleBVH::new(vertices, triangles, materials);
Box::new(scene) as Box<dyn Scene<R> + Sync>
};
ExampleScene {
scene: f,
camera_pos: Pos3::new(-150.0, 160.0, 250.0),
camera_look_at: Pos3::new(0.0, 60.0, 0.0),
camera_up: Dir3::up(),
horizontal_fov: 90.0_f32.to_radians(),
}
}
impl<R: Rng + 'static> ExampleScene<R> for StanfordDragon<R> {
fn get_scene(&self) -> Box<dyn Scene<R> + Sync> {
let s = self.scene.get_or_init(|| {
let obj = ObjData::new("ray-tracing-scene/obj/stanford_dragon.obj").unwrap();
let mut triangles = obj
.triangle_faces()
.map(|t| Triangle::new(t.v, 0))
.collect::<Vec<_>>();
let color = Color::new(0.2, 0.2, 0.9);
let materials = vec![
BVHMaterial::new_material(Microfacet::new(BeckmannDistribution::new(0.01), color)),
BVHMaterial::new_material(OrenNayar::new(0.5, Color::new(0.8, 0.8, 0.8))),
BVHMaterial::new_material(OrenNayar::new(0.5, Color::new(0.9, 0.0, 0.0))),
BVHMaterial::new_material(OrenNayar::new(0.5, Color::new(0.0, 0.9, 0.0))),
BVHMaterial::new_light(AreaLight::new(Color::white() * 30.0)),
];
let mut vertices = obj.vertices;
for v in &mut vertices {
*v = Pos3::new(v.x(), v.z() + 60.0, -v.y());
}
let side_length = 400.0;
let light_size = 150.0;
let light_offset = 0.01;
let offset = vertices.len() as u32;
vertices.extend_from_slice(&[
Pos3::new(side_length, 2.0 * side_length, side_length),
Pos3::new(side_length, 2.0 * side_length, -side_length),
Pos3::new(side_length, 0.0, side_length),
Pos3::new(side_length, 0.0, -side_length),
Pos3::new(-side_length, 2.0 * side_length, side_length),
Pos3::new(-side_length, 2.0 * side_length, -side_length),
Pos3::new(-side_length, 0.0, side_length),
Pos3::new(-side_length, 0.0, -side_length),
Pos3::new(light_size, 2.0 * side_length - light_offset, light_size),
Pos3::new(light_size, 2.0 * side_length - light_offset, -light_size),
Pos3::new(-light_size, 2.0 * side_length - light_offset, light_size),
Pos3::new(-light_size, 2.0 * side_length - light_offset, -light_size),
]);
triangles.extend_from_slice(&[
Triangle::new([offset, 1 + offset, 2 + offset], 1),
Triangle::new([1 + offset, 3 + offset, 2 + offset], 1),
Triangle::new([offset, 4 + offset, 1 + offset], 1),
Triangle::new([1 + offset, 4 + offset, 5 + offset], 1),
Triangle::new([2 + offset, 3 + offset, 6 + offset], 1),
Triangle::new([3 + offset, 7 + offset, 6 + offset], 1),
Triangle::new([offset, 2 + offset, 4 + offset], 2),
Triangle::new([6 + offset, 4 + offset, 2 + offset], 2),
Triangle::new([1 + offset, 5 + offset, 3 + offset], 3),
Triangle::new([7 + offset, 3 + offset, 5 + offset], 3),
Triangle::new([8 + offset, 10 + offset, 9 + offset], 4),
Triangle::new([11 + offset, 9 + offset, 10 + offset], 4),
]);
TriangleBVH::new(vertices, triangles, materials)
});
Box::new(s.clone())
}
fn get_camera_pos(&self) -> Pos3 {
Pos3::new(-150.0, 160.0, 250.0)
}
fn get_camera_look_at(&self) -> Pos3 {
Pos3::new(0.0, 60.0, 0.0)
}
fn get_camera_up(&self) -> Dir3 {
Dir3::up()
}
fn get_horizontal_fov(&self) -> Float {
Float::to_radians(90.0)
}
}

View file

@ -4,6 +4,7 @@ use ray_tracing_core::{
scene::{Intersection, LightSample, Scene},
};
use sampling::sample_triangle;
use std::sync::Arc;
type Index = u32;
@ -11,11 +12,23 @@ type Index = u32;
pub struct TriangleBVH<R: Rng> {
vertices: Vec<Pos3>,
triangles: Vec<Triangle>,
materials: Vec<BVHMaterial<R>>,
materials: Arc<[BVHMaterial<R>]>,
bvh: Vec<Node>,
lights: Vec<Triangle>,
}
impl<R: Rng> Clone for TriangleBVH<R> {
fn clone(&self) -> Self {
Self {
vertices: self.vertices.clone(),
triangles: self.triangles.clone(),
materials: Arc::clone(&self.materials),
bvh: self.bvh.clone(),
lights: self.lights.clone(),
}
}
}
#[derive(Debug)]
pub struct BVHMaterial<R: Rng> {
pub material: Option<Box<dyn Material<R>>>,
@ -223,7 +236,7 @@ impl<R: Rng> TriangleBVH<R> {
vertices,
bvh,
triangles,
materials,
materials: materials.into(),
lights,
}
}