diff options
author | Julian T <julian@jtle.dk> | 2021-02-07 17:52:30 +0100 |
---|---|---|
committer | Julian T <julian@jtle.dk> | 2021-02-07 17:52:46 +0100 |
commit | c24d1e52b3f173ba5f4cc04f5a6a449a011a60c7 (patch) | |
tree | ff39abb0473a78aa15fbd2ab4c7f5c82660fe3ab /src | |
parent | 33e747fa1c0957546c10e4d7b490ac7fbb0fd2d2 (diff) |
Add reflecting material
Diffstat (limited to 'src')
-rw-r--r-- | src/core/ray.rs | 7 | ||||
-rw-r--r-- | src/core/spectrum.rs | 2 | ||||
-rw-r--r-- | src/core/vector3.rs | 10 | ||||
-rw-r--r-- | src/lib.rs | 3 | ||||
-rw-r--r-- | src/main.rs | 12 | ||||
-rw-r--r-- | src/material/mod.rs | 2 | ||||
-rw-r--r-- | src/material/reflectant.rs | 39 | ||||
-rw-r--r-- | src/trace/pathtrace.rs | 12 |
8 files changed, 77 insertions, 10 deletions
diff --git a/src/core/ray.rs b/src/core/ray.rs index c944184..0517e50 100644 --- a/src/core/ray.rs +++ b/src/core/ray.rs @@ -8,6 +8,13 @@ pub struct Ray { } impl Ray { + pub fn new(origin: Vector3f, direction: Vector3f) -> Ray { + Ray { + origin, + direction, + } + } + pub fn new_to(origin: Vector3f, target: Vector3f) -> Ray { let dir = (target - origin).norm(); Ray { diff --git a/src/core/spectrum.rs b/src/core/spectrum.rs index 9cca7dc..c33d3af 100644 --- a/src/core/spectrum.rs +++ b/src/core/spectrum.rs @@ -12,6 +12,8 @@ pub struct Spectrum { } impl Spectrum { + pub const ZERO: Self = Spectrum { c: [0.0; 3] }; + pub fn new_rgb(r: Float, g: Float, b: Float) -> Spectrum { Spectrum { c: [r, g, b] } } diff --git a/src/core/vector3.rs b/src/core/vector3.rs index ff5a678..9d6c1cf 100644 --- a/src/core/vector3.rs +++ b/src/core/vector3.rs @@ -2,7 +2,7 @@ //! //! Also add more 3d math things needed for shading and 3d calculations. use crate::{Float, Number, NEAR_ZERO}; -use std::ops::{Mul, Sub, Add, DivAssign, Neg}; +use std::ops::{Mul, Sub, Add, DivAssign, Neg, AddAssign}; use std::fmt; #[derive(Clone, Copy)] @@ -85,6 +85,14 @@ impl<T: Number> Neg for Vector3<T> { } } +impl<T: Number> AddAssign<&Self> for Vector3<T> { + fn add_assign(&mut self, op: &Self) { + self.x += op.x; + self.y += op.y; + self.z += op.z; + } +} + impl<T: Number> DivAssign<T> for Vector3<T> { fn div_assign(&mut self, op: T) { self.x /= op; @@ -6,7 +6,7 @@ pub mod trace; pub mod sample; pub mod material; -use std::ops::{Add, Sub, Mul, DivAssign, Neg}; +use std::ops::{Add, Sub, Mul, DivAssign, AddAssign, Neg}; use std::cmp; use std::fmt; use std::f64::consts::PI; @@ -22,6 +22,7 @@ pub trait Number: Mul<Output = Self> + Neg<Output = Self> + DivAssign + + AddAssign + fmt::Display {} diff --git a/src/main.rs b/src/main.rs index 759cbf9..ac197a1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use pathtrace::scene::shapes::Sphere; use pathtrace::core::{Vector2i, Vector3f, Spectrum}; use pathtrace::render::{RenderContext, RenderTask}; use pathtrace::sample::UniformSampler; -use pathtrace::material::Lambertian; +use pathtrace::material::{Reflectant, Lambertian}; use std::rc::Rc; @@ -13,8 +13,8 @@ fn main() { let res = Vector2i::new_xy(500, 500); let cam = Camera::new(&CameraSettings { - target: Vector3f::new_xyz(0.0, 0.0, -1.0), - origin: Vector3f::new_xyz(0.0, 0.0, 0.0), + target: Vector3f::new_xyz(0.5, 0.0, -1.0), + origin: Vector3f::new_xyz(0.0, 0.0, 0.5), up: Vector3f::new_xyz(0.0, 1.0, 0.0), fov: 90.0, screensize: res, @@ -22,10 +22,12 @@ fn main() { let brown = Rc::new(Lambertian::new(Spectrum::new_rgb(0.5, 0.3, 0.0))); let blue = Rc::new(Lambertian::new(Spectrum::new_rgb(0.0, 0.3, 0.7))); + let metal = Rc::new(Reflectant::new(Spectrum::new_rgb(0.75, 0.75, 0.75), Some(0.1))); let mut scn = Scene::new(); scn.add_objects(vec![ - Object::new(blue.clone(), Box::new(Sphere::new(0.5, Vector3f::new_xyz(0.0, 0.0, -1.0)))), + Object::new(metal.clone(), Box::new(Sphere::new(0.5, Vector3f::new_xyz(0.0, 0.0, -1.0)))), + Object::new(blue.clone(), Box::new(Sphere::new(0.5, Vector3f::new_xyz(1.0, 0.0, -1.0)))), Object::new(brown.clone(), Box::new(Sphere::new(100.0, Vector3f::new_xyz(0.0, -100.5, -1.0)))), ]); @@ -38,7 +40,7 @@ fn main() { let mut film = Film::new(res); let tile = film.get_tile(&film.frame); - let mut task = RenderTask::new(Box::new(tile), 10); + let mut task = RenderTask::new(Box::new(tile), 100); task.render(&ctx, &mut sampler); film.commit_tile(&task.tile); diff --git a/src/material/mod.rs b/src/material/mod.rs index 62cbf9a..c939385 100644 --- a/src/material/mod.rs +++ b/src/material/mod.rs @@ -2,8 +2,10 @@ use crate::core::{Ray, Intersection, Spectrum}; use crate::sample::Sampler; mod lambertian; +mod reflectant; pub use lambertian::Lambertian; +pub use reflectant::Reflectant; pub trait Material { fn scatter(&self, ray: &Ray, i: &Intersection, sampler: &mut dyn Sampler) -> Option<(Spectrum, Ray)>; diff --git a/src/material/reflectant.rs b/src/material/reflectant.rs new file mode 100644 index 0000000..f4b110c --- /dev/null +++ b/src/material/reflectant.rs @@ -0,0 +1,39 @@ +use crate::Float; +use crate::core::{Ray, Intersection, Spectrum, Vector3f}; +use super::Material; +use crate::sample::Sampler; + +pub struct Reflectant { + color: Spectrum, + fuzz: Option<Float>, +} + +impl Reflectant { + pub fn new(c: Spectrum, fuzz: Option<Float>) -> Reflectant { + Reflectant { + color: c, + fuzz, + } + } +} + +fn reflect(v: &Vector3f, n: &Vector3f) -> Vector3f { + *v - *n * (2.0 * v.dot(n)) +} + +impl Material for Reflectant { + fn scatter(&self, ray: &Ray, i: &Intersection, sampler: &mut dyn Sampler) -> Option<(Spectrum, Ray)> { + // Find reflectance vector + let mut reflected = reflect(&ray.direction, &i.n); + if let Some(fuzz) = self.fuzz { + reflected += &(sampler.get_unit_vector() * fuzz); + } + + Some(( + self.color, + Ray::new(i.p, reflected.norm()), + )) + } +} + + diff --git a/src/trace/pathtrace.rs b/src/trace/pathtrace.rs index a3a688a..811b653 100644 --- a/src/trace/pathtrace.rs +++ b/src/trace/pathtrace.rs @@ -18,11 +18,17 @@ impl PathTracer<'_> { } } - pub fn trace_recur(&self, sampler: &mut dyn Sampler, ray: &Ray) -> Spectrum { + pub fn trace_recur(&self, sampler: &mut dyn Sampler, ray: &Ray, depth: i32) -> Spectrum { + + if depth == 0 { + return Spectrum::ZERO; + } if let Some((mat, i)) = self.scn.intersect(ray) { if let Some((scalar, nray)) = mat.scatter(ray, &i, sampler) { - return self.trace_recur(sampler, &nray) * scalar; + return self.trace_recur(sampler, &nray, depth-1) * scalar; + } else { + return Spectrum::ZERO; } } @@ -35,6 +41,6 @@ impl PathTracer<'_> { impl Tracer for PathTracer<'_> { fn trace(&self, sampler: &mut dyn Sampler, ray: &Ray) -> Spectrum { - self.trace_recur(sampler, ray) + self.trace_recur(sampler, ray, self.depth) } } |