[Bf-blender-cvs] [0f7bafed382] soc-2022-many-lights-sampling: Cycles: re-implement distant lights in many lights sampling

Jeffrey Liu noreply at git.blender.org
Sat Jul 2 19:57:47 CEST 2022


Commit: 0f7bafed3826f09e2c96126bd401de5e0540e038
Author: Jeffrey Liu
Date:   Sat Jul 2 13:55:19 2022 -0400
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB0f7bafed3826f09e2c96126bd401de5e0540e038

Cycles: re-implement distant lights in many lights sampling

This uses a basic heuristic to determine whether Cycles should sample
from the distant lights group or the light tree, using the total energy.
A better solution would be to compute some importance value.

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

M	intern/cycles/kernel/light/light_tree.h
M	intern/cycles/kernel/types.h
M	intern/cycles/scene/light.cpp

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

diff --git a/intern/cycles/kernel/light/light_tree.h b/intern/cycles/kernel/light/light_tree.h
index 9cf601407b7..57f2792cc35 100644
--- a/intern/cycles/kernel/light/light_tree.h
+++ b/intern/cycles/kernel/light/light_tree.h
@@ -248,8 +248,6 @@ ccl_device int light_tree_sample(KernelGlobals kg,
 
 /* to-do: assign relative importances for the background and distant lights.
  * Can we somehow adjust the importance measure to account for these as well? */
-
-/*
 ccl_device float light_tree_distant_light_importance(KernelGlobals kg,
                                                      const float3 P,
                                                      const float3 N,
@@ -301,7 +299,6 @@ ccl_device int light_tree_sample_distant_lights(KernelGlobals kg,
     }
   }
 }
-*/
 
 ccl_device bool light_tree_sample_from_position(KernelGlobals kg,
                                                 ccl_private const RNGState *rng_state,
@@ -314,45 +311,19 @@ ccl_device bool light_tree_sample_from_position(KernelGlobals kg,
                                                 const uint32_t path_flag,
                                                 ccl_private LightSample *ls)
 {
-  /*
-  const int num_distant_lights = kernel_data.integrator.num_distant_lights;
-  const int num_light_tree_prims = kernel_data.integrator.num_distribution - num_distant_lights;
-  */
-
   float pdf_factor = 1.0f;
-  bool ret = light_tree_sample<false>(
-        kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
-  /*
-  bool ret = false;
-  if (num_distant_lights == 0) {
+  bool ret;
+  float tree_u = path_state_rng_1D(kg, rng_state, 1);
+  if (tree_u < kernel_data.integrator.pdf_light_tree) {
+    pdf_factor *= kernel_data.integrator.pdf_light_tree;
     ret = light_tree_sample<false>(
         kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
   }
-  else if (num_light_tree_prims == 0) {
+  else {
+    pdf_factor *= (1 - kernel_data.integrator.pdf_light_tree);
     ret = light_tree_sample_distant_lights<false>(
         kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
   }
-  else {
-    const ccl_global KernelLightTreeNode *knode = &kernel_data_fetch(light_tree_nodes, 0);
-    const float light_tree_importance = light_tree_cluster_importance(kg, P, N, knode);
-    const float distant_light_importance = light_tree_distant_light_importance(kg, P, N, num_distant_lights);
-
-    const float light_tree_probability = light_tree_importance /
-                                         (light_tree_importance +
-                                          distant_light_importance);
-
-    if (randu < light_tree_probability) {
-      ret = light_tree_sample<false>(
-          kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
-      pdf_factor *= light_tree_probability;
-    }
-    else {
-      ret = light_tree_sample_distant_lights<false>(
-          kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
-      pdf_factor *= (1 - light_tree_probability);
-    }
-  }
-  */
 
   ls->pdf *= pdf_factor;
   return ret;
diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h
index f360940b54a..3e9fcd19609 100644
--- a/intern/cycles/kernel/types.h
+++ b/intern/cycles/kernel/types.h
@@ -1300,11 +1300,12 @@ typedef struct KernelIntegrator {
   int direct_light_sampling_type;
 
   /* Light tree. */
+  float pdf_light_tree;
   int use_light_tree;
   float splitting_threshold;
 
   /* padding */
-  int pad1, pad2;
+  int pad1;
 } KernelIntegrator;
 static_assert_align(KernelIntegrator, 16);
 
diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp
index c7f252d13f9..242665387ca 100644
--- a/intern/cycles/scene/light.cpp
+++ b/intern/cycles/scene/light.cpp
@@ -383,7 +383,11 @@ void LightManager::device_update_distribution(Device *device,
     object_id++;
   }
 
-  if (light_tree_enabled) {
+  size_t num_distribution = num_triangles + num_lights;
+  VLOG_INFO << "Total " << num_distribution << " of light distribution primitives.";
+
+  float pdf_light_tree = 0.0f;
+  if (light_tree_enabled && num_distribution > 0) {
     /* For now, we'll start with a smaller number of max lights in a node.
      * More benchmarking is needed to determine what number works best. */
     LightTree light_tree(light_prims, scene, 8);
@@ -392,10 +396,15 @@ void LightManager::device_update_distribution(Device *device,
     /* First initialize the light tree's nodes. */
     const vector<PackedLightTreeNode> &linearized_bvh = light_tree.get_nodes();
     KernelLightTreeNode *light_tree_nodes = dscene->light_tree_nodes.alloc(linearized_bvh.size());
+    float light_tree_energy = 0.0f;
     for (int index = 0; index < linearized_bvh.size(); index++) {
       const PackedLightTreeNode &node = linearized_bvh[index];
 
       light_tree_nodes[index].energy = node.energy;
+      if (index == 0) {
+        light_tree_energy = node.energy;
+      }
+
       for (int i = 0; i < 3; i++) {
         light_tree_nodes[index].bounding_box_min[i] = node.bbox.min[i];
         light_tree_nodes[index].bounding_box_max[i] = node.bbox.max[i];
@@ -471,8 +480,8 @@ void LightManager::device_update_distribution(Device *device,
 
     /* We also add distant lights to a separate group. */
     KernelLightTreeDistantEmitter *light_tree_distant_group =
-        dscene->light_tree_distant_group.alloc(num_distant_lights + 1);
-    float total_energy = 0.0f;
+        dscene->light_tree_distant_group.alloc(num_distant_lights);
+    float distant_light_energy = 0.0f;
     for (int index = 0; index < num_distant_lights; index++) {
       LightTreePrimitive prim = distant_lights[index];
       Light *light = scene->lights[prim.lamp_id];
@@ -502,24 +511,16 @@ void LightManager::device_update_distribution(Device *device,
       }
 
       light_tree_distant_group[index].energy = energy;
-      total_energy += energy;
+      distant_light_energy += energy;
     }
 
-    /* The final node is just used to store the total energy. */
-    if (num_distant_lights > 0) {
-      light_tree_distant_group[num_distant_lights].energy = total_energy;
-      for (int i = 0; i < 3; i++) {
-        light_tree_distant_group[num_distant_lights].direction[i] = 0.0f;
-      }
-      light_tree_distant_group[num_distant_lights].bounding_radius = 0.0f;
+    if (light_tree_energy > 0.0f) {
+      pdf_light_tree = light_tree_energy / (light_tree_energy + distant_light_energy);
     }
 
     dscene->light_tree_distant_group.copy_to_device();
   }
 
-  size_t num_distribution = num_triangles + num_lights;
-  VLOG_INFO << "Total " << num_distribution << " of light distribution primitives.";
-
   /* emission area */
   KernelLightDistribution *distribution = dscene->light_distribution.alloc(num_distribution + 1);
   float totarea = 0.0f;
@@ -670,6 +671,7 @@ void LightManager::device_update_distribution(Device *device,
     /* pdf_lights is used when sampling lights, and assumes that
      * the light has been sampled through the light distribution.
      * Therefore, we override it for now and adjust the pdf manually in the light tree.*/
+    kintegrator->pdf_light_tree = pdf_light_tree;
     if (light_tree_enabled) {
       kintegrator->pdf_triangles = 1.0f;
       kintegrator->pdf_lights = 1.0f;



More information about the Bf-blender-cvs mailing list