[Bf-blender-cvs] [2b8f717be6b] soc-2022-many-lights-sampling: Cleanup: make distant lights part of the light tree

Weizhen Huang noreply at git.blender.org
Wed Nov 23 14:46:34 CET 2022


Commit: 2b8f717be6b5a0b28731a566ae0b3f0a7210bd55
Author: Weizhen Huang
Date:   Wed Nov 23 14:45:23 2022 +0100
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB2b8f717be6b5a0b28731a566ae0b3f0a7210bd55

Cleanup: make distant lights part of the light tree

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

M	intern/cycles/kernel/data_arrays.h
M	intern/cycles/kernel/data_template.h
M	intern/cycles/kernel/light/sample.h
M	intern/cycles/kernel/light/tree.h
M	intern/cycles/kernel/types.h
M	intern/cycles/scene/light.cpp
M	intern/cycles/scene/light_tree.cpp
M	intern/cycles/scene/light_tree.h
M	intern/cycles/scene/scene.cpp
M	intern/cycles/scene/scene.h

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

diff --git a/intern/cycles/kernel/data_arrays.h b/intern/cycles/kernel/data_arrays.h
index 9c57a0176b8..6914a4642e9 100644
--- a/intern/cycles/kernel/data_arrays.h
+++ b/intern/cycles/kernel/data_arrays.h
@@ -63,7 +63,6 @@ KERNEL_DATA_ARRAY(float2, light_background_conditional_cdf)
 /* light tree */
 KERNEL_DATA_ARRAY(KernelLightTreeNode, light_tree_nodes)
 KERNEL_DATA_ARRAY(KernelLightTreeEmitter, light_tree_emitters)
-KERNEL_DATA_ARRAY(KernelLightTreeDistantEmitter, light_tree_distant_group)
 KERNEL_DATA_ARRAY(uint, light_to_tree)
 KERNEL_DATA_ARRAY(uint, object_lookup_offset)
 KERNEL_DATA_ARRAY(uint, triangle_to_tree)
diff --git a/intern/cycles/kernel/data_template.h b/intern/cycles/kernel/data_template.h
index 7d6c1fd6804..994e7f7446c 100644
--- a/intern/cycles/kernel/data_template.h
+++ b/intern/cycles/kernel/data_template.h
@@ -155,8 +155,6 @@ KERNEL_STRUCT_MEMBER(integrator, int, num_distribution)
 KERNEL_STRUCT_MEMBER(integrator, float, distribution_pdf_triangles)
 KERNEL_STRUCT_MEMBER(integrator, float, distribution_pdf_lights)
 KERNEL_STRUCT_MEMBER(integrator, float, light_inv_rr_threshold)
-/* Light tree. */
-KERNEL_STRUCT_MEMBER(integrator, int, num_tree_lights)
 /* Bounces. */
 KERNEL_STRUCT_MEMBER(integrator, int, min_bounce)
 KERNEL_STRUCT_MEMBER(integrator, int, max_bounce)
@@ -210,6 +208,7 @@ KERNEL_STRUCT_MEMBER(integrator, int, use_guiding_mis_weights)
 /* Padding */
 KERNEL_STRUCT_MEMBER(integrator, int, pad1)
 KERNEL_STRUCT_MEMBER(integrator, int, pad2)
+KERNEL_STRUCT_MEMBER(integrator, int, pad3)
 KERNEL_STRUCT_END(KernelIntegrator)
 
 /* SVM. For shader specialization. */
