diff options
-rw-r--r-- | src/core/ray.rs | 7 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/main.rs | 5 | ||||
-rw-r--r-- | src/render.rs | 14 | ||||
-rw-r--r-- | src/scene/scene.rs | 2 | ||||
-rw-r--r-- | src/scene/shapes/mod.rs | 8 | ||||
-rw-r--r-- | src/scene/shapes/sphere.rs | 6 | ||||
-rw-r--r-- | src/trace/mod.rs | 30 |
8 files changed, 60 insertions, 13 deletions
diff --git a/src/core/ray.rs b/src/core/ray.rs index 2368315..f5517ce 100644 --- a/src/core/ray.rs +++ b/src/core/ray.rs @@ -1,8 +1,15 @@ //! The ray class used when probing the 3d scene use crate::core::Vector3f; +use crate::Float; pub struct Ray { pub origin: Vector3f, pub direction: Vector3f, } +impl Ray { + pub fn at(&self, t: Float) -> Vector3f { + self.origin + self.direction * t + } +} + @@ -2,6 +2,7 @@ pub mod core; pub mod camera; pub mod render; pub mod scene; +pub mod trace; use std::ops::{Add, Sub, Mul, DivAssign}; use std::cmp; diff --git a/src/main.rs b/src/main.rs index 05d6617..9985a80 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use pathtrace::camera::{Camera, Film}; use pathtrace::scene::Scene; +use pathtrace::trace::Tracer; use pathtrace::scene::shapes::Sphere; use pathtrace::core::{Vector2i, Vector3f}; use pathtrace::render::{RenderContext, RenderTask}; @@ -19,7 +20,9 @@ fn main() { Box::new(Sphere::new(4.0, Vector3f::new(0.0))), ); - let ctx = RenderContext { cam: &cam, scn: &scn }; + let tracer = Tracer::new(); + + let ctx = RenderContext { cam: &cam, scn: &scn, trc: &tracer }; let mut film = Film::new(res); let tile = film.get_tile(&film.frame); diff --git a/src/render.rs b/src/render.rs index dcda672..7d05aba 100644 --- a/src/render.rs +++ b/src/render.rs @@ -4,12 +4,11 @@ use crate::camera::film::FilmTile; use crate::camera::Camera; use crate::scene::Scene; +use crate::trace::Tracer; -use crate::core::{Vector2f, Spectrum}; +use crate::core::{Vector2f, Vector3f, Spectrum}; use crate::Float; -const HALF_PIXEL: Vector2f = Vector2f {x: 0.5, y: 0.5 }; - pub struct RenderTask { pub tile: Box<FilmTile>, samples: u32, @@ -18,6 +17,7 @@ pub struct RenderTask { pub struct RenderContext<'a> { pub scn: &'a Scene, pub cam: &'a Camera, + pub trc: &'a Tracer, } impl RenderTask { @@ -29,13 +29,7 @@ impl RenderTask { // Create a ray let (r, _) = ctx.cam.generate_ray(&Vector2f::new_xy(x as Float, y as Float)); - // Trace ray - if let Some(_) = ctx.scn.intersect(r) { - return Spectrum::new_rgb(0.5, 0.5, 0.0); - } - - Spectrum::new_rgb(0.0, 0.0, 0.0) - + ctx.trc.trace(ctx.scn, &r) } pub fn render(&mut self, ctx: &RenderContext) { diff --git a/src/scene/scene.rs b/src/scene/scene.rs index a2f5b88..33a7613 100644 --- a/src/scene/scene.rs +++ b/src/scene/scene.rs @@ -22,7 +22,7 @@ impl Scene { self.shps.push(shp); } - pub fn intersect(&self, ray: Ray) -> Option<Intersection> { + pub fn intersect(&self, ray: &Ray) -> Option<Intersection> { for shp in self.shps.iter() { if let Some(t) = shp.intersect(&ray) { return Some(Intersection { diff --git a/src/scene/shapes/mod.rs b/src/scene/shapes/mod.rs index 7fbb8db..9b6bdfd 100644 --- a/src/scene/shapes/mod.rs +++ b/src/scene/shapes/mod.rs @@ -2,9 +2,15 @@ mod sphere; pub use sphere::Sphere; -use crate::core::Ray; +use crate::core::{Vector3f, Ray}; use crate::Float; pub trait Shape { fn intersect(&self, ray: &Ray) -> Option<Float>; + + /// Calculates the normal at point + /// + /// Point is assumed to be on the circle. + /// The resulting vector is assumed to be normalized. + fn norm_at(&self, point: &Vector3f) -> Vector3f; } diff --git a/src/scene/shapes/sphere.rs b/src/scene/shapes/sphere.rs index e30c1ec..da7f321 100644 --- a/src/scene/shapes/sphere.rs +++ b/src/scene/shapes/sphere.rs @@ -35,6 +35,12 @@ impl Shape for Sphere { } } + + fn norm_at(&self, point: &Vector3f) -> Vector3f { + let mut v = *point - self.center; + v /= self.radius; + v + } } #[cfg(test)] diff --git a/src/trace/mod.rs b/src/trace/mod.rs new file mode 100644 index 0000000..90f12da --- /dev/null +++ b/src/trace/mod.rs @@ -0,0 +1,30 @@ +use crate::scene::Scene; +use crate::core::{Spectrum, Ray, Vector3f}; + +/// Simple surface normal tracer +/// +/// This ray tracer bases color values on the hit surface normals +pub struct NormTracer {} + +/// Alias for chosen trace implementation. +/// +/// This is swiched at compile time to save alot of time. +pub type Tracer = NormTracer; + +impl NormTracer { + pub fn new() -> NormTracer { + NormTracer {} + } + + pub fn trace(&self, scn: &Scene, ray: &Ray) -> Spectrum { + // Trace ray + if let Some(i) = scn.intersect(ray) { + let p = ray.at(i.t); + let norm = i.shp.norm_at(&p) * 0.5 + Vector3f::new(0.5); + + return Spectrum::new_rgb(norm.x, norm.y, norm.z); + } + + Spectrum::new_rgb(0.0, 0.0, 0.0) + } +} |