Cycles volume: change homogeneous volume sampling in branched path first hit.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Sat, 29 Mar 2014 12:03:49 +0000 (13:03 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Sat, 29 Mar 2014 12:03:49 +0000 (13:03 +0100)
Similar to surfaces, this will now always scatter rather than probabilistically
scattering or not depending on the transmittance.

This also makes calculation of branched path throughput non-probalistic, which
makes thing slower too. That's to be solved by decoupled ray marching later.

intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_volume.h

index a4a7a2db6f5674314269699b446ebdf8e5551507..e6b3dd7521bee131068aa2ddc42afa891b553b97 100644 (file)
@@ -261,7 +261,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, ccl_g
 
                        ShaderData volume_sd;
                        VolumeIntegrateResult result = kernel_volume_integrate(kg, &state,
-                               &volume_sd, &volume_ray, L, &throughput, rng);
+                               &volume_sd, &volume_ray, L, &throughput, rng, false);
 
                        if(result == VOLUME_PATH_SCATTERED) {
                                if(kernel_path_integrate_scatter_lighting(kg, rng, &volume_sd, &throughput, &state, L, &ray, 1.0f))
@@ -650,7 +650,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
 
                        ShaderData volume_sd;
                        VolumeIntegrateResult result = kernel_volume_integrate(kg, &state,
-                               &volume_sd, &volume_ray, &L, &throughput, rng);
+                               &volume_sd, &volume_ray, &L, &throughput, rng, false);
 
                        if(result == VOLUME_PATH_SCATTERED) {
                                if(kernel_path_integrate_scatter_lighting(kg, rng, &volume_sd, &throughput, &state, &L, &ray, 1.0f))
@@ -1092,7 +1092,6 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
 
                        int num_samples = kernel_data.integrator.volume_samples;
                        float num_samples_inv = 1.0f/num_samples;
-                       float3 avg_tp = make_float3(0.0f, 0.0f, 0.0f);
 
                        /* todo: we should cache the shader evaluations from stepping
                         * through the volume, for now we redo them multiple times */
@@ -1107,7 +1106,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
                                path_state_branch(&ps, j, num_samples);
 
                                VolumeIntegrateResult result = kernel_volume_integrate(kg, &ps,
-                                       &volume_sd, &volume_ray, &L, &tp, rng);
+                                       &volume_sd, &volume_ray, &L, &tp, rng, true);
                                
                                if(result == VOLUME_PATH_SCATTERED) {
                                        /* todo: use all-light sampling */
@@ -1120,11 +1119,10 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
                                                path_radiance_reset_indirect(&L);
                                        }
                                }
-                               else
-                                       avg_tp += tp;
                        }
 
-                       throughput = avg_tp * num_samples_inv;
+                       /* todo: avoid this calculation using decoupled ray marching */
+                       kernel_volume_shadow(kg, &state, &volume_ray, &throughput);
                }
 #endif
 
