-
Notifications
You must be signed in to change notification settings - Fork 0
/
Dielectric.carp
43 lines (40 loc) · 1.5 KB
/
Dielectric.carp
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
(with Generics
(defn refract [v n ni-over-nt]
(let [uv (Vector3.normalize v)
dt (Vector3.dot &uv n)
discriminant (- (one) (* (squared ni-over-nt) (- (one) (squared dt))))
]
(if (> discriminant (zero))
(Maybe.Just (Vector3.sub &(Vector3.mul
&(Vector3.sub &uv &(Vector3.mul n dt))
ni-over-nt)
&(Vector3.mul n (sqrt discriminant))))
(Maybe.Nothing))))
(defn schlick [cosine ref-idx]
(let [r0 (squared (/ (- (one) ref-idx)
(+ (one) ref-idx)))
]
(+ r0 (* (- (one) r0) (pow (- (one) cosine) (five))))))
(defn dielectric [ref-idx]
(fn [ray hit]
(let [hn (Hit.normal hit)
rd (Ray.direction ray)
reflected (reflect rd hn)
pos (pos? (Vector3.dot rd hn))
ddn (/ (Vector3.dot rd hn) (Vector3.mag rd))
outward-normal (if pos (Vector3.neg hn) @hn)
ni-over-nt (if pos ref-idx (inverse ref-idx))
cosine (if pos (* ref-idx ddn) (neg ddn))
attenuation (Vector3.init (one) (one) (one))
]
(Maybe.Just
(Scatter.init
attenuation
(Ray.init
@(Hit.p hit)
(match (refract rd &outward-normal ni-over-nt)
(Maybe.Just refracted) (if (< (random-0-1) (schlick cosine ref-idx))
reflected
refracted)
(Maybe.Nothing) reflected)))))))
)