bsdf/
emissive.rs

1//! [BSDF] that emits light but reflects none
2use std::f64::consts;
3
4use crate::{RgbF, BSDF, Vec3d, SampleIncomingResponse, RgbD, Vec2d, SampleEmissionResponse, utils::{self, SafeCast}};
5
6
7
8
9/// A [BSDF] that emits light but scatters none
10/// Can be used for lights
11pub struct Emissive {
12    /// the amount of emission
13    pub emission: RgbF,
14}
15
16impl BSDF for Emissive {
17    fn sample_incoming(
18        &self,
19        _omega_o: Vec3d,
20        _rd: Vec3d
21    ) -> SampleIncomingResponse {
22        SampleIncomingResponse {
23            omega_i: Vec3d::new(0.0, 0.0, 0.0),
24            bsdf: RgbD::ZERO,
25            emission: self.emission.safe_cast(),
26            pdf: 1.0,
27        }
28    }
29
30    fn evaluate(&self, omega_o: Vec3d, omega_i: Vec3d) -> RgbD {
31        assert!(omega_o.is_normalized() && omega_i.is_normalized());
32        RgbD::ZERO
33    }
34
35    fn emission(&self, omega_o: Vec3d) -> RgbD {
36        assert!(omega_o.is_normalized());
37        self.emission.safe_cast()
38    }
39
40    fn sample_emission_pdf(&self, omega_o: Vec3d) -> f64 {
41        assert!(omega_o.is_normalized());
42        omega_o.z.abs() / (2.0 * consts::PI)
43    }
44
45    fn sample_emission(&self, rdf: Vec2d) -> SampleEmissionResponse {
46        let (omega_o, pdf) = utils::spherical_sample_abs_cos_weighted_uv(rdf.x, rdf.y);
47        SampleEmissionResponse {
48            omega_o,
49            emission: self.emission.safe_cast(),
50            pdf,
51        }
52    }
53
54    fn sample_incoming_pdf(&self, omega_o: Vec3d, omega_i: Vec3d) -> f64 {
55        assert!(omega_o.is_normalized() && omega_i.is_normalized());
56        1.0
57    }
58
59    fn base_color(&self, _omega_o: Vec3d) -> RgbD {
60        self.emission.safe_cast()
61    }
62}
63
64