Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/integrator/integrator_intersect_shadow.h
| Show All 13 Lines | |||||
| * limitations under the License. | * limitations under the License. | ||||
| */ | */ | ||||
| #pragma once | #pragma once | ||||
| CCL_NAMESPACE_BEGIN | CCL_NAMESPACE_BEGIN | ||||
| /* Visibility for the shadow ray. */ | /* Visibility for the shadow ray. */ | ||||
| ccl_device_forceinline uint integrate_intersect_shadow_visibility(INTEGRATOR_STATE_CONST_ARGS) | ccl_device_forceinline uint integrate_intersect_shadow_visibility(KernelGlobals kg, | ||||
| ConstIntegratorState state) | |||||
| { | { | ||||
| uint visibility = PATH_RAY_SHADOW; | uint visibility = PATH_RAY_SHADOW; | ||||
| #ifdef __SHADOW_CATCHER__ | #ifdef __SHADOW_CATCHER__ | ||||
| const uint32_t path_flag = INTEGRATOR_STATE(shadow_path, flag); | const uint32_t path_flag = INTEGRATOR_STATE(state, shadow_path, flag); | ||||
| visibility = SHADOW_CATCHER_PATH_VISIBILITY(path_flag, visibility); | visibility = SHADOW_CATCHER_PATH_VISIBILITY(path_flag, visibility); | ||||
| #endif | #endif | ||||
| return visibility; | return visibility; | ||||
| } | } | ||||
| ccl_device bool integrate_intersect_shadow_opaque(INTEGRATOR_STATE_ARGS, | ccl_device bool integrate_intersect_shadow_opaque(KernelGlobals kg, | ||||
| IntegratorState state, | |||||
| ccl_private const Ray *ray, | ccl_private const Ray *ray, | ||||
| const uint visibility) | const uint visibility) | ||||
| { | { | ||||
| /* Mask which will pick only opaque visibility bits from the `visibility`. | /* Mask which will pick only opaque visibility bits from the `visibility`. | ||||
| * Calculate the mask at compile time: the visibility will either be a high bits for the shadow | * Calculate the mask at compile time: the visibility will either be a high bits for the shadow | ||||
| * catcher objects, or lower bits for the regular objects (there is no need to check the path | * catcher objects, or lower bits for the regular objects (there is no need to check the path | ||||
| * state here again). */ | * state here again). */ | ||||
| constexpr const uint opaque_mask = SHADOW_CATCHER_VISIBILITY_SHIFT(PATH_RAY_SHADOW_OPAQUE) | | constexpr const uint opaque_mask = SHADOW_CATCHER_VISIBILITY_SHIFT(PATH_RAY_SHADOW_OPAQUE) | | ||||
| PATH_RAY_SHADOW_OPAQUE; | PATH_RAY_SHADOW_OPAQUE; | ||||
| Intersection isect; | Intersection isect; | ||||
| const bool opaque_hit = scene_intersect(kg, ray, visibility & opaque_mask, &isect); | const bool opaque_hit = scene_intersect(kg, ray, visibility & opaque_mask, &isect); | ||||
| if (!opaque_hit) { | if (!opaque_hit) { | ||||
| INTEGRATOR_STATE_WRITE(shadow_path, num_hits) = 0; | INTEGRATOR_STATE_WRITE(state, shadow_path, num_hits) = 0; | ||||
| } | } | ||||
| return opaque_hit; | return opaque_hit; | ||||
| } | } | ||||
| ccl_device_forceinline int integrate_shadow_max_transparent_hits(INTEGRATOR_STATE_CONST_ARGS) | ccl_device_forceinline int integrate_shadow_max_transparent_hits(KernelGlobals kg, | ||||
| ConstIntegratorState state) | |||||
| { | { | ||||
| const int transparent_max_bounce = kernel_data.integrator.transparent_max_bounce; | const int transparent_max_bounce = kernel_data.integrator.transparent_max_bounce; | ||||
| const int transparent_bounce = INTEGRATOR_STATE(shadow_path, transparent_bounce); | const int transparent_bounce = INTEGRATOR_STATE(state, shadow_path, transparent_bounce); | ||||
| return max(transparent_max_bounce - transparent_bounce - 1, 0); | return max(transparent_max_bounce - transparent_bounce - 1, 0); | ||||
| } | } | ||||
| #ifdef __TRANSPARENT_SHADOWS__ | #ifdef __TRANSPARENT_SHADOWS__ | ||||
| ccl_device bool integrate_intersect_shadow_transparent(INTEGRATOR_STATE_ARGS, | ccl_device bool integrate_intersect_shadow_transparent(KernelGlobals kg, | ||||
| IntegratorState state, | |||||
| ccl_private const Ray *ray, | ccl_private const Ray *ray, | ||||
| const uint visibility) | const uint visibility) | ||||
| { | { | ||||
| Intersection isect[INTEGRATOR_SHADOW_ISECT_SIZE]; | Intersection isect[INTEGRATOR_SHADOW_ISECT_SIZE]; | ||||
| /* Limit the number hits to the max transparent bounces allowed and the size that we | /* Limit the number hits to the max transparent bounces allowed and the size that we | ||||
| * have available in the integrator state. */ | * have available in the integrator state. */ | ||||
| const uint max_transparent_hits = integrate_shadow_max_transparent_hits(INTEGRATOR_STATE_PASS); | const uint max_transparent_hits = integrate_shadow_max_transparent_hits(kg, state); | ||||
| const uint max_hits = min(max_transparent_hits, (uint)INTEGRATOR_SHADOW_ISECT_SIZE); | const uint max_hits = min(max_transparent_hits, (uint)INTEGRATOR_SHADOW_ISECT_SIZE); | ||||
| uint num_hits = 0; | uint num_hits = 0; | ||||
| bool opaque_hit = scene_intersect_shadow_all(kg, ray, isect, visibility, max_hits, &num_hits); | bool opaque_hit = scene_intersect_shadow_all(kg, ray, isect, visibility, max_hits, &num_hits); | ||||
| /* If number of hits exceed the transparent bounces limit, make opaque. */ | /* If number of hits exceed the transparent bounces limit, make opaque. */ | ||||
| if (num_hits > max_transparent_hits) { | if (num_hits > max_transparent_hits) { | ||||
| opaque_hit = true; | opaque_hit = true; | ||||
| } | } | ||||
| if (!opaque_hit) { | if (!opaque_hit) { | ||||
| uint num_recorded_hits = min(num_hits, max_hits); | uint num_recorded_hits = min(num_hits, max_hits); | ||||
| if (num_recorded_hits > 0) { | if (num_recorded_hits > 0) { | ||||
| sort_intersections(isect, num_recorded_hits); | sort_intersections(isect, num_recorded_hits); | ||||
| /* Write intersection result into global integrator state memory. | /* Write intersection result into global integrator state memory. | ||||
| * More efficient may be to do this directly from the intersection kernel. */ | * More efficient may be to do this directly from the intersection kernel. */ | ||||
| for (int hit = 0; hit < num_recorded_hits; hit++) { | for (int hit = 0; hit < num_recorded_hits; hit++) { | ||||
| integrator_state_write_shadow_isect(INTEGRATOR_STATE_PASS, &isect[hit], hit); | integrator_state_write_shadow_isect(state, &isect[hit], hit); | ||||
| } | } | ||||
| } | } | ||||
| INTEGRATOR_STATE_WRITE(shadow_path, num_hits) = num_hits; | INTEGRATOR_STATE_WRITE(state, shadow_path, num_hits) = num_hits; | ||||
| } | } | ||||
| else { | else { | ||||
| INTEGRATOR_STATE_WRITE(shadow_path, num_hits) = 0; | INTEGRATOR_STATE_WRITE(state, shadow_path, num_hits) = 0; | ||||
| } | } | ||||
| return opaque_hit; | return opaque_hit; | ||||
| } | } | ||||
| #endif | #endif | ||||
| ccl_device void integrator_intersect_shadow(INTEGRATOR_STATE_ARGS) | ccl_device void integrator_intersect_shadow(KernelGlobals kg, IntegratorState state) | ||||
| { | { | ||||
| PROFILING_INIT(kg, PROFILING_INTERSECT_SHADOW); | PROFILING_INIT(kg, PROFILING_INTERSECT_SHADOW); | ||||
| /* Read ray from integrator state into local memory. */ | /* Read ray from integrator state into local memory. */ | ||||
| Ray ray ccl_optional_struct_init; | Ray ray ccl_optional_struct_init; | ||||
| integrator_state_read_shadow_ray(INTEGRATOR_STATE_PASS, &ray); | integrator_state_read_shadow_ray(kg, state, &ray); | ||||
| /* Compute visibility. */ | /* Compute visibility. */ | ||||
| const uint visibility = integrate_intersect_shadow_visibility(INTEGRATOR_STATE_PASS); | const uint visibility = integrate_intersect_shadow_visibility(kg, state); | ||||
| #ifdef __TRANSPARENT_SHADOWS__ | #ifdef __TRANSPARENT_SHADOWS__ | ||||
| /* TODO: compile different kernels depending on this? Especially for OptiX | /* TODO: compile different kernels depending on this? Especially for OptiX | ||||
| * conditional trace calls are bad. */ | * conditional trace calls are bad. */ | ||||
| const bool opaque_hit = | const bool opaque_hit = (kernel_data.integrator.transparent_shadows) ? | ||||
| (kernel_data.integrator.transparent_shadows) ? | integrate_intersect_shadow_transparent(kg, state, &ray, visibility) : | ||||
| integrate_intersect_shadow_transparent(INTEGRATOR_STATE_PASS, &ray, visibility) : | integrate_intersect_shadow_opaque(kg, state, &ray, visibility); | ||||
| integrate_intersect_shadow_opaque(INTEGRATOR_STATE_PASS, &ray, visibility); | |||||
| #else | #else | ||||
| const bool opaque_hit = integrate_intersect_shadow_opaque( | const bool opaque_hit = integrate_intersect_shadow_opaque(kg, state, &ray, visibility); | ||||
| INTEGRATOR_STATE_PASS, &ray, visibility); | |||||
| #endif | #endif | ||||
| if (opaque_hit) { | if (opaque_hit) { | ||||
| /* Hit an opaque surface, shadow path ends here. */ | /* Hit an opaque surface, shadow path ends here. */ | ||||
| INTEGRATOR_SHADOW_PATH_TERMINATE(DEVICE_KERNEL_INTEGRATOR_INTERSECT_SHADOW); | INTEGRATOR_SHADOW_PATH_TERMINATE(DEVICE_KERNEL_INTEGRATOR_INTERSECT_SHADOW); | ||||
| return; | return; | ||||
| } | } | ||||
| else { | else { | ||||
| Show All 12 Lines | |||||