diff options
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/kernel/kernel_volume.h | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index 0f45b0e7d60..dd7b0d9812d 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -245,11 +245,18 @@ ccl_device float kernel_volume_equiangular_sample(Ray *ray, float3 light_P, floa float t = ray->t; float delta = dot((light_P - ray->P) , ray->D); - float D = sqrtf(len_squared(light_P - ray->P) - delta * delta); + float D = safe_sqrtf(len_squared(light_P - ray->P) - delta * delta); + if(UNLIKELY(D == 0.0f)) { + *pdf = 0.0f; + return 0.0f; + } float theta_a = -atan2f(delta, D); float theta_b = atan2f(t - delta, D); float t_ = D * tanf((xi * theta_b) + (1 - xi) * theta_a); - + if(UNLIKELY(theta_b == theta_a)) { + *pdf = 0.0f; + return 0.0f; + } *pdf = D / ((theta_b - theta_a) * (D * D + t_ * t_)); return min(t, delta + t_); /* min is only for float precision errors */ @@ -258,13 +265,19 @@ ccl_device float kernel_volume_equiangular_sample(Ray *ray, float3 light_P, floa ccl_device float kernel_volume_equiangular_pdf(Ray *ray, float3 light_P, float sample_t) { float delta = dot((light_P - ray->P) , ray->D); - float D = sqrtf(len_squared(light_P - ray->P) - delta * delta); + float D = safe_sqrtf(len_squared(light_P - ray->P) - delta * delta); + if(UNLIKELY(D == 0.0f)) { + return 0.0f; + } float t = ray->t; float t_ = sample_t - delta; float theta_a = -atan2f(delta, D); float theta_b = atan2f(t - delta, D); + if(UNLIKELY(theta_b == theta_a)) { + return 0.0f; + } float pdf = D / ((theta_b - theta_a) * (D * D + t_ * t_)); @@ -958,6 +971,9 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter( mis_weight = 2.0f*power_heuristic(pdf, distance_pdf); } } + if(sample_t < 1e-6f) { + return VOLUME_PATH_SCATTERED; + } /* compute transmittance up to this step */ if(step != segment->steps) |