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}