bs_trace/trace/
material.rs

1use crate::image::prelude::Colour;
2use crate::linalg;
3use crate::trace::prelude::Vec3;
4use rand::RngCore;
5use std::fmt::Debug;
6
7pub trait Material: Debug + Send + Sync {
8    fn colour(&self) -> Colour;
9    fn bounce(
10        &self,
11        rng: &mut Box<dyn RngCore>,
12        incident_direction: Vec3,
13        surface_normal: Vec3,
14    ) -> Option<Vec3>;
15}
16
17#[derive(Debug, Clone, Copy, PartialEq)]
18pub struct Lambertian {
19    pub colour: Colour,
20}
21
22#[derive(Debug, Clone, Copy, PartialEq)]
23pub struct Metal {
24    pub colour: Colour,
25    pub fuzz: f64,
26}
27
28impl Lambertian {
29    pub const fn new(colour: Colour) -> Self {
30        Self { colour }
31    }
32}
33
34impl Material for Lambertian {
35    fn colour(&self) -> Colour {
36        self.colour
37    }
38
39    fn bounce(
40        &self,
41        rng: &mut Box<dyn RngCore>,
42        incident_direction: Vec3,
43        surface_normal: Vec3,
44    ) -> Option<Vec3> {
45        loop {
46            let bounce_direction = linalg::rand::random_unit3(rng) + surface_normal;
47            if bounce_direction.mag() < 1.0e-9 {
48                continue;
49            }
50            break Some(bounce_direction.normalised());
51        }
52    }
53}
54
55impl Metal {
56    pub const fn new(colour: Colour, fuzz: f64) -> Self {
57        Self { colour, fuzz }
58    }
59}
60
61impl Material for Metal {
62    fn colour(&self) -> Colour {
63        self.colour
64    }
65
66    fn bounce(
67        &self,
68        rng: &mut Box<dyn RngCore>,
69        incident_direction: Vec3,
70        surface_normal: Vec3,
71    ) -> Option<Vec3> {
72        let b_height = incident_direction.dot(surface_normal);
73        let pure_bounce = incident_direction - surface_normal * 2.0 * b_height;
74        let fuzz_displacement = linalg::rand::random_unit3(rng) * self.fuzz;
75        let bounce = pure_bounce + fuzz_displacement;
76        if bounce.dot(surface_normal) < 0.0 {
77            None
78        } else {
79            Some(bounce)
80        }
81    }
82}