index f2a02e172937d172f51321eebbfddb8268a52de8..451d28bfb5225d2d3684b7f4bf31d307ae031ad4 100644 (file)
@@ -295,7 +295,7 @@ ccl_device float3 kernel_volume_emission_integrate(VolumeShaderCoefficients *coe
  * the volume shading coefficient for the entire line segment */
 ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGlobals *kg,
        PathState *state, Ray *ray, ShaderData *sd, PathRadiance *L, float3 *throughput,
-       RNG *rng)
+       RNG *rng, bool branched)
 {
        VolumeShaderCoefficients coeff;
 
@@ -318,19 +318,14 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
                int channel = (int)(rphase*3.0f);
                sd->randb_closure = rphase*3.0f - channel;
 
-               /* decide if we will hit or miss */
                float xi = path_state_rng_1D(kg, rng, state, PRNG_SCATTER_DISTANCE);
-               float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
-               float sample_transmittance = expf(-sample_sigma_t * t);
 
-               if(xi >= sample_transmittance) {
-                       /* scattering */
+               if(branched) {
+                       /* branched path tracing: we always scatter in the segment */
                        float3 pdf;
                        float sample_t;
 
-                       /* rescale random number so we can reuse it */
-                       xi = (xi - sample_transmittance)/(1.0f - sample_transmittance);
-
+                       /* scattering */
                        if(kernel_data.integrator.volume_homogeneous_sampling == 0 || !kernel_data.integrator.num_all_lights) { 
                                /* distance sampling */
                                sample_t = kernel_volume_distance_sample(ray, sigma_t, channel, xi, &transmittance, &pdf);
@@ -346,17 +341,52 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
                                pdf = make_float3(equi_pdf, equi_pdf, equi_pdf);
                        }
 
-                       /* modifiy pdf for hit/miss decision */
-                       pdf *= make_float3(1.0f, 1.0f, 1.0f) - volume_color_transmittance(sigma_t, t);
-
                        new_tp = *throughput * coeff.sigma_s * transmittance / ((pdf.x + pdf.y + pdf.z) * (1.0f/3.0f));
                        t = sample_t;
                }
                else {
-                       /* no scattering */
-                       transmittance = volume_color_transmittance(sigma_t, t);
-                       float pdf = (transmittance.x + transmittance.y + transmittance.z) * (1.0f/3.0f);
-                       new_tp = *throughput * transmittance / pdf;
+                       /* regular path tracing: we probalistically scatter in the segment
+                        * with probability the transmittance over the segment */
+
+                       /* decide if we will hit or miss */
+                       float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
+                       float sample_transmittance = expf(-sample_sigma_t * t);
+
+                       if(xi >= sample_transmittance) {
+                               /* scattering */
+                               float3 pdf;
+                               float sample_t;
+
+                               /* rescale random number so we can reuse it */
+                               xi = (xi - sample_transmittance)/(1.0f - sample_transmittance);
+
+                               if(kernel_data.integrator.volume_homogeneous_sampling == 0 || !kernel_data.integrator.num_all_lights) { 
+                                       /* distance sampling */
+                                       sample_t = kernel_volume_distance_sample(ray, sigma_t, channel, xi, &transmittance, &pdf);
+                               }
+                               else {
+                                       /* equiangular sampling */
+                                       float3 light_P;
+                                       float equi_pdf;
+                                       if(!kernel_volume_equiangular_light_position(kg, state, ray, rng, &light_P))
+                                               return VOLUME_PATH_MISSED;
+
+                                       sample_t = kernel_volume_equiangular_sample(ray, sigma_t, light_P, xi, &transmittance, &equi_pdf);
+                                       pdf = make_float3(equi_pdf, equi_pdf, equi_pdf);
+                               }
+
+                               /* modifiy pdf for hit/miss decision */
+                               pdf *= make_float3(1.0f, 1.0f, 1.0f) - volume_color_transmittance(sigma_t, t);
+
+                               new_tp = *throughput * coeff.sigma_s * transmittance / ((pdf.x + pdf.y + pdf.z) * (1.0f/3.0f));
+                               t = sample_t;
+                       }
+                       else {
+                               /* no scattering */
+                               transmittance = volume_color_transmittance(sigma_t, t);
+                               float pdf = (transmittance.x + transmittance.y + transmittance.z) * (1.0f/3.0f);
+                               new_tp = *throughput * transmittance / pdf;
+                       }
                }
        }
        else if(closure_flag & SD_ABSORPTION) {
@@ -547,7 +577,8 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous(KernelGlo
  * ray, with the assumption that there are no surfaces blocking light
  * between the endpoints */
 ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(KernelGlobals *kg,
-       PathState *state, ShaderData *sd, Ray *ray, PathRadiance *L, float3 *throughput, RNG *rng)
+       PathState *state, ShaderData *sd, Ray *ray, PathRadiance *L, float3 *throughput, RNG *rng,
+       bool branched)
 {
        /* workaround to fix correlation bug in T38710, can find better solution
         * in random number generator later, for now this is done here to not impact
@@ -560,7 +591,7 @@ ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(KernelGlobals
        if(heterogeneous)
                return kernel_volume_integrate_heterogeneous(kg, state, ray, sd, L, throughput, &tmp_rng);
        else
-               return kernel_volume_integrate_homogeneous(kg, state, ray, sd, L, throughput, &tmp_rng);
+               return kernel_volume_integrate_homogeneous(kg, state, ray, sd, L, throughput, &tmp_rng, branched);
 }
 
 /* Volume Stack