[Bf-blender-cvs] [8d20d9d9eea] soc-2020-production-ready-light-tree: Initial attempt at splitting for volumes.

Sam Kottler noreply at git.blender.org
Tue Aug 4 22:17:04 CEST 2020


Commit: 8d20d9d9eea981884bf1a2ee7de032391954ffaf
Author: Sam Kottler
Date:   Tue Aug 4 15:15:52 2020 -0500
Branches: soc-2020-production-ready-light-tree
https://developer.blender.org/rB8d20d9d9eea981884bf1a2ee7de032391954ffaf

Initial attempt at splitting for volumes.

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

M	intern/cycles/kernel/kernel_path_volume.h

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

diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h
index 83e1019a2f2..1b9a8006382 100644
--- a/intern/cycles/kernel/kernel_path_volume.h
+++ b/intern/cycles/kernel/kernel_path_volume.h
@@ -137,6 +137,212 @@ ccl_device_noinline_cpu bool kernel_path_volume_bounce(KernelGlobals *kg,
 }
 
 #  if !defined(__SPLIT_KERNEL__) && (defined(__BRANCHED_PATH__) || defined(__VOLUME_DECOUPLED__))
+ccl_device void accum_light_tree_contribution_volume(KernelGlobals *kg,
+                                                     float randu,
+                                                     float randv,
+                                                     int offset,
+                                                     float pdf_factor,
+                                                     bool can_split,
+                                                     float3 throughput,
+                                                     float scale_factor,
+                                                     PathRadiance *L,
+                                                     ccl_addr_space PathState *state,
+                                                     ShaderData *sd,
+                                                     ShaderData *emission_sd,
+                                                     Ray *ray,
+                                                     const VolumeSegment *segment)
+{
+  float3 P = sd->P_pick;
+  float3 N = sd->N_pick;
+  float t = sd->t_pick;
+
+  float time = sd->time;
+  int bounce = state->bounce;
+
+  float randu_stack[64];
+  float randv_stack[64];
+  int offset_stack[64];
+  float pdf_stack[64];
+
+  randu_stack[0] = randu;
+  randv_stack[0] = randv;
+  offset_stack[0] = offset;
+  pdf_stack[0] = pdf_factor;
+
+  int stack_idx = 0;
+
+  while (stack_idx > -1) {
+    randu = randu_stack[stack_idx];
+    randv = randv_stack[stack_idx];
+    offset = offset_stack[stack_idx];
+    pdf_factor = pdf_stack[stack_idx];
+    /* read in first part of node of light tree */
+    int right_child_offset, distribution_id, num_emitters;
+    update_node(kg, offset, &right_child_offset, &distribution_id, &num_emitters);
+
+    /* found a leaf */
+    if (right_child_offset == -1) {
+
+      /* if there are several emitters in this leaf then pick one of them */
+      if (num_emitters > 1) {
+
+        /* create and sample CDF without dynamic allocation.
+         * see comment in light_tree_sample() for this piece of code */
+        float sum = 0.0f;
+        for (int i = 0; i < num_emitters; ++i) {
+          sum += calc_light_importance(kg, t, P, N, offset, i);
+        }
+
+        if (sum == 0.0f) {
+          --stack_idx;
+          continue;
+        }
+
+        float sum_inv = 1.0f / sum;
+        float cdf_L = 0.0f;
+        float cdf_R = 0.0f;
+        float prob = 0.0f;
+        int light = num_emitters - 1;
+        for (int i = 1; i < num_emitters + 1; ++i) {
+          prob = calc_light_importance(kg, t, P, N, offset, i - 1) * sum_inv;
+          cdf_R = cdf_L + prob;
+          if (randu < cdf_R) {
+            light = i - 1;
+            break;
+          }
+
+          cdf_L = cdf_R;
+        }
+        distribution_id += light;
+        pdf_factor *= prob;
+
+        /* rescale random number */
+        randu = (randu - cdf_L) / (cdf_R - cdf_L);
+      }
+
+      /* pick a point on the chosen light(distribution_id) and calculate the
+       * probability of picking this point */
+      LightSample ls;
+      light_point_sample(kg, -1, randu, randv, time, P, bounce, distribution_id, &ls);
+
+      /* combine pdfs */
+      ls.pdf *= pdf_factor;
+
+      /* compute and accumulate the total contribution of this light */
+      Ray light_ray;
+      light_ray.t = 0.0f;
+#    ifdef __OBJECT_MOTION__
+      light_ray.time = sd->time;
+#    endif
+      float3 tp = throughput;
+      bool has_emission = false;
+      bool is_lamp = false;
+      BsdfEval L_light ccl_optional_struct_init;
+      /* sample position on volume segment */
+      float rphase = path_branched_rng_1D(
+          kg, state->rng_hash, state, distribution_id, 1.0f, PRNG_PHASE_CHANNEL);
+      float rscatter = path_branched_rng_1D(
+          kg, state->rng_hash, state, distribution_id, 1.0f, PRNG_SCATTER_DISTANCE);
+
+      VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
+                                                                     state,
+                                                                     ray,
+                                                                     sd,
+                                                                     &tp,
+                                                                     rphase,
+                                                                     rscatter,
+                                                                     segment,
+                                                                     (ls.t != FLT_MAX) ? &ls.P :
+                                                                                         NULL,
+                                                                     false);
+      if (result == VOLUME_PATH_SCATTERED) {
+        light_point_sample(kg, -1, randu, randv, time, sd->P_pick, bounce, distribution_id, &ls);
+        if (ls.pdf <= 0.0f) {
+          --stack_idx;
+          continue;
+        }
+        /* sample random light */
+        float terminate = path_branched_rng_light_termination(
+            kg, state->rng_hash, state, distribution_id, 1.0f);
+        has_emission = direct_emission(
+            kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate);
+      }
+
+      /* trace shadow ray */
+      float3 shadow;
+
+      const bool blocked = shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow);
+
+      if (has_emission && !blocked) {
+        /* accumulate */
+        path_radiance_accum_light(kg, L, state, tp, &L_light, shadow, 1.0f, is_lamp);
+      }
+
+      --stack_idx;
+      can_split = true;
+      continue;
+    }
+    else {  // Interior node, choose which child(ren) to go down
+
+      int child_offsetL = offset + 4;
+      int child_offsetR = 4 * right_child_offset;
+
+      /* choose whether to go down both(split) or only one of the children */
+      if (can_split && split(kg, P, offset)) {
+        /* go down both child nodes */
+        //++stack_idx;
+        randu_stack[stack_idx] = randu;
+        randv_stack[stack_idx] = randv;
+        offset_stack[stack_idx] = child_offsetL;
+        pdf_stack[stack_idx] = pdf_factor;
+
+        ++stack_idx;
+        randu_stack[stack_idx] = randu;
+        randv_stack[stack_idx] = randv;
+        offset_stack[stack_idx] = child_offsetR;
+        pdf_stack[stack_idx] = pdf_factor;
+      }
+      else {
+        /* go down one of the child nodes */
+
+        /* evaluate the importance of each of the child nodes */
+        float I_L = calc_node_importance(kg, t, P, N, child_offsetL);
+        float I_R = calc_node_importance(kg, t, P, N, child_offsetR);
+
+        if ((I_L == 0.0f) && (I_R == 0.0f)) {
+          return;
+        }
+
+        /* calculate the probability of going down the left node */
+        float P_L = I_L / (I_L + I_R);
+
+        /* choose which node to go down */
+        if (randu <= P_L) {  // Going down left node
+          /* rescale random number */
+          randu = randu / P_L;
+
+          offset = child_offsetL;
+          pdf_factor *= P_L;
+        }
+        else {  // Going down right node
+          /* rescale random number */
+          randu = (randu * (I_L + I_R) - I_L) / I_R;
+
+          offset = child_offsetR;
+          pdf_factor *= 1.0f - P_L;
+        }
+
+        //++stack_idx;
+        can_split = false;
+        randu_stack[stack_idx] = randu;
+        randv_stack[stack_idx] = randv;
+        offset_stack[stack_idx] = offset;
+        pdf_stack[stack_idx] = pdf_factor;
+      }
+    }
+  }
+}
+
 ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg,
                                                           ShaderData *sd,
                                                           ShaderData *emission_sd,
@@ -151,127 +357,227 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg,
   BsdfEval L_light ccl_optional_struct_init;
 
   bool use_light_tree = kernel_data.integrator.use_light_tree;
-  int num_lights = 1;
-  if (sample_all_lights && !use_light_tree) {
-    num_lights = kernel_data.integrator.num_all_lights;
-    if (kernel_data.integrator.pdf_triangles != 0.0f) {
-      num_lights += 1;
+  if (use_light_tree) {
+    Ray light_ray;
+    bool is_lamp;
+
+    light_ray.t = 0.0f;
+#      ifdef __OBJECT_MOTION__
+    light_ray.time = sd->time;
+#      endif
+
+    int index;
+    float randu, randv;
+    path_state_rng_2D(kg, state, PRNG_LIGHT_U, &randu, &randv);
+
+    /* sample light group distribution */
+    int group = light_group_distribution_sample(kg, &randu);
+    float group_prob = kernel_tex_fetch(__light_group_sample_prob, group);
+    float pdf = 1.0f;
+
+    if (group == LIGHTGROUP_TREE) {
+      /* accumulate contribution to L from potentially several lights */
+      accum_light_tree_contribution_volume(kg,
+                                           randu,
+                                           randv,
+                                           0,
+                                           group_prob,
+                                           true,
+                                           throughput,
+                                           1.0f,
+                                           L,  // todo: is num_samples_adjust correct here?
+                                           state,
+                                           sd,
+                                           emission_sd,
+                                           ray,
+                                           segment);
+
+      /* have accumulated all the contributions so return */
+      return;
+    }
+    else if (group == LIGHTGROUP_DISTANT) {
+      /* pick a single distant light */
+  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list