1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use std::f32;
use film::Colorf;
use linalg;
fn dielectric(cos_i: f32, cos_t: f32, eta_i: f32, eta_t: f32) -> Colorf {
let r_par = (eta_t * cos_i - eta_i * cos_t) / (eta_t * cos_i + eta_i * cos_t);
let r_perp = (eta_i * cos_i - eta_t * cos_t) / (eta_i * cos_i + eta_t * cos_t);
Colorf::broadcast(0.5 * (r_par * r_par + r_perp * r_perp))
}
fn conductor(cos_i: f32, eta: &Colorf, k: &Colorf) -> Colorf {
let a = (*eta * *eta + *k * *k) * cos_i * cos_i;
let col = Colorf::broadcast(1.0);
let r_par = (a - *eta * cos_i * 2.0 + col) / (a + *eta * cos_i * 2.0 + col);
let b = *eta * *eta + *k * *k;
let col = Colorf::broadcast(cos_i * cos_i);
let r_perp = (b - *eta * cos_i * 2.0 + col) / (b + *eta * cos_i * 2.0 + col);
(r_par + r_perp) * 0.5
}
pub trait Fresnel {
fn fresnel(&self, cos_i: f32) -> Colorf;
}
#[derive(Clone, Copy, Debug)]
pub struct Dielectric {
pub eta_i: f32,
pub eta_t: f32,
}
impl Dielectric {
pub fn new(eta_i: f32, eta_t: f32) -> Dielectric { Dielectric { eta_i: eta_i, eta_t: eta_t } }
}
impl Fresnel for Dielectric {
fn fresnel(&self, cos_i: f32) -> Colorf {
let ci = linalg::clamp(cos_i, -1.0, 1.0);
let (ei, et) =
if ci > 0.0 {
(self.eta_i, self.eta_t)
} else {
(self.eta_t, self.eta_i)
};
let sin_t = ei / et * f32::sqrt(f32::max(0.0, 1.0 - ci * ci));
if sin_t >= 1.0 {
Colorf::broadcast(1.0)
} else {
let ct = f32::sqrt(f32::max(0.0, 1.0 - sin_t * sin_t));
dielectric(f32::abs(ci), ct, ei, et)
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct Conductor {
pub eta: Colorf,
pub k: Colorf,
}
impl Conductor {
pub fn new(eta: &Colorf, k: &Colorf) -> Conductor { Conductor { eta: *eta, k: *k } }
}
impl Fresnel for Conductor {
fn fresnel(&self, cos_i: f32) -> Colorf { conductor(f32::abs(cos_i), &self.eta, &self.k) }
}