[Bf-blender-cvs] [e8f195e44e7] cycles-x: Cycles X: add volume multiple importance between equiangular and distance

Brecht Van Lommel noreply at git.blender.org
Fri Jul 23 19:29:02 CEST 2021


Commit: e8f195e44e7407c35f1e215ba6ba6f19f30fb675
Author: Brecht Van Lommel
Date:   Wed Jul 7 20:25:23 2021 +0200
Branches: cycles-x
https://developer.blender.org/rBe8f195e44e7407c35f1e215ba6ba6f19f30fb675

Cycles X: add volume multiple importance between equiangular and distance

Ref D11845

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

M	intern/cycles/kernel/integrator/integrator_shade_volume.h

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

diff --git a/intern/cycles/kernel/integrator/integrator_shade_volume.h b/intern/cycles/kernel/integrator/integrator_shade_volume.h
index 1482b0b5c4d..ac5907c8074 100644
--- a/intern/cycles/kernel/integrator/integrator_shade_volume.h
+++ b/intern/cycles/kernel/integrator/integrator_shade_volume.h
@@ -395,17 +395,29 @@ typedef struct VolumeIntegrateState {
   float rscatter;
   float rphase;
 
-  /* Sampling. */
+  /* Multiple importance sampling. */
   VolumeSampleMethod direct_sample_method;
+  bool use_mis;
+  float distance_pdf;
+  float equiangular_pdf;
 } VolumeIntegrateState;
 
 ccl_device_forceinline void volume_integrate_step_scattering(
     const ShaderData *sd,
+    const Ray *ray,
+    const float3 equiangular_light_P,
     const VolumeShaderCoefficients &ccl_restrict coeff,
     const float3 transmittance,
     VolumeIntegrateState &ccl_restrict vstate,
     VolumeIntegrateResult &ccl_restrict result)
 {
+  /* Pick random color channel, we use the Veach one-sample
+   * model with balance heuristic for the channels. */
+  const float3 albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t);
+  float3 channel_pdf;
+  const int channel = volume_sample_channel(
+      albedo, result.indirect_throughput, vstate.rphase, &channel_pdf);
+
   /* Equiangular sampling for direct lighting. */
   if (vstate.direct_sample_method == VOLUME_SAMPLE_EQUIANGULAR && !result.direct_scatter) {
     if (result.direct_t >= vstate.start_t && result.direct_t <= vstate.end_t) {
@@ -413,23 +425,25 @@ ccl_device_forceinline void volume_integrate_step_scattering(
       const float3 new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt);
 
       result.direct_scatter = true;
-      result.direct_throughput *= coeff.sigma_s * new_transmittance;
+      result.direct_throughput *= coeff.sigma_s * new_transmittance / vstate.equiangular_pdf;
       shader_copy_volume_phases(&result.direct_phases, sd);
+
+      /* Multiple importance sampling. */
+      if (vstate.use_mis) {
+        const float distance_pdf = vstate.distance_pdf *
+                                   dot(channel_pdf, coeff.sigma_t * new_transmittance);
+        const float mis_weight = 2.0f * power_heuristic(vstate.equiangular_pdf, distance_pdf);
+        result.direct_throughput *= mis_weight;
+      }
     }
     else {
       result.direct_throughput *= transmittance;
+      vstate.distance_pdf *= dot(channel_pdf, transmittance);
     }
   }
 
   /* Distance sampling for indirect and optional direct lighting. */
   if (!result.indirect_scatter) {
-    /* Pick random color channel, we use the Veach one-sample
-     * model with balance heuristic for the channels. */
-    const float3 albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t);
-    float3 channel_pdf;
-    const int channel = volume_sample_channel(
-        albedo, result.indirect_throughput, vstate.rphase, &channel_pdf);
-
     /* decide if we will scatter or continue */
     const float sample_transmittance = volume_channel_get(transmittance, channel);
 
@@ -456,12 +470,23 @@ ccl_device_forceinline void volume_integrate_step_scattering(
         result.direct_t = result.indirect_t;
         result.direct_throughput = result.indirect_throughput;
         shader_copy_volume_phases(&result.direct_phases, sd);
+
+        /* Multiple importance sampling. */
+        if (vstate.use_mis) {
+          const float equiangular_pdf = volume_equiangular_pdf(ray, equiangular_light_P, new_t);
+          const float mis_weight = power_heuristic(vstate.distance_pdf * distance_pdf,
+                                                   equiangular_pdf);
+          result.direct_throughput *= 2.0f * mis_weight;
+        }
       }
     }
     else {
       /* throughput */
       const float pdf = dot(channel_pdf, transmittance);
       result.indirect_throughput *= transmittance / pdf;
+      if (vstate.direct_sample_method != VOLUME_SAMPLE_EQUIANGULAR) {
+        vstate.distance_pdf *= pdf;
+      }
 
       /* remap rscatter so we can reuse it and keep thing stratified */
       vstate.rscatter = 1.0f - (1.0f - vstate.rscatter) / sample_transmittance;
@@ -504,7 +529,22 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
   vstate.absorption_only = true;
   vstate.rscatter = path_state_rng_1D(kg, rng_state, PRNG_SCATTER_DISTANCE);
   vstate.rphase = path_state_rng_1D(kg, rng_state, PRNG_PHASE_CHANNEL);
+
+  /* Multiple importance sampling: pick between equiangular and distance sampling strategy. */
   vstate.direct_sample_method = direct_sample_method;
+  vstate.use_mis = (direct_sample_method == VOLUME_SAMPLE_MIS);
+  if (vstate.use_mis) {
+    if (vstate.rscatter < 0.5f) {
+      vstate.rscatter *= 2.0f;
+      vstate.direct_sample_method = VOLUME_SAMPLE_DISTANCE;
+    }
+    else {
+      vstate.rscatter = (vstate.rscatter - 0.5f) * 2.0f;
+      vstate.direct_sample_method = VOLUME_SAMPLE_EQUIANGULAR;
+    }
+  }
+  vstate.equiangular_pdf = 0.0f;
+  vstate.distance_pdf = 1.0f;
 
   /* Initialize volume integration result. */
   const float3 throughput = INTEGRATOR_STATE(path, throughput);
@@ -513,10 +553,8 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
 
   /* Equiangular sampling: compute distance and PDF in advance. */
   if (vstate.direct_sample_method == VOLUME_SAMPLE_EQUIANGULAR) {
-    float equiangular_pdf;
     result.direct_t = volume_equiangular_sample(
-        ray, equiangular_light_P, vstate.rscatter, &equiangular_pdf);
-    result.direct_throughput /= equiangular_pdf;
+        ray, equiangular_light_P, vstate.rscatter, &vstate.equiangular_pdf);
   }
 
   for (int i = 0; i < max_steps; i++) {
@@ -552,7 +590,8 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
       if (closure_flag & SD_EXTINCTION) {
         if ((closure_flag & SD_SCATTER) || !vstate.absorption_only) {
           /* Scattering and absorption. */
-          volume_integrate_step_scattering(sd, coeff, transmittance, vstate, result);
+          volume_integrate_step_scattering(
+              sd, ray, equiangular_light_P, coeff, transmittance, vstate, result);
         }
         else {
           /* Absorption only. */



More information about the Bf-blender-cvs mailing list