11struct SGPTRayPayload {
2- inv_bsdf_pdf: f32, // Inverse BSDF pdf
3- inv_guided_pdf: f32, // Inverse Guided pdf
4- contrib: Color, // Current contribution
5- depth: i32, // Current depth
6- eta: f32, // Current eta (n1 / n2)
7- gen_technique: i32, // Technique which generated the previous vertex (0=BSDF, 1=Guiding)
2+ inv_pdf: f32, // Inverse pdf
3+ contrib: Color, // Current contribution
4+ depth: i32, // Current depth
5+ eta: f32, // Current eta (n1 / n2)
6+ gen_technique: i32, // Technique which generated the previous vertex (0=BSDF, 1=Guiding)
87}
98
109fn @write_sgptraypayload(payload: RayPayload, pt: SGPTRayPayload) -> () {
11- payload.set(0, pt.inv_bsdf_pdf);
12- payload.set(1, pt.inv_guided_pdf);
13- payload.set(2, pt.contrib.r);
14- payload.set(3, pt.contrib.g);
15- payload.set(4, pt.contrib.b);
16- payload.set(5, pt.depth as f32);
17- payload.set(6, pt.eta);
18- payload.set(7, pt.gen_technique as f32);
10+ payload.set(0, pt.inv_pdf);
11+ payload.set(1, pt.contrib.r);
12+ payload.set(2, pt.contrib.g);
13+ payload.set(3, pt.contrib.b);
14+ payload.set(4, pt.depth as f32);
15+ payload.set(5, pt.eta);
16+ payload.set(6, pt.gen_technique as f32);
1917}
2018
2119fn @unwrap_sgptraypayload(payload: RayPayload) = SGPTRayPayload {
22- inv_bsdf_pdf = payload.get(0),
23- inv_guided_pdf = payload.get(1),
24- contrib = make_color(payload.get(2), payload.get(3), payload.get(4), 1),
25- depth = payload.get(5) as i32,
26- eta = payload.get(6),
27- gen_technique = payload.get(7) as i32,
20+ inv_pdf = payload.get(0),
21+ contrib = make_color(payload.get(1), payload.get(2), payload.get(3), 1),
22+ depth = payload.get(4) as i32,
23+ eta = payload.get(5),
24+ gen_technique = payload.get(6) as i32,
2825};
2926
3027fn @init_sgpt_raypayload(payload: RayPayload) = write_sgptraypayload(payload, SGPTRayPayload {
31- inv_bsdf_pdf = 0,
32- inv_guided_pdf = 0,
33- contrib = color_builtins::white,
34- depth = 1,
35- eta = 1,
36- gen_technique = 0
28+ inv_pdf = 0,
29+ contrib = color_builtins::white,
30+ depth = 1,
31+ eta = 1,
32+ gen_technique = 0
3733});
3834
3935struct SimpleGuidingTechnique {
@@ -42,13 +38,9 @@ struct SimpleGuidingTechnique {
4238 prob: fn () -> f32 // Probability to use this guider
4339}
4440
45- fn @make_sgpt_renderer(device : Device, max_path_len: i32, min_path_len: i32, spi : i32, light_selector: LightSelector, clamp_value: f32, enable_nee: bool, enable_aovs : bool, guider: SimpleGuidingTechnique) -> Technique {
41+ fn @make_sgpt_renderer(_device : Device, max_path_len: i32, min_path_len: i32, _spi : i32, light_selector: LightSelector, clamp_value: f32, enable_nee: bool, _enable_aovs : bool, guider: SimpleGuidingTechnique) -> Technique {
4642 let offset : f32 = 0.001;
4743
48- let aov_bsdf = if enable_aovs { device.load_aov_image("BSDF Weights", spi, 0) } else { make_empty_aov_image(0, 0) };
49- let aov_guided = if enable_aovs { device.load_aov_image("Guided Weights", spi, 0) } else { make_empty_aov_image(0, 0) };
50- let aov_nee = if enable_aovs { device.load_aov_image("NEE Weights", spi, 0) } else { make_empty_aov_image(0, 0) };
51-
5244 let handle_color = make_std_color_handler(clamp_value);
5345
5446 fn @on_shadow( ctx: ShadingContext
@@ -129,25 +121,11 @@ fn @make_sgpt_renderer(device: Device, max_path_len: i32, min_path_len: i32, spi
129121 let pt = unwrap_sgptraypayload(payload);
130122 let dot = -vec3_dot(ctx.ray.dir, ctx.surf.local.col(2));
131123 if dot > flt_eps { // Only contribute proper aligned directions
132- let emit = mat.emission(ctx);
133- let pdf_s = emit.pdf.as_solid(dot, ctx.hit.distance * ctx.hit.distance);
134-
135- let mis_denom = 1 + if pt.gen_technique == 0 { safe_div(pt.inv_bsdf_pdf, pt.inv_guided_pdf) } else { safe_div(pt.inv_guided_pdf, pt.inv_bsdf_pdf) };
136- let mis = if enable_nee {
137- let inv_pdf_b = if pt.gen_technique == 0 { pt.inv_bsdf_pdf } else { pt.inv_guided_pdf }; // The actual (inverse) pdf used for the previous vertex
138- let pdf_l_s = light_selector.pdf(mat.light, ctx.ray.org) * pdf_s;
139- 1 / (mis_denom + inv_pdf_b * pdf_l_s)
140- } else {
141- 1 / mis_denom
142- };
124+ let emit = mat.emission(ctx);
125+ let pdf_s = emit.pdf.as_solid(dot, ctx.hit.distance * ctx.hit.distance);
126+ let mis = if enable_nee { 1 / (1 + pt.inv_pdf * light_selector.pdf(mat.light, ctx.ray.org) * pdf_s) } else { 1:f32 };
143127
144128 let contrib = handle_color(color_mulf(color_mul(pt.contrib, emit.intensity), mis));
145-
146- if pt.gen_technique == 0 {
147- aov_bsdf.splat(ctx.pixel, contrib);
148- } else {
149- aov_guided.splat(ctx.pixel, contrib);
150- }
151129
152130 return(make_option(contrib))
153131 }
@@ -168,29 +146,18 @@ fn @make_sgpt_renderer(device: Device, max_path_len: i32, min_path_len: i32, spi
168146 if light.infinite && !light.delta {
169147 inflights += 1;
170148
171- let emit = light.emission(ctx);
149+ let emit = light.emission(ctx);
150+ if is_black_eps(emit, flt_eps) { continue() }
151+
172152 let pdf = light.pdf_direct(ctx.ray, make_invalid_surface_element());
173153 let pdf_s = pdf.as_solid(1, 1/* We assume infinite lights are always given in solid angle measure */);
174-
175- let mis_denom = 1 + if pt.gen_technique == 0 { safe_div(pt.inv_bsdf_pdf, pt.inv_guided_pdf) } else { safe_div(pt.inv_guided_pdf, pt.inv_bsdf_pdf) };
176- let mis = if enable_nee {
177- let inv_pdf_b = if pt.gen_technique == 0 { pt.inv_bsdf_pdf } else { pt.inv_guided_pdf }; // The actual (inverse) pdf used for the previous vertex
178- let pdf_l_s = light_selector.pdf(light, ctx.ray.org) * pdf_s;
179- 1 / (mis_denom + inv_pdf_b * pdf_l_s)
180- } else {
181- 1 / mis_denom
182- };
154+ let mis = if enable_nee { 1 / (1 + pt.inv_pdf * light_selector.pdf(light, ctx.ray.org) * pdf_s) } else { 1:f32 };
183155
184156 color = color_add(color, handle_color(color_mulf(color_mul(pt.contrib, emit), mis)));
185157 }
186158 }
187159
188160 if inflights > 0 {
189- if pt.gen_technique == 0 {
190- aov_bsdf.splat(ctx.pixel, color);
191- } else {
192- aov_guided.splat(ctx.pixel, color);
193- }
194161 make_option(color)
195162 } else {
196163 Option[Color]::None
@@ -221,25 +188,29 @@ fn @make_sgpt_renderer(device: Device, max_path_len: i32, min_path_len: i32, spi
221188 return(Option[Ray]::None)
222189 }
223190
224- let inv_guided_pdf = 1 / (g_prob * pdf_g_s);
225- let mat_eval = mat.bsdf.eval(in_dir, out_dir);
191+ let full_pdf = (1 - g_prob) * mat.bsdf.pdf(in_dir, out_dir) + g_prob * pdf_g_s;
192+ let inv_pdf = 1 / full_pdf;
193+ let mat_eval = mat.bsdf.eval(in_dir, out_dir);
226194
227- let contrib = color_mul(pt.contrib, color_mulf(mat_eval, inv_guided_pdf ));
195+ let contrib = color_mul(pt.contrib, color_mulf(mat_eval, inv_pdf ));
228196 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 };
229197 if rnd.next_f32() >= rr_prob {
230198 return(Option[Ray]::None)
231199 }
232200
233- let inv_bsdf_pdf = safe_div(1, (1 - g_prob) * mat.bsdf.pdf(in_dir, out_dir));
234- let new_contrib = color_mulf(contrib, 1 / rr_prob);
201+ let new_contrib = color_mulf(contrib, 1 / rr_prob);
202+
203+ // This might happen due to wrong hemisphere, texture, etc
204+ if color_average(new_contrib) <= flt_eps {
205+ return(Option[Ray]::None)
206+ }
235207
236208 write_sgptraypayload(payload, SGPTRayPayload {
237- inv_bsdf_pdf = inv_bsdf_pdf,
238- inv_guided_pdf = inv_guided_pdf,
239- contrib = new_contrib,
240- depth = pt.depth + 1,
241- eta = pt.eta, // * mat_sample.eta (TODO)
242- gen_technique = 1 /* Guiding */
209+ inv_pdf = inv_pdf,
210+ contrib = new_contrib,
211+ depth = pt.depth + 1,
212+ eta = pt.eta, // * mat_sample.eta (TODO)
213+ gen_technique = 1 /* Guiding */
243214 });
244215 make_option(
245216 make_ray(ctx.surf.point, in_dir, offset, flt_max, ray_flag_bounce)
@@ -252,23 +223,29 @@ fn @make_sgpt_renderer(device: Device, max_path_len: i32, min_path_len: i32, spi
252223 return(Option[Ray]::None)
253224 }
254225
255- let contrib = color_mul(pt.contrib, mat_sample.color/* Pdf and cosine are already applied!*/);
226+ let full_pdf = if mat_sample.is_delta { mat_sample.pdf } else { (1 - g_prob) * mat_sample.pdf + g_prob * guider.pdf(mat_sample.in_dir, out_dir) };
227+ let inv_pdf = 1/ full_pdf;
228+ let mat_eval = color_mulf(mat_sample.color, mat_sample.pdf);
229+
230+ let contrib = color_mul(pt.contrib, color_mulf(mat_eval, inv_pdf));
256231 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 };
257232 if rnd.next_f32() >= rr_prob {
258233 return(Option[Ray]::None)
259234 }
260235
261- let inv_bsdf_pdf = if mat_sample.is_delta { 0 } else { 1 / ((1 - g_prob) * mat_sample.pdf) };
262- let inv_guided_pdf = if mat_sample.is_delta { 0 } else { safe_div(1, g_prob * guider.pdf(mat_sample.in_dir, out_dir)) };
263236 let new_contrib = color_mulf(contrib, 1 / (rr_prob * (1 - g_prob)));
237+
238+ // This might happen due to wrong hemisphere, texture, etc
239+ if color_average(new_contrib) <= flt_eps {
240+ return(Option[Ray]::None)
241+ }
264242
265243 write_sgptraypayload(payload, SGPTRayPayload {
266- inv_bsdf_pdf = inv_bsdf_pdf,
267- inv_guided_pdf = inv_guided_pdf,
268- contrib = new_contrib,
269- depth = pt.depth + 1,
270- eta = pt.eta * mat_sample.eta,
271- gen_technique = 0 /* BSDF */
244+ inv_pdf = inv_pdf,
245+ contrib = new_contrib,
246+ depth = pt.depth + 1,
247+ eta = pt.eta * mat_sample.eta,
248+ gen_technique = 0 /* BSDF */
272249 });
273250 make_option(
274251 make_ray(ctx.surf.point, mat_sample.in_dir, offset, flt_max, ray_flag_bounce)
@@ -279,20 +256,11 @@ fn @make_sgpt_renderer(device: Device, max_path_len: i32, min_path_len: i32, spi
279256 }
280257 }
281258
282- fn @on_shadow_miss( ctx: ShadingContext
283- , _shader: MaterialShader
284- , _: RayPayload
285- , color: Color) -> Option[Color] {
286- aov_nee.splat(ctx.pixel, color);
287- make_option(color)
288- }
289-
290259 make_empty_technique().{
291- on_hit = on_hit,
292- on_miss = on_miss,
293- on_shadow = on_shadow,
294- on_bounce = on_bounce,
295- on_shadow_miss = if enable_aovs { on_shadow_miss } else { TechniqueNoShadowMissFunction },
260+ on_hit = on_hit,
261+ on_miss = on_miss,
262+ on_shadow = on_shadow,
263+ on_bounce = on_bounce
296264 }
297265}
298266
0 commit comments