diff options
author | Brecht Van Lommel <brecht@blender.org> | 2021-11-19 19:35:08 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2021-11-19 19:42:22 +0300 |
commit | 1b686c60b5a7f7f7604d7ba5012aa5afa15f0d07 (patch) | |
tree | 6f340596fdc6936063c02f3dcb1a48312fd20649 /intern/cycles/kernel | |
parent | 0f1a200a67e8fb309872bbd5d6f7890efdd88086 (diff) |
Fix T93046: Cycles world volume rendering very slow in OptiX with some scenes
With very long ray distance, OptiX ends up traversing many BVH nodes due to
a feature that improves precision. However this causes very slow rendering.
We now avoid generating such long rays by rejecting the few samples that have
long ray distances and very low probability of being generated. This should not
meaningfully affect render results.
Thanks to Sergey and Patrick for the investigation.
Diffstat (limited to 'intern/cycles/kernel')
-rw-r--r-- | intern/cycles/kernel/integrator/shade_volume.h | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/intern/cycles/kernel/integrator/shade_volume.h b/intern/cycles/kernel/integrator/shade_volume.h index f42614cc87f..3a2bf04d533 100644 --- a/intern/cycles/kernel/integrator/shade_volume.h +++ b/intern/cycles/kernel/integrator/shade_volume.h @@ -263,6 +263,12 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg, /* Equi-angular sampling as in: * "Importance Sampling Techniques for Path Tracing in Participating Media" */ +/* Below this pdf we ignore samples, as they tend to lead to very long distances. + * This can cause performance issues with BVH traversal in OptiX, leading it to + * traverse many nodes. Since these contribute very little to the image, just ignore + * those samples. */ +# define VOLUME_SAMPLE_PDF_CUTOFF 1e-8f + ccl_device float volume_equiangular_sample(ccl_private const Ray *ccl_restrict ray, const float3 light_P, const float xi, @@ -437,7 +443,8 @@ ccl_device_forceinline void volume_integrate_step_scattering( /* 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) { + if (result.direct_t >= vstate.start_t && result.direct_t <= vstate.end_t && + vstate.equiangular_pdf > VOLUME_SAMPLE_PDF_CUTOFF) { const float new_dt = result.direct_t - vstate.start_t; const float3 new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt); @@ -474,26 +481,28 @@ ccl_device_forceinline void volume_integrate_step_scattering( const float3 new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt); const float distance_pdf = dot(channel_pdf, coeff.sigma_t * new_transmittance); - /* throughput */ - result.indirect_scatter = true; - result.indirect_t = new_t; - result.indirect_throughput *= coeff.sigma_s * new_transmittance / distance_pdf; - shader_copy_volume_phases(&result.indirect_phases, sd); - - if (vstate.direct_sample_method != VOLUME_SAMPLE_EQUIANGULAR) { - /* If using distance sampling for direct light, just copy parameters - * of indirect light since we scatter at the same point then. */ - result.direct_scatter = true; - 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; + if (vstate.distance_pdf * distance_pdf > VOLUME_SAMPLE_PDF_CUTOFF) { + /* throughput */ + result.indirect_scatter = true; + result.indirect_t = new_t; + result.indirect_throughput *= coeff.sigma_s * new_transmittance / distance_pdf; + shader_copy_volume_phases(&result.indirect_phases, sd); + + if (vstate.direct_sample_method != VOLUME_SAMPLE_EQUIANGULAR) { + /* If using distance sampling for direct light, just copy parameters + * of indirect light since we scatter at the same point then. */ + result.direct_scatter = true; + 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; + } } } } |