Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/kernel/kernel_shadow.h')
-rw-r--r--intern/cycles/kernel/kernel_shadow.h185
1 files changed, 114 insertions, 71 deletions
diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h
index fab5946970d..8a0da6c3b13 100644
--- a/intern/cycles/kernel/kernel_shadow.h
+++ b/intern/cycles/kernel/kernel_shadow.h
@@ -16,6 +16,42 @@
CCL_NAMESPACE_BEGIN
+#ifdef __VOLUME__
+typedef struct VolumeState {
+# ifdef __SPLIT_KERNEL__
+# else
+ PathState ps;
+# endif
+} VolumeState;
+
+/* Get PathState ready for use for volume stack evaluation. */
+# ifdef __SPLIT_KERNEL__
+ccl_addr_space
+# endif
+ccl_device_inline PathState *shadow_blocked_volume_path_state(
+ KernelGlobals *kg,
+ VolumeState *volume_state,
+ ccl_addr_space PathState *state,
+ ShaderData *sd,
+ Ray *ray)
+{
+# ifdef __SPLIT_KERNEL__
+ ccl_addr_space PathState *ps =
+ &kernel_split_state.state_shadow[ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0)];
+# else
+ PathState *ps = &volume_state->ps;
+# endif
+ *ps = *state;
+ /* We are checking for shadow on the "other" side of the surface, so need
+ * to discard volume we are currently at.
+ */
+ if(dot(sd->Ng, ray->D) < 0.0f) {
+ kernel_volume_stack_enter_exit(kg, sd, ps->volume_stack);
+ }
+ return ps;
+}
+#endif /* __VOLUME__ */
+
/* Attenuate throughput accordingly to the given intersection event.
* Returns true if the throughput is zero and traversal can be aborted.
*/
@@ -49,11 +85,8 @@ ccl_device_forceinline bool shadow_handle_transparent_isect(
path_state_modify_bounce(state, true);
shader_eval_surface(kg,
shadow_sd,
- NULL,
state,
- 0.0f,
- PATH_RAY_SHADOW,
- SHADER_CONTEXT_SHADOW);
+ PATH_RAY_SHADOW);
path_state_modify_bounce(state, false);
*throughput *= shader_bsdf_transparency(kg, shadow_sd);
}
@@ -72,13 +105,14 @@ ccl_device_forceinline bool shadow_handle_transparent_isect(
ccl_device bool shadow_blocked_opaque(KernelGlobals *kg,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
+ const uint visibility,
Ray *ray,
Intersection *isect,
float3 *shadow)
{
const bool blocked = scene_intersect(kg,
*ray,
- PATH_RAY_SHADOW_OPAQUE,
+ visibility & PATH_RAY_SHADOW_OPAQUE,
isect,
NULL,
0.0f, 0.0f);
@@ -126,9 +160,10 @@ ccl_device bool shadow_blocked_opaque(KernelGlobals *kg,
* Note that hits array should be as big as max_hits+1.
*/
ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
+ ShaderData *sd,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
- const int skip_object,
+ const uint visibility,
Ray *ray,
Intersection *hits,
uint max_hits,
@@ -141,9 +176,12 @@ ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
const bool blocked = scene_intersect_shadow_all(kg,
ray,
hits,
- skip_object,
+ visibility,
max_hits,
&num_hits);
+# ifdef __VOLUME__
+ VolumeState volume_state;
+# endif
/* If no opaque surface found but we did find transparent hits,
* shade them.
*/
@@ -155,12 +193,13 @@ ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
Intersection *isect = hits;
# ifdef __VOLUME__
# ifdef __SPLIT_KERNEL__
- ccl_addr_space PathState *ps = &kernel_split_state.state_shadow[ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0)];
-# else
- PathState ps_object;
- PathState *ps = &ps_object;
+ ccl_addr_space
# endif
- *ps = *state;
+ PathState *ps = shadow_blocked_volume_path_state(kg,
+ &volume_state,
+ state,
+ sd,
+ ray);
# endif
sort_intersections(hits, num_hits);
for(int hit = 0; hit < num_hits; hit++, isect++) {
@@ -205,8 +244,16 @@ ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
}
# ifdef __VOLUME__
if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
- /* Apply attenuation from current volume shader/ */
- kernel_volume_shadow(kg, shadow_sd, state, ray, shadow);
+ /* Apply attenuation from current volume shader. */
+# ifdef __SPLIT_KERNEL__
+ ccl_addr_space
+# endif
+ PathState *ps = shadow_blocked_volume_path_state(kg,
+ &volume_state,
+ state,
+ sd,
+ ray);
+ kernel_volume_shadow(kg, shadow_sd, ps, ray, shadow);
}
# endif
return blocked;
@@ -216,9 +263,10 @@ ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
* loop to help readability of the actual logic.
*/
ccl_device bool shadow_blocked_transparent_all(KernelGlobals *kg,
+ ShaderData *sd,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
- const int skip_object,
+ const uint visibility,
Ray *ray,
uint max_hits,
float3 *shadow)
@@ -251,9 +299,10 @@ ccl_device bool shadow_blocked_transparent_all(KernelGlobals *kg,
# endif /* __KERNEL_GPU__ */
/* Invoke actual traversal. */
return shadow_blocked_transparent_all_loop(kg,
+ sd,
shadow_sd,
state,
- skip_object,
+ visibility,
ray,
hits,
max_hits,
@@ -276,27 +325,32 @@ ccl_device bool shadow_blocked_transparent_all(KernelGlobals *kg,
*/
ccl_device bool shadow_blocked_transparent_stepped_loop(
KernelGlobals *kg,
+ ShaderData *sd,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
- const int skip_object,
+ const uint visibility,
Ray *ray,
Intersection *isect,
const bool blocked,
const bool is_transparent_isect,
float3 *shadow)
{
- if((blocked && is_transparent_isect) || skip_object != OBJECT_NONE) {
+# ifdef __VOLUME__
+ VolumeState volume_state;
+# endif
+ if(blocked && is_transparent_isect) {
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
float3 Pend = ray->P + ray->D*ray->t;
int bounce = state->transparent_bounce;
# ifdef __VOLUME__
# ifdef __SPLIT_KERNEL__
- ccl_addr_space PathState *ps = &kernel_split_state.state_shadow[ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0)];
-# else
- PathState ps_object;
- PathState *ps = &ps_object;
+ ccl_addr_space
# endif
- *ps = *state;
+ PathState *ps = shadow_blocked_volume_path_state(kg,
+ &volume_state,
+ state,
+ sd,
+ ray);
# endif
for(;;) {
if(bounce >= kernel_data.integrator.transparent_max_bounce) {
@@ -304,30 +358,13 @@ ccl_device bool shadow_blocked_transparent_stepped_loop(
}
if(!scene_intersect(kg,
*ray,
- PATH_RAY_SHADOW_TRANSPARENT,
+ visibility & PATH_RAY_SHADOW_TRANSPARENT,
isect,
NULL,
0.0f, 0.0f))
{
break;
}
-#ifdef __SHADOW_TRICKS__
- if(skip_object != OBJECT_NONE) {
- const int isect_object = (isect->object == PRIM_NONE)
- ? kernel_tex_fetch(__prim_object, isect->prim)
- : isect->object;
- if(isect_object == skip_object) {
- shader_setup_from_ray(kg, shadow_sd, isect, ray);
- /* Move ray forward. */
- ray->P = ray_offset(shadow_sd->P, -shadow_sd->Ng);
- if(ray->t != FLT_MAX) {
- ray->D = normalize_len(Pend - ray->P, &ray->t);
- }
- bounce++;
- continue;
- }
- }
-#endif
if(!shader_transparent_shadow(kg, isect)) {
return true;
}
@@ -363,7 +400,15 @@ ccl_device bool shadow_blocked_transparent_stepped_loop(
# ifdef __VOLUME__
if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
/* Apply attenuation from current volume shader. */
- kernel_volume_shadow(kg, shadow_sd, state, ray, shadow);
+# ifdef __SPLIT_KERNEL__
+ ccl_addr_space
+# endif
+ PathState *ps = shadow_blocked_volume_path_state(kg,
+ &volume_state,
+ state,
+ sd,
+ ray);
+ kernel_volume_shadow(kg, shadow_sd, ps, ray, shadow);
}
# endif
return blocked;
@@ -371,33 +416,28 @@ ccl_device bool shadow_blocked_transparent_stepped_loop(
ccl_device bool shadow_blocked_transparent_stepped(
KernelGlobals *kg,
+ ShaderData *sd,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
- const int skip_object,
+ const uint visibility,
Ray *ray,
Intersection *isect,
float3 *shadow)
{
- bool blocked, is_transparent_isect;
- if(skip_object == OBJECT_NONE) {
- blocked = scene_intersect(kg,
- *ray,
- PATH_RAY_SHADOW_OPAQUE,
- isect,
- NULL,
- 0.0f, 0.0f);
- is_transparent_isect = blocked
- ? shader_transparent_shadow(kg, isect)
- : false;
- }
- else {
- blocked = false;
- is_transparent_isect = false;
- }
+ bool blocked = scene_intersect(kg,
+ *ray,
+ visibility & PATH_RAY_SHADOW_OPAQUE,
+ isect,
+ NULL,
+ 0.0f, 0.0f);
+ bool is_transparent_isect = blocked
+ ? shader_transparent_shadow(kg, isect)
+ : false;
return shadow_blocked_transparent_stepped_loop(kg,
+ sd,
shadow_sd,
state,
- skip_object,
+ visibility,
ray,
isect,
blocked,
@@ -409,6 +449,7 @@ ccl_device bool shadow_blocked_transparent_stepped(
#endif /* __TRANSPARENT_SHADOWS__ */
ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
+ ShaderData *sd,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
Ray *ray_input,
@@ -422,25 +463,24 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
return false;
}
#ifdef __SHADOW_TRICKS__
- const int skip_object = state->catcher_object;
+ const uint visibility = (state->flag & PATH_RAY_SHADOW_CATCHER)
+ ? PATH_RAY_SHADOW_NON_CATCHER
+ : PATH_RAY_SHADOW;
#else
- const int skip_object = OBJECT_NONE;
+ const uint visibility = PATH_RAY_SHADOW;
#endif
/* Do actual shadow shading. */
/* First of all, we check if integrator requires transparent shadows.
* if not, we use simplest and fastest ever way to calculate occlusion.
- *
- * NOTE: We can't do quick opaque test here if we are on shadow-catcher
- * path because we don't want catcher object to be casting shadow here.
*/
#ifdef __TRANSPARENT_SHADOWS__
- if(!kernel_data.integrator.transparent_shadows &&
- skip_object == OBJECT_NONE)
+ if(!kernel_data.integrator.transparent_shadows)
#endif
{
return shadow_blocked_opaque(kg,
shadow_sd,
state,
+ visibility,
ray,
&isect,
shadow);
@@ -467,7 +507,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
*/
const bool blocked = scene_intersect(kg,
*ray,
- PATH_RAY_SHADOW_OPAQUE,
+ visibility & PATH_RAY_SHADOW_OPAQUE,
&isect,
NULL,
0.0f, 0.0f);
@@ -478,9 +518,10 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
max_hits + 1 >= SHADOW_STACK_MAX_HITS)
{
return shadow_blocked_transparent_stepped_loop(kg,
+ sd,
shadow_sd,
state,
- skip_object,
+ visibility,
ray,
&isect,
blocked,
@@ -489,18 +530,20 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
}
# endif /* __KERNEL_GPU__ */
return shadow_blocked_transparent_all(kg,
+ sd,
shadow_sd,
state,
- skip_object,
+ visibility,
ray,
max_hits,
shadow);
# else /* __SHADOW_RECORD_ALL__ */
/* Fallback to a slowest version which works on all devices. */
return shadow_blocked_transparent_stepped(kg,
+ sd,
shadow_sd,
state,
- skip_object,
+ visibility,
ray,
&isect,
shadow);