Skip to content

Commit 3051a73

Browse files
committed
be a bit more risky
1 parent d51972b commit 3051a73

1 file changed

Lines changed: 67 additions & 74 deletions

File tree

src/artic/technique/vmfguidedpathtracer.art

Lines changed: 67 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)