Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/bvh/bvh_embree.cpp
| Show First 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args) | ||||
| CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt; | CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt; | ||||
| const KernelGlobalsCPU *kg = ctx->kg; | const KernelGlobalsCPU *kg = ctx->kg; | ||||
| switch (ctx->type) { | switch (ctx->type) { | ||||
| case CCLIntersectContext::RAY_SHADOW_ALL: { | case CCLIntersectContext::RAY_SHADOW_ALL: { | ||||
| Intersection current_isect; | Intersection current_isect; | ||||
| kernel_embree_convert_hit(kg, ray, hit, ¤t_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); | 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; | ctx->opaque_hit = true; | ||||
| return; | 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. */ | /* 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 | /* If maximum number of hits was reached, replace the intersection with the | ||||
| * highest distance. We want to find the N closest intersections. */ | * highest distance. We want to find the N closest intersections. */ | ||||
| const int num_recorded_hits = min(ctx->num_hits, ctx->max_hits); | const uint num_recorded_hits = min(ctx->num_recorded_hits, max_record_hits); | ||||
| int isect_index = num_recorded_hits; | uint isect_index = num_recorded_hits; | ||||
| if (num_recorded_hits + 1 >= ctx->max_hits) { | if (num_recorded_hits + 1 >= max_record_hits) { | ||||
| float max_t = ctx->isect_s[0].t; | 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) { | if (ctx->isect_s[i].t > max_t) { | ||||
| max_recorded_hit = i; | max_recorded_hit = i; | ||||
| max_t = ctx->isect_s[i].t; | 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; | isect_index = max_recorded_hit; | ||||
| } | } | ||||
| /* Limit the ray distance and stop counting hits beyond this. | /* Limit the ray distance and stop counting hits beyond this. | ||||
| * TODO: is there some way we can tell Embree to stop intersecting beyond | * TODO: is there some way we can tell Embree to stop intersecting beyond | ||||
| * this distance when max number of hits is reached?. Or maybe it will | * this distance when max number of hits is reached?. Or maybe it will | ||||
| * become irrelevant if we make max_hits a very high number on the CPU. */ | * become irrelevant if we make max_hits a very high number on the CPU. */ | ||||
| ctx->max_t = max(current_isect.t, max_t); | ctx->max_t = max(current_isect.t, max_t); | ||||
| } | } | ||||
| ctx->isect_s[isect_index] = current_isect; | ctx->isect_s[isect_index] = current_isect; | ||||
| } | } | ||||
| /* Always increase the number of hits, even beyond ray.max_hits so that | /* Always increase the number of recorded hits, even beyond the maximum, | ||||
| * the caller can detect this as and consider it opaque, or trace another | * so that we can detect this and trace another ray if needed. */ | ||||
| * ray. */ | ++ctx->num_recorded_hits; | ||||
| ++ctx->num_hits; | |||||
| /* This tells Embree to continue tracing. */ | /* This tells Embree to continue tracing. */ | ||||
| *args->valid = 0; | *args->valid = 0; | ||||
| break; | break; | ||||
| } | } | ||||
| case CCLIntersectContext::RAY_LOCAL: | case CCLIntersectContext::RAY_LOCAL: | ||||
| case CCLIntersectContext::RAY_SSS: { | case CCLIntersectContext::RAY_SSS: { | ||||
| /* Check if it's hitting the correct object. */ | /* Check if it's hitting the correct object. */ | ||||
| Show All 22 Lines | case CCLIntersectContext::RAY_SSS: { | ||||
| break; | break; | ||||
| } | } | ||||
| LocalIntersection *local_isect = ctx->local_isect; | LocalIntersection *local_isect = ctx->local_isect; | ||||
| int hit_idx = 0; | int hit_idx = 0; | ||||
| if (ctx->lcg_state) { | if (ctx->lcg_state) { | ||||
| /* See triangle_intersect_subsurface() for the native equivalent. */ | /* 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) { | if (local_isect->hits[i].t == ray->tfar) { | ||||
| /* This tells Embree to continue tracing. */ | /* This tells Embree to continue tracing. */ | ||||
| *args->valid = 0; | *args->valid = 0; | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| local_isect->num_hits++; | local_isect->num_hits++; | ||||
| ▲ Show 20 Lines • Show All 540 Lines • Show Last 20 Lines | |||||