Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/kernel_shadow_catcher.h
| Show All 16 Lines | |||||
| #pragma once | #pragma once | ||||
| #include "kernel/integrator/integrator_state_util.h" | #include "kernel/integrator/integrator_state_util.h" | ||||
| #include "kernel/kernel_path_state.h" | #include "kernel/kernel_path_state.h" | ||||
| CCL_NAMESPACE_BEGIN | CCL_NAMESPACE_BEGIN | ||||
| /* Check whether current surface bounce is where path is to be split for the shadow catcher. */ | /* Check whether current surface bounce is where path is to be split for the shadow catcher. */ | ||||
| ccl_device_inline bool kernel_shadow_catcher_is_path_split_bounce(INTEGRATOR_STATE_ARGS, | ccl_device_inline bool kernel_shadow_catcher_is_path_split_bounce(KernelGlobals kg, | ||||
| IntegratorState state, | |||||
| const int object_flag) | const int object_flag) | ||||
| { | { | ||||
| #ifdef __SHADOW_CATCHER__ | #ifdef __SHADOW_CATCHER__ | ||||
| if (!kernel_data.integrator.has_shadow_catcher) { | if (!kernel_data.integrator.has_shadow_catcher) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* Check the flag first, avoiding fetches form global memory. */ | /* Check the flag first, avoiding fetches form global memory. */ | ||||
| if ((object_flag & SD_OBJECT_SHADOW_CATCHER) == 0) { | if ((object_flag & SD_OBJECT_SHADOW_CATCHER) == 0) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (object_flag & SD_OBJECT_HOLDOUT_MASK) { | if (object_flag & SD_OBJECT_HOLDOUT_MASK) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| const int path_flag = INTEGRATOR_STATE(path, flag); | const int path_flag = INTEGRATOR_STATE(state, path, flag); | ||||
| if ((path_flag & PATH_RAY_TRANSPARENT_BACKGROUND) == 0) { | if ((path_flag & PATH_RAY_TRANSPARENT_BACKGROUND) == 0) { | ||||
| /* Split only on primary rays, secondary bounces are to treat shadow catcher as a regular | /* Split only on primary rays, secondary bounces are to treat shadow catcher as a regular | ||||
| * object. */ | * object. */ | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (path_flag & PATH_RAY_SHADOW_CATCHER_PASS) { | if (path_flag & PATH_RAY_SHADOW_CATCHER_PASS) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| return true; | return true; | ||||
| #else | #else | ||||
| (void)object_flag; | (void)object_flag; | ||||
| return false; | return false; | ||||
| #endif | #endif | ||||
| } | } | ||||
| /* Check whether the current path can still split. */ | /* Check whether the current path can still split. */ | ||||
| ccl_device_inline bool kernel_shadow_catcher_path_can_split(INTEGRATOR_STATE_CONST_ARGS) | ccl_device_inline bool kernel_shadow_catcher_path_can_split(KernelGlobals kg, | ||||
| ConstIntegratorState state) | |||||
| { | { | ||||
| if (INTEGRATOR_PATH_IS_TERMINATED && INTEGRATOR_SHADOW_PATH_IS_TERMINATED) { | if (INTEGRATOR_PATH_IS_TERMINATED && INTEGRATOR_SHADOW_PATH_IS_TERMINATED) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| const int path_flag = INTEGRATOR_STATE(path, flag); | const int path_flag = INTEGRATOR_STATE(state, path, flag); | ||||
| if (path_flag & PATH_RAY_SHADOW_CATCHER_HIT) { | if (path_flag & PATH_RAY_SHADOW_CATCHER_HIT) { | ||||
| /* Shadow catcher was already hit and the state was split. No further split is allowed. */ | /* Shadow catcher was already hit and the state was split. No further split is allowed. */ | ||||
| return false; | return false; | ||||
| } | } | ||||
| return (path_flag & PATH_RAY_TRANSPARENT_BACKGROUND) != 0; | return (path_flag & PATH_RAY_TRANSPARENT_BACKGROUND) != 0; | ||||
| } | } | ||||
| /* NOTE: Leaves kernel scheduling information untouched. Use INIT semantic for one of the paths | /* NOTE: Leaves kernel scheduling information untouched. Use INIT semantic for one of the paths | ||||
| * after this function. */ | * after this function. */ | ||||
| ccl_device_inline bool kernel_shadow_catcher_split(INTEGRATOR_STATE_ARGS, const int object_flags) | ccl_device_inline bool kernel_shadow_catcher_split(KernelGlobals kg, | ||||
| IntegratorState state, | |||||
| const int object_flags) | |||||
| { | { | ||||
| #ifdef __SHADOW_CATCHER__ | #ifdef __SHADOW_CATCHER__ | ||||
| if (!kernel_shadow_catcher_is_path_split_bounce(INTEGRATOR_STATE_PASS, object_flags)) { | if (!kernel_shadow_catcher_is_path_split_bounce(kg, state, object_flags)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* The split is to be done. Mark the current state as such, so that it stops contributing to the | /* The split is to be done. Mark the current state as such, so that it stops contributing to the | ||||
| * shadow catcher matte pass, but keeps contributing to the combined pass. */ | * shadow catcher matte pass, but keeps contributing to the combined pass. */ | ||||
| INTEGRATOR_STATE_WRITE(path, flag) |= PATH_RAY_SHADOW_CATCHER_HIT; | INTEGRATOR_STATE_WRITE(state, path, flag) |= PATH_RAY_SHADOW_CATCHER_HIT; | ||||
| /* Split new state from the current one. This new state will only track contribution of shadow | /* Split new state from the current one. This new state will only track contribution of shadow | ||||
| * catcher objects ignoring non-catcher objects. */ | * catcher objects ignoring non-catcher objects. */ | ||||
| integrator_state_shadow_catcher_split(INTEGRATOR_STATE_PASS); | integrator_state_shadow_catcher_split(kg, state); | ||||
| return true; | return true; | ||||
| #else | #else | ||||
| (void)object_flags; | (void)object_flags; | ||||
| return false; | return false; | ||||
| #endif | #endif | ||||
| } | } | ||||
| #ifdef __SHADOW_CATCHER__ | #ifdef __SHADOW_CATCHER__ | ||||
| ccl_device_forceinline bool kernel_shadow_catcher_is_matte_path(INTEGRATOR_STATE_CONST_ARGS) | ccl_device_forceinline bool kernel_shadow_catcher_is_matte_path(KernelGlobals kg, | ||||
| ConstIntegratorState state) | |||||
| { | { | ||||
| return (INTEGRATOR_STATE(path, flag) & PATH_RAY_SHADOW_CATCHER_HIT) == 0; | return (INTEGRATOR_STATE(state, path, flag) & PATH_RAY_SHADOW_CATCHER_HIT) == 0; | ||||
| } | } | ||||
| ccl_device_forceinline bool kernel_shadow_catcher_is_object_pass(INTEGRATOR_STATE_CONST_ARGS) | ccl_device_forceinline bool kernel_shadow_catcher_is_object_pass(KernelGlobals kg, | ||||
| ConstIntegratorState state) | |||||
| { | { | ||||
| return INTEGRATOR_STATE(path, flag) & PATH_RAY_SHADOW_CATCHER_PASS; | return INTEGRATOR_STATE(state, path, flag) & PATH_RAY_SHADOW_CATCHER_PASS; | ||||
| } | } | ||||
| #endif /* __SHADOW_CATCHER__ */ | #endif /* __SHADOW_CATCHER__ */ | ||||
| CCL_NAMESPACE_END | CCL_NAMESPACE_END | ||||