pbrt_r3/core/reflection/
math.rs1use crate::core::base::*;
2
3#[inline]
5pub fn cos_theta(w: &Vector3f) -> Float {
6 return w.z;
7}
8
9#[inline]
10pub fn cos_2_theta(w: &Vector3f) -> Float {
11 return w.z * w.z;
12}
13
14#[inline]
15pub fn abs_cos_theta(w: &Vector3f) -> Float {
16 return Float::abs(w.z);
17}
18
19#[inline]
20pub fn sin_2_theta(w: &Vector3f) -> Float {
21 return Float::max(0.0, 1.0 - cos_2_theta(w));
22}
23
24#[inline]
25pub fn sin_theta(w: &Vector3f) -> Float {
26 return Float::sqrt(sin_2_theta(w));
27}
28
29#[inline]
30pub fn tan_theta(w: &Vector3f) -> Float {
31 return sin_theta(w) / cos_theta(w);
32}
33
34#[inline]
35pub fn tan_2_theta(w: &Vector3f) -> Float {
36 return sin_2_theta(w) / cos_2_theta(w);
37}
38
39#[inline]
40pub fn cos_phi(w: &Vector3f) -> Float {
41 let sin = sin_theta(w);
42 return if sin == 0.0 {
43 1.0
44 } else {
45 Float::clamp(w.x / sin, -1.0, 1.0)
46 };
47}
48
49#[inline]
50pub fn sin_phi(w: &Vector3f) -> Float {
51 let sin = sin_theta(w);
52 return if sin == 0.0 {
53 0.0
54 } else {
55 Float::clamp(w.y / sin, -1.0, 1.0)
56 };
57}
58
59#[inline]
60pub fn cos_2_phi(w: &Vector3f) -> Float {
61 return cos_phi(w) * cos_phi(w);
62}
63
64#[inline]
65pub fn sin_2_phi(w: &Vector3f) -> Float {
66 return sin_phi(w) * sin_phi(w);
67}
68
69#[inline]
70pub fn cos_d_phi(wa: &Vector3f, wb: &Vector3f) -> Float {
71 let waxy = wa.x * wa.x + wa.y * wa.y;
72 let wbxy = wb.x * wb.x + wb.y * wb.y;
73 if waxy <= 0.0 || wbxy <= 0.0 {
74 return 1.0;
75 }
76 return Float::clamp(
77 (wa.x * wb.x + wa.y * wb.y) / Float::sqrt(waxy * wbxy),
78 -1.0,
79 1.0,
80 );
81}
82
83#[inline]
84pub fn reflect(wo: &Vector3f, n: &Vector3f) -> Vector3f {
85 let a = 2.0 * Vector3f::dot(wo, n) * *n;
86 let b = -*wo;
87 return a + b;
88}
89
90#[inline]
91pub fn refract(wi: &Vector3f, n: &Vector3f, eta: Float) -> Option<Vector3f> {
92 let cos_theta_i = Vector3f::dot(n, wi);
94 let sin2_theta_i = Float::max(0.0, 1.0 - cos_theta_i * cos_theta_i);
95 let sin2_theta_t = eta * eta * sin2_theta_i;
96 if sin2_theta_t >= 1.0 {
98 return None;
99 } else {
100 let cos_theta_t = Float::sqrt(1.0 - sin2_theta_t);
101 let a = eta * -*wi;
102 let b = (eta * cos_theta_i - cos_theta_t) * *n;
103 let wt = a + b;
104 return Some(wt);
105 }
106}
107
108#[inline]
109pub fn same_hemisphere(w: &Vector3f, wp: &Vector3f) -> bool {
110 return w.z * wp.z > 0.0;
111}