[Bf-blender-cvs] [673ec13ffc5] soc-2022-many-lights-sampling: Add volume support

Weizhen Huang noreply at git.blender.org
Wed Nov 9 13:16:51 CET 2022


Commit: 673ec13ffc5691543839f1f1a6950324459f3694
Author: Weizhen Huang
Date:   Tue Nov 8 17:09:03 2022 +0100
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rB673ec13ffc5691543839f1f1a6950324459f3694

Add volume support

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

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

M	intern/cycles/kernel/integrator/shade_volume.h
M	intern/cycles/kernel/light/sample.h
M	intern/cycles/kernel/light/tree.h

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

diff --git a/intern/cycles/kernel/integrator/shade_volume.h b/intern/cycles/kernel/integrator/shade_volume.h
index daaf480e8c1..5b5abe05720 100644
--- a/intern/cycles/kernel/integrator/shade_volume.h
+++ b/intern/cycles/kernel/integrator/shade_volume.h
@@ -697,7 +697,7 @@ ccl_device_forceinline bool integrate_volume_sample_light(
   /* Sample position on a light. */
   const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
   const uint bounce = INTEGRATOR_STATE(state, path, bounce);
-  const float2 rand_light = path_state_rng_2D(kg, rng_state, PRNG_VOLUME_SEGMENT_LIGHT);
+  float2 rand_light = path_state_rng_2D(kg, rng_state, PRNG_VOLUME_SEGMENT_LIGHT);
 
   if (!light_sample_from_volume_segment(kg,
                                         rng_state,
@@ -740,7 +740,7 @@ ccl_device_forceinline void integrate_volume_direct_light(
 
   /* Sample position on the same light again, now from the shading point where we scattered.
    *
-   * Note that this means we sample the light three twice when equiangular sampling is used.
+   * Note that this means we sample the light tree twice when equiangular sampling is used.
    * We could consider sampling the light tree just once and use the same light position again.
    *
    * This would make the PDFs for MIS weights more complicated due to having to account for
diff --git a/intern/cycles/kernel/light/sample.h b/intern/cycles/kernel/light/sample.h
index 366deafb4d7..a9bb9bdbc44 100644
--- a/intern/cycles/kernel/light/sample.h
+++ b/intern/cycles/kernel/light/sample.h
@@ -322,7 +322,7 @@ ccl_device_inline float light_sample_mis_weight_nee(KernelGlobals kg,
 
 ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
                                                         ccl_private const RNGState *rng_state,
-                                                        const float randu,
+                                                        float randu,
                                                         const float randv,
                                                         const float time,
                                                         const float3 P,
@@ -332,29 +332,23 @@ ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
                                                         const uint32_t path_flag,
                                                         ccl_private LightSample *ls)
 {
-  /* TODO: implement light tree support. */
-#if 0
   if (kernel_data.integrator.use_light_tree) {
-    return light_tree_sample<true>(
-        kg,
-        rng_state,
-        randu,
-        randv,
-        time,
-        P,
-        D,
-        t,
-        SD_BSDF_HAS_TRANSMISSION,
-        bounce,
-        path_flag,
-        ls);
+    return light_tree_sample<true>(kg,
+                                   rng_state,
+                                   randu,
+                                   randv,
+                                   time,
+                                   P,
+                                   D,
+                                   t,
+                                   SD_BSDF_HAS_TRANSMISSION,
+                                   bounce,
+                                   path_flag,
+                                   ls);
   }
   else {
-#endif
-  return light_distribution_sample<true>(kg, randu, randv, time, P, bounce, path_flag, ls);
-#if 0
+    return light_distribution_sample<true>(kg, randu, randv, time, P, bounce, path_flag, ls);
   }
-#endif
 }
 
 ccl_device bool light_sample_from_position(KernelGlobals kg,
@@ -371,7 +365,7 @@ ccl_device bool light_sample_from_position(KernelGlobals kg,
 {
   if (kernel_data.integrator.use_light_tree) {
     return light_tree_sample<false>(
-        kg, rng_state, randu, randv, time, P, N, shader_flags, bounce, path_flag, ls);
+        kg, rng_state, randu, randv, time, P, N, 0, shader_flags, bounce, path_flag, ls);
   }
   else {
     return light_distribution_sample<false>(kg, randu, randv, time, P, bounce, path_flag, ls);
diff --git a/intern/cycles/kernel/light/tree.h b/intern/cycles/kernel/light/tree.h
index 4e9a560c10c..6e229a87957 100644
--- a/intern/cycles/kernel/light/tree.h
+++ b/intern/cycles/kernel/light/tree.h
@@ -40,13 +40,16 @@ ccl_device float light_tree_cos_bounding_box_angle(const float3 bbox_min,
 
 /* 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,
+template<bool in_volume_segment>
+ccl_device void light_tree_cluster_importance(const float3 N_or_D,
                                               const bool has_transmission,
                                               const float3 point_to_centroid,
+                                              /* point_to_centroid is unnormalized for volume */
                                               const float cos_theta_u,
                                               const float3 bcone_axis,
-                                              const float inv_max_distance_squared,
-                                              const float inv_min_distance_squared,
+                                              const float max_distance,
+                                              const float min_distance,
+                                              const float t,
                                               const float theta_o,
                                               const float theta_e,
                                               const float energy,
@@ -56,22 +59,48 @@ ccl_device void light_tree_cluster_importance(const float3 N,
   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));
+  float cos_theta, cos_theta_i, sin_theta_i;
+  float cos_min_outgoing_angle;         /* minimum angle an emitter’s axis would form with the
+                                       direction to the shading point, cos(theta') in the paper */
+  float cos_min_incidence_angle = 1.0f; /* cos(theta_i') in the paper, omitted for volume */
   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;
+  if (in_volume_segment) {
+    const float3 D = N_or_D;
+    const float3 v0 = -normalize(point_to_centroid);
+    const float3 v1 = normalize(-point_to_centroid + D * fminf(t, 1e12f));
+
+    const float3 o0 = v0;
+    float3 o1, o2;
+    make_orthonormals_tangent(o0, v1, &o1, &o2);
+
+    const float dot_o0_a = dot(o0, bcone_axis);
+    const float dot_o1_a = dot(o1, bcone_axis);
+    const float cos_phi0 = dot_o0_a / sqrtf(sqr(dot_o0_a) + sqr(dot_o1_a));
+
+    /* Eq. (6) */
+    cos_theta = (dot_o1_a < 0 || dot(v0, v1) > cos_phi0) ?
+                    fmaxf(dot_o0_a, dot(v1, bcone_axis)) : /* b_max */
+                    dot(bcone_axis, cos_phi0 * o0 + safe_sqrtf(1.0f - sqr(cos_phi0)) * o1);
+  }
+  else {
+    const float3 N = N_or_D;
+
+    cos_theta = dot(bcone_axis, -point_to_centroid);
+    cos_theta_i = has_transmission ? fabsf(dot(point_to_centroid, N)) : dot(point_to_centroid, N);
+    sin_theta_i = safe_sqrtf(1.0f - sqr(cos_theta_i));
+
+    /* cos_min_incidence_angle = cos(max{theta_i - theta_u, 0}), also cos(theta_i') in the paper*/
+    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) */
@@ -81,9 +110,6 @@ ccl_device void light_tree_cluster_importance(const float3 N,
   float cos_theta_o, sin_theta_o;
   fast_sincosf(theta_o, &sin_theta_o, &cos_theta_o);
 
-  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);
@@ -98,19 +124,23 @@ ccl_device void light_tree_cluster_importance(const float3 N,
                              sin_theta_minus_theta_u * sin_theta_o;
   }
   else {
+    /* cluster invisible */
     return;
   }
 
   /* 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);
+  /* TODO: also consider t (or theta_a, theta_b) for volume */
+  max_importance = fabsf(f_a * cos_min_incidence_angle * energy * cos_min_outgoing_angle /
+                         (in_volume_segment ? min_distance : sqr(min_distance)));
 
-  if (inv_max_distance_squared == inv_min_distance_squ

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list