aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/camera/camera.rs71
-rw-r--r--src/core/bound.rs4
-rw-r--r--src/core/hittable.rs2
-rw-r--r--src/core/vector3.rs2
-rw-r--r--src/main.rs24
-rw-r--r--src/scene/scene.rs16
-rw-r--r--src/scene/shapes/sphere.rs5
-rw-r--r--src/trace/mod.rs4
-rw-r--r--src/trace/pathtrace.rs4
9 files changed, 83 insertions, 49 deletions
diff --git a/src/camera/camera.rs b/src/camera/camera.rs
index d49220b..e770efe 100644
--- a/src/camera/camera.rs
+++ b/src/camera/camera.rs
@@ -6,23 +6,28 @@
//! # Examples
//!
//! ```
-//! use pathtrace::camera::Camera;
-//! use pathtrace::core::{Vector3f, Vector2f, Vector2i};
+//! use rendering::camera::{CameraSettings, Camera};
+//! use rendering::core::{Vector3f, Vector2f, Vector2i};
//!
-//! let cam = Camera::new(
-//! Vector3f::new(10.0),
-//! Vector3f::new(0.0),
-//! Vector3f::new_xyz(0.0, 1.0, 0.0),
-//! 90.0, Vector2i::new(10.0),
-//! );
+//! let set = CameraSettings {
+//! origin: Vector3f::new(10.0),
+//! target: Vector3f::new(0.0),
+//! up: Vector3f::new_xyz(0.0, 1.0, 0.0),
+//! fov: 90.0,
+//! filmsize: Vector2i::new(10),
+//! focus: None,
+//! aperture: 0.0,
+//! };
+//!
+//! let cam = Camera::new(&set);
//!
//! let (r, _) = cam.generate_ray(&Vector2f::new(5.0));
//! let dir = r.direction;
//!
//! assert!(
-//! dir.x == -0.44792563 &&
-//! dir.y == -0.659974 &&
-//! dir.z == -0.6031559
+//! dir.x == -0.6031558065478413 &&
+//! dir.y == -0.6599739684616743 &&
+//! dir.z == -0.4479257014065748
//! );
//!
//! ```
@@ -33,43 +38,58 @@ use crate::core::{Vector3f, Vector2f, Vector2i, Ray};
pub struct Camera {
/// The camera origin in the screen
origin: Vector3f,
- /// Vector from camera origin to the screen lower left corner
+ /// Vector from camera origin to the screen lower left corner of the film plane
screen_origin: Vector3f,
/// Scaling vectors from screen_origin
qx: Vector3f,
qy: Vector3f,
}
+/// Settings for initializing camera
pub struct CameraSettings {
+ /// Where rays originate from
pub origin: Vector3f,
+ /// Point where center of image is pointed at
pub target: Vector3f,
+ /// Vector that will be up in the resulting image
pub up: Vector3f,
+ /// The vertical field of view in degrees.
+ /// Currently must be between [0; 180[.
pub fov: Float,
- pub screensize: Vector2i,
+ /// The film aspect ratio, height / width
+ pub filmsize: Vector2i,
+ /// The lens aperture
+ pub aperture: Float,
+ /// The distance to the focus plane
+ ///
+ /// if None it will be set to the distance between origin and target
+ pub focus: Option<Float>,
}
impl Camera {
/// Create a new camera look at a target
- ///
- /// The field of view specifies how wide the image should be.
- /// Currently must be between [0; 180[.
pub fn new(set: &CameraSettings) -> Camera {
- let screensize = Vector2f::from(set.screensize);
+ let filmsize = Vector2f::from(set.filmsize);
// Calculate translation vectors
- let forward = (set.target - set.origin).norm();
+ let mut forward = set.target - set.origin;
+
+ let focus = set.focus.unwrap_or(forward.len());
+
+ forward.norm_in();
+
let right = set.up.cross(&forward).norm();
let newup = forward.cross(&right).norm();
- // Calculate screen size from fov
- let aspect = screensize.y / screensize.x;
- let width = 2.0 * (set.fov / 2.0).to_radians().tan();
+ let aspect = (filmsize.y) / (filmsize.x);
+ // Calculate screen size from fov and focus distance
+ let width = 2.0 * focus * (set.fov / 2.0).to_radians().tan();
let height = aspect * width;
// Calculate screen scaling vectors
- let qx = right * (width / (screensize.x - 1.0));
- let qy = newup * (height / (screensize.y - 1.0));
+ let qx = right * (width / (filmsize.x - 1.0));
+ let qy = newup * (height / (filmsize.y - 1.0));
- let screen_origin = forward - (right * (width/2.0)) + (newup * (height/2.0));
+ let screen_origin = forward * focus - (right * (width/2.0)) + (newup * (height/2.0));
Camera {
origin: set.origin,
@@ -81,8 +101,7 @@ impl Camera {
/// Generates a ray a screen space point
///
- /// The point coordinates should be between [0,0] (lower left corner) and [screensize.x,
- /// screensize.y] (upper right corner)
+ /// The point coordinates should be between [0,1) with (0, 0) being the upper let corner
///
/// Will return a ray and a weight
///
diff --git a/src/core/bound.rs b/src/core/bound.rs
index 635218a..a1c1070 100644
--- a/src/core/bound.rs
+++ b/src/core/bound.rs
@@ -52,7 +52,7 @@ impl<T: Number> Bound2<T> {
/// # Examples
///
/// ```
- /// use pathtrace::core::Bound2i;
+ /// use rendering::core::Bound2i;
/// let b = Bound2i::new_xyxy(2, 2, 6, 7);
/// let diag = b.diagonal();
///
@@ -67,7 +67,7 @@ impl<T: Number> Bound2<T> {
/// # Examples
///
/// ```
- /// use pathtrace::core::Bound2i;
+ /// use rendering::core::Bound2i;
/// let b = Bound2i::new_xyxy(10, 10, 20, 20);
///
/// assert!(b.area() == 100);
diff --git a/src/core/hittable.rs b/src/core/hittable.rs
index 20c82f7..e495d5b 100644
--- a/src/core/hittable.rs
+++ b/src/core/hittable.rs
@@ -1,10 +1,12 @@
use crate::core::{Vector3f, Ray};
+use crate::Float;
/// Returns the context of a intersection
pub struct Intersection {
/// Normal vector at intersection
pub n: Vector3f,
pub p: Vector3f,
+ pub t: Float,
}
impl Intersection {
diff --git a/src/core/vector3.rs b/src/core/vector3.rs
index 9d6c1cf..1ae4db2 100644
--- a/src/core/vector3.rs
+++ b/src/core/vector3.rs
@@ -128,7 +128,7 @@ impl Vector3f {
/// # Example
///
/// ```
- /// use pathtrace::core::Vector3f;
+ /// use rendering::core::Vector3f;
/// let mut v = Vector3f::new_xyz(10.0, 0.0, 0.0);
/// v.norm_in();
/// assert!(v.x == 1.0);
diff --git a/src/main.rs b/src/main.rs
index ac197a1..1707360 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,11 +1,11 @@
-use pathtrace::camera::{Camera, Film, CameraSettings};
-use pathtrace::scene::{Scene, Object};
-use pathtrace::trace::DefaultTracer;
-use pathtrace::scene::shapes::Sphere;
-use pathtrace::core::{Vector2i, Vector3f, Spectrum};
-use pathtrace::render::{RenderContext, RenderTask};
-use pathtrace::sample::UniformSampler;
-use pathtrace::material::{Reflectant, Lambertian};
+use rendering::camera::{Camera, Film, CameraSettings};
+use rendering::scene::{Scene, Object};
+use rendering::trace::DefaultTracer;
+use rendering::scene::shapes::Sphere;
+use rendering::core::{Vector2i, Vector3f, Spectrum};
+use rendering::render::{RenderContext, RenderTask};
+use rendering::sample::UniformSampler;
+use rendering::material::{Reflectant, Lambertian};
use std::rc::Rc;
@@ -14,10 +14,12 @@ fn main() {
let cam = Camera::new(&CameraSettings {
target: Vector3f::new_xyz(0.5, 0.0, -1.0),
- origin: Vector3f::new_xyz(0.0, 0.0, 0.5),
+ origin: Vector3f::new_xyz(1.7, 0.0, 0.0),
up: Vector3f::new_xyz(0.0, 1.0, 0.0),
fov: 90.0,
- screensize: res,
+ filmsize: res,
+ focus: None,
+ aperture: 0.5,
});
let brown = Rc::new(Lambertian::new(Spectrum::new_rgb(0.5, 0.3, 0.0)));
@@ -40,7 +42,7 @@ fn main() {
let mut film = Film::new(res);
let tile = film.get_tile(&film.frame);
- let mut task = RenderTask::new(Box::new(tile), 100);
+ let mut task = RenderTask::new(Box::new(tile), 10);
task.render(&ctx, &mut sampler);
film.commit_tile(&task.tile);
diff --git a/src/scene/scene.rs b/src/scene/scene.rs
index 8575217..83a43c7 100644
--- a/src/scene/scene.rs
+++ b/src/scene/scene.rs
@@ -7,6 +7,11 @@ pub struct Scene {
objs: Vec<Object>,
}
+pub struct SceneIntersect<'a> {
+ pub mat: &'a dyn Material,
+ pub i: Intersection,
+}
+
impl Scene {
pub fn new() -> Self {
Self {
@@ -24,14 +29,19 @@ impl Scene {
}
}
- pub fn intersect(&self, ray: &Ray) -> Option<(&dyn Material, Intersection)> {
+ pub fn intersect(&self, ray: &Ray) -> Option<SceneIntersect> {
+ let mut min: Option<SceneIntersect> = None;
+
for obj in self.objs.iter() {
if let Some(i) = obj.shape.intersect(&ray) {
- return Some((obj.mat.as_ref(), i))
+ match min {
+ Some(ref si) if si.i.t < i.t => (),
+ _ => min = Some(SceneIntersect {i, mat: obj.mat.as_ref() }),
+ }
}
}
- None
+ min
}
}
diff --git a/src/scene/shapes/sphere.rs b/src/scene/shapes/sphere.rs
index 3f07b9e..eaa6625 100644
--- a/src/scene/shapes/sphere.rs
+++ b/src/scene/shapes/sphere.rs
@@ -44,6 +44,7 @@ impl Hittable for Sphere {
Some(Intersection {
n: self.norm_at(&w),
p: w,
+ t: distance,
})
}
@@ -63,7 +64,7 @@ mod tests {
direction: Vector3f::new_xyz(0.0, 1.0, 1.5).norm(),
};
- let dist = sph.intersect(&ray);
- assert!((dist.unwrap() - 3.28).abs() < 0.01);
+ let dist = sph.intersect(&ray).unwrap();
+ assert!((dist.t - 3.28).abs() < 0.01);
}
}
diff --git a/src/trace/mod.rs b/src/trace/mod.rs
index cf06246..6c2c9f3 100644
--- a/src/trace/mod.rs
+++ b/src/trace/mod.rs
@@ -30,8 +30,8 @@ impl NormTracer<'_> {
impl Tracer for NormTracer<'_> {
fn trace(&self, _: &mut dyn Sampler, ray: &Ray) -> Spectrum {
// Trace ray, we dont care about material
- if let Some((_, i)) = self.scn.intersect(ray) {
- let norm = i.n * 0.5 + Vector3f::new(0.5);
+ if let Some(si) = self.scn.intersect(ray) {
+ let norm = si.i.n * 0.5 + Vector3f::new(0.5);
return Spectrum::new_rgb(norm.x, norm.y, norm.z);
}
diff --git a/src/trace/pathtrace.rs b/src/trace/pathtrace.rs
index 811b653..af24118 100644
--- a/src/trace/pathtrace.rs
+++ b/src/trace/pathtrace.rs
@@ -24,8 +24,8 @@ impl PathTracer<'_> {
return Spectrum::ZERO;
}
- if let Some((mat, i)) = self.scn.intersect(ray) {
- if let Some((scalar, nray)) = mat.scatter(ray, &i, sampler) {
+ if let Some(si) = self.scn.intersect(ray) {
+ if let Some((scalar, nray)) = si.mat.scatter(ray, &si.i, sampler) {
return self.trace_recur(sampler, &nray, depth-1) * scalar;
} else {
return Spectrum::ZERO;