master
max.nuding 2022-07-06 08:48:00 +02:00
parent 28105145c4
commit 6f6fc5e375
Failed to extract signature
6 changed files with 70 additions and 56 deletions

View File

@ -19,22 +19,11 @@ impl Default for Aabb {
} }
} }
//impl Hittable for Aabb {
impl Aabb { impl Aabb {
pub fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> bool { pub fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> bool {
let mut t_min = t_min; let mut t_min = t_min;
let mut t_max = t_max; let mut t_max = t_max;
for a in 0..3 { for a in 0..3 {
/*
let t0 = ((self.minimum[a] - ray.origin()[a]) / ray.direction()[a])
.min((self.maximum[a] - ray.origin()[a]) / ray.direction()[a]);
let t1 = ((self.minimum[a] - ray.origin()[a]) / ray.direction()[a])
.max((self.maximum[a] - ray.origin()[a]) / ray.direction()[a]);
t_min = t0.min(t_min);
t_max = t1.max(t_max);
if t_max <= t_min {
return false;
}*/
let inv_d = 1.0 / ray.direction()[a]; let inv_d = 1.0 / ray.direction()[a];
let mut t0 = (self.minimum[a] - ray.origin()[a]) * inv_d; let mut t0 = (self.minimum[a] - ray.origin()[a]) * inv_d;
let mut t1 = (self.maximum[a] - ray.origin()[a]) * inv_d; let mut t1 = (self.maximum[a] - ray.origin()[a]) * inv_d;

View File

@ -1,4 +1,4 @@
use crate::hittable::{HittableList, Hittable, HitRecord}; use crate::hittable::{HittableList, Hittable, HitRecord, HittableObject};
use crate::aabb::Aabb; use crate::aabb::Aabb;
use std::cmp; use std::cmp;
use crate::Ray; use crate::Ray;
@ -7,7 +7,7 @@ use crate::Ray;
enum BVHNode { enum BVHNode {
Branch { left: Box<BVH>, right: Box<BVH> }, Branch { left: Box<BVH>, right: Box<BVH> },
Leaf(Box<dyn Hittable>) Leaf(HittableObject)
} }
pub struct BVH { pub struct BVH {
@ -17,7 +17,7 @@ pub struct BVH {
impl BVH { impl BVH {
pub fn new(mut objects: HittableList, time0: f64, time1: f64) -> Self { pub fn new(mut objects: HittableList, time0: f64, time1: f64) -> Self {
fn box_compare(time0: f64, time1: f64, axis: usize) -> impl FnMut(&Box<dyn Hittable + Sync>, &Box<dyn Hittable + Sync>) -> cmp::Ordering { fn box_compare(time0: f64, time1: f64, axis: usize) -> impl FnMut(&HittableObject, &HittableObject) -> cmp::Ordering {
move |a, b| { move |a, b| {
let a_bbox = a.bounding_box(time0, time1); let a_bbox = a.bounding_box(time0, time1);
let b_bbox = b.bounding_box(time0, time1); let b_bbox = b.bounding_box(time0, time1);
@ -90,7 +90,7 @@ impl Hittable for BVH {
} }
} }
} }
fn bounding_box(&self, time0: f64, time1: f64) -> Option<Aabb> { fn bounding_box(&self, _time0: f64, _time1: f64) -> Option<Aabb> {
Some(self.bounding_box) Some(self.bounding_box)
} }
} }

View File

@ -2,8 +2,10 @@ use crate::{Point3, Ray, Vec3};
use crate::material::{Material}; use crate::material::{Material};
use crate::aabb::Aabb; use crate::aabb::Aabb;
use std::f64::consts::PI; use std::f64::consts::PI;
use std::sync::Arc;
pub type HittableList = Vec<Box<dyn Hittable + Sync>>; pub type HittableObject = Arc<dyn Hittable + Sync + Send>;
pub type HittableList = Vec<HittableObject>;
//#[derive(Debug, Clone, Copy)] //#[derive(Debug, Clone, Copy)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -14,7 +16,7 @@ pub struct HitRecord<'material> {
pub u: f64, pub u: f64,
pub v: f64, pub v: f64,
pub front_face: bool, pub front_face: bool,
pub material: &'material Material pub material: &'material Arc<Material>
} }
pub trait Hittable { pub trait Hittable {
@ -26,10 +28,10 @@ pub trait Hittable {
pub struct Sphere { pub struct Sphere {
pub center: Point3, pub center: Point3,
pub radius: f64, pub radius: f64,
pub material: Material pub material: Arc<Material>
} }
impl Sphere { impl Sphere {
pub fn new(center: Point3, radius: f64, material: Material) -> Sphere { pub fn new(center: Point3, radius: f64, material: Arc<Material>) -> Sphere {
Sphere { center, radius, material } Sphere { center, radius, material }
} }
pub fn uv(point: &Point3) -> (f64, f64) { pub fn uv(point: &Point3) -> (f64, f64) {
@ -51,7 +53,7 @@ impl Default for Sphere {
Sphere { Sphere {
center: Point3::default(), center: Point3::default(),
radius: 0.0, radius: 0.0,
material: Material::default() material: Arc::new(Material::default())
} }
} }
} }
@ -100,7 +102,7 @@ pub struct MovableSphere {
pub center0: Point3, pub center0: Point3,
pub center1: Point3, pub center1: Point3,
pub radius: f64, pub radius: f64,
pub material: Material, pub material: Arc<Material>,
pub time0: f64, pub time0: f64,
pub time1: f64, pub time1: f64,
} }
@ -109,7 +111,7 @@ impl MovableSphere {
center0: Point3, center0: Point3,
center1: Point3, center1: Point3,
radius: f64, radius: f64,
material: Material, material: Arc<Material>,
time0: f64, time0: f64,
time1: f64) -> Self { time1: f64) -> Self {
MovableSphere { center0, center1, radius, material, time0, time1 } MovableSphere { center0, center1, radius, material, time0, time1 }
@ -124,7 +126,7 @@ impl Default for MovableSphere {
center0: Point3::default(), center0: Point3::default(),
center1: Point3::default(), center1: Point3::default(),
radius: 0.0, radius: 0.0,
material: Material::default(), material: Arc::new(Material::default()),
time0: 0.0, time0: 0.0,
time1: 0.0 time1: 0.0
} }

View File

@ -1,8 +1,8 @@
use std::sync::Mutex; use std::sync::{Arc, Mutex};
use std::time::Instant; use std::time::Instant;
use crate::camera::Camera; use crate::camera::Camera;
use crate::hittable::{Hittable, Sphere, HittableList}; use crate::hittable::{Hittable, Sphere, HittableList, HittableObject};
use crate::output::{Output, PNG}; use crate::output::{Output, PNG};
use crate::ray::Ray; use crate::ray::Ray;
use crate::vec3::{Color, Point3, Vec3}; use crate::vec3::{Color, Point3, Vec3};
@ -25,20 +25,38 @@ mod aabb;
mod bvh; mod bvh;
mod texture; mod texture;
fn random_scene() -> HittableList { fn two_spheres() -> HittableList {
let mut world:HittableList = Vec::new(); let mut world:HittableList = Vec::new();
//let material_ground = Material::Lambertian(Lambertian::new(Color::new(0.5, 0.5, 0.5)));
let checker = CheckerTexture::colored( let checker = CheckerTexture::colored(
Color::new(0.2, 0.3, 0.1), Color::new(0.2, 0.3, 0.1),
Color::new(0.9, 0.9, 0.9)); Color::new(0.9, 0.9, 0.9));
let material_ground = Material::Lambertian(Lambertian::textured(Box::new(checker))); let checker_material = Arc::new(Material::Lambertian(Lambertian::textured(Arc::new(checker))));
world.push(Arc::new(Sphere {
center: Point3::new(0.0, -10.0, 0.0),
radius: 10.0,
material: Arc::clone(&checker_material)
}));
world.push(Arc::new(Sphere {
center: Point3::new(0.0, 10.0, 0.0),
radius: 10.0,
material: checker_material
}));
world
}
fn random_scene() -> HittableList {
let mut world: HittableList = Vec::new();
let checker = CheckerTexture::colored(
Color::new(0.2, 0.3, 0.1),
Color::new(0.9, 0.9, 0.9));
let material_ground = Arc::new(Material::Lambertian(Lambertian::textured(Arc::new(checker))));
let ground = Sphere { let ground = Sphere {
center: Point3::new(0.0, -1000.0, 0.0), center: Point3::new(0.0, -1000.0, 0.0),
radius: 1000.0, radius: 1000.0,
material: material_ground material: material_ground
}; };
world.push(Box::new(ground)); world.push(Arc::new(ground));
let unit_range = Uniform::from(0.0..1.0); let unit_range = Uniform::from(0.0..1.0);
let fuzz_range = Uniform::from(0.0..0.5); let fuzz_range = Uniform::from(0.0..0.5);
@ -55,17 +73,17 @@ fn random_scene() -> HittableList {
continue; continue;
} }
let material = match choose_material { let material = match choose_material {
_ if choose_material < 0.8 => Material::Lambertian(Lambertian::new( _ if choose_material < 0.8 => Arc::new(Material::Lambertian(Lambertian::new(
Color::random(0.0, 1.0) * Color::random(0.0, 1.0))), Color::random(0.0, 1.0) * Color::random(0.0, 1.0)))),
_ if choose_material < 0.95 => Material::Metal(Metal::new( _ if choose_material < 0.95 => Arc::new(Material::Metal(Metal::new(
Color::random(0.5, 1.0), Color::random(0.5, 1.0),
fuzz_range.sample(&mut rng))), fuzz_range.sample(&mut rng)))),
_ => Material::Dielectric(Dielectric::new(1.5)), _ => Arc::new(Material::Dielectric(Dielectric::new(1.5))),
}; };
let sphere: Box<dyn Hittable + Sync> = match rng.gen_bool(1.0 / 3.0) { let sphere: HittableObject = match rng.gen_bool(1.0 / 3.0) {
true => { true => {
let center1 = center + Vec3::new(0.0, fuzz_range.sample(&mut rng) / 2.0, 0.0); let center1 = center + Vec3::new(0.0, fuzz_range.sample(&mut rng) / 2.0, 0.0);
Box::new(MovableSphere { Arc::new(MovableSphere {
center0: center, center0: center,
center1, center1,
radius: 0.2, radius: 0.2,
@ -74,7 +92,7 @@ fn random_scene() -> HittableList {
time1: 1.0 time1: 1.0
}) })
} }
false => Box::new(Sphere { false => Arc::new(Sphere {
center, center,
radius: 0.2, radius: 0.2,
material material
@ -84,20 +102,20 @@ fn random_scene() -> HittableList {
} }
} }
let material1 = Material::Dielectric(Dielectric::new(1.5)); let material1 = Arc::new(Material::Dielectric(Dielectric::new(1.5)));
world.push(Box::new(Sphere { world.push(Arc::new(Sphere {
center: Point3::new(0.0, 1.0, 0.0), center: Point3::new(0.0, 1.0, 0.0),
radius: 1.0, radius: 1.0,
material: material1 material: material1
})); }));
let material2 = Material::Lambertian(Lambertian::new(Color::new(0.4, 0.2, 0.1))); let material2 = Arc::new(Material::Lambertian(Lambertian::new(Color::new(0.4, 0.2, 0.1))));
world.push(Box::new(Sphere { world.push(Arc::new(Sphere {
center: Point3::new(-4.0, 1.0, 0.0), center: Point3::new(-4.0, 1.0, 0.0),
radius: 1.0, radius: 1.0,
material: material2 material: material2
})); }));
let material3 = Material::Metal(Metal::new(Color::new(0.7, 0.6, 0.5), 0.0)); let material3 = Arc::new(Material::Metal(Metal::new(Color::new(0.7, 0.6, 0.5), 0.0)));
world.push(Box::new(Sphere { world.push(Arc::new(Sphere {
center: Point3::new(4.0, 1.0, 0.0), center: Point3::new(4.0, 1.0, 0.0),
radius: 1.0, radius: 1.0,
material: material3 material: material3
@ -117,20 +135,25 @@ fn main() {
let look_from = Point3::new(13.0, 2.0, 3.0); let look_from = Point3::new(13.0, 2.0, 3.0);
let look_at = Point3::new(0.0, 0.0, 0.0); let look_at = Point3::new(0.0, 0.0, 0.0);
let focus_dist = 10.0; let focus_dist = 10.0;
// Camera // Camera
let cam = Camera::new( let cam = Camera::new(
look_from, look_from,
look_at, look_at,
Vec3::new(0.0, 1.0, 0.0), Vec3::new(0.0, 1.0, 0.0),
ASPECT_RATIO, ASPECT_RATIO,
20.0, 40.0,
0.1, 0.0,
focus_dist, focus_dist,
0.0, 0.0,
1.0); 1.0);
// World // World
let world= random_scene(); let scene: u8 = 0;
let world = match scene {
0 => two_spheres(),
_ => random_scene()
};
let between = Uniform::from(0.0..1.0); let between = Uniform::from(0.0..1.0);

View File

@ -1,3 +1,5 @@
use std::rc::Rc;
use std::sync::Arc;
use rand::Rng; use rand::Rng;
use crate::hittable::HitRecord; use crate::hittable::HitRecord;
use crate::{Color, Ray, Vec3}; use crate::{Color, Ray, Vec3};
@ -7,7 +9,6 @@ pub trait Scatterable {
fn scatter(&self, ray: &Ray, hit_record: &HitRecord) -> Option<(Option<Ray>, Color)>; fn scatter(&self, ray: &Ray, hit_record: &HitRecord) -> Option<(Option<Ray>, Color)>;
} }
//#[derive(Debug, Clone)]
pub enum Material { pub enum Material {
Lambertian(Lambertian), Lambertian(Lambertian),
Metal(Metal), Metal(Metal),
@ -30,16 +31,15 @@ impl Scatterable for Material {
} }
} }
//#[derive(Debug, Clone)]
pub struct Lambertian { pub struct Lambertian {
pub albedo: Box<dyn Texture> pub albedo: Arc<dyn Texture>
} }
impl Lambertian { impl Lambertian {
pub fn new(albedo: Color) -> Self { pub fn new(albedo: Color) -> Self {
let texture = SolidColor::from(albedo); let texture = SolidColor::from(albedo);
Lambertian { albedo: Box::new(texture) } Lambertian { albedo: Arc::new(texture) }
} }
pub fn textured(albedo: Box<dyn Texture>) -> Self { pub fn textured(albedo: Arc<dyn Texture>) -> Self {
Lambertian { albedo } Lambertian { albedo }
} }
} }

View File

@ -1,6 +1,6 @@
use crate::{Point3, Color}; use crate::{Point3, Color};
pub trait Texture: Sync { pub trait Texture: Sync + Send {
fn value(&self, u: f64, v: f64, point: &Point3) -> Color; fn value(&self, u: f64, v: f64, point: &Point3) -> Color;
} }
@ -45,9 +45,9 @@ impl CheckerTexture {
impl Texture for CheckerTexture { impl Texture for CheckerTexture {
fn value(&self, u: f64, v: f64, point: &Point3) -> Color { fn value(&self, u: f64, v: f64, point: &Point3) -> Color {
let sines = (10.0 * point.x().sin()) * let sines = (10.0 * point.x()).sin() *
(10.0 * point.y().sin()) * (10.0 * point.y()).sin() *
(10.0 * point.z().sin()); (10.0 * point.z()).sin();
match sines { match sines {
sines if sines < 0.0 => self.odd.value(u, v, point), sines if sines < 0.0 => self.odd.value(u, v, point),
_ => self.even.value(u, v, point), _ => self.even.value(u, v, point),