From cd871055ba4af6067696a6eabce7ac77d19b6e48 Mon Sep 17 00:00:00 2001 From: Bruno BELANYI Date: Wed, 1 Apr 2020 02:46:01 +0200 Subject: [PATCH] library: light: point_light: add sample_ray method --- pathtracer/src/light/point_light.rs | 32 +++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/pathtracer/src/light/point_light.rs b/pathtracer/src/light/point_light.rs index 2e69ec8..19f9d59 100644 --- a/pathtracer/src/light/point_light.rs +++ b/pathtracer/src/light/point_light.rs @@ -1,7 +1,9 @@ use super::{Light, SpatialLight}; use crate::core::LinearColor; use crate::{Point, Vector}; +use beevee::ray::Ray; use nalgebra::Unit; +use rand::{distributions::Uniform, Rng}; use serde::Deserialize; /// Represent a light emanating from a point in space, following the square distance law. @@ -29,6 +31,36 @@ impl PointLight { pub fn new(position: Point, color: LinearColor) -> Self { PointLight { position, color } } + + /// Uniformly sample a ray from the point-light in a random direction. + /// + /// # Examles + /// + ///``` + /// # use pathtracer::light::PointLight; + /// # use pathtracer::core::color::LinearColor; + /// # use pathtracer::Point; + /// # + /// let dir_light = PointLight::new( + /// Point::origin(), + /// LinearColor::new(1.0, 0.0, 1.0), + /// ); + /// let sampled = dir_light.sample_ray(); + /// ``` + pub fn sample_ray(&self) -> Ray { + let mut rng = rand::thread_rng(); + // Sample sphere uniformly + // See + let theta = rng.gen_range(0., std::f32::consts::PI * 2.); + let y = rng.sample(Uniform::new(-1., 1.)); // Inclusive for the poles + let dir = Unit::new_unchecked(Vector::new( + // this vector is already of unit length + f32::sqrt(1. - y * y) * f32::cos(theta), + y, + f32::sqrt(1. - y * y) * f32::sin(theta), + )); + Ray::new(self.position, dir) + } } impl Light for PointLight {