Cycles: Fix two numerical issues in the volume code
authorLukas Stockner <lukas.stockner@freenet.de>
Wed, 8 Jun 2016 01:17:19 +0000 (03:17 +0200)
committerLukas Stockner <lukas.stockner@freenet.de>
Wed, 8 Jun 2016 01:17:19 +0000 (03:17 +0200)
This hopefully fixes T48383 by avoiding two numerical problems that I found in the volume code.

Reviewers: sergey, dingto, brecht

Reviewed By: sergey, dingto, brecht

Maniphest Tasks: T48383

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

intern/cycles/kernel/kernel_volume.h

index 0e313b8e88c61bf3fae41ef89a498af744f7c321..bf8301fe5fb6df50f4e17f1f0bf223cae644ae98 100644 (file)
@@ -276,7 +276,7 @@ ccl_device float kernel_volume_distance_sample(float max_t, float3 sigma_t, int
        float sample_t = min(max_t, -logf(1.0f - xi*(1.0f - sample_transmittance))/sample_sigma_t);
 
        *transmittance = volume_color_transmittance(sigma_t, sample_t);
-       *pdf = (sigma_t * *transmittance)/(make_float3(1.0f, 1.0f, 1.0f) - full_transmittance);
+       *pdf = safe_divide_color(sigma_t * *transmittance, make_float3(1.0f, 1.0f, 1.0f) - full_transmittance);
 
        /* todo: optimization: when taken together with hit/miss decision,
         * the full_transmittance cancels out drops out and xi does not
@@ -290,7 +290,7 @@ ccl_device float3 kernel_volume_distance_pdf(float max_t, float3 sigma_t, float
        float3 full_transmittance = volume_color_transmittance(sigma_t, max_t);
        float3 transmittance = volume_color_transmittance(sigma_t, sample_t);
 
-       return (sigma_t * transmittance)/(make_float3(1.0f, 1.0f, 1.0f) - full_transmittance);
+       return safe_divide_color(sigma_t * transmittance, make_float3(1.0f, 1.0f, 1.0f) - full_transmittance);
 }
 
 /* Emission */
@@ -625,11 +625,13 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta
                const int global_max_steps = kernel_data.integrator.volume_max_steps;
                step_size = kernel_data.integrator.volume_step_size;
                /* compute exact steps in advance for malloc */
-               max_steps = max((int)ceilf(ray->t/step_size), 1);
-               if(max_steps > global_max_steps) {
+               if(ray->t > global_max_steps*step_size) {
                        max_steps = global_max_steps;
                        step_size = ray->t / (float)max_steps;
                }
+               else {
+                       max_steps = max((int)ceilf(ray->t/step_size), 1);
+               }
 #ifdef __KERNEL_CPU__
                /* NOTE: For the branched path tracing it's possible to have direct
                 * and indirect light integration both having volume segments allocated.