diff --git a/intern/cycles/kernel/light/sample.h b/intern/cycles/kernel/light/sample.h
index 5f6b981a369..a462d0e01ac 100644
--- a/intern/cycles/kernel/light/sample.h
+++ b/intern/cycles/kernel/light/sample.h
@@ -463,20 +463,8 @@ ccl_device_inline float light_sample_mis_weight_forward_distant(KernelGlobals kg
                                                                 const uint32_t path_flag,
                                                                 const ccl_private LightSample *ls)
 {
-  const float mis_ray_pdf = INTEGRATOR_STATE(state, path, mis_ray_pdf);
-  float pdf = ls->pdf;
-
-  /* Light selection pdf. */
-  if (kernel_data.integrator.use_light_tree) {
-    const float3 ray_P = INTEGRATOR_STATE(state, ray, P);
-    const float3 N = INTEGRATOR_STATE(state, path, mis_origin_n);
-    pdf *= light_tree_pdf_distant(kg, ray_P, N, path_flag, ls->lamp);
-  }
-  else {
-    pdf *= light_distribution_pdf_lamp(kg);
-  }
-
-  return light_sample_mis_weight_forward(kg, mis_ray_pdf, pdf);
+  const float3 ray_P = INTEGRATOR_STATE(state, ray, P);
+  return light_sample_mis_weight_forward_lamp(kg, state, path_flag, ls, ray_P);
 }
 
 ccl_device_inline float light_sample_mis_weight_forward_background(KernelGlobals kg,
@@ -492,7 +480,7 @@ ccl_device_inline float light_sample_mis_weight_forward_background(KernelGlobals
   /* Light selection pdf. */
   if (kernel_data.integrator.use_light_tree) {
     const float3 N = INTEGRATOR_STATE(state, path, mis_origin_n);
-    pdf *= light_tree_pdf_distant(kg, ray_P, N, path_flag, kernel_data.background.light_index);
+    pdf *= light_tree_pdf(kg, ray_P, N, path_flag, ~kernel_data.background.light_index);
   }
   else {
     pdf *= light_distribution_pdf_lamp(kg);
diff --git a/intern/cycles/kernel/light/tree.h b/intern/cycles/kernel/light/tree.h
index c762f2b4cbf..e1498486f84 100644
--- a/intern/cycles/kernel/light/tree.h
+++ b/intern/cycles/kernel/light/tree.h
@@ -181,6 +181,8 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
   ccl_global const KernelLightTreeEmitter *kemitter = &kernel_data_fetch(light_tree_emitters,
                                                                          emitter_index);
 
+  max_importance = 0.0f;
+  min_importance = 0.0f;
   float theta_o = kemitter->theta_o;
   float min_distance, distance;
   float max_distance = 0.0f;
@@ -191,7 +193,7 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
   const int prim = kemitter->prim_id;
   /* TODO: pack in functions and move to header files for respective light types */
   if (prim < 0) {
-    const int lamp = -prim - 1;
+    const int lamp = ~prim;
     const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp);
     centroid = make_float3(klight->co[0], klight->co[1], klight->co[2]);
     point_to_centroid = safe_normalize_len(centroid - P, &distance);
@@ -203,9 +205,9 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
       max_distance = sqrtf(sqr(radius) + sqr(distance));
       const float hypotenus = max_distance;
       cos_theta_u = distance / hypotenus;
-      bbox_is_visible = true; /* will be tested later */
+      bbox_is_visible = true; /* will be tested when computing the importance */
     }
-    else { /* area light */
+    else if (klight->type == LIGHT_AREA) {
       bcone_axis = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
       const float3 extentu = make_float3(
           klight->area.extentu[0], klight->area.extentu[1], klight->area.extentu[2]);
@@ -224,6 +226,27 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
        * the overhead to compute the accurate minimal distance? */
       min_distance = distance;
     }
+    else { /* distant light */
+      if (in_volume_segment) {
+        return;
+      }
+      if (klight->type == LIGHT_DISTANT) {
+        /* Treating it as a disk light 1 unit away */
+        cos_theta_u = fast_cosf(theta_o);
+        theta_o = 0.0f;
+        max_distance = 1.0f / cos_theta_u;
+      }
+      else {
+        /* Set an arbitrary direction for the background light. */
+        centroid = -N_or_D;
+        cos_theta_u = -1.0f;
+        max_distance = 1.0f;
+      }
+      bcone_axis = centroid;
+      point_to_centroid = -centroid;
+      min_distance = 1.0f;
+      bbox_is_visible = true; /* will be tested when computing the importance */
+    }
     if (klight->type == LIGHT_POINT) {
       bcone_axis = -point_to_centroid; /* disk oriented normal */
       theta_o = 0.0f;
@@ -255,9 +278,8 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
     min_distance = distance;
   }
 
+  /* TODO: rename `bbox_is_visible` to `is_visible`? */
   if (!bbox_is_visible) {
-    max_importance = 0.0f;
-    min_importance = 0.0f;
     return;
   }
 
@@ -296,45 +318,59 @@ ccl_device void light_tree_node_importance(KernelGlobals kg,
                                            ccl_private float &max_importance,
                                            ccl_private float &min_importance)
 {
-  if (knode->child_index <= 0 && knode->num_prims == 1) {
-    /* at a leaf node and there is only one emitter */
+  max_importance = 0.0f;
+  min_importance = 0.0f;
+  if (knode->num_prims == 1) {
+    /* At a leaf node with only one emitter */
     light_tree_emitter_importance<in_volume_segment>(
         kg, P, N_or_D, t, has_transmission, -knode->child_index, max_importance, min_importance);
   }
-  else {
-    const float3 bbox_min = make_float3(
-        knode->bounding_box_min[0], knode->bounding_box_min[1], knode->bounding_box_min[2]);
-    const float3 bbox_max = make_float3(
-        knode->bounding_box_max[0], knode->bounding_box_max[1], knode->bounding_box_max[2]);
+  else if (knode->num_prims != 0) {
     const float3 bcone_axis = make_float3(
         knode->bounding_cone_axis[0], knode->bounding_cone_axis[1], knode->bounding_cone_axis[2]);
 
-    const float3 centroid = 0.5f * (bbox_min + bbox_max);
+    float3 point_to_centroid;
+    float cos_theta_u;
     float distance;
-    float3 point_to_centroid = normalize_len(centroid - P, &distance);
-    bool bbox_is_visible = has_transmission;
-    float cos_theta_u = light_tree_cos_bounding_box_angle(
-        bbox_min, bbox_max, P, N_or_D, point_to_centroid, bbox_is_visible);
-
-    /* If the node is guaranteed to be behind the surface we're sampling, and the surface is
-     * opaque, then we can give the node an importance of 0 as it contributes nothing to the
-     * surface. */
-    if (!bbox_is_visible) {
-      max_importance = 0.0f;
-      min_importance = 0.0f;
-      return;
+    if (knode->bit_trail == 1) {
+      /* distant light node */
+      if (in_volume_segment) {
+        return;
+      }
+      point_to_centroid = -bcone_axis;
+      cos_theta_u = fmaxf(fast_cosf(knode->theta_o), 0.0f);
+      distance = 1.0f;
     }
+    else {
+      const float3 bbox_min = make_float3(
+          knode->bounding_box_min[0], knode->bounding_box_min[1], knode->bounding_box_min[2]);
+      const float3 bbox_max = make_float3(
+          knode->bounding_box_max[0], knode->bounding_box_max[1], knode->bounding_box_max[2]);
 
-    if (in_volume_segment) {
-      const float3 D = N_or_D;
-      const float3 closest_point = P + D * dot(point_to_centroid, D);
-      /* minimal distance of the ray to the cluster */
-      distance = len(centroid - closest_point);
-      point_to_centroid = centroid - P;
-    }
-    /* clamp distance to half the radius of the cluster when splitting is disabled */
-    distance = fmaxf(0.5f * len(centroid - bbox_max), distance);
+      const float3 centroid = 0.5f * (bbox_min + bbox_max);
 
+      point_to_centroid = normalize_len(centroid - P, &distance);
+      bool bbox_is_visible = has_transmission;
+      cos_theta_u = light_tree_cos_bounding_box_angle(
+          bbox_min, bbox_max, P, N_or_D, point_to_centroid, bbox_is_visible);
+
+      /* If the node is guaranteed to be behind the surface we're sampling, and the surface is
+       * opaque, then we can give the node an importance of 0 as it contributes nothing to the
+       * surface. */
+      if (!bbox_is_visible) {
+        return;
+      }
+
+      if (in_volume_segment) {
+        const float3 D = N_or_D;
+        const float3 closest_point = P + D * dot(point_to_centroid, D);
+        /* minimal distance of the ray to the cluster */
+        distance = len(centroid - closest_point);
+        point_to_centroid = centroid - P;
+      }
+      /* clamp distance to half the radius of the cluster when splitting is disabled */
+      dis

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list