aboutsummaryrefslogtreecommitdiff
path: root/src/trace
diff options
context:
space:
mode:
authorJulian T <julian@jtle.dk>2021-02-06 23:43:06 +0100
committerJulian T <julian@jtle.dk>2021-02-06 23:43:06 +0100
commitb64c7e972c52b7d015d661866f0cf902370343e5 (patch)
tree8d3dc9a8ae6b491b9f8f639f2d0bad6387d59069 /src/trace
parent0d5e6bd9363d5ed5c4f28174819fc0f5fd9aa586 (diff)
Implement pathtracing
Diffstat (limited to 'src/trace')
-rw-r--r--src/trace/mod.rs26
-rw-r--r--src/trace/pathtrace.rs41
2 files changed, 60 insertions, 7 deletions
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<i32>) -> 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)
+ }
+}