[Bf-blender-cvs] [e636d7f7eb0] soc-2020-production-ready-light-tree: Initial volume support in light tree.

Sam Kottler noreply at git.blender.org
Tue Jul 21 22:01:36 CEST 2020


Commit: e636d7f7eb0ec5dbd8d84453b30e603e765b0378
Author: Sam Kottler
Date:   Tue Jul 21 13:59:26 2020 -0600
Branches: soc-2020-production-ready-light-tree
https://developer.blender.org/rBe636d7f7eb0ec5dbd8d84453b30e603e765b0378

Initial volume support in light tree.

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

M	intern/cycles/kernel/kernel_bake.h
M	intern/cycles/kernel/kernel_emission.h
M	intern/cycles/kernel/kernel_light.h
M	intern/cycles/kernel/kernel_path.h
M	intern/cycles/kernel/kernel_path_branched.h
M	intern/cycles/kernel/kernel_path_surface.h
M	intern/cycles/kernel/kernel_path_volume.h
M	intern/cycles/kernel/kernel_types.h
M	intern/cycles/kernel/kernel_volume.h
M	intern/cycles/kernel/split/kernel_direct_lighting.h
M	intern/cycles/kernel/split/kernel_do_volume.h

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

diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index dde8f0b1a1b..8829df4d323 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -85,6 +85,7 @@ ccl_device_noinline void compute_light_pass(
           kernel_path_subsurface_setup_indirect(kg, &ss_indirect, &state, &ray, L, &throughput);
           indirect_sd.P_pick = sd->P_pick;
           indirect_sd.N_pick = sd->N_pick;
+          indirect_sd.t_pick = sd->t_pick;
           kernel_path_indirect(kg, &indirect_sd, emission_sd, &ray, throughput, &state, L);
         }
         is_sss_sample = true;
