aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian T <julian@jtle.dk>2021-08-05 15:42:43 +0200
committerJulian T <julian@jtle.dk>2021-08-05 15:42:43 +0200
commitc5505ab84820248c6dba35fc06aef9e0ced183de (patch)
treebb1d508c31c6a5aa5d57aed86daaeb6f9cffc88e
parent02fedfc9653cb37219849de7dae14ae13d2f6c36 (diff)
Add XY rectangle
-rw-r--r--src/core/spectrum.rs2
-rw-r--r--src/main.rs25
-rw-r--r--src/trace/pathtrace.rs1
-rw-r--r--src/world/shapes/mod.rs2
-rw-r--r--src/world/shapes/rectangle.rs105
-rw-r--r--src/world/shapes/sphere.rs1
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);
}
}