From b64c7e972c52b7d015d661866f0cf902370343e5 Mon Sep 17 00:00:00 2001 From: Julian T Date: Sat, 6 Feb 2021 23:43:06 +0100 Subject: Implement pathtracing --- src/trace/mod.rs | 26 +++++++++++++++++++------- src/trace/pathtrace.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 src/trace/pathtrace.rs (limited to 'src/trace') diff --git a/src/trace/mod.rs b/src/trace/mod.rs index 9c8b0b8..7f02f6f 100644 --- a/src/trace/mod.rs +++ b/src/trace/mod.rs @@ -1,24 +1,36 @@ use crate::scene::Scene; use crate::core::{Spectrum, Ray, Vector3f}; +use crate::sample::Sampler; + +mod pathtrace; +pub use pathtrace::PathTracer; /// Simple surface normal tracer /// /// This ray tracer bases color values on the hit surface normals -pub struct NormTracer {} +pub struct NormTracer<'a> { + scn: &'a Scene, +} /// Alias for chosen trace implementation. /// /// This is swiched at compile time to save alot of time. -pub type Tracer = NormTracer; +pub type DefaultTracer<'a> = PathTracer<'a>; -impl NormTracer { - pub fn new() -> NormTracer { - NormTracer {} +pub trait Tracer { + fn trace(&self, sampler: &mut dyn Sampler, ray: &Ray) -> Spectrum; +} + +impl NormTracer<'_> { + pub fn new(scn: &Scene) -> NormTracer { + NormTracer {scn} } +} - pub fn trace(&self, scn: &Scene, ray: &Ray) -> Spectrum { +impl Tracer for NormTracer<'_> { + fn trace(&self, sampler: &mut dyn Sampler, ray: &Ray) -> Spectrum { // Trace ray - if let Some(i) = scn.intersect(ray) { + if let Some(i) = self.scn.intersect(ray) { let norm = 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 new file mode 100644 index 0000000..32a8e15 --- /dev/null +++ b/src/trace/pathtrace.rs @@ -0,0 +1,41 @@ +use crate::scene::Scene; +use crate::core::{Ray, Spectrum}; +use crate::sample::Sampler; +use super::Tracer; + +pub struct PathTracer<'a> { + depth: i32, + scn: &'a Scene, +} + +impl PathTracer<'_> { + pub fn new(scn: &Scene, depth: Option) -> PathTracer { + let depth = depth.unwrap_or(-1); + + PathTracer { + depth, + scn, + } + } + + pub fn trace_recur(&self, sampler: &mut dyn Sampler, ray: &Ray) -> Spectrum { + + if let Some(i) = self.scn.intersect(ray) { + // Get a random direction in the hemisphere a i.p + // This is Lambertian reflection + let target = i.p + i.n + sampler.get_unit_vector(); + return self.trace_recur(sampler, &Ray::new_to(i.p, target)) * 0.5; + } + + // Simulates a sky + let t = (ray.direction.norm().y + 1.0) * 0.5; + Spectrum::new_rgb(1.0, 1.0, 1.0) * (1.0-t) + Spectrum::new_rgb(0.5, 0.7, 1.0) * t + + } +} + +impl Tracer for PathTracer<'_> { + fn trace(&self, sampler: &mut dyn Sampler, ray: &Ray) -> Spectrum { + self.trace_recur(sampler, ray) + } +} -- cgit v1.2.3