diff options
Diffstat (limited to 'intern/cycles/kernel/bvh/shadow_all.h')
-rw-r--r-- | intern/cycles/kernel/bvh/shadow_all.h | 73 |
1 files changed, 39 insertions, 34 deletions
diff --git a/intern/cycles/kernel/bvh/shadow_all.h b/intern/cycles/kernel/bvh/shadow_all.h index a5769e91a28..2f58929c1e5 100644 --- a/intern/cycles/kernel/bvh/shadow_all.h +++ b/intern/cycles/kernel/bvh/shadow_all.h @@ -29,8 +29,8 @@ ccl_device_inline IntegratorShadowState state, const uint visibility, const uint max_hits, - ccl_private uint *num_recorded_hits, - ccl_private float *throughput) + ccl_private uint *r_num_recorded_hits, + ccl_private float *r_throughput) { /* todo: * - likely and unlikely for if() statements @@ -60,15 +60,18 @@ ccl_device_inline * recorded hits is exceeded and we no longer need to find hits beyond the max * distance found. */ float t_max_world = ray->t; - /* Equal to t_max_world when traversing top level BVH, transformed into local - * space when entering instances. */ - float t_max_current = t_max_world; + + /* Current maximum distance to the intersection. + * Is calculated as a ray length, transformed to an object space when entering + * instance node. */ + float t_max_current = ray->t; + /* Conversion from world to local space for the current instance if any, 1.0 * otherwise. */ float t_world_to_instance = 1.0f; - *num_recorded_hits = 0; - *throughput = 1.0f; + *r_num_recorded_hits = 0; + *r_throughput = 1.0f; /* traversal loop */ do { @@ -237,10 +240,10 @@ ccl_device_inline /* Always use baked shadow transparency for curves. */ if (isect.type & PRIMITIVE_CURVE) { - *throughput *= intersection_curve_shadow_transparency( + *r_throughput *= intersection_curve_shadow_transparency( kg, isect.object, isect.prim, isect.u); - if (*throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) { + if (*r_throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) { return true; } else { @@ -249,37 +252,39 @@ ccl_device_inline } if (record_intersection) { - /* Increase the number of hits, possibly beyond max_hits, we will - * simply not record those and only keep the max_hits closest. */ - uint record_index = (*num_recorded_hits)++; - + /* Test if we need to record this transparent intersection. */ const uint max_record_hits = min(max_hits, INTEGRATOR_SHADOW_ISECT_SIZE); - if (record_index >= max_record_hits - 1) { - /* If maximum number of hits reached, find the intersection with - * the largest distance to potentially replace when another hit - * is found. */ - const int num_recorded_hits = min(max_record_hits, record_index); - float max_recorded_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t); - int max_recorded_hit = 0; - - for (int i = 1; i < num_recorded_hits; i++) { - const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t); - if (isect_t > max_recorded_t) { - max_recorded_t = isect_t; - max_recorded_hit = i; + if (*r_num_recorded_hits < max_record_hits || isect.t < t_max_world) { + /* If maximum number of hits was reached, replace the intersection with the + * highest distance. We want to find the N closest intersections. */ + const uint num_recorded_hits = min(*r_num_recorded_hits, max_record_hits); + uint isect_index = num_recorded_hits; + if (num_recorded_hits + 1 >= max_record_hits) { + float max_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t); + uint max_recorded_hit = 0; + + for (uint i = 1; i < num_recorded_hits; ++i) { + const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t); + if (isect_t > max_t) { + max_recorded_hit = i; + max_t = isect_t; + } + } + + if (num_recorded_hits >= max_record_hits) { + isect_index = max_recorded_hit; } - } - if (record_index >= max_record_hits) { - record_index = max_recorded_hit; + /* Limit the ray distance and stop counting hits beyond this. */ + t_max_world = max(isect.t, max_t); } - /* Limit the ray distance and stop counting hits beyond this. */ - t_max_world = max(max_recorded_t, isect.t); - t_max_current = t_max_world * t_world_to_instance; + integrator_state_write_shadow_isect(state, &isect, isect_index); } - integrator_state_write_shadow_isect(state, &isect, record_index); + /* Always increase the number of recorded hits, even beyond the maximum, + * so that we can detect this and trace another ray if needed. */ + ++(*r_num_recorded_hits); } } } @@ -318,7 +323,7 @@ ccl_device_inline #endif /* Restore world space ray length. */ - t_max_current = t_max_world; + t_max_current = ray->t; object = OBJECT_NONE; t_world_to_instance = 1.0f; |