[Bf-blender-cvs] [9a97eb549c4] soc-2022-many-lights-sampling: Refactor: move light tree parameters computation to light type header files

Weizhen Huang noreply at git.blender.org
Tue Nov 29 17:02:39 CET 2022


Commit: 9a97eb549c4c0c8c1064f11d7c9c6d57decef4be
Author: Weizhen Huang
Date:   Tue Nov 29 17:01:32 2022 +0100
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB9a97eb549c4c0c8c1064f11d7c9c6d57decef4be

Refactor: move light tree parameters computation to light type header files

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

M	intern/cycles/kernel/light/area.h
M	intern/cycles/kernel/light/background.h
M	intern/cycles/kernel/light/distant.h
M	intern/cycles/kernel/light/point.h
M	intern/cycles/kernel/light/spot.h
M	intern/cycles/kernel/light/tree.h
M	intern/cycles/kernel/light/triangle.h

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

diff --git a/intern/cycles/kernel/light/area.h b/intern/cycles/kernel/light/area.h
index f7c52db1692..8daadebe67d 100644
--- a/intern/cycles/kernel/light/area.h
+++ b/intern/cycles/kernel/light/area.h
@@ -322,31 +322,42 @@ ccl_device_inline bool area_light_sample_from_intersection(
   return true;
 }
 
