[Bf-blender-cvs] [29b5ff759b3] soc-2022-many-lights-sampling: Compute upper and lower bounds of emitter importance. Splitting is disabled due to increased noise

Weizhen Huang noreply at git.blender.org
Tue Oct 25 11:09:09 CEST 2022


Commit: 29b5ff759b34959af61445f229fe61b276c0412b
Author: Weizhen Huang
Date:   Fri Oct 21 18:50:13 2022 +0200
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB29b5ff759b34959af61445f229fe61b276c0412b

Compute upper and lower bounds of emitter importance. Splitting is disabled due to increased noise

Differential Revision: https://developer.blender.org/D16315

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

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 da5e4869c3b..5eedcd9081d 100644
--- a/intern/cycles/kernel/light/light_tree.h
+++ b/intern/cycles/kernel/light/light_tree.h
@@ -4,37 +4,17 @@
 
 CCL_NAMESPACE_BEGIN
 
-/* This is the general function for calculating the importance of either a cluster or an emitter.
- * Both of the specialized functions obtain the necessary data before calling this function. */
-ccl_device float light_tree_node_importance(const float3 P,
-                                            const float3 N,
-                                            const bool has_transmission,
-                                            const float3 bbox_min,
-                                            const float3 bbox_max,
-                                            const float3 bcone_axis,
-                                            const float theta_o,
-                                            const float theta_e,
-                                            const float energy)
+/* TODO: this seems like a relative expensive computation, and we can make it a lot cheaper
+ * by using a bounding sphere instead of a bounding box. This will be more inaccurate, but it
+ * might be fine when used along with the adaptive splitting. */
+ccl_device float light_tree_cos_bounding_box_angle(const float3 bbox_min,
+                                                   const float3 bbox_max,
+                                                   const float3 P,
+                                                   const float3 N,
+                                                   const float3 point_to_centroid,
+                                                   ccl_private bool &bbox_is_visible)
 {
-  const float3 centroid = 0.5f * bbox_min + 0.5f * bbox_max;
-  const float3 point_to_centroid = normalize(centroid - P);
-
-  /* TODO: we're using the splitting heuristic now, do we still need to clamp the distance to half
-   * the radius of the cluster? */
-  const float distance_squared = fmaxf(0.25f * len_squared(centroid - bbox_max),
-                                       len_squared(centroid - P));
-
-  const float cos_theta = dot(bcone_axis, -point_to_centroid);
-  const float cos_theta_i = has_transmission ? fabsf(dot(point_to_centroid, N)) :
-                                               dot(point_to_centroid, N);
-
-  bool bbox_is_behind_surface = !has_transmission && (cos_theta_i < 0);
-
-  /* TODO: this seems like a relative expensive computation, and we can make it a lot cheaper
-   * by using a bounding sphere instead of a bounding box. This will be more inaccurate, but it
-   * might be fine when used along with the adaptive splitting. */
   float cos_theta_u = 1.0f;
-
   /* Iterate through all 8 possible points of the bounding box. */
   for (int i = 0; i < 8; ++i) {
     const float3 corner = make_float3((i & 1) ? bbox_max.x : bbox_min.x,
@@ -46,19 +26,47 @@ ccl_device float light_tree_node_importance(const float3 P,
     cos_theta_u = fminf(cos_theta_u, dot(point_to_centroid, point_to_corner));
 
     /* Figure out whether or not the bounding box is in front or behind the shading point. */
-    if (bbox_is_behind_surface && dot(point_to_corner, N) >= 0) {
-      bbox_is_behind_surface = false;
-    }
+    bbox_is_visible |= dot(point_to_corner, N) > 0;
   }
+  return cos_theta_u;
+}
 
-  /* 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_behind_surface) {
-    return 0.0f;
-  }
+/* This is the general function for calculating the importance of either a cluster or an emitter.
+ * Both of the specialized functions obtain the necessary data before calling this function. */
+ccl_device void light_tree_cluster_importance(const float3 N,
+                                              const bool has_transmission,
+                                              const float3 point_to_centroid,
+                                              const float cos_theta_u,
+                                              const float3 bcone_axis,
+                                              const float inv_max_distance_squared,
+                                              const float inv_min_distance_squared,
+                                              const float theta_o,
+                                              const float theta_e,
+                                              const float energy,
+                                              ccl_private float &max_importance,
+                                              ccl_private float &min_importance)
+{
+  max_importance = 0.0f;
+  min_importance = 0.0f;
 
+  const float cos_theta = dot(bcone_axis, -point_to_centroid);
+  const float cos_theta_i = has_transmission ? fabsf(dot(point_to_centroid, N)) :
+                                               dot(point_to_centroid, N);
+  const float sin_theta_i = safe_sqrtf(1.0f - sqr(cos_theta_i));
   const float sin_theta_u = safe_sqrtf(1.0f - sqr(cos_theta_u));
 
+  /* cos_min_incidence_angle = cos(max{theta_i - theta_u, 0}), also cos(theta_i') in the paper*/
+  const float cos_min_incidence_angle = cos_theta_i > cos_theta_u ?
+                                            1.0f :
+                                            cos_theta_i * cos_theta_u + sin_theta_i * sin_theta_u;
+  /* 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.
+   * This is more accurate than the bbox test if we are calculating the importance of an emitter
+   * with radius */
+  if (!has_transmission && cos_min_incidence_angle < 0) {
+    return;
+  }
+
   /* cos(theta - theta_u) */
   const float sin_theta = safe_sqrtf(1.0f - sqr(cos_theta));
   const float cos_theta_minus_theta_u = cos_theta * cos_theta_u + sin_theta * sin_theta_u;
@@ -66,38 +74,54 @@ ccl_device float light_tree_node_importance(const float3 P,
   float cos_theta_o, sin_theta_o;
   fast_sincosf(theta_o, &sin_theta_o, &cos_theta_o);
 
-  float cos_theta_prime;
+  float cos_min_outgoing_angle; /* minimum angle an emitter’s normal would form with the direction
+                                 to the shading point, cos(theta') in the paper */
+
   if ((cos_theta > cos_theta_u) || (cos_theta_minus_theta_u > cos_theta_o)) {
     /* theta - theta_o - theta_u < 0 */
     kernel_assert((fast_acosf(cos_theta) - theta_o - fast_acosf(cos_theta_u)) < 5e-4f);
-    cos_theta_prime = 1.0f;
+    cos_min_outgoing_angle = 1.0f;
   }
   else if ((cos_theta > cos_theta_u) || (theta_o + theta_e > M_PI_F) ||
            (cos_theta_minus_theta_u > cos(theta_o + theta_e))) {
     /* theta' = theta - theta_o - theta_u < theta_e */
     kernel_assert((fast_acosf(cos_theta) - theta_o - fast_acosf(cos_theta_u) - theta_e) < 5e-4f);
     const float sin_theta_minus_theta_u = safe_sqrtf(1.0f - sqr(cos_theta_minus_theta_u));
-    cos_theta_prime = cos_theta_minus_theta_u * cos_theta_o +
-                      sin_theta_minus_theta_u * sin_theta_o;
+    cos_min_outgoing_angle = cos_theta_minus_theta_u * cos_theta_o +
+                             sin_theta_minus_theta_u * sin_theta_o;
   }
   else {
-    return 0.f;
+    return;
   }
 
-  /* cos_theta_i_prime = |cos(max{theta_i - theta_u, 0})| */
-  float cos_theta_i_prime;
-  if (cos_theta_i > cos_theta_u) {
-    cos_theta_i_prime = 1.0f;
+  /* TODO: find a good approximation for f_a. */
+  const float f_a = 1.0f;
+  max_importance = fabsf(f_a * cos_min_incidence_angle * energy * inv_min_distance_squared *
+                         cos_min_outgoing_angle);
+
+  if (inv_max_distance_squared == inv_min_distance_squared) {
+    min_importance = max_importance;
+    return;
+  }
+
+  /* cos_max_incidence_angle = cos(min{theta_i + theta_u, pi}) */
+  const float cos_max_incidence_angle = fmaxf(
+      cos_theta_i * cos_theta_u - sin_theta_i * sin_theta_u, 0.0f);
+
+  /* cos(theta + theta_o + theta_u) if theta + theta_o + theta_u < theta_e, 0 otherwise */
+  float cos_max_outgoing_angle;
+  const float cos_theta_plus_theta_u = cos_theta * cos_theta_u - sin_theta * sin_theta_u;
+  if (theta_e - theta_o < 0 || cos_theta < 0 || cos_theta_u < 0 ||
+      cos_theta_plus_theta_u < cos(theta_e - theta_o)) {
+    min_importance = 0.f;
   }
   else {
-    kernel_assert(fast_acosf(cos_theta_i) >= fast_acosf(cos_theta_u));
-    const float sin_theta_i = safe_sqrtf(1.0f - sqr(cos_theta_i));
-    cos_theta_i_prime = cos_theta_i * cos_theta_u + sin_theta_i * sin_theta_u;
+    const float sin_theta_plus_theta_u = safe_sqrtf(1.0f - sqr(cos_theta_plus_theta_u));
+    cos_max_outgoing_angle = cos_theta_plus_theta_u * cos_theta_o -
+                             sin_theta_plus_theta_u * sin_theta_o;
+    min_importance = fabsf(f_a * cos_max_incidence_angle * energy * inv_max_distance_squared *
+                           cos_max_outgoing_angle);
   }
-
-  /* TODO: find a good approximation for this value. */
-  const float f_a = 1.0f;
-  return fabsf(f_a * cos_theta_i_prime * energy / distance_squared * cos_theta_prime);
 }
 
 /* This is uniformly sampling the reservoir for now. */
@@ -167,38 +191,111 @@ ccl_device float light_tree_emitter_reservoir_weight(KernelGlobals kg,
   return 1.0f;
 }
 
-ccl_device float light_tree_emitter_importance(KernelGlobals kg,
-                                               const float3 P,
-                                               const float3 N,
-                                               const bool has_transmission,
-                                               int emitter_index)
+ccl_device void light_tree_emitter_importance(KernelGlobals kg,
+                                              const float3 P,
+                                              const float3 N,
+                                              const bool has_transmission,
+                                              int emitter_index,
+                                              ccl_private float &max_importance,
+                               

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list