[Bf-blender-cvs] [2a94f93fc95] soc-2022-many-lights-sampling: Fix wrong pdf when picking emitter from a cluster

Weizhen Huang noreply at git.blender.org
Wed Nov 16 16:07:36 CET 2022


Commit: 2a94f93fc955ed7d849d2f7c4d286e8509e04988
Author: Weizhen Huang
Date:   Wed Nov 16 16:04:43 2022 +0100
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB2a94f93fc955ed7d849d2f7c4d286e8509e04988

Fix wrong pdf when picking emitter from a cluster

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

M	intern/cycles/kernel/light/tree.h

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

diff --git a/intern/cycles/kernel/light/tree.h b/intern/cycles/kernel/light/tree.h
index 0f3069af41b..5e2e1503ba5 100644
--- a/intern/cycles/kernel/light/tree.h
+++ b/intern/cycles/kernel/light/tree.h
@@ -448,7 +448,7 @@ ccl_device_inline void sample_resevoir(const int current_index,
  * lower bounds */
 template<bool in_volume_segment>
 ccl_device int light_tree_cluster_select_emitter(KernelGlobals kg,
-                                                 ccl_private float *randu,
+                                                 ccl_private float *rand,
                                                  const float3 P,
                                                  const float3 N_or_D,
                                                  const float t,
@@ -456,80 +456,74 @@ ccl_device int light_tree_cluster_select_emitter(KernelGlobals kg,
                                                  const ccl_global KernelLightTreeNode *knode,
                                                  ccl_private float *pdf_factor)
 {
-  /* the first emitter in the cluster */
-  int selected_prim_index_max = -knode->child_index;
-  float max_importance, min_importance;
-  light_tree_emitter_importance<in_volume_segment>(
-      kg, P, N_or_D, t, has_transmission, selected_prim_index_max, max_importance, min_importance);
-  float selected_max_importance = max_importance;
-  float total_max_importance = max_importance;
-
-  int selected_prim_index_min = selected_prim_index_max;
-  float total_min_importance = min_importance;
-  float selected_min_importance = min_importance;
-
-  /* Mark emitters with zero importance. Used for resevoir when total_min_importance = 0 */
+  float2 importance;
+  float2 selected_importance = zero_float2();
+  float2 total_importance = zero_float2();
+  int selected_index = -1;
+
+  /* Mark emitters with zero importance. Used for resevoir when total minimum importance = 0 */
   kernel_assert(knode->num_prims <= sizeof(uint) * 8);
-  uint has_importance = max_importance > 0;
+  uint has_importance = 0;
 
-  for (int i = 1; i < knode->num_prims; i++) {
-    int current_prim_index = -knode->child_index + i;
+  bool sample_max = (*rand > 0.5f); /* sampling using the maximum importance */
+  *rand = *rand * 2.0f - float(sample_max);
+
+  for (int i = 0; i < knode->num_prims; i++) {
+    int current_index = -knode->child_index + i;
+    /* maximum importance = importance[0], mininum importance = importance[1] */
     light_tree_emitter_importance<in_volume_segment>(
-        kg, P, N_or_D, t, has_transmission, current_prim_index, max_importance, min_importance);
-
-    has_importance |= ((max_importance > 0) << i);
-
-    /* resevoir sampling using the maximum importance */
-    sample_resevoir(current_prim_index,
-                    max_importance,
-                    selected_prim_index_max,
-                    selected_max_importance,
-                    total_max_importance,
-                    randu);
-
-    /* resevoir sampling using the mininum importance */
-    sample_resevoir(current_prim_index,
-                    min_importance,
-                    selected_prim_index_min,
-                    selected_min_importance,
-                    total_min_importance,
-                    randu);
+        kg, P, N_or_D, t, has_transmission, current_index, importance[0], importance[1]);
+
+    sample_resevoir(current_index,
+                    importance[!sample_max],
+                    selected_index,
+                    selected_importance[!sample_max],
+                    total_importance[!sample_max],
+                    rand);
+    if (selected_index == current_index) {
+      selected_importance[sample_max] = importance[sample_max];
+    }
+    total_importance[sample_max] += importance[sample_max];
+
+    has_importance |= ((importance[0] > 0) << i);
   }
 
-  if (total_max_importance == 0.0f) {
+  if (total_importance[0] == 0.0f) {
     return -1;
   }
 
-  if (total_min_importance == 0.0f) {
-    /* uniformly sample emitters with positive max_importance */
-    selected_prim_index_min = -1;
-    for (int i = 0; i < knode->num_prims; i++) {
-      int current_prim_index = -knode->child_index + i;
-      min_importance = float(has_importance & 1);
-      has_importance >>= 1;
-      sample_resevoir(current_prim_index,
-                      min_importance,
-                      selected_prim_index_min,
-                      selected_min_importance,
-                      total_min_importance,
-                      randu);
+  if (total_importance[1] == 0.0f) {
+    /* uniformly sample emitters with positive maximum importance */
+    if (sample_max) {
+      selected_importance[1] = 1.0f;
+      total_importance[1] = float(popcount(has_importance));
+    }
+    else {
+      selected_index = -1;
+      for (int i = 0; i < knode->num_prims; i++) {
+        int current_index = -knode->child_index + i;
+        sample_resevoir(current_index,
+                        float(has_importance & 1),
+                        selected_index,
+                        selected_importance[1],
+                        total_importance[1],
+                        rand);
+        has_importance >>= 1;
+      }
+      light_tree_emitter_importance<in_volume_segment>(kg,
+                                                       P,
+                                                       N_or_D,
+                                                       t,
+                                                       has_transmission,
+                                                       selected_index,
+                                                       selected_importance[0],
+                                                       importance[1]);
     }
   }
 
-  int selected_prim_index;
-  if (*randu < 0.5f) {
-    selected_prim_index = selected_prim_index_max;
-    *randu = *randu * 2.0f;
-  }
-  else {
-    selected_prim_index = selected_prim_index_min;
-    *randu = *randu * 2.0f - 1.0f;
-  }
-
-  *pdf_factor = 0.5f * (selected_min_importance / total_min_importance +
-                        selected_max_importance / total_max_importance);
+  *pdf_factor = average(selected_importance / total_importance);
 
-  return selected_prim_index;
+  return selected_index;
 }
 
 template<bool in_volume_segment>
@@ -950,6 +944,7 @@ ccl_device float light_tree_pdf(KernelGlobals kg,
     float left_probability;
     if (!get_left_probability<false>(
             kg, P, N, 0, has_transmission, left_index, right_index, left_probability)) {
+      pdf = 0.0f;
       stack_index--;
       continue;
     }



More information about the Bf-blender-cvs mailing list