-ccl_device_inline float area_light_tree_weight(const ccl_global KernelLight *klight,
-                                               const float3 P,
-                                               const float3 N)
+template<bool in_volume_segment>
+ccl_device_forceinline bool area_light_tree_parameters(const ccl_global KernelLight *klight,
+                                                       const float3 centroid,
+                                                       const float3 P,
+                                                       const float3 N,
+                                                       const float3 bcone_axis,
+                                                       ccl_private float &cos_theta_u,
+                                                       ccl_private float2 &distance,
+                                                       ccl_private float3 &point_to_centroid)
 {
-  float3 light_P = klight->co;
-
-  float3 extentu = klight->area.extentu;
-  float3 extentv = klight->area.extentv;
-  float3 Ng = klight->area.dir;
-  bool is_round = (klight->area.invarea < 0.0f);
-
-  if (dot(light_P - P, Ng) > 0.0f) {
-    return 0.0f;
+  if (!in_volume_segment) {
+    /* TODO: a cheap substitute for minimal distance between point and primitive. Does it
+     * worth the overhead to compute the accurate minimal distance? */
+    point_to_centroid = safe_normalize_len(centroid - P, &distance.y);
+    distance.x = distance.y;
   }
 
-  if (!is_round) {
-    if (klight->area.tan_spread > 0.0f) {
-      if (!area_light_spread_clamp_area_light(
-              P, Ng, &light_P, &extentu, &extentv, klight->area.tan_spread)) {
-        return 0.0f;
-      }
+  const float3 extentu = klight->area.extentu;
+  const float3 extentv = klight->area.extentv;
+  for (int i = 0; i < 4; i++) {
+    const float3 corner = ((i & 1) - 0.5f) * extentu + 0.5f * ((i & 2) - 1) * extentv + centroid;
+    float distance_point_to_corner;
+    const float3 point_to_corner = safe_normalize_len(corner - P, &distance_point_to_corner);
+    cos_theta_u = fminf(cos_theta_u, dot(point_to_centroid, point_to_corner));
+    if (!in_volume_segment) {
+      distance.x = fmaxf(distance.x, distance_point_to_corner);
     }
   }
 
-  return 1.0f;
+  const bool front_facing = dot(bcone_axis, point_to_centroid) < 0;
+  const bool shape_above_surface = dot(N, centroid - P) + fabsf(dot(N, extentu)) +
+                                       fabsf(dot(N, extentv)) >
+                                   0;
+  const bool in_volume = is_zero(N);
+
+  return (front_facing && shape_above_surface) || in_volume;
 }
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/light/background.h b/intern/cycles/kernel/light/background.h
index 95bd5d47f9f..b37b4410ed4 100644
--- a/intern/cycles/kernel/light/background.h
+++ b/intern/cycles/kernel/light/background.h
@@ -430,4 +430,18 @@ ccl_device float background_light_pdf(KernelGlobals kg, float3 P, float3 directi
   return pdf;
 }
 
+ccl_device_forceinline bool background_light_tree_parameters(const float3 centroid,
+                                                             ccl_private float &cos_theta_u,
+                                                             ccl_private float2 &distance,
+                                                             ccl_private float3 &point_to_centroid)
+{
+  /* Cover the whole sphere */
+  cos_theta_u = -1.0f;
+
+  distance = make_float2(1.0f, 1.0f);
+  point_to_centroid = -centroid;
+
+  return true;
+}
+
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/light/distant.h b/intern/cycles/kernel/light/distant.h
index c074a6bf097..3b6aa505fd2 100644
--- a/intern/cycles/kernel/light/distant.h
+++ b/intern/cycles/kernel/light/distant.h
@@ -108,4 +108,20 @@ ccl_device bool distant_light_sample_from_intersection(KernelGlobals kg,
   return true;
 }
 
+ccl_device_forceinline bool distant_light_tree_parameters(const float3 centroid,
+                                                          const float theta_e,
+                                                          ccl_private float &cos_theta_u,
+                                                          ccl_private float2 &distance,
+                                                          ccl_private float3 &point_to_centroid)
+{
+  /* Treating it as a disk light 1 unit away */
+  cos_theta_u = fast_cosf(theta_e);
+
+  distance = make_float2(1.0f / cos_theta_u, 1.0f);
+
+  point_to_centroid = -centroid;
+
+  return true;
+}
+
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/light/point.h b/intern/cycles/kernel/light/point.h
index edf4f899aed..7597bc12b84 100644
--- a/intern/cycles/kernel/light/point.h
+++ b/intern/cycles/kernel/light/point.h
@@ -109,4 +109,27 @@ ccl_device_inline bool point_light_sample_from_intersection(
   return true;
 }
 
+template<bool in_volume_segment>
+ccl_device_forceinline bool point_light_tree_parameters(const ccl_global KernelLight *klight,
+                                                        const float3 centroid,
+                                                        const float3 P,
+                                                        ccl_private float &cos_theta_u,
+                                                        ccl_private float2 &distance,
+                                                        ccl_private float3 &point_to_centroid)
+{
+  if (in_volume_segment) {
+    cos_theta_u = 1.0f; /* Any value in [-1, 1], irrelevant since theta = 0 */
+    return true;
+  }
+  point_to_centroid = safe_normalize_len(centroid - P, &distance.y);
+
+  const float radius = klight->spot.radius;
+  const float hypotenus = sqrtf(sqr(radius) + sqr(distance.y));
+  cos_theta_u = distance.y / hypotenus;
+
+  distance.x = hypotenus;
+
+  return true;
+}
+
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/light/spot.h b/intern/cycles/kernel/light/spot.h
index 13fe1f63e74..b1d652f13f9 100644
--- a/intern/cycles/kernel/light/spot.h
+++ b/intern/cycles/kernel/light/spot.h
@@ -151,23 +151,29 @@ ccl_device_inline bool spot_light_sample_from_intersection(
   return true;
 }
 
-ccl_device_inline float spot_light_tree_weight(const ccl_global KernelLight *klight,
-                                               const float3 P,
-                                               const float3 N)
+template<bool in_volume_segment>
+ccl_device_forceinline bool spot_light_tree_parameters(const ccl_global KernelLight *klight,
+                                                       const float3 centroid,
+                                                       const float3 P,
+                                                       ccl_private float &cos_theta_u,
+                                                       ccl_private float2 &distance,
+                                                       ccl_private float3 &point_to_centroid)
 {
+  float min_distance;
+  const float3 point_to_centroid_ = safe_normalize_len(centroid - P, &min_distance);
+
   const float radius = klight->spot.radius;
-  const float cos_theta = klight->spot.cos_half_spot_angle;
-  const float theta = fast_acosf(cos_theta);
-  const float3 light_dir = klight->spot.dir;
+  const float hypotenus = sqrtf(sqr(radius) + sqr(min_distance));
+  cos_theta_u = min_distance / hypotenus;
 
-  const float h1 = radius * fast_sinf(theta);
-  const float d1 = radius * cos_theta;
-  const float h2 = d1 / fast_tanf(theta);
+  if (in_volume_segment) {
+    return true;
+  }
 
-  const float3 apex = klight->co - (h1 + h2) * light_dir;
-  const float3 apex_to_point = normalize(P - apex);
+  distance = make_float2(hypotenus, min_distance);
+  point_to_centroid = point_to_centroid_;
 
-  return (dot(apex_to_point, light_dir) < cos_theta) ? 0.0f : 1.0f;
+  return true;
 }
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/light/tree.h b/intern/cycles/kernel/light/tree.h
index 2ad37e046c4..7f78d96f3f6 100644
--- a/intern/cycles/kernel/light/tree.h
+++ b/intern/cycles/kernel/light/tree.h
@@ -89,7 +89,7 @@ ccl_device void light_tree_cluster_importance(const float3 N_or_D,
   float cos_max_incidence_angle = 1.0f;
   /* when sampling the light tree for the second time in `shade_volume.h` and when query the pdf in
    * `sample.h` */
-  const bool in_volume = (dot(N_or_D, N_or_D) < 5e-4f);
+  const bool in_volume = is_zero(N_or_D);
 
   cos_theta = dot(bcone.axis, -point_to_centroid);
   if (!in_volume_segment && !in_volume) {
@@ -98,7 +98,7 @@ ccl_device void light_tree_cluster_importance(const float3 N_or_D,
     sin_theta_i = safe_sqrtf(1.0f - sqr(cos_theta_i));
 
     /* cos_min_incidence_angle = cos(max{theta_i - theta_u, 0}) = cos(theta_i') in the paper */
-    cos_min_incidence_angle = cos_theta_i > cos_theta_u ?
+    cos_min_incidence_angle = cos_theta_i >= cos_theta_u ?
                                   1.0f :
                                   cos_theta_i * cos_theta_u + sin_theta_i * sin_theta_u;
 
@@ -171,6 +171,62 @@ ccl_device void light_tree_cluster_importance(const float3 N_or_D,
   }
 }
 
+template<bool in_volume_segment>
+ccl_device_inline bool compute_emitter_centroid_and_dir(
+    KernelGlobals kg,
+    ccl_global const KernelLightTreeEmitter *kemitter,
+    const float3 P,
+    ccl_private float3 &centroid,
+    ccl_private packed_float3 &dir)
+{
+  const int prim_id = kemitter->prim_id;
+  if (prim_id < 0) {
+    const ccl_global KernelLight *klight = &kernel_data_fetch(lights, ~prim_id);
+    centroid = klight->co;
+
+    switch (klight->type) {
+      case LIGHT_SPOT:
+        dir = klight->spot.dir;
+        break;
+      case LIGHT_POINT:
+        /* Disk-oriented normal */
+        dir = safe_normalize(P - centroid);
+        break;
+      case LIGHT_AREA:
+        dir = klight->area.dir;
+        break;
+      case LIGHT_BACKGROUND:
+        /* Aarbitrary centroid and direction */
+        centroid = make_float3(0.0f, 0.0f, 1.0f);
+        dir = 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list