@@ -103,6 +104,7 @@ ccl_device_noinline void compute_light_pass(
         /* compute indirect light */
         indirect_sd.P_pick = sd->P_pick;
         indirect_sd.N_pick = sd->N_pick;
+        indirect_sd.t_pick = sd->t_pick;
         kernel_path_indirect(kg, &indirect_sd, emission_sd, &ray, throughput, &state, L);
 
         /* sum and reset indirect light pass variables for the next samples */
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 46ff209e6f1..4a6c3796fec 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -228,7 +228,12 @@ ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg,
     /* multiple importance sampling, get triangle light pdf,
      * and compute weight with respect to BSDF pdf */
     float pdf = triangle_light_pdf(kg, sd, t);
-    pdf *= light_distribution_pdf(kg, P, N, sd->prim, sd->object, has_volume);
+    if ((path_flag & PATH_RAY_VOLUME_SCATTER) && sd->t_pick > 0.0f) {
+      pdf *= light_distribution_pdf(kg, sd->P_pick, sd->N_pick, sd->t_pick, sd->prim, sd->object);
+    }
+    else {
+      pdf *= light_distribution_pdf(kg, P, N, -1.0f, sd->prim, sd->object);
+    }
     float mis_weight = power_heuristic(bsdf_pdf, pdf);
 
     return L * mis_weight;
@@ -269,7 +274,6 @@ ccl_device_noinline_cpu void indirect_lamp_emission(KernelGlobals *kg,
     float3 lamp_L = direct_emissive_eval(
         kg, emission_sd, &ls, state, -ray->D, ray->dD, ls.t, ray->time);
 
-    bool has_volume = false;
 #ifdef __VOLUME__
     if (state->volume_stack[0].shader != SHADER_NONE) {
       /* shadow attenuation */
@@ -280,7 +284,6 @@ ccl_device_noinline_cpu void indirect_lamp_emission(KernelGlobals *kg,
       lamp_L *= volume_tp;
     }
 
-    has_volume = ((emission_sd->flag & SD_HAS_VOLUME) != 0);
 #endif
 
     if (!(state->flag & PATH_RAY_MIS_SKIP)) {
@@ -288,7 +291,13 @@ ccl_device_noinline_cpu void indirect_lamp_emission(KernelGlobals *kg,
        * and compute weight with respect to BSDF pdf */
 
       /* multiply with light picking probablity to pdf */
-      ls.pdf *= light_distribution_pdf(kg, ray->P, N, ~ls.lamp, -1, has_volume);
+      if ((state->flag & PATH_RAY_VOLUME_SCATTER) && emission_sd->t_pick > 0.0f) {
+        ls.pdf *= light_distribution_pdf(
+            kg, emission_sd->P_pick, emission_sd->N_pick, emission_sd->t_pick, ~ls.lamp, -1);
+      }
+      else {
+        ls.pdf *= light_distribution_pdf(kg, ray->P, N, -1.0f, ~ls.lamp, -1);
+      }
       float mis_weight = power_heuristic(state->ray_pdf, ls.pdf);
       lamp_L *= mis_weight;
     }
@@ -321,11 +330,6 @@ ccl_device_noinline_cpu float3 indirect_background(KernelGlobals *kg,
       return make_float3(0.0f, 0.0f, 0.0f);
   }
 
-  bool has_volume = false;
-#  if defined(__BACKGROUND_MIS__) && defined(__VOLUME__)
-  /* This has to be done before shader_setup_* below. */
-  has_volume = ((emission_sd->flag & SD_HAS_VOLUME) != 0);
-#  endif
   /* Evaluate background shader. */
   float3 L = make_float3(0.0f, 0.0f, 0.0f);
   if (!shader_constant_emission_eval(kg, shader, &L)) {
@@ -360,7 +364,7 @@ ccl_device_noinline_cpu float3 indirect_background(KernelGlobals *kg,
      * direction, and compute weight with respect to BSDF pdf */
     float pdf = background_light_pdf(kg, P_pick, ray->D);
     int background_index = kernel_data.integrator.background_light_index;
-    pdf *= light_distribution_pdf(kg, P_pick, N_pick, ~background_index, -1, has_volume);
+    pdf *= light_distribution_pdf(kg, P_pick, N_pick, -1.0f, ~background_index, -1);
     float mis_weight = power_heuristic(state->ray_pdf, pdf);
 
     return L * mis_weight;
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index b05bdde8d43..41afe50b41a 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -44,8 +44,16 @@ typedef struct LightSample {
  * importance calculations or to flip the normal if we know it must refract. */
 ccl_device void kernel_update_light_picking(KernelGlobals *kg,
                                             ShaderData *sd,
-                                            ccl_addr_space PathState *state)
+                                            ccl_addr_space PathState *state,
+                                            Ray *ray)
 {
+  if (ray) {
+    sd->P_pick = ray->P + ray->D * ray->t;
+    sd->N_pick = -ray->D;
+    sd->t_pick = ray->t;
+    return;
+  }
+  sd->t_pick = -1.0f;
   bool transmission = false;
   bool reflective = false;
   bool glass = false;
@@ -1172,44 +1180,21 @@ ccl_device_inline bool light_select_reached_max_bounces(KernelGlobals *kg, int i
   return (bounce > kernel_tex_fetch(__lights, index).max_bounces);
 }
 
-/* calculates the importance metric for the given node and shading point P */
-ccl_device float calc_importance(KernelGlobals *kg,
-                                 float3 P,
-                                 float3 N,
-                                 float3 bboxMax,
-                                 float3 bboxMin,
-                                 float theta_o,
-                                 float theta_e,
-                                 float3 axis,
-                                 float energy,
-                                 float3 centroid)
+ccl_device float calc_bbox_solid_angle(float3 P,
+                                       float3 centroid_to_P_dir,
+                                       float3 bboxMin,
+                                       float3 bboxMax)
 {
-  /* eq. 3 */
-
-  const float3 centroid_to_P = P - centroid;
-  const float3 centroid_to_P_dir = normalize(centroid_to_P);
-  const float r2 = len_squared(bboxMax - centroid);
-  float d2 = len_squared(centroid_to_P);
-
-  /* based on comment in the implementation details of the paper */
-  const bool splitting = kernel_data.integrator.splitting_threshold != 0.0f;
-  if (!splitting) {
-    d2 = fmaxf(d2, r2 * 0.25f);
-  }
-
-  /* "theta_u captures the solid angle of the entire box" */
-
-  float theta_u;
   if (P.x < bboxMax.x && P.y < bboxMax.y && P.z < bboxMax.z && P.x > bboxMin.x &&
       P.y > bboxMin.y && P.z > bboxMin.z) {
     /* P is inside bounding box */
-    theta_u = M_PI_F;
+    return M_PI_F;
   }
   else {
     /* Find the smallest cone that contains the bounding box by checking which bbox vertex is
      * farthest out. If we use a bounding sphere we get a too big cone. For example consider a long
      * skinny bbox oriented with P next to one of the small sides. */
-    theta_u = 0;
+    float theta_u = 0;
     float3 corners[8];
     corners[0] = bboxMin;
     corners[1] = make_float3(bboxMin.x, bboxMin.y, bboxMax.z);
@@ -1224,32 +1209,106 @@ ccl_device float calc_importance(KernelGlobals *kg,
       const float cos_theta_u = dot(-centroid_to_P_dir, P_to_corner);
       theta_u = fmaxf(fast_acosf(cos_theta_u), theta_u);
     }
+    return theta_u;
   }
+}
 
-  /* cos(theta') */
-  float cos_theta = dot(axis, centroid_to_P_dir);
-  const float theta = fast_acosf(cos_theta);
-  const float theta_prime = fmaxf(theta - theta_o - theta_u, 0.0f);
-  if (theta_prime >= theta_e) {
-    return 0.0f;
-  }
-  const float cos_theta_prime = fast_cosf(theta_prime);
-
-  /* f_a|cos(theta'_i)| -- diffuse approximation */
-  if (N != make_float3(0.0f, 0.0f, 0.0f)) {
-    const float cos_theta_i = dot(N, -centroid_to_P_dir);
-    const float theta_i = fast_acosf(cos_theta_i);
-    const float theta_i_prime = fmaxf(theta_i - theta_u, 0.0f);
-    const float cos_theta_i_prime = fast_cosf(theta_i_prime);
-    const float abs_cos_theta_i_prime = fabsf(cos_theta_i_prime);
-    /* doing something similar to bsdf_diffuse_eval_reflect() */
-    /* TODO: Use theta_i or theta_i_prime here? */
-    const float f_a = fmaxf(cos_theta_i_prime, 0.0f) * M_1_PI_F;
-
-    return f_a * abs_cos_theta_i_prime * energy * cos_theta_prime / d2;
+/* calculates the importance metric for the given node and shading point P */
+ccl_device float calc_importance(KernelGlobals *kg,
+                                 float t_max,
+                                 float3 P,
+                                 float3 N,
+                                 float3 bboxMax,
+                                 float3 bboxMin,
+                                 float theta_o,
+                                 float theta_e,
+                                 float3 axis,
+                                 float energy,
+                                 float3 centroid)
+{
+  if (t_max < 0.0f) {
+    /* eq. 3 */
+
+    const float3 centroid_to_P = P - centroid;
+    const float3 centroid_to_P_dir = normalize(centroid_to_P);
+    const float r2 = len_squared(bboxMax - centroid);
+    float d2 = len_squared(centroid_to_P);
+
+    /* based on comment in the implementation details of the paper */
+    const bool splitting = kernel_data.integrator.splitting_threshold != 0.0f;
+    if (!splitting) {
+      d2 = fmaxf(d2, r2 * 0.25f);
+    }
+
+    /* "theta_u captures the solid angle of the entire box" */
+
+    float theta_u = calc_bbox_solid_angle(P, centroid_to_P_dir, bboxMin, bboxMax);
+
+    /* cos(theta') */
+    float cos_theta = dot(axis, centroid_to_P_dir);
+    const float theta = fast_acosf(cos_theta);
+    const float theta_prime = fmaxf(theta - theta_o - theta_u, 0.0f);
+    if (theta_prime >= theta_e) {
+      return 0.0f;
+    }
+    const float cos_theta_prime = fast_cosf(theta_prime);
+
+    /* f_a|cos(theta'_i)| -- diffuse approximation */
+    if (N != make_float3(0.0f, 0.0f, 0.0f))

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list