diff options
-rw-r--r-- | src/core/spectrum.rs | 2 | ||||
-rw-r--r-- | src/main.rs | 25 | ||||
-rw-r--r-- | src/trace/pathtrace.rs | 1 | ||||
-rw-r--r-- | src/world/shapes/mod.rs | 2 | ||||
-rw-r--r-- | src/world/shapes/rectangle.rs | 105 | ||||
-rw-r--r-- | src/world/shapes/sphere.rs | 1 |
6 files changed, 121 insertions, 15 deletions
diff --git a/src/core/spectrum.rs b/src/core/spectrum.rs index ed3505b..e683eb1 100644 --- a/src/core/spectrum.rs +++ b/src/core/spectrum.rs @@ -5,7 +5,7 @@ use crate::Float; // TODO implement SampledSpectrum instead for nicer images -#[derive(Clone, Copy, Default)] +#[derive(Clone, Copy, Default, Debug)] pub struct Spectrum { c: [Float; 3], } diff --git a/src/main.rs b/src/main.rs index 221752b..9cd2fc2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ use rendering::camera::{Camera, Film, CameraSettings}; -use rendering::world::{Scene, Object, shapes::Sphere, Instancable}; +use rendering::world::{Scene, Object, shapes::{Rect, Plane, Sphere}, Instancable}; use rendering::trace::DefaultTracer; use rendering::core::{Vector2i, Vector3f, Spectrum}; use rendering::render::{RenderContext, RenderCoord}; @@ -15,33 +15,34 @@ fn main() { target: Vector3f::new_xyz(0.0, 0.0, -1.0), origin: Vector3f::new_xyz(0.0, 0.0, 1.0), up: Vector3f::new_xyz(0.0, 1.0, 0.0), - fov: 45.0, + fov: 50.0, filmsize: res, focus: None, - aperture: Some(10.0), - //aperture: None, + aperture: None, }); let brown = Arc::new(Lambertian::new(Spectrum::new_rgb(0.5, 0.3, 0.0))); let blue = Arc::new(Lambertian::new(Spectrum::new_rgb(0.0, 0.3, 0.7))); let green = Arc::new(Lambertian::new(Spectrum::new_rgb(0.0, 0.7, 0.3))); let metal = Arc::new(Reflectant::new(Spectrum::new_rgb(0.8, 0.8, 0.9), Some(1.0))); + let mirror = Arc::new(Reflectant::new(Spectrum::new_rgb(1.0, 1.0, 1.0), None)); let glass = Arc::new(Dielectric::new(1.5)); - let sun = Arc::new(DiffuseLight::new_white(50.0)); + let sun = Arc::new(DiffuseLight::new_white(14.0)); let mut scn = Scene::new(); scn.add_objects(vec![ Object::new(glass, Sphere::new(0.2).translate(0.0, 0.0, -1.0)), Object::new(blue, Sphere::new(0.5).translate(1.0, 0.0, -1.5)), - Object::new(green, Sphere::new(0.3).translate(0.5, 0.0, -2.5)), + Object::new(mirror, Rect::new(0.4, 0.7, Plane::XY).translate(0.5, 0.0, -2.5)), + Object::new(brown.clone(), Rect::new(10.0, 2.0, Plane::XY).translate(0.5, 0.0, -2.6)), Object::new(brown, Sphere::new(100.0).translate(0.0, -100.5, -1.0)), - Object::new(metal, Sphere::new(0.2).translate(-0.5, 0.0, -1.0)), - Object::new(sun, Sphere::new(0.4).translate(-1.0, 3.0, 0.0)), + Object::new(green, Sphere::new(0.4).translate(-0.5, 0.0, -2.0)), + //Object::new(sun, Sphere::new(0.4).translate(-1.0, 6.0, 0.0)), ]); - let tracer = DefaultTracer::new(&scn, Some(50), - //Some(Box::new(SkyLight::new())) - None + let tracer = DefaultTracer::new(&scn, Some(10), + Some(Box::new(SkyLight::new())) + //None ); let mut sampler = UniformSampler::new(); @@ -50,7 +51,7 @@ fn main() { let mut film = Film::new(res); { - let coord = RenderCoord::new(&mut film, Vector2i::new_xy(50, 50), 50); + let coord = RenderCoord::new(&mut film, Vector2i::new_xy(50, 50), 200); coord.run_threaded(&ctx, &mut sampler, 8); } diff --git a/src/trace/pathtrace.rs b/src/trace/pathtrace.rs index f53e433..cebbaa1 100644 --- a/src/trace/pathtrace.rs +++ b/src/trace/pathtrace.rs @@ -28,7 +28,6 @@ impl PathTracer<'_> { } if let Some(i) = self.scn.intersect(ray) { - // Extract material or default if let Some(mat) = i.m { let mut col = Spectrum::ZERO; diff --git a/src/world/shapes/mod.rs b/src/world/shapes/mod.rs index a11df5d..6e4b2ce 100644 --- a/src/world/shapes/mod.rs +++ b/src/world/shapes/mod.rs @@ -1,6 +1,8 @@ mod sphere; +mod rectangle; pub use sphere::Sphere; +pub use rectangle::{Rect, Plane}; use crate::world::{Hittable, Intersection}; use crate::core::{Bound3f, Ray}; diff --git a/src/world/shapes/rectangle.rs b/src/world/shapes/rectangle.rs new file mode 100644 index 0000000..313ebb8 --- /dev/null +++ b/src/world/shapes/rectangle.rs @@ -0,0 +1,105 @@ +use crate::{NEAR_ZERO, Float}; +use crate::core::{Ray, Vector3f, Bound3f}; +use crate::world::{Hittable, DynHittable, Intersection, Instancable}; + +const OUT_XY: Vector3f = Vector3f { x: 0.0, y: 0.0, z: 1.0 }; + +pub enum Plane { + XY, +} + +pub struct Rect { + // Size of rectangle in first dimension + d1: Float, + // Size in second + d2: Float, + // Offset of plane plane. Should only be used when composing other types + offset: Float, + + plane: Plane, +} + +impl Rect { + pub fn new(width: Float, height: Float, plane: Plane) -> Self { + Rect {d1: width, d2: height, offset: 0.0, plane} + } + + pub fn new_with_offset(d1: Float, d2: Float, offset: Float, plane: Plane) -> Self { + Rect { + d1, d2, + offset, + plane + } + } +} + +impl Hittable for Rect { + fn intersect(&self, ray: &Ray) -> Option<Intersection> { + let t = (self.offset-ray.origin.z) / ray.direction.z; + if t <= NEAR_ZERO { + return None; + } + + let poi = ray.at(t); + // Check if at is inside rectangle on plane + if poi.x.abs() > (self.d1/2.0) || poi.y.abs() > (self.d2/2.0) { + // No collision + return None; + } + + Some(Intersection::new(OUT_XY, poi, ray, t)) + } + + fn bounding_box(&self) -> Bound3f { + // A rectangle has no area, but we will give it some for its bounding box + Bound3f::new( + Vector3f::new_xyz(-self.d1, -self.d2, self.offset - 0.0001), + Vector3f::new_xyz(self.d1, self.d2, self.offset + 0.0001) + ) + } +} + +impl Into<DynHittable> for Rect { + fn into(self) -> DynHittable { + DynHittable::new(Box::new(self)) + } +} + +impl Instancable for Rect {} + +impl Plane { + pub fn switch(&self, v: Vector3f) -> Vector3f { + match self { + Plane::XY => v, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn xy_rect() { + let rect = Rect::new_xy(5.0, 5.0); + let ray = Ray { + origin: Vector3f::new_xyz(0.0, 1.0, 1.5), + direction: Vector3f::new_xyz(0.0, 0.0, -1.0), + }; + + let t = rect.intersect(&ray).unwrap().t; + assert!((t - 1.5).abs() < 0.01); + } + + #[test] + fn xy_rect_offset() { + let rect = Rect::new_with_offset(5.0, 5.0, -1.0, Plane::XY); + let ray = Ray { + origin: Vector3f::new_xyz(0.0, 1.0, 1.5), + direction: Vector3f::new_xyz(0.0, 0.0, -1.0), + }; + + let t = rect.intersect(&ray).unwrap().t; + assert!((t - 2.5).abs() < 0.01); + } +} diff --git a/src/world/shapes/sphere.rs b/src/world/shapes/sphere.rs index 36c9d13..5f32c7f 100644 --- a/src/world/shapes/sphere.rs +++ b/src/world/shapes/sphere.rs @@ -97,7 +97,6 @@ mod tests { }; let dist = sph.intersect(&ray).unwrap(); - println!("Yay {}", dist.t); assert!((dist.t - 1.732).abs() < 0.01); } } |