@@ -81,6 +81,8 @@ function get_material(scene::Scene, shape::Triangle)
81
81
get_material (scene. aggregate, shape)
82
82
end
83
83
84
+ using KernelAbstractions. Extras. LoopInfo: @unroll
85
+
84
86
function li (
85
87
sampler, max_depth, ray:: RayDifferentials , scene:: Scene , depth:: Int64 ,
86
88
):: RGBSpectrum
@@ -138,13 +140,121 @@ function li(
138
140
l
139
141
end
140
142
143
+
144
+ function only_light (lights, ray)
145
+ l = RGBSpectrum (0.0f0 )
146
+ Base. Cartesian. @nexprs 8 i -> begin
147
+ if i <= length (lights)
148
+ light = lights[i]
149
+ l += le (light, ray)
150
+ end
151
+ end
152
+ return l
153
+ end
154
+
155
+ function li_iterative (scene, sampler, ray, lights)
156
+ l = RGBSpectrum (0.0f0 )
157
+ srf = RGBSpectrum (1.0f0 )
158
+ stf = RGBSpectrum (1.0f0 )
159
+ i = Int32 (0 )
160
+ max_depth = Int32 (3 )
161
+ reflect = false
162
+ transmit = false
163
+ recursion_depth = Int32 (0 )
164
+ last_ray = ray
165
+ while i ≤ max_depth
166
+ i += Int32 (1 )
167
+ if reflect && i == max_depth
168
+ # i = recursion_depth
169
+ reflect = false
170
+ srf = RGBSpectrum (1.0f0 )
171
+ ray = last_ray
172
+ end
173
+ if transmit && i == max_depth
174
+ # i = recursion_depth
175
+ transmit = false
176
+ stf = RGBSpectrum (1.0f0 )
177
+ end
178
+ l *= srf
179
+ l *= stf
180
+ # Find closest ray intersection or return background radiance.
181
+ hit, shape, si = intersect! (scene, ray)
182
+ if ! hit
183
+ l = only_light (lights, ray)
184
+ break
185
+ end
186
+ f, _ray, bsdf = li_norec (shape, sampler, ray, scene, si)
187
+ l += f
188
+ if _ray != = ray
189
+ last_ray = ray
190
+ ray = _ray
191
+
192
+ continue
193
+ end
194
+ # Trace rays for specular reflection & refraction.
195
+ srf, rayr = specular_reflect (bsdf, sampler, ray, si)
196
+ if rayr != = ray
197
+ last_ray = ray
198
+ ray = rayr
199
+ reflect = true
200
+ # recursion_depth = i
201
+ continue
202
+ end
203
+ stf, rayt = specular_transmit (bsdf, sampler, ray, si)
204
+ if rayt != = ray
205
+ ray = rayt
206
+ transmit = true
207
+ recursion_depth = i
208
+ continue
209
+ end
210
+ end
211
+ return l
212
+ end
213
+
214
+ function li_norec (
215
+ shape, sampler, ray:: RayDifferentials , scene:: Scene , si:: SurfaceInteraction
216
+ )
217
+
218
+ l = RGBSpectrum (0.0f0 )
219
+ lights = scene. lights
220
+ bsdf = BSDF ()
221
+ # Compute emmited & reflected light at ray intersection point.
222
+ # Initialize common variables for Whitted integrator.
223
+ core = si. core
224
+ n = si. shading. n
225
+ wo = core. wo
226
+ # Compute scattering functions for surface interaction.
227
+ si = compute_differentials (si, ray)
228
+ m = get_material (scene, shape)
229
+ if m. type === NO_MATERIAL
230
+ return l, RayDifferentials (spawn_ray (si, ray. d)), bsdf
231
+ end
232
+ bsdf = m (si, false , Radiance)
233
+ # Compute emitted light if ray hit an area light source.
234
+ l += le (si, wo)
235
+ # Add contribution of each light source.
236
+ Base. Cartesian. @nexprs 8 i -> begin
237
+ if i <= length (lights)
238
+ light = lights[i]
239
+ sampled_li, wi, pdf, visibility_tester = sample_li (
240
+ light, core, get_2d (sampler),
241
+ )
242
+ if ! (is_black (sampled_li) || pdf ≈ 0.0f0 )
243
+ f = bsdf (wo, wi)
244
+ if ! is_black (f) && unoccluded (visibility_tester, scene)
245
+ l += f * sampled_li * abs (wi ⋅ n) / pdf
246
+ end
247
+ end
248
+ end
249
+ end
250
+ return l, ray, bsdf
251
+ end
252
+
141
253
@inline function specular_reflect (
142
- bsdf, sampler, max_depth, ray:: RayDifferentials ,
143
- si:: SurfaceInteraction , scene:: Scene , depth:: Int64 ,
254
+ bsdf, sampler, ray:: RayDifferentials , si:: SurfaceInteraction
144
255
)
145
256
146
257
# Compute specular reflection direction `wi` and BSDF value.
147
-
148
258
wo = si. core. wo
149
259
type = BSDF_REFLECTION | BSDF_SPECULAR
150
260
wi, f, pdf, sampled_type = sample_f (
153
263
# Return contribution of specular reflection.
154
264
ns = si. shading. n
155
265
if ! (pdf > 0f0 && ! is_black (f) && abs (wi ⋅ ns) != 0f0 )
156
- return RGBSpectrum (0f0 )
266
+ return RGBSpectrum (1f0 ), ray
157
267
end
158
268
# # Compute ray differential for specular reflection.
159
269
rd = RayDifferentials (spawn_ray (si, wi))
@@ -179,12 +289,12 @@ end
179
289
ry_direction = wi - ∂wo∂y + 2f0 * (wo ⋅ ns) * ∂n∂y + ∂dn∂y * ns
180
290
rd = RayDifferentials (rd, rx_origin= rx_origin, ry_origin= ry_origin, rx_direction= rx_direction, ry_direction= ry_direction)
181
291
end
182
- return f * li (sampler, max_depth, rd, scene, depth + 1 ) * abs (wi ⋅ ns) / pdf
292
+ return f * abs (wi ⋅ ns) / pdf, rd
183
293
end
184
294
185
295
@inline function specular_transmit (
186
- bsdf, sampler, max_depth, ray:: RayDifferentials ,
187
- surface_intersect:: SurfaceInteraction , scene :: Scene , depth :: Int64 ,
296
+ bsdf, sampler, ray:: RayDifferentials ,
297
+ surface_intersect:: SurfaceInteraction
188
298
)
189
299
190
300
# Compute specular reflection direction `wi` and BSDF value.
196
306
197
307
ns = surface_intersect. shading. n
198
308
if ! (pdf > 0f0 && ! is_black (f) && abs (wi ⋅ ns) != 0f0 )
199
- return RGBSpectrum (0f0 )
309
+ return RGBSpectrum (1f0 ), ray
200
310
end
201
311
# TODO shift in ray direction instead of normal?
202
312
rd = RayDifferentials (spawn_ray (surface_intersect, wi))
236
346
ry_direction = wi - η * ∂wo∂y + μ * ∂n∂y + ∂μ∂y * ns
237
347
rd = RayDifferentials (rd, rx_origin= rx_origin, ry_origin= ry_origin, rx_direction= rx_direction, ry_direction= ry_direction)
238
348
end
239
- f * li (sampler, max_depth, rd, scene, depth + 1 ) * abs (wi ⋅ ns) / pdf
349
+ f * abs (wi ⋅ ns) / pdf, rd
240
350
end
0 commit comments