[Bf-blender-cvs] [998b7234ebb] soc-2022-many-lights-sampling: Optimize emitter sampling from a leaf node using reservoir

Weizhen Huang noreply at git.blender.org
Wed Oct 12 12:55:02 CEST 2022


Commit: 998b7234ebb4687df0690acfc1a85090fece87b5
Author: Weizhen Huang
Date:   Wed Oct 12 11:30:54 2022 +0200
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB998b7234ebb4687df0690acfc1a85090fece87b5

Optimize emitter sampling from a leaf node using reservoir

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

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

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

diff --git a/intern/cycles/kernel/light/light_tree.h b/intern/cycles/kernel/light/light_tree.h
index f78351b0e41..3dba7553c76 100644
--- a/intern/cycles/kernel/light/light_tree.h
+++ b/intern/cycles/kernel/light/light_tree.h
@@ -242,6 +242,7 @@ ccl_device float light_tree_cluster_importance(KernelGlobals kg,
                                     knode->energy);
 }
 
+/* pick an emitter from a leaf node using resevoir sampling */
 ccl_device int light_tree_cluster_select_emitter(KernelGlobals kg,
                                                  ccl_private float *randu,
                                                  const float3 P,
@@ -250,38 +251,39 @@ ccl_device int light_tree_cluster_select_emitter(KernelGlobals kg,
                                                  const ccl_global KernelLightTreeNode *knode,
                                                  ccl_private float *pdf_factor)
 {
-  /* TODO: use single loop over prims to avoid computing light_tree_emitter_importance twice? */
-  float total_emitter_importance = 0.0f;
-  for (int i = 0; i < knode->num_prims; i++) {
-    const int prim_index = -knode->child_index + i;
-    total_emitter_importance += light_tree_emitter_importance(
-        kg, P, N, has_transmission, prim_index);
-  }
+  /* the first emitter in the cluster */
+  int selected_prim_index = -knode->child_index;
+  float total_weight = light_tree_emitter_importance(
+      kg, P, N, has_transmission, selected_prim_index);
+  float selected_weight = total_weight;
+
+  for (int i = 1; i < knode->num_prims; i++) {
+    int current_prim_index = -knode->child_index + i;
+    float current_weight = light_tree_emitter_importance(
+        kg, P, N, has_transmission, current_prim_index);
+    total_weight += current_weight;
+
+    if (total_weight == 0.0f) {
+      continue;
+    }
 
-  if (total_emitter_importance == 0.0f) {
-    return -1;
+    float thresh = current_weight / total_weight;
+    if (*randu < thresh) {
+      selected_prim_index = current_prim_index;
+      selected_weight = current_weight;
+      *randu = *randu / thresh;
+    }
+    else {
+      *randu = (*randu - thresh) / (1.0f - thresh);
+    }
   }
 
-  /* Once we have the total importance, we can normalize the CDF and sample it. */
-  float emitter_cdf = 0.0f;
-  for (int i = 0; i < knode->num_prims; i++) {
-    const int prim_index = -knode->child_index + i;
-    /* to-do: is there any way to cache these values, so that recalculation isn't needed? */
-    const float emitter_pdf = light_tree_emitter_importance(
-                                  kg, P, N, has_transmission, prim_index) /
-                              total_emitter_importance;
-    if (*randu <= emitter_cdf + emitter_pdf) {
-      *randu = (*randu - emitter_cdf) / emitter_pdf;
-      *pdf_factor *= emitter_pdf;
-      return prim_index;
-    }
-    emitter_cdf += emitter_pdf;
+  if (total_weight == 0.0f) {
+    return -1;
   }
 
-  /* TODO: change implementation so that even under precision issues, we always end
-   * up selecting a light and this can't happen? */
-  kernel_assert(false);
-  return -1;
+  *pdf_factor = selected_weight / total_weight;
+  return selected_prim_index;
 }
 
 /* to-do: for now, we're not going to worry about being in a volume,



More information about the Bf-blender-cvs mailing list