Commit: 07de832e22f5052d042605fdf3f8161a213c4f80
Author: Lukas Stockner
Date:   Sun Sep 25 22:11:50 2016 +0200
Branches: master
https://developer.blender.org/rB07de832e22f5052d042605fdf3f8161a213c4f80

Cycles: Use correct light sampling PDF for MIS calculation with Branched Path 
Tracing

The light sampling functions calculate light sampling PDF for the case that the 
light has been randomly selected out of all lights.
However, since BPT handles lamps and meshlights separately, this isn't the 
case. So, to avoid a wrong result, the code just included the 0.5 factor in the 
throughput.

In theory, however, the correction should be made to the sampling probability, 
which needs to be doubled. Now, for the regular calculation, that's no real 
difference since the throughput is divided by the pdf.
However, it does matter for the MIS calculation - it's unbiased both ways, but 
including the factor in the PDF instead of the throughput should give slightly 
better results.

Reviewers: sergey, brecht, dingto, juicyfruit

Differential Revision: https://developer.blender.org/D2258

===================================================================

M       intern/cycles/kernel/kernel_path_surface.h
M       intern/cycles/kernel/kernel_path_volume.h

===================================================================

diff --git a/intern/cycles/kernel/kernel_path_surface.h 
b/intern/cycles/kernel/kernel_path_surface.h
index 27acf81..45f0f1c 100644
--- a/intern/cycles/kernel/kernel_path_surface.h
+++ b/intern/cycles/kernel/kernel_path_surface.h
@@ -46,15 +46,17 @@ ccl_device_noinline void 
kernel_branched_path_surface_connect_light(KernelGlobal
                        float num_samples_inv = 
num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights);
                        RNG lamp_rng = cmj_hash(*rng, i);
 
-                       if(kernel_data.integrator.pdf_triangles != 0.0f)
-                               num_samples_inv *= 0.5f;
-
                        for(int j = 0; j < num_samples; j++) {
                                float light_u, light_v;
                                path_branched_rng_2D(kg, &lamp_rng, state, j, 
num_samples, PRNG_LIGHT_U, &light_u, &light_v);
 
                                LightSample ls;
                                if(lamp_light_sample(kg, i, light_u, light_v, 
ccl_fetch(sd, P), &ls)) {
+                                       /* The sampling probability returned by 
lamp_light_sample assumes that all lights were sampled.
+                                        * However, this code only samples 
lamps, so if the scene also had mesh lights, the real probability is twice as 
high. */
+                                       if(kernel_data.integrator.pdf_triangles 
!= 0.0f)
+                                               ls.pdf *= 2.0f;
+
                                        if(direct_emission(kg, sd, emission_sd, 
&ls, state, &light_ray, &L_light, &is_lamp)) {
                                                /* trace shadow ray */
                                                float3 shadow;
@@ -73,9 +75,6 @@ ccl_device_noinline void 
kernel_branched_path_surface_connect_light(KernelGlobal
                        int num_samples = 
ceil_to_int(num_samples_adjust*kernel_data.integrator.mesh_light_samples);
                        float num_samples_inv = num_samples_adjust/num_samples;
 
-                       if(kernel_data.integrator.num_all_lights)
-                               num_samples_inv *= 0.5f;
-
                        for(int j = 0; j < num_samples; j++) {
                                float light_t = path_branched_rng_1D(kg, rng, 
state, j, num_samples, PRNG_LIGHT);
                                float light_u, light_v;
@@ -87,6 +86,10 @@ ccl_device_noinline void 
kernel_branched_path_surface_connect_light(KernelGlobal
 
                                LightSample ls;
                                if(light_sample(kg, light_t, light_u, light_v, 
ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls)) {
+                                       /* Same as above, probability needs to 
be corrected since the sampling was forced to select a mesh light. */
+                                       
if(kernel_data.integrator.num_all_lights)
+                                               ls.pdf *= 2.0f;
+
                                        if(direct_emission(kg, sd, emission_sd, 
&ls, state, &light_ray, &L_light, &is_lamp)) {
                                                /* trace shadow ray */
                                                float3 shadow;
diff --git a/intern/cycles/kernel/kernel_path_volume.h 
b/intern/cycles/kernel/kernel_path_volume.h
index 0bb8f1c..5ee1912 100644
--- a/intern/cycles/kernel/kernel_path_volume.h
+++ b/intern/cycles/kernel/kernel_path_volume.h
@@ -136,9 +136,6 @@ ccl_device void 
kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
                        float num_samples_inv = 
1.0f/(num_samples*kernel_data.integrator.num_all_lights);
                        RNG lamp_rng = cmj_hash(*rng, i);
 
-                       if(kernel_data.integrator.pdf_triangles != 0.0f)
-                               num_samples_inv *= 0.5f;
-
                        for(int j = 0; j < num_samples; j++) {
                                /* sample random position on given light */
                                float light_u, light_v;
@@ -161,6 +158,9 @@ ccl_device void 
kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
 
                                /* todo: split up light_sample so we don't have 
to call it again with new position */
                                if(lamp_light_sample(kg, i, light_u, light_v, 
sd->P, &ls)) {
+                                       if(kernel_data.integrator.pdf_triangles 
!= 0.0f)
+                                               ls.pdf *= 2.0f;
+
                                        if(direct_emission(kg, sd, emission_sd, 
&ls, state, &light_ray, &L_light, &is_lamp)) {
                                                /* trace shadow ray */
                                                float3 shadow;
@@ -179,9 +179,6 @@ ccl_device void 
kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
                        int num_samples = 
kernel_data.integrator.mesh_light_samples;
                        float num_samples_inv = 1.0f/num_samples;
 
-                       if(kernel_data.integrator.num_all_lights)
-                               num_samples_inv *= 0.5f;
-
                        for(int j = 0; j < num_samples; j++) {
                                /* sample random position on random triangle */
                                float light_t = 
path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_LIGHT);
@@ -209,6 +206,9 @@ ccl_device void 
kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
 
                                /* todo: split up light_sample so we don't have 
to call it again with new position */
                                if(light_sample(kg, light_t, light_u, light_v, 
sd->time, sd->P, state->bounce, &ls)) {
+                                       
if(kernel_data.integrator.num_all_lights)
+                                               ls.pdf *= 2.0f;
+
                                        if(direct_emission(kg, sd, emission_sd, 
&ls, state, &light_ray, &L_light, &is_lamp)) {
                                                /* trace shadow ray */
                                                float3 shadow;

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to