[Bf-blender-cvs] [2c48ba0244f] soc-2022-many-lights-sampling: Fix: various Cycles light tree importance issues

Jeffrey Liu noreply at git.blender.org
Sat Jul 9 06:57:06 CEST 2022


Commit: 2c48ba0244fd21d8976ab8faf4a1e653f75dbc71
Author: Jeffrey Liu
Date:   Sat Jul 9 00:55:00 2022 -0400
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB2c48ba0244fd21d8976ab8faf4a1e653f75dbc71

Fix: various Cycles light tree importance issues

This fixes a variety of Cycles light tree importance issues,
namely issues with bounding cone construction and usage.
Some of the heuristics have also been adjusted for better results
(tentatively). The next step is to determine a better heuristic for
distant lights.

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

M	intern/cycles/kernel/integrator/shade_light.h
M	intern/cycles/kernel/integrator/shade_surface.h
M	intern/cycles/kernel/light/light.h
M	intern/cycles/kernel/light/light_tree.h
M	intern/cycles/scene/light_tree.cpp

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

diff --git a/intern/cycles/kernel/integrator/shade_light.h b/intern/cycles/kernel/integrator/shade_light.h
index 4053e01737c..0e925f73afe 100644
--- a/intern/cycles/kernel/integrator/shade_light.h
+++ b/intern/cycles/kernel/integrator/shade_light.h
@@ -74,7 +74,7 @@ ccl_device_inline void integrate_light(KernelGlobals kg,
     const float mis_ray_pdf = INTEGRATOR_STATE(state, path, mis_ray_pdf);
     if (kernel_data.integrator.use_light_tree) {
       const float3 N = INTEGRATOR_STATE(state, path, mis_origin_n);
-      ls.pdf *= light_tree_pdf(kg, ray_P, N, ~isect.prim);
+      ls.pdf *= light_tree_pdf(kg, ray_P, N, ~ls.lamp);
     }
     const float mis_weight = light_sample_mis_weight_forward(kg, mis_ray_pdf, ls.pdf);
     light_eval *= mis_weight;
diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h
index a01b03ad9d0..b172b3d2e03 100644
--- a/intern/cycles/kernel/integrator/shade_surface.h
+++ b/intern/cycles/kernel/integrator/shade_surface.h
@@ -78,13 +78,16 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg,
 #  endif
   {
     const float bsdf_pdf = INTEGRATOR_STATE(state, path, mis_ray_pdf);
-    const float t = sd->ray_length + INTEGRATOR_STATE(state, path, mis_ray_t);
+    const float mis_ray_t = INTEGRATOR_STATE(state, path, mis_ray_t);
+    const float t = sd->ray_length + mis_ray_t;
 
     /* Multiple importance sampling, get triangle light pdf,
      * and compute weight with respect to BSDF pdf. */
     float pdf = triangle_light_pdf(kg, sd, t);
     if (kernel_data.integrator.use_light_tree) {
-      const float3 ray_P = INTEGRATOR_STATE(state, ray, P);
+      float3 ray_P = INTEGRATOR_STATE(state, ray, P);
+      const float3 ray_D = INTEGRATOR_STATE(state, ray, D);
+      ray_P -= ray_D * mis_ray_t;
       const float3 N = INTEGRATOR_STATE(state, path, mis_origin_n);
       pdf *= light_tree_pdf(kg, ray_P, N, sd->prim);
     }
diff --git a/intern/cycles/kernel/light/light.h b/intern/cycles/kernel/light/light.h
index e9140298257..c81b6db42fd 100644
--- a/intern/cycles/kernel/light/light.h
+++ b/intern/cycles/kernel/light/light.h
@@ -796,6 +796,10 @@ ccl_device_forceinline void triangle_light_sample(KernelGlobals kg,
         triangle_world_space_vertices(kg, object, prim, -1.0f, V);
         area = triangle_area(V[0], V[1], V[2]);
       }
+
+      if (kernel_data.integrator.use_light_tree) {
+        area = 1.0f;
+      }
       const float pdf = area * kernel_data.integrator.pdf_triangles;
       ls->pdf = pdf / solid_angle;
     }
@@ -824,7 +828,9 @@ ccl_device_forceinline void triangle_light_sample(KernelGlobals kg,
        * area = the area the sample was taken from
        * area_pre = the are from which pdf_triangles was calculated from */
       triangle_world_space_vertices(kg, object, prim, -1.0f, V);
-      const float area_pre = triangle_area(V[0], V[1], V[2]);
+      const float area_pre = (kernel_data.integrator.use_light_tree) ?
+                                 1.0 :
+                                 triangle_area(V[0], V[1], V[2]);
       ls->pdf = ls->pdf * area_pre / area;
     }
     ls->u = u;
diff --git a/intern/cycles/kernel/light/light_tree.h b/intern/cycles/kernel/light/light_tree.h
index 4df1dd7adc7..1b9e5d3806b 100644
--- a/intern/cycles/kernel/light/light_tree.h
+++ b/intern/cycles/kernel/light/light_tree.h
@@ -45,8 +45,7 @@ ccl_device float light_tree_node_importance(const float3 P,
 
   /* Since we're not using the splitting heuristic, we clamp
    * the distance to half the radius of the cluster. */
-  const float distance_squared = fminf(len_squared(centroid - P),
-                                       0.25f * len_squared(bbox_max - centroid));
+  const float distance_squared = len_squared(centroid - P);
 
   const float theta = fast_acosf(dot(bcone_axis, -point_to_centroid));
   const float theta_i = fast_acosf(dot(point_to_centroid, N));
@@ -61,7 +60,11 @@ ccl_device float light_tree_node_importance(const float3 P,
   const float cos_theta_prime = fast_cosf(theta_prime);
 
   float cos_theta_i_prime = 1;
-  if (theta_i - theta_u > 0) {
+  if (theta_i - theta_u > M_PI_2_F) {
+    /* If the lights are guaranteed to be completely behind the shading point,
+     * should we still perform further calculations? */
+    cos_theta_i_prime = 0;
+  } else if (theta_i - theta_u > 0) {
     cos_theta_i_prime = fabsf(fast_cosf(theta_i - theta_u));
   }
 
@@ -106,7 +109,7 @@ ccl_device float light_tree_cluster_importance(KernelGlobals kg,
   const float3 bbox_max = make_float3(
       knode->bounding_box_max[0], knode->bounding_box_max[1], knode->bounding_box_max[2]);
   const float3 bcone_axis = make_float3(
-      knode->bounding_cone_axis[0], knode->bounding_cone_axis[1], knode->bounding_cone_axis[1]);
+      knode->bounding_cone_axis[0], knode->bounding_cone_axis[1], knode->bounding_cone_axis[2]);
 
   return light_tree_node_importance(
       P, N, bbox_min, bbox_max, bcone_axis, knode->theta_o, knode->theta_e, knode->energy);
@@ -131,7 +134,6 @@ ccl_device int light_tree_sample(KernelGlobals kg,
   /* Also keep track of the probability of traversing to a given node, */
   /* so that we can scale our PDF accordingly later. */
   int index = 0;
-  *pdf_factor = 1.0f;
 
   /* to-do: is it better to generate a new random sample for each step of the traversal? */
   float tree_u = path_state_rng_1D(kg, rng_state, 1);
@@ -144,19 +146,18 @@ ccl_device int light_tree_sample(KernelGlobals kg,
 
     const float left_importance = light_tree_cluster_importance(kg, P, N, left);
     const float right_importance = light_tree_cluster_importance(kg, P, N, right);
-    const float left_probability = left_importance / (left_importance + right_importance);
+    float left_probability = left_importance / (left_importance + right_importance);
 
     if (tree_u < left_probability) {
       index = index + 1;
       knode = left;
-      tree_u = tree_u * (left_importance + right_importance) / left_importance;
+      tree_u = tree_u * left_probability;
       *pdf_factor *= left_probability;
     }
     else {
       index = knode->child_index;
       knode = right;
-      tree_u = (tree_u * (left_importance + right_importance) - left_importance) /
-               right_importance;
+      tree_u = (tree_u - left_probability) / (1 - left_probability);
       *pdf_factor *= (1 - left_probability);
     }
   }
@@ -282,51 +283,25 @@ ccl_device int light_tree_sample_distant_lights(KernelGlobals kg,
   return -1;
 }
 
-ccl_device bool light_tree_sample_from_position(KernelGlobals kg,
-                                                ccl_private const RNGState *rng_state,
-                                                float randu,
-                                                const float randv,
-                                                const float time,
-                                                const float3 P,
-                                                const float3 N,
-                                                const int bounce,
-                                                const uint32_t path_flag,
-                                                ccl_private LightSample *ls)
-{
-  float pdf_factor = 1.0f;
-  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 {
-    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);
-  }
-
-  ls->pdf *= pdf_factor;
-  return ret;
-}
-
 /* We need to be able to find the probability of selecting a given light, for MIS. */
 ccl_device float light_tree_pdf(KernelGlobals kg, const float3 P, const float3 N, const int prim)
 {
   float pdf = kernel_data.integrator.pdf_light_tree;
 
-  const int emitter = (prim >= 0) ? kernel_data_fetch(triangle_to_tree, prim) : kernel_data_fetch(light_to_tree, ~prim);
-  ccl_global const KernelLightTreeEmitter* kemitter = &kernel_data_fetch(light_tree_emitters,
+  const int emitter = (prim >= 0) ? kernel_data_fetch(triangle_to_tree, prim) :
+                                    kernel_data_fetch(light_to_tree, ~prim);
+  ccl_global const KernelLightTreeEmitter *kemitter = &kernel_data_fetch(light_tree_emitters,
                                                                          emitter);
   int parent = kemitter->parent_index;
-  ccl_global const KernelLightTreeNode* kleaf = &kernel_data_fetch(light_tree_nodes, parent);
+  ccl_global const KernelLightTreeNode *kleaf = &kernel_data_fetch(light_tree_nodes, parent);
 
   /* First, we find the probability of selecting the primitive out of the leaf node. */
   float total_importance = 0.0f;
   float emitter_importance = 0.0f;
   for (int i = 0; i < kleaf->num_prims; i++) {
-    int prim = i - kleaf->child_index; /* At a leaf node, the negative value is the index into first prim. */
+    int prim =
+        i -
+        kleaf->child_index; /* At a leaf node, the negative value is the index into first prim. */
     const float importance = light_tree_emitter_importance(kg, P, N, prim);
     if (prim == emitter) {
       emitter_importance = importance;
@@ -336,7 +311,7 @@ ccl_device float light_tree_pdf(KernelGlobals kg, const float3 P, const float3 N
   pdf *= emitter_importance / total_importance;
 
   /* Next, we find the probability of traversing to that leaf node. */
-  int child_index = parent; 
+  int child_index = parent;
   parent = kleaf->parent_index;
   while (parent != -1) {
     const ccl_global KernelLightTreeNode *kparent = &kernel_data_fetch(light_tree_nodes, parent);
@@ -344,13 +319,19 @@ ccl_device float light_tree_pdf(KernelGlobals kg, const float3 P, const float3 N
     const int left_index = parent + 1;
     const int right_index = kparent->child_index;
     const ccl_global KernelLightTreeNode *kleft = &kernel_data_fetch(light_tree_nodes, left_index);
-    const ccl_global KernelLight

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list