[Bf-blender-cvs] [37e651e62c8] soc-2022-many-lights-sampling: Fix: light tree random number usage

Jeffrey Liu noreply at git.blender.org
Sun Jul 17 19:20:15 CEST 2022


Commit: 37e651e62c80b669f3b73a52e694caef85969641
Author: Jeffrey Liu
Date:   Sat Jul 16 23:40:42 2022 -0400
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB37e651e62c80b669f3b73a52e694caef85969641

Fix: light tree random number usage

This rescales the random numbers that are passed as arguments, rather
than calling the random number generator again.

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

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 03d412d69ec..5d9dd069b73 100644
--- a/intern/cycles/kernel/light/light_tree.h
+++ b/intern/cycles/kernel/light/light_tree.h
@@ -54,18 +54,18 @@ ccl_device float light_tree_node_importance(const float3 P,
 
   /* to-do: compare this with directly using fmaxf and cosf. */
   /* Avoid using cosine until needed. */
-  const float theta_prime = fmaxf(theta - theta_o - theta_u, 0);
+  const float theta_prime = fmaxf(theta - theta_o - theta_u, 0.0f);
   if (theta_prime >= theta_e) {
     return 0;
   }
   const float cos_theta_prime = fast_cosf(theta_prime);
 
-  float cos_theta_i_prime = 1;
+  float cos_theta_i_prime = 1.0f;
   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) {
+    return 0.0f;
+  } else if (theta_i - theta_u > 0.0f) {
     cos_theta_i_prime = fabsf(fast_cosf(theta_i - theta_u));
   }
 
@@ -121,7 +121,7 @@ ccl_device float light_tree_cluster_importance(KernelGlobals kg,
 template<bool in_volume_segment>
 ccl_device int light_tree_sample(KernelGlobals kg,
                                   ccl_private const RNGState *rng_state,
-                                  float randu,
+                                  float *randu,
                                   const float randv,
                                   const float time,
                                   const float3 N,
@@ -137,7 +137,6 @@ ccl_device int light_tree_sample(KernelGlobals kg,
   int index = 0;
 
   /* 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);
   const ccl_global KernelLightTreeNode *knode = &kernel_data_fetch(light_tree_nodes, index);
   while (knode->child_index > 0) {
     /* At an interior node, the left child is directly next to the parent,
@@ -149,17 +148,17 @@ ccl_device int light_tree_sample(KernelGlobals kg,
     const float right_importance = light_tree_cluster_importance(kg, P, N, right);
     float left_probability = left_importance / (left_importance + right_importance);
 
-    if (tree_u < left_probability) {
+    if (*randu < left_probability) {
       index = index + 1;
       knode = left;
-      tree_u = tree_u / left_probability;
+      *randu = *randu / left_probability;
       *pdf_factor *= left_probability;
     }
     else {
       index = knode->child_index;
       knode = right;
-      tree_u = (tree_u - left_probability) / (1 - left_probability);
-      *pdf_factor *= (1 - left_probability);
+      *randu = (*randu - left_probability) / (1.0f - left_probability);
+      *pdf_factor *= (1.0f - left_probability);
     }
   }
 
@@ -177,15 +176,15 @@ ccl_device int light_tree_sample(KernelGlobals kg,
   }
 
   /* Once we have the total importance, we can normalize the CDF and sample it. */
-  const float inv_total_importance = 1 / total_emitter_importance;
+  const float inv_total_importance = 1.0f / total_emitter_importance;
   float emitter_cdf = 0.0f;
   for (int i = 0; i < knode->num_prims; i++) {
     const int prim_index = -knode->child_index + i;
     /* to-do: is there any way to cache these values, so that recalculation isn't needed? */
     const float emitter_pdf = light_tree_emitter_importance(kg, P, N, prim_index) *
                               inv_total_importance;
-    emitter_cdf += emitter_pdf;
-    if (tree_u < emitter_cdf) {
+    if (*randu < emitter_cdf + emitter_pdf) {
+      *randu = (*randu - emitter_cdf) / emitter_pdf;
       *pdf_factor *= emitter_pdf;
       ccl_global const KernelLightTreeEmitter *kemitter = &kernel_data_fetch(
           light_tree_emitters, prim_index);
@@ -205,7 +204,7 @@ ccl_device int light_tree_sample(KernelGlobals kg,
         }
 
         const int shader_flag = kemitter->mesh_light.shader_flag;
-        triangle_light_sample<in_volume_segment>(kg, prim, object, randu, randv, time, ls, P);
+        triangle_light_sample<in_volume_segment>(kg, prim, object, *randu, randv, time, ls, P);
         ls->shader |= shader_flag;
 
         return (ls->pdf > 0.0f);
@@ -217,8 +216,9 @@ ccl_device int light_tree_sample(KernelGlobals kg,
         return false;
       }
 
-      return light_sample<in_volume_segment>(kg, lamp, randu, randv, P, path_flag, ls);
+      return light_sample<in_volume_segment>(kg, lamp, *randu, randv, P, path_flag, ls);
     }
+    emitter_cdf += emitter_pdf;
   }
 
   /* We should never reach this point. */
@@ -243,10 +243,10 @@ ccl_device float light_tree_distant_light_importance(KernelGlobals kg,
   const float theta = fast_acosf(dot(N, light_axis));
   const float theta_i_prime = theta - kdistant->bounding_radius;
 
-  float cos_theta_i_prime = 1;
+  float cos_theta_i_prime = 1.0f;
   if (theta_i_prime > M_PI_2_F) {
     return 0.0f;
-  } else if (theta - kdistant->bounding_radius > 0) {
+  } else if (theta - kdistant->bounding_radius > 0.0f) {
     cos_theta_i_prime = fast_cosf(theta - kdistant->bounding_radius);
   }
 
@@ -260,7 +260,7 @@ ccl_device float light_tree_distant_light_importance(KernelGlobals kg,
 template<bool in_volume_segment>
 ccl_device int light_tree_sample_distant_lights(KernelGlobals kg,
                                                 ccl_private const RNGState *rng_state,
-                                                float randu,
+                                                float *randu,
                                                 const float randv,
                                                 const float time,
                                                 const float3 N,
@@ -275,15 +275,14 @@ ccl_device int light_tree_sample_distant_lights(KernelGlobals kg,
   for (int i = 0; i < num_distant_lights; i++) {
     total_importance += light_tree_distant_light_importance(kg, P, N, i);
   }
-  const float inv_total_importance = 1 / total_importance;
+  const float inv_total_importance = 1.0f / total_importance;
 
   float light_cdf = 0.0f;
-  float distant_u = path_state_rng_1D(kg, rng_state, 1);
   for (int i = 0; i < num_distant_lights; i++) {
     const float light_pdf = light_tree_distant_light_importance(kg, P, N, i) *
                             inv_total_importance;
-    light_cdf += light_pdf;
-    if (distant_u < light_cdf) {
+    if (*randu < light_cdf + light_pdf) {
+      *randu = (*randu - light_cdf) / light_pdf;
       *pdf_factor *= light_pdf;
       ccl_global const KernelLightTreeDistantEmitter *kdistant = &kernel_data_fetch(
           light_tree_distant_group, i);
@@ -294,8 +293,9 @@ ccl_device int light_tree_sample_distant_lights(KernelGlobals kg,
         return false;
       }
 
-      return light_sample<in_volume_segment>(kg, lamp, randu, randv, P, path_flag, ls);
+      return light_sample<in_volume_segment>(kg, lamp, *randu, randv, P, path_flag, ls);
     }
+    light_cdf += light_pdf;
   }
 
   /* We should never reach this point. */
@@ -328,9 +328,8 @@ ccl_device float light_tree_pdf(KernelGlobals kg, const float3 P, const float3 N
   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. */
+    /* At a leaf node, the negative value is the index into first prim. */
+    int prim = i - kleaf->child_index;
     const float importance = light_tree_emitter_importance(kg, P, N, prim);
     if (prim == emitter) {
       emitter_importance = importance;
@@ -355,17 +354,13 @@ ccl_device float light_tree_pdf(KernelGlobals kg, const float3 P, const float3 N
     const float right_importance = light_tree_cluster_importance(kg, P, N, kright);
     float left_probability = left_importance / (left_importance + right_importance);
 
-    if (left_probability > kernel_data.integrator.splitting_threshold) {
-      left_probability = kernel_data.integrator.splitting_threshold;
-    }
-
     /* If the child index matches the left index, then we must've traversed left, otherwise right.
      */
     if (left_index == child_index) {
       pdf *= left_probability;
     }
     else {
-      pdf *= (1 - left_probability);
+      pdf *= (1.0f - left_probability);
     }
 
     child_index = parent;
@@ -438,16 +433,17 @@ ccl_device bool light_tree_sample_from_position(KernelGlobals kg,
 
   float pdf_factor = 1.0f;
   bool ret;
-  float tree_u = path_state_rng_1D(kg, rng_state, 1);
-  if (tree_u < light_tree_probability) {
+  if (randu < light_tree_probability) {
+    randu = randu / light_tree_probability;
     pdf_factor *= light_tree_probability;
     ret = light_tree_sample<false>(
-        kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
+        kg, rng_state, &randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
   }
   else {
-    pdf_factor *= (1 - light_tree_probability);
+    randu = (randu - light_tree_probability) / (1.0f - light_tree_probability);
+    pdf_factor *= (1.0f - light_tree_probability);
     ret = light_tree_sample_distant_lights<false>(
-        kg, rng_state, randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
+        kg, rng_state, &randu, randv, time, N, P, bounce, path_flag, ls, &pdf_factor);
   }
 
   ls->pdf *= pdf_factor;



More information about the Bf-blender-cvs mailing list