@@ -85,79 +85,6 @@ render(scene_2_spheres(; elem_type=ELEM_TYPE), t_default_cam, 96, 1) # 1 sample
85
85
86
86
# render(scene_4_spheres(; elem_type=ELEM_TYPE), t_default_cam, 96, 16)
87
87
88
- # md"""# Dielectrics
89
-
90
- # from Section 10.2 Snell's Law:
91
- # 
92
-
93
- # Refracted angle `sinθ′ = (η/η′)⋅sinθ`, where η (\eta) are the refractive indices.
94
-
95
- # Split the parts of the ray into `R′=R′⊥+R′∥` (perpendicular and parallel to n⃗′)."""
96
-
97
- # """
98
- # Args:
99
- # refraction_ratio: incident refraction index divided by refraction index of
100
- # hit surface. i.e. η/η′ in the figure above"""
101
- @inline @fastmath function refract (dir:: Vec3{T} , n⃗:: Vec3{T} , refraction_ratio:: T ) where T
102
- cosθ = min (- dir ⋅ n⃗, one (T))
103
- r_out_perp = refraction_ratio * (dir + cosθ* n⃗)
104
- r_out_parallel = -√ (abs (one (T)- squared_length (r_out_perp))) * n⃗
105
- normalize (r_out_perp + r_out_parallel)
106
- end
107
-
108
- # unchanged angle
109
- @assert refract ((@SVector [0.6 ,- 0.8 ,0 ]), (@SVector [0.0 ,1.0 ,0.0 ]), 1.0 ) == @SVector [0.6 ,- 0.8 ,0.0 ]
110
-
111
- # wider angle
112
- t_refract_widerθ = refract (@SVector [0.6 ,- 0.8 ,0.0 ], @SVector [0.0 ,1.0 ,0.0 ], 2.0 )
113
- @assert isapprox (t_refract_widerθ, @SVector [0.87519 ,- 0.483779 ,0.0 ]; atol= 1e-3 )
114
-
115
- # narrower angle
116
- t_refract_narrowerθ = refract (@SVector [0.6 ,- 0.8 ,0.0 ], @SVector [0.0 ,1.0 ,0.0 ], 0.5 )
117
- @assert isapprox (t_refract_narrowerθ, @SVector [0.3 ,- 0.953939 ,0.0 ]; atol= 1e-3 )
118
-
119
- struct Dielectric{T} <: Material{T}
120
- ir:: T # index of refraction, i.e. η.
121
- end
122
-
123
- @inline @fastmath function reflectance (cosθ, refraction_ratio)
124
- # Use Schlick's approximation for reflectance.
125
- # claforte: may be buggy? I'm getting black pixels in the Hollow Glass Sphere...
126
- r0 = (1 - refraction_ratio) / (1 + refraction_ratio)
127
- r0 = r0^ 2
128
- r0 + (1 - r0)* ((1 - cosθ)^ 5 )
129
- end
130
-
131
- @inline @fastmath function scatter (mat:: Dielectric{T} , r_in:: Ray{T} , rec:: HitRecord{T} ) where T
132
- attenuation = SA{T}[1 ,1 ,1 ]
133
- refraction_ratio = rec. front_face ? (one (T)/ mat. ir) : mat. ir # i.e. ηᵢ/ηₜ
134
- cosθ = min (- r_in. dir⋅ rec. n⃗, one (T))
135
- sinθ = √ (one (T) - cosθ^ 2 )
136
- cannot_refract = refraction_ratio * sinθ > one (T)
137
- if cannot_refract || reflectance (cosθ, refraction_ratio) > trand (T)
138
- dir = reflect (r_in. dir, rec. n⃗)
139
- else
140
- dir = refract (r_in. dir, rec. n⃗, refraction_ratio)
141
- end
142
- Scatter (Ray {T} (rec. p, dir), attenuation) # TODO : rename reflected -> !absorbed?
143
- end
144
-
145
- # "From C++: Image 15: Glass sphere that sometimes refracts"
146
- @inline function scene_diel_spheres (left_radius= 0.5 ; elem_type:: Type{T} ) where T # dielectric spheres
147
- spheres = Sphere[]
148
-
149
- # small center sphere
150
- push! (spheres, Sphere ((SA{T}[0 ,0 ,- 1 ]), T (0.5 ), Lambertian (SA{T}[0.1 ,0.2 ,0.5 ])))
151
-
152
- # ground sphere (planet?)
153
- push! (spheres, Sphere ((SA{T}[0 ,- 100.5 ,- 1 ]), T (100 ), Lambertian (SA{T}[0.8 ,0.8 ,0.0 ])))
154
-
155
- # # left and right spheres.
156
- # # Use a negative radius on the left sphere to create a "thin bubble"
157
- push! (spheres, Sphere ((SA{T}[- 1 ,0 ,- 1 ]), T (left_radius), Dielectric (T (1.5 ))))
158
- push! (spheres, Sphere ((SA{T}[1 ,0 ,- 1 ]), T (0.5 ), Metal ((SA{T}[0.8 ,0.6 ,0.2 ]), T (0 ))))
159
- HittableList (spheres)
160
- end
161
88
162
89
# render(scene_diel_spheres(; elem_type=ELEM_TYPE), t_default_cam, 96, 16)
163
90
# render(scene_diel_spheres(), default_camera(), 320, 32)
169
96
# (SA{ELEM_TYPE}[0,1,0]), ELEM_TYPE(20)), 96, 16)
170
97
171
98
172
- # md"# Positioning camera"
173
-
174
- function scene_blue_red_spheres (; elem_type:: Type{T} ) where T # dielectric spheres
175
- spheres = Sphere[]
176
- R = cos (pi / 4 )
177
- push! (spheres, Sphere ((SA{T}[- R,0 ,- 1 ]), R, Lambertian (SA{T}[0 ,0 ,1 ])))
178
- push! (spheres, Sphere ((SA{T}[ R,0 ,- 1 ]), R, Lambertian (SA{T}[1 ,0 ,0 ])))
179
- HittableList (spheres)
180
- end
181
-
182
99
# render(scene_blue_red_spheres(; elem_type=ELEM_TYPE), t_default_cam, 96, 16)
183
100
184
- # md"# Random spheres"
185
-
186
- function scene_random_spheres (; elem_type:: Type{T} ) where T
187
- spheres = Sphere[]
188
-
189
- # ground
190
- push! (spheres, Sphere ((SA{T}[0 ,- 1000 ,- 1 ]), T (1000 ),
191
- Lambertian (SA{T}[0.5 ,0.5 ,0.5 ])))
192
-
193
- for a in - 11 : 10 , b in - 11 : 10
194
- choose_mat = trand (T)
195
- center = SA[a + T (0.9 )* trand (T), T (0.2 ), b + T (0.9 )* trand (T)]
196
-
197
- # skip spheres too close?
198
- if norm (center - SA{T}[4 ,0.2 ,0 ]) < T (0.9 ) continue end
199
-
200
- if choose_mat < T (0.8 )
201
- # diffuse
202
- albedo = @SVector [trand (T) for i ∈ 1 : 3 ] .* @SVector [trand (T) for i ∈ 1 : 3 ]
203
- push! (spheres, Sphere (center, T (0.2 ), Lambertian (albedo)))
204
- elseif choose_mat < T (0.95 )
205
- # metal
206
- albedo = @SVector [random_between (T (0.5 ),T (1.0 )) for i ∈ 1 : 3 ]
207
- fuzz = random_between (T (0.0 ), T (5.0 ))
208
- push! (spheres, Sphere (center, T (0.2 ), Metal (albedo, fuzz)))
209
- else
210
- # glass
211
- push! (spheres, Sphere (center, T (0.2 ), Dielectric (T (1.5 ))))
212
- end
213
- end
214
-
215
- push! (spheres, Sphere ((SA{T}[0 ,1 ,0 ]), T (1 ), Dielectric (T (1.5 ))))
216
- push! (spheres, Sphere ((SA{T}[- 4 ,1 ,0 ]), T (1 ),
217
- Lambertian (SA{T}[0.4 ,0.2 ,0.1 ])))
218
- push! (spheres, Sphere ((SA{T}[4 ,1 ,0 ]), T (1 ),
219
- Metal ((SA{T}[0.7 ,0.6 ,0.5 ]), T (0 ))))
220
- HittableList (spheres)
221
- end
222
-
223
101
t_cam1 = default_camera ([13 ,2 ,3 ], [0 ,0 ,0 ], [0 ,1 ,0 ], 20 , 16 / 9 , 0.1 , 10.0 ; elem_type= ELEM_TYPE)
224
102
225
103
# took ~20s (really rough timing) in REPL, before optimization
0 commit comments