library: light: point_light: add sample_ray method

This commit is contained in:
Bruno BELANYI 2020-04-01 02:46:01 +02:00
parent 7eefd7b574
commit bb7fa79fc3

View file

@ -1,7 +1,9 @@
use super::{Light, SpatialLight}; use super::{Light, SpatialLight};
use crate::core::LinearColor; use crate::core::LinearColor;
use crate::{Point, Vector}; use crate::{Point, Vector};
use beevee::ray::Ray;
use nalgebra::Unit; use nalgebra::Unit;
use rand::{distributions::Uniform, Rng};
use serde::Deserialize; use serde::Deserialize;
/// Represent a light emanating from a point in space, following the square distance law. /// 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 { pub fn new(position: Point, color: LinearColor) -> Self {
PointLight { position, color } 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 <https://mathworld.wolfram.com/SpherePointPicking.html>
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 { impl Light for PointLight {