@@ -77,10 +77,11 @@ mod vmf {
7777 }
7878
7979 struct GuidingCache {
80- compute_index: fn (Vec3, Vec3) -> super::Option[i32],
81- get_from_index: fn (i32, Vec3) -> GuidingCellAccessor,
82- normalize_host: fn (f32) -> (), // Normalize on the host
83- reset_host: fn () -> (), // Reset on the host
80+ compute_index: fn (Vec3, Vec3) -> super::Option[i32],
81+ compute_index_unsafe: fn (Vec3, Vec3) -> i32,
82+ get_from_index: fn (i32, Vec3) -> GuidingCellAccessor,
83+ normalize_host: fn (f32) -> (), // Normalize on the host
84+ reset_host: fn () -> (), // Reset on the host
8485 }
8586
8687 fn @make_guidingcache(device: super::Device, scene_bbox: super::BBox) -> GuidingCache {
@@ -201,6 +202,7 @@ mod vmf {
201202 }
202203
203204 GuidingCache {
205+ compute_index_unsafe = get_index,
204206 compute_index = @ |pos: Vec3, norm: Vec3| if super::bbox_check_point(bigger_box, pos) {
205207 super::make_option(get_index(pos, norm))
206208 } else {
@@ -313,16 +315,11 @@ fn @make_vmf_renderer(device: Device, max_path_len: i32, min_path_len: i32, spi:
313315 let mis = if light.delta {
314316 1:f32
315317 } else {
316- let pdf_e_bsdf_s = mat.bsdf.pdf(in_dir, out_dir); // Pdf to sample the light based on bsdf
317- if let Option[i32]::Some(gidx) = cache.compute_index(ctx.surf.point, ctx.surf.local.col(2)) {
318- let acc = cache.get_from_index(gidx, ctx.surf.local.col(2));
319- let guiding_prob = (1 - defensive) * acc.prob();
320- let pdf_e_s = (1 - guiding_prob) * pdf_e_bsdf_s + guiding_prob * acc.pdf(in_dir);
321- 1 / (1 + pdf_e_s / pdf_l_s)
322- } else {
323- 1 / (1 + pdf_e_bsdf_s / pdf_l_s)
324- }
325-
318+ let gidx = cache.compute_index_unsafe(ctx.surf.point, ctx.surf.local.col(2));
319+ let acc = cache.get_from_index(gidx, ctx.surf.local.col(2));
320+ let guiding_prob = (1 - defensive) * acc.prob();
321+ let pdf_e_s = (1 - guiding_prob) * mat.bsdf.pdf(in_dir, out_dir) + guiding_prob * acc.pdf(in_dir);
322+ 1 / (1 + pdf_e_s / pdf_l_s)
326323 };
327324
328325 // The intensity is already divided by the pdf, adapt to the (possible) change of domain
@@ -437,32 +434,68 @@ fn @make_vmf_renderer(device: Device, max_path_len: i32, min_path_len: i32, spi:
437434 // Bounce
438435 let out_dir = vec3_neg(ctx.ray.dir);
439436
440- if let Option[i32]::Some( gidx) = cache.compute_index (ctx.surf.point, ctx.surf.local.col(2)) {
441- let cell = cache.get_from_index(gidx, ctx.surf.local.col(2));
442- let g_prob = if mat.bsdf.is_all_delta { 0:f32 } else { (1 - defensive) * cell.prob() };
437+ let gidx = cache.compute_index_unsafe (ctx.surf.point, ctx.surf.local.col(2));
438+ let cell = cache.get_from_index(gidx, ctx.surf.local.col(2));
439+ let g_prob = if mat.bsdf.is_all_delta { 0:f32 } else { (1 - defensive) * cell.prob() };
443440
444- if rnd.next_f32() < g_prob {
445- // Guiding Sampling
446- let dir_sample = cell.sample(make_vec2(rnd.next_f32(), rnd.next_f32()));
447-
441+ if rnd.next_f32() < g_prob {
442+ // Guiding Sampling
443+ let dir_sample = cell.sample(make_vec2(rnd.next_f32(), rnd.next_f32()));
444+
445+ // This should not really happen, but better be safe
446+ if g_prob * dir_sample.pdf <= flt_eps {
447+ return(Option[Ray]::None)
448+ }
449+
450+ let full_pdf = (1 - g_prob) * mat.bsdf.pdf(dir_sample.dir, out_dir) + g_prob * dir_sample.pdf;
451+ let inv_pdf = safe_div(1, full_pdf);
452+ let mat_eval = mat.bsdf.eval(dir_sample.dir, out_dir);
453+
454+ let contrib = color_mul(pt.contrib, color_mulf(mat_eval, inv_pdf));
455+ let rr_prob = if pt.depth + 1 > min_path_len { russian_roulette_pbrt(color_mulf(contrib, pt.eta * pt.eta), 0.95) } else { 1.0 };
456+ if rnd.next_f32() >= rr_prob {
457+ return(Option[Ray]::None)
458+ }
459+
460+ let new_contrib = color_mulf(contrib, 1 / rr_prob);
461+
462+ // This might happen due to wrong hemisphere, texture, etc
463+ if color_average(new_contrib) <= flt_eps {
464+ return(Option[Ray]::None)
465+ }
466+
467+ write_vmfraypayload(payload, VMFRayPayload {
468+ inv_pdf = inv_pdf,
469+ contrib = new_contrib,
470+ depth = pt.depth + 1,
471+ eta = pt.eta, // * mat_sample.eta (TODO)
472+ prim_index = if pt.prim_index < 0 { gidx } else { pt.prim_index },
473+ prim_dir = if pt.prim_index < 0 { dir_sample.dir } else { pt.prim_dir },
474+ });
475+ make_option(
476+ make_ray(ctx.surf.point, dir_sample.dir, offset, flt_max, ray_flag_bounce)
477+ )
478+ } else {
479+ // BSDF Sampling
480+ if let Option[BsdfSample]::Some(mat_sample) = mat.bsdf.sample(rnd, out_dir, false) {
448481 // This should not really happen, but better be safe
449- if g_prob * dir_sample .pdf <= flt_eps {
482+ if mat_sample .pdf <= flt_eps {
450483 return(Option[Ray]::None)
451484 }
452-
453- let full_pdf = (1 - g_prob) * mat.bsdf. pdf(dir_sample.dir, out_dir) + g_prob * dir_sample .pdf;
485+
486+ let full_pdf = if mat_sample.is_delta { mat_sample.pdf } else { (1 - g_prob) * mat_sample. pdf + g_prob * cell .pdf(mat_sample.in_dir) } ;
454487 let inv_pdf = safe_div(1, full_pdf);
455- let mat_eval = mat.bsdf.eval(dir_sample.dir, out_dir );
456-
488+ let mat_eval = color_mulf(mat_sample.color, mat_sample.pdf );
489+
457490 let contrib = color_mul(pt.contrib, color_mulf(mat_eval, inv_pdf));
458491 let rr_prob = if pt.depth + 1 > min_path_len { russian_roulette_pbrt(color_mulf(contrib, pt.eta * pt.eta), 0.95) } else { 1.0 };
459492 if rnd.next_f32() >= rr_prob {
460493 return(Option[Ray]::None)
461494 }
462-
463- let new_contrib = color_mulf(contrib, 1 / rr_prob);
464495
465- // This might happen due to wrong hemisphere, etc
496+ let new_contrib = color_mulf(contrib, 1 / rr_prob);
497+
498+ // This might happen due to wrong hemisphere, texture, etc
466499 if color_average(new_contrib) <= flt_eps {
467500 return(Option[Ray]::None)
468501 }
@@ -471,56 +504,16 @@ fn @make_vmf_renderer(device: Device, max_path_len: i32, min_path_len: i32, spi:
471504 inv_pdf = inv_pdf,
472505 contrib = new_contrib,
473506 depth = pt.depth + 1,
474- eta = pt.eta, // * mat_sample.eta (TODO)
475- prim_index = if pt.prim_index < 0 { gidx } else { pt.prim_index },
476- prim_dir = if pt.prim_index < 0 { dir_sample.dir } else { pt.prim_dir },
507+ eta = pt.eta * mat_sample.eta,
508+ prim_index = if pt.prim_index < 0 && !mat_sample.is_delta { gidx } else { pt.prim_index },
509+ prim_dir = if pt.prim_index < 0 && !mat_sample.is_delta { mat_sample.in_dir } else { pt.prim_dir },
477510 });
478511 make_option(
479- make_ray(ctx.surf.point, dir_sample.dir , offset, flt_max, ray_flag_bounce)
512+ make_ray(ctx.surf.point, mat_sample.in_dir , offset, flt_max, ray_flag_bounce)
480513 )
481514 } else {
482- // BSDF Sampling
483- if let Option[BsdfSample]::Some(mat_sample) = mat.bsdf.sample(rnd, out_dir, false) {
484- // This should not really happen, but better be safe
485- if mat_sample.pdf <= flt_eps {
486- return(Option[Ray]::None)
487- }
488-
489- let full_pdf = if mat_sample.is_delta { mat_sample.pdf } else { (1 - g_prob) * mat_sample.pdf + g_prob * cell.pdf(mat_sample.in_dir) };
490- let inv_pdf = safe_div(1, full_pdf);
491- let mat_eval = color_mulf(mat_sample.color, mat_sample.pdf);
492-
493- let contrib = color_mul(pt.contrib, color_mulf(mat_eval, inv_pdf));
494- let rr_prob = if pt.depth + 1 > min_path_len { russian_roulette_pbrt(color_mulf(contrib, pt.eta * pt.eta), 0.95) } else { 1.0 };
495- if rnd.next_f32() >= rr_prob {
496- return(Option[Ray]::None)
497- }
498-
499- let new_contrib = color_mulf(contrib, 1 / rr_prob);
500-
501- // This might happen due to wrong hemisphere, etc
502- if color_average(new_contrib) <= flt_eps {
503- return(Option[Ray]::None)
504- }
505-
506- write_vmfraypayload(payload, VMFRayPayload {
507- inv_pdf = inv_pdf,
508- contrib = new_contrib,
509- depth = pt.depth + 1,
510- eta = pt.eta * mat_sample.eta,
511- prim_index = if pt.prim_index < 0 && !mat_sample.is_delta { gidx } else { pt.prim_index },
512- prim_dir = if pt.prim_index < 0 && !mat_sample.is_delta { mat_sample.in_dir } else { pt.prim_dir },
513- });
514- make_option(
515- make_ray(ctx.surf.point, mat_sample.in_dir, offset, flt_max, ray_flag_bounce)
516- )
517- } else {
518- Option[Ray]::None
519- }
515+ Option[Ray]::None
520516 }
521- } else {
522- // Should never happen as the cache is over the entire scene!
523- Option[Ray]::None
524517 }
525518 }
526519
0 commit comments