diff --git a/pathtracer/src/render/bidirectional/bidirectional_pathtracer.rs b/pathtracer/src/render/bidirectional/bidirectional_pathtracer.rs index f2bff2a..91fbf5b 100644 --- a/pathtracer/src/render/bidirectional/bidirectional_pathtracer.rs +++ b/pathtracer/src/render/bidirectional/bidirectional_pathtracer.rs @@ -1,7 +1,11 @@ use super::super::Renderer; use super::path::*; -use crate::scene::Scene; +use crate::material::Material; +use crate::render::utils::sample_hemisphere; +use crate::scene::{Object, Scene}; +use crate::shape::Shape; use crate::{Point, Vector}; +use beevee::ray::Ray; use image::RgbImage; use nalgebra::Unit; @@ -30,17 +34,35 @@ impl BidirectionalPathtracer { } #[allow(unused)] - fn construct_path(&self, point: Point, _direction: Unit) -> Path { - let mut res = Path::new(point); + fn construct_path(&self, mut origin: Point, mut direction: Unit) -> Path { + let mut res = Path::new(origin); for _ in 0..self.scene.reflection_limit { - // FIXME: - // * cast_ray: if no intersection, return the empty path - // * look-up information at intersection - // * append to path - // * start again with new origin + let ray = Ray::new(origin, direction); + match self.cast_ray(ray) { + Some((distance, obj)) => { + let hit_pos = origin + direction.as_ref() * distance; + let texel = obj.shape.project_texel(&hit_pos); + let properties = obj.material.properties(texel); + let normal = obj.shape.normal(&hit_pos); + let p = PathPoint::new(origin, direction, normal, properties); + + res.push_point(p); + + let (new_direction, _) = sample_hemisphere(normal); + // Calculate the incoming light along the new ray + origin = hit_pos + new_direction.as_ref() * 0.001; + direction = new_direction; + } + None => break, + } } res } + + #[allow(unused)] + fn cast_ray(&self, ray: Ray) -> Option<(f32, &Object)> { + self.scene.bvh.walk(&ray, &self.scene.objects) + } } impl Renderer for BidirectionalPathtracer {