@@ -4,6 +4,8 @@ use crate::{
4
4
utils:: {
5
5
random_in_unit_sphere,
6
6
reflect,
7
+ refract,
8
+ schlick,
7
9
} ,
8
10
} ;
9
11
@@ -17,13 +19,15 @@ pub trait Scatter {
17
19
pub enum Material {
18
20
Lambert ( Lambert ) ,
19
21
Metal ( Metal ) ,
22
+ Dielectric ( Dielectric ) ,
20
23
}
21
24
22
25
impl Scatter for Material {
23
26
fn scatter ( & self , ray_in : & Ray , rec : & HitRecord , attenuation : & mut Vec3D , scattered : & mut Ray ) -> bool {
24
27
match self {
25
28
Material :: Lambert ( material) => material. scatter ( ray_in, rec, attenuation, scattered) ,
26
29
Material :: Metal ( material) => material. scatter ( ray_in, rec, attenuation, scattered) ,
30
+ Material :: Dielectric ( material) => material. scatter ( ray_in, rec, attenuation, scattered) ,
27
31
}
28
32
}
29
33
}
@@ -67,6 +71,7 @@ impl Metal {
67
71
}
68
72
}
69
73
}
74
+
70
75
impl Scatter for Metal {
71
76
fn scatter ( & self , ray_in : & Ray , rec : & HitRecord , attenuation : & mut Vec3D , scattered : & mut Ray ) -> bool {
72
77
let reflected = reflect ( ray_in. direction . unit ( ) , rec. normal ) ;
@@ -79,3 +84,59 @@ impl Scatter for Metal {
79
84
scattered. direction . dot ( rec. normal ) > 0.0
80
85
}
81
86
}
87
+
88
+ #[ derive( Clone , Copy ) ]
89
+ pub struct Dielectric {
90
+ ref_idx : f64 ,
91
+ }
92
+
93
+ impl Dielectric {
94
+ pub fn new ( ref_idx : f64 ) -> Dielectric {
95
+ Dielectric {
96
+ ref_idx
97
+ }
98
+ }
99
+ }
100
+
101
+ impl Scatter for Dielectric {
102
+ fn scatter ( & self , ray_in : & Ray , rec : & HitRecord , attenuation : & mut Vec3D , scattered : & mut Ray ) -> bool {
103
+ let outward_normal: Vec3D ;
104
+ let ni_over_nt: f64 ;
105
+ let mut refracted = Vec3D :: new ( 0.0 , 0.0 , 0.0 ) ;
106
+ let reflect_prob: f64 ;
107
+ let cosine: f64 ;
108
+
109
+ let reflected = reflect ( ray_in. direction . unit ( ) , rec. normal ) ;
110
+ attenuation. x = 1.0 ;
111
+ attenuation. y = 1.0 ;
112
+ attenuation. z = 1.0 ;
113
+
114
+ if ray_in. direction . dot ( rec. normal ) > 0.0 {
115
+ outward_normal = rec. normal * -1.0 ;
116
+ ni_over_nt = self . ref_idx ;
117
+ cosine = self . ref_idx * ray_in. direction . dot ( rec. normal ) / ray_in. direction . mag ( ) ;
118
+ } else {
119
+ outward_normal = rec. normal ;
120
+ ni_over_nt = 1.0 / self . ref_idx ;
121
+ cosine = ray_in. direction . dot ( rec. normal ) * -1.0 / ray_in. direction . mag ( ) ;
122
+ }
123
+
124
+ if refract ( ray_in. direction , outward_normal, ni_over_nt, & mut refracted) {
125
+ reflect_prob = schlick ( cosine, self . ref_idx ) ;
126
+ } else {
127
+ reflect_prob = 1.0 ;
128
+ }
129
+
130
+ if rand:: random :: < f64 > ( ) < reflect_prob {
131
+ // let new_scattered = Ray::new(rec.p, reflected);
132
+ scattered. direction = reflected;
133
+ scattered. origin = rec. p ;
134
+ } else {
135
+ // let new_scattered = Ray::new(rec.p, refracted);
136
+ scattered. direction = refracted;
137
+ scattered. origin = rec. p ;
138
+ }
139
+
140
+ true
141
+ }
142
+ }
0 commit comments