bsdf/
core.rs

1/// used for colors
2pub type RgbD = glam::f64::DVec3;
3/// used for colors
4pub type RgbF = glam::f32::Vec3;
5
6/// used for direction vectors
7pub type Vec3d = glam::f64::DVec3;
8/// used for direction vectors
9pub type Vec2d = glam::f64::DVec2;
10
11/// Contains the Data that is returned by [`BSDF::sample_incoming`]
12pub struct SampleIncomingResponse {
13    /// # Incoming Direction
14    ///The direction where light could be arriving at the surface
15    pub omega_i: Vec3d,
16
17    /// The value of the BSDF at the given direction. Indicates how much light is scattered from the incoming
18    /// direction to the outgoing direction
19    pub bsdf: RgbD,
20
21    /// Indicates how much light is emitted in the outgoing direction
22    pub emission: RgbD,
23
24    /// The probability distribution for choosing `omega_i` given `omega_o`
25    pub pdf: f64,
26}
27
28/// Contains the Data that is returned by [`BSDF::sample_outgoing`]
29pub struct SampleOutgoingResponse {
30    /// The direction to which light is scattered to
31    pub omega_o: Vec3d,
32
33    /// The value of the BSDF at the given direction. Indicates how much light is scattered from the incoming
34    /// direction to the outgoing direction
35    pub bsdf: RgbD,
36
37    /// The value of the adjoint BSDF at the given direction. Indicates how much light is scattered from the incoming
38    /// direction to the outgoing direction
39    pub adjoint_bsdf: RgbD,
40
41    /// The probability distribution for choosing `omega_o` given `omega_i`
42    pub pdf: f64,
43}
44
45/// Contains the Data that is returned by [`BSDF::sample_emission`]
46pub struct SampleEmissionResponse {
47    /// The direction to which light is emitted to
48    pub omega_o: Vec3d,
49
50    /// The amount of light which is emitted
51    pub emission: RgbD,
52
53    /// The probability density of choosing that exact direction
54    pub pdf: f64,
55}
56
57/// Bidirectional Scattering Distribution Functions. A trait that describes the surface properties
58/// of a material if you will.
59///
60/// This trait contains functions to importance sample and evaluate a specific BSDF
61pub trait BSDF {
62    /// Given a direction where light is scattered to, samples an incident direction, from which the light
63    /// may come from
64    ///
65    /// # Arguments
66    /// * `omega_o` - The direction where light is scattered to. Outgoing direction
67    /// * `rd` - A random distribution for sampling
68    ///
69    /// # Return
70    /// See [`SampleIncomingResponse`]
71    fn sample_incoming(&self, omega_o: Vec3d, rdf: Vec3d) -> SampleIncomingResponse;
72
73    /// Given an incident light direction, samples a direction where light is scattered to
74    ///
75    /// # Arguments
76    /// * `omega_i` - A direction where light is coming from
77    /// * `surface` - The properties of the surface at a given point
78    /// * `rd` - A random distribution for sampling
79    /// # Return
80    /// See [`SampleOutgoingResponse`]
81    fn sample_outgoing(&self, omega_i: Vec3d, rdf: Vec3d) -> SampleOutgoingResponse {
82        assert!(omega_i.is_normalized());
83        let response = self.sample_incoming(omega_i, rdf);
84        // many materials have symmetric brdfs. Therefore, adjoint_bsdf and bsdf are the same
85        SampleOutgoingResponse {
86            omega_o: response.omega_i,
87            bsdf: response.bsdf,
88            adjoint_bsdf: response.bsdf,
89            pdf: response.pdf,
90        }
91    }
92
93    /// Returns the value of the BSDF at the given directions
94    ///
95    /// # Arguments
96    /// * `omega_o` - Exitant light direction
97    /// * `omega_i` - Incident light direction
98    fn evaluate(&self, omega_o: Vec3d, omega_i: Vec3d) -> RgbD;
99
100    /// Returns the probability density sampling an incoming direction given an outgoing direction
101    /// See [`BSDF::sample_incoming`] and [`SampleIncomingResponse`]
102    fn sample_incoming_pdf(&self, omega_o: Vec3d, omega_i: Vec3d) -> f64;
103
104    /// Returns the probability density sampling an outgoing direction given an incoming direction
105    /// See [`BSDF::sample_outgoing_pdf`] and [`SampleOutgoingResponse`]
106    fn sample_outgoing_pdf(&self, omega_o: Vec3d, omega_i: Vec3d) -> f64 {
107        assert!(omega_o.is_normalized());
108        assert!(omega_i.is_normalized());
109        self.sample_incoming_pdf(omega_i, omega_o)
110    }
111
112    /// Returns how much light is emitted to the given direction `omega_o`
113    fn emission(&self, omega_o: Vec3d) -> RgbD {
114        assert!(omega_o.is_normalized());
115        RgbD::ZERO
116    }
117
118    /// Returns the probability density of choosing the given direction when sampled with
119    /// [`BSDF::sample_emission`]
120    /// Returns `0.0` if the surface does not emit light
121    fn sample_emission_pdf(&self, omega_o: Vec3d) -> f64 {
122        assert!(omega_o.is_normalized());
123        0.0
124    }
125
126    /// Samples a direction in which light is emitted to and also returns the amount of emission
127    /// The returned vector is the null vector, if this surface does not emit any light
128    /// See also: [`SampleEmissionResponse`]
129    fn sample_emission(&self, _rdf: Vec2d) -> SampleEmissionResponse {
130        SampleEmissionResponse {
131            omega_o: Vec3d::ZERO,
132            emission: RgbD::ZERO,
133            pdf: 0.0,
134        }
135    }
136
137    /// Returns the base color of the surface.
138    /// This function is used to generate auxiliary images for AI tools such as Open Image Denoise
139    fn base_color(&self, omega_o: Vec3d) -> RgbD;
140}
141
142/// this is only used for testing
143#[cfg(test)]
144pub trait TransmissiveBsdf: BSDF {
145    fn ior(&self) -> f64;
146}