Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/bvh/bvh_shadow_all.h
| Show All 35 Lines | |||||
| #else | #else | ||||
| ccl_device_inline | ccl_device_inline | ||||
| #endif | #endif | ||||
| bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals kg, | bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals kg, | ||||
| ccl_private const Ray *ray, | ccl_private const Ray *ray, | ||||
| IntegratorShadowState state, | IntegratorShadowState state, | ||||
| const uint visibility, | const uint visibility, | ||||
| const uint max_hits, | const uint max_hits, | ||||
| ccl_private uint *num_hits) | ccl_private uint *num_recorded_hits, | ||||
| ccl_private float *throughput) | |||||
| { | { | ||||
| /* todo: | /* todo: | ||||
| * - likely and unlikely for if() statements | * - likely and unlikely for if() statements | ||||
| * - test restrict attribute for pointers | * - test restrict attribute for pointers | ||||
| */ | */ | ||||
| /* traversal stack in CUDA thread-local memory */ | /* traversal stack in CUDA thread-local memory */ | ||||
| int traversal_stack[BVH_STACK_SIZE]; | int traversal_stack[BVH_STACK_SIZE]; | ||||
| traversal_stack[0] = ENTRYPOINT_SENTINEL; | traversal_stack[0] = ENTRYPOINT_SENTINEL; | ||||
| /* traversal variables in registers */ | /* traversal variables in registers */ | ||||
| int stack_ptr = 0; | int stack_ptr = 0; | ||||
| int node_addr = kernel_data.bvh.root; | int node_addr = kernel_data.bvh.root; | ||||
| /* ray parameters in registers */ | /* ray parameters in registers */ | ||||
| float3 P = ray->P; | float3 P = ray->P; | ||||
| float3 dir = bvh_clamp_direction(ray->D); | float3 dir = bvh_clamp_direction(ray->D); | ||||
| float3 idir = bvh_inverse_direction(dir); | float3 idir = bvh_inverse_direction(dir); | ||||
| int object = OBJECT_NONE; | int object = OBJECT_NONE; | ||||
| uint num_hits = 0; | |||||
| #if BVH_FEATURE(BVH_MOTION) | #if BVH_FEATURE(BVH_MOTION) | ||||
| Transform ob_itfm; | Transform ob_itfm; | ||||
| #endif | #endif | ||||
| /* Max distance in world space. May be dynamically reduced when max number of | /* Max distance in world space. May be dynamically reduced when max number of | ||||
| * recorded hits is exceeded and we no longer need to find hits beyond the max | * recorded hits is exceeded and we no longer need to find hits beyond the max | ||||
| * distance found. */ | * distance found. */ | ||||
| float t_max_world = ray->t; | float t_max_world = ray->t; | ||||
| /* Equal to t_max_world when traversing top level BVH, transformed into local | /* Equal to t_max_world when traversing top level BVH, transformed into local | ||||
| * space when entering instances. */ | * space when entering instances. */ | ||||
| float t_max_current = t_max_world; | float t_max_current = t_max_world; | ||||
| /* Conversion from world to local space for the current instance if any, 1.0 | /* Conversion from world to local space for the current instance if any, 1.0 | ||||
| * otherwise. */ | * otherwise. */ | ||||
| float t_world_to_instance = 1.0f; | float t_world_to_instance = 1.0f; | ||||
| *num_hits = 0; | *num_recorded_hits = 0; | ||||
| *throughput = 1.0f; | |||||
| /* traversal loop */ | /* traversal loop */ | ||||
| do { | do { | ||||
| do { | do { | ||||
| /* traverse internal nodes */ | /* traverse internal nodes */ | ||||
| while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) { | while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) { | ||||
| int node_addr_child1, traverse_mask; | int node_addr_child1, traverse_mask; | ||||
| float dist[2]; | float dist[2]; | ||||
| ▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | #endif | ||||
| /* Convert intersection distance to world space. */ | /* Convert intersection distance to world space. */ | ||||
| isect.t /= t_world_to_instance; | isect.t /= t_world_to_instance; | ||||
| /* detect if this surface has a shader with transparent shadows */ | /* detect if this surface has a shader with transparent shadows */ | ||||
| /* todo: optimize so primitive visibility flag indicates if | /* todo: optimize so primitive visibility flag indicates if | ||||
| * the primitive has a transparent shadow shader? */ | * the primitive has a transparent shadow shader? */ | ||||
| const int flags = intersection_get_shader_flags(kg, isect.prim, isect.type); | const int flags = intersection_get_shader_flags(kg, isect.prim, isect.type); | ||||
| if (!(flags & SD_HAS_TRANSPARENT_SHADOW) || max_hits == 0) { | if (!(flags & SD_HAS_TRANSPARENT_SHADOW) || num_hits >= max_hits) { | ||||
| /* If no transparent shadows, all light is blocked and we can | /* If no transparent shadows, all light is blocked and we can | ||||
| * stop immediately. */ | * stop immediately. */ | ||||
| return true; | return true; | ||||
| } | } | ||||
| num_hits++; | |||||
| bool record_intersection = true; | |||||
| /* Always use baked shadow transparency for curves. */ | |||||
| if (isect.type & PRIMITIVE_ALL_CURVE) { | |||||
| *throughput *= intersection_curve_shadow_transparency( | |||||
| kg, isect.object, isect.prim, isect.u); | |||||
| if (*throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) { | |||||
| return true; | |||||
| } | |||||
| else { | |||||
| record_intersection = false; | |||||
| } | |||||
| } | |||||
| if (record_intersection) { | |||||
| /* Increase the number of hits, possibly beyond max_hits, we will | /* Increase the number of hits, possibly beyond max_hits, we will | ||||
| * simply not record those and only keep the max_hits closest. */ | * simply not record those and only keep the max_hits closest. */ | ||||
| uint record_index = (*num_hits)++; | uint record_index = (*num_recorded_hits)++; | ||||
| if (record_index >= max_hits - 1) { | 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 | /* If maximum number of hits reached, find the intersection with | ||||
| * the largest distance to potentially replace when another hit | * the largest distance to potentially replace when another hit | ||||
| * is found. */ | * is found. */ | ||||
| const int num_recorded_hits = min(max_hits, record_index); | const int num_recorded_hits = min(max_record_hits, record_index); | ||||
| float max_recorded_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t); | float max_recorded_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t); | ||||
| int max_recorded_hit = 0; | int max_recorded_hit = 0; | ||||
| for (int i = 1; i < num_recorded_hits; i++) { | for (int i = 1; i < num_recorded_hits; i++) { | ||||
| const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t); | const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t); | ||||
| if (isect_t > max_recorded_t) { | if (isect_t > max_recorded_t) { | ||||
| max_recorded_t = isect_t; | max_recorded_t = isect_t; | ||||
| max_recorded_hit = i; | max_recorded_hit = i; | ||||
| } | } | ||||
| } | } | ||||
| if (record_index >= max_hits) { | if (record_index >= max_record_hits) { | ||||
| record_index = max_recorded_hit; | record_index = max_recorded_hit; | ||||
| } | } | ||||
| /* Limit the ray distance and stop counting hits beyond this. */ | /* Limit the ray distance and stop counting hits beyond this. */ | ||||
| t_max_world = max(max_recorded_t, isect.t); | t_max_world = max(max_recorded_t, isect.t); | ||||
| t_max_current = t_max_world * t_world_to_instance; | t_max_current = t_max_world * t_world_to_instance; | ||||
| } | } | ||||
| integrator_state_write_shadow_isect(state, &isect, record_index); | integrator_state_write_shadow_isect(state, &isect, record_index); | ||||
| } | } | ||||
| } | |||||
| prim_addr++; | prim_addr++; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* instance push */ | /* instance push */ | ||||
| object = kernel_tex_fetch(__prim_object, -prim_addr - 1); | object = kernel_tex_fetch(__prim_object, -prim_addr - 1); | ||||
| Show All 39 Lines | #endif | ||||
| return false; | return false; | ||||
| } | } | ||||
| ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals kg, | ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals kg, | ||||
| ccl_private const Ray *ray, | ccl_private const Ray *ray, | ||||
| IntegratorShadowState state, | IntegratorShadowState state, | ||||
| const uint visibility, | const uint visibility, | ||||
| const uint max_hits, | const uint max_hits, | ||||
| ccl_private uint *num_hits) | ccl_private uint *num_recorded_hits, | ||||
| ccl_private float *throughput) | |||||
| { | { | ||||
| return BVH_FUNCTION_FULL_NAME(BVH)(kg, ray, state, visibility, max_hits, num_hits); | return BVH_FUNCTION_FULL_NAME(BVH)( | ||||
| kg, ray, state, visibility, max_hits, num_recorded_hits, throughput); | |||||
| } | } | ||||
| #undef BVH_FUNCTION_NAME | #undef BVH_FUNCTION_NAME | ||||
| #undef BVH_FUNCTION_FEATURES | #undef BVH_FUNCTION_FEATURES | ||||
| #undef NODE_INTERSECT | #undef NODE_INTERSECT | ||||