diff options
Diffstat (limited to 'intern/cycles/bvh/bvh_embree.cpp')
-rw-r--r-- | intern/cycles/bvh/bvh_embree.cpp | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/intern/cycles/bvh/bvh_embree.cpp b/intern/cycles/bvh/bvh_embree.cpp index 343d62dedf4..cd19e009bf3 100644 --- a/intern/cycles/bvh/bvh_embree.cpp +++ b/intern/cycles/bvh/bvh_embree.cpp @@ -80,31 +80,49 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args) Intersection current_isect; kernel_embree_convert_hit(kg, ray, hit, ¤t_isect); - /* If no transparent shadows, all light is blocked. */ + /* If no transparent shadows or max number of hits exceeded, all light is blocked. */ const int flags = intersection_get_shader_flags(kg, current_isect.prim, current_isect.type); - if (!(flags & (SD_HAS_TRANSPARENT_SHADOW)) || ctx->max_hits == 0) { + if (!(flags & (SD_HAS_TRANSPARENT_SHADOW)) || ctx->num_hits >= ctx->max_hits) { ctx->opaque_hit = true; return; } + ++ctx->num_hits; + + /* Always use baked shadow transparency for curves. */ + if (current_isect.type & PRIMITIVE_ALL_CURVE) { + ctx->throughput *= intersection_curve_shadow_transparency( + kg, current_isect.object, current_isect.prim, current_isect.u); + + if (ctx->throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) { + ctx->opaque_hit = true; + return; + } + else { + *args->valid = 0; + return; + } + } + /* Test if we need to record this transparent intersection. */ - if (ctx->num_hits < ctx->max_hits || ray->tfar < ctx->max_t) { + const uint max_record_hits = min(ctx->max_hits, INTEGRATOR_SHADOW_ISECT_SIZE); + if (ctx->num_recorded_hits < max_record_hits || ray->tfar < ctx->max_t) { /* If maximum number of hits was reached, replace the intersection with the * highest distance. We want to find the N closest intersections. */ - const int num_recorded_hits = min(ctx->num_hits, ctx->max_hits); - int isect_index = num_recorded_hits; - if (num_recorded_hits + 1 >= ctx->max_hits) { + const uint num_recorded_hits = min(ctx->num_recorded_hits, max_record_hits); + uint isect_index = num_recorded_hits; + if (num_recorded_hits + 1 >= max_record_hits) { float max_t = ctx->isect_s[0].t; - int max_recorded_hit = 0; + uint max_recorded_hit = 0; - for (int i = 1; i < num_recorded_hits; ++i) { + for (uint i = 1; i < num_recorded_hits; ++i) { if (ctx->isect_s[i].t > max_t) { max_recorded_hit = i; max_t = ctx->isect_s[i].t; } } - if (num_recorded_hits >= ctx->max_hits) { + if (num_recorded_hits >= max_record_hits) { isect_index = max_recorded_hit; } @@ -118,10 +136,9 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args) ctx->isect_s[isect_index] = current_isect; } - /* Always increase the number of hits, even beyond ray.max_hits so that - * the caller can detect this as and consider it opaque, or trace another - * ray. */ - ++ctx->num_hits; + /* Always increase the number of recorded hits, even beyond the maximum, + * so that we can detect this and trace another ray if needed. */ + ++ctx->num_recorded_hits; /* This tells Embree to continue tracing. */ *args->valid = 0; @@ -160,7 +177,7 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args) if (ctx->lcg_state) { /* See triangle_intersect_subsurface() for the native equivalent. */ - for (int i = min(ctx->max_hits, local_isect->num_hits) - 1; i >= 0; --i) { + for (int i = min((int)ctx->max_hits, local_isect->num_hits) - 1; i >= 0; --i) { if (local_isect->hits[i].t == ray->tfar) { /* This tells Embree to continue tracing. */ *args->valid = 0; |