diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2016-11-24 18:37:27 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2016-11-24 18:39:02 +0300 |
commit | 729affe7c99a3fef892ec0810fc89dbead10db8e (patch) | |
tree | f00a3efcc7e45852215ed6f524da7e9d793bb4c0 | |
parent | 4d3d2d02993488dda03094ecc580fe26ebec4f39 (diff) |
Cycles: Avoid divisions by zero in volume sampling code
Was giving huge artifacts in the barber shop file here in the studio,
Maybe not fully optimal solution, but committing it for now to have
closer look later.
-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) |