From e5f544dd92704381bfd6f54a8024c62982a50448 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 16 Oct 2011 17:54:43 +0000 Subject: Cycles: add transparent shadow support, i.e. shadows through Transparent BSDF shaders, enabled by default. --- intern/cycles/blender/addon/ui.py | 1 + intern/cycles/blender/blender_sync.cpp | 1 + intern/cycles/kernel/kernel_bvh.h | 2 +- intern/cycles/kernel/kernel_emission.h | 2 +- intern/cycles/kernel/kernel_path.h | 36 +++++++++++++++++++--------------- intern/cycles/kernel/kernel_types.h | 25 +++++++++++++---------- 6 files changed, 39 insertions(+), 28 deletions(-) (limited to 'intern/cycles') diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index d8f776b0114..10754ed6b9f 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -67,6 +67,7 @@ class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel): sub.label("Transparency:") sub.prop(cscene, "transparent_max_bounces", text="Max") sub.prop(cscene, "transparent_min_bounces", text="Min") + sub.prop(cscene, "use_transparent_shadows", text="Shadows") sub.prop(cscene, "no_caustics") col = split.column() diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 6f03cac315c..4babb612bdd 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -146,6 +146,7 @@ void BlenderSync::sync_integrator() integrator->transparent_max_bounce = get_int(cscene, "transparent_max_bounces"); integrator->transparent_min_bounce = get_int(cscene, "transparent_min_bounces"); + integrator->transparent_shadows = get_boolean(cscene, "use_transparent_shadows"); integrator->no_caustics = get_boolean(cscene, "no_caustics"); integrator->blur_caustics = get_float(cscene, "blur_caustics"); diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h index df7663b5555..b5f59b94516 100644 --- a/intern/cycles/kernel/kernel_bvh.h +++ b/intern/cycles/kernel/kernel_bvh.h @@ -253,7 +253,7 @@ __device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const ui bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr); /* shadow ray early termination */ - if(visibility == PATH_RAY_SHADOW && isect->prim != ~0) + if(visibility == PATH_RAY_SHADOW_OPAQUE && isect->prim != ~0) return true; primAddr++; diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 22970f66669..b81db721eb3 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -124,7 +124,7 @@ __device float3 indirect_emission(KernelGlobals *kg, ShaderData *sd, float t, in /* evaluate emissive closure */ float3 L = shader_emissive_eval(kg, sd); - if(!(path_flag & PATH_RAY_SINGULAR) && (sd->flag & SD_SAMPLE_AS_LIGHT)) { + if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT)) { /* multiple importance sampling */ float pdf = triangle_light_pdf(kg, sd->Ng, sd->I, t); float mis_weight = power_heuristic(bsdf_pdf, pdf); diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index e438780b1c8..c609f6f13fe 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -70,7 +70,7 @@ typedef struct PathState { __device_inline void path_state_init(PathState *state) { - state->flag = PATH_RAY_CAMERA|PATH_RAY_SINGULAR; + state->flag = PATH_RAY_CAMERA|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP; state->bounce = 0; state->diffuse_bounce = 0; state->glossy_bounce = 0; @@ -78,7 +78,7 @@ __device_inline void path_state_init(PathState *state) state->transparent_bounce = 0; } -__device_inline void path_state_next(PathState *state, int label) +__device_inline void path_state_next(KernelGlobals *kg, PathState *state, int label) { /* ray through transparent keeps same flags from previous ray and is not counted as a regular bounce, transparent has separate max */ @@ -86,6 +86,9 @@ __device_inline void path_state_next(PathState *state, int label) state->flag |= PATH_RAY_TRANSPARENT; state->transparent_bounce++; + if(!kernel_data.integrator.transparent_shadows) + state->flag |= PATH_RAY_MIS_SKIP; + return; } @@ -113,16 +116,16 @@ __device_inline void path_state_next(PathState *state, int label) /* diffuse/glossy/singular */ if(label & LABEL_DIFFUSE) { state->flag |= PATH_RAY_DIFFUSE; - state->flag &= ~(PATH_RAY_GLOSSY|PATH_RAY_SINGULAR); + state->flag &= ~(PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP); } else if(label & LABEL_GLOSSY) { state->flag |= PATH_RAY_GLOSSY; - state->flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_SINGULAR); + state->flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP); } else { kernel_assert(label & LABEL_SINGULAR); - state->flag |= PATH_RAY_GLOSSY|PATH_RAY_SINGULAR; + state->flag |= PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP; state->flag &= ~PATH_RAY_DIFFUSE; } } @@ -167,7 +170,7 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra if(ray->t == 0.0f) return false; - bool result = scene_intersect(kg, ray, PATH_RAY_SHADOW, isect); + bool result = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, isect); #ifdef __TRANSPARENT_SHADOWS__ if(result && kernel_data.integrator.transparent_shadows) { @@ -175,11 +178,11 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra in cases where we don't need them. after a regular shadow ray is cast we check if the hit primitive was potentially transparent, and only in that case start marching. this gives on extra ray cast for - the cases were we do want transparency */ + the cases were we do want transparency. + + also note that for this to work correct, multi close sampling must + be used, since we don't pass a random number to shader_eval_surface */ if(shader_transparent_shadow(kg, isect)) { - /* todo: fix double contribution from indirect for triangle lights */ - /* if(kernel_data.integrator.transparent_shadows && (path_flag & PATH_RAY_TRANSPARENT)) */ - float3 throughput = make_float3(1.0f, 1.0f, 1.0f); float3 Pend = ray->P + ray->D*ray->t; int bounce = state->transparent_bounce; @@ -192,7 +195,7 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra /* todo: get random number somewhere for probabilistic terminate */ #if 0 float probability = average(throughput); - float terminate = 0.0f; /* todo: get this random number */ + float terminate = 0.0f; if(terminate >= probability) return true; @@ -201,22 +204,23 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra #endif } - /* todo: fix it so we get first hit */ - if(!scene_intersect(kg, ray, PATH_RAY_SHADOW, isect)) { + if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, isect)) { *light_L *= throughput; return false; } + if(!shader_transparent_shadow(kg, isect)) return true; ShaderData sd; shader_setup_from_ray(kg, &sd, isect, ray); - shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW); /* todo: state flag? */ + shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW); throughput *= shader_bsdf_transparency(kg, &sd); ray->P = ray_offset(sd.P, -sd.Ng); - ray->t = (ray->t == FLT_MAX)? FLT_MAX: len(Pend - ray->P); + if(ray->t != FLT_MAX) + ray->D = normalize_len(Pend - ray->P, &ray->t); bounce++; } @@ -360,7 +364,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R #endif /* update path state */ - path_state_next(&state, label); + path_state_next(kg, &state, label); /* setup ray */ ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng); diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index c789601cd27..df438fe8d90 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -45,7 +45,7 @@ CCL_NAMESPACE_BEGIN #define __TEXTURES__ #define __HOLDOUT__ #define __MULTI_CLOSURE__ -//#define __TRANSPARENT_SHADOWS__ +#define __TRANSPARENT_SHADOWS__ //#define __MULTI_LIGHT__ #endif @@ -83,15 +83,20 @@ enum PathTraceDimension { enum PathRayFlag { PATH_RAY_CAMERA = 1, - PATH_RAY_SHADOW = 2, - PATH_RAY_REFLECT = 4, - PATH_RAY_TRANSMIT = 8, - PATH_RAY_DIFFUSE = 16, - PATH_RAY_GLOSSY = 32, - PATH_RAY_SINGULAR = 64, - PATH_RAY_TRANSPARENT = 128, - - PATH_RAY_ALL = (1|2|4|8|16|32|64|128) + PATH_RAY_REFLECT = 2, + PATH_RAY_TRANSMIT = 4, + PATH_RAY_DIFFUSE = 8, + PATH_RAY_GLOSSY = 16, + PATH_RAY_SINGULAR = 32, + PATH_RAY_TRANSPARENT = 64, + + PATH_RAY_SHADOW_OPAQUE = 128, + PATH_RAY_SHADOW_TRANSPARENT = 256, + PATH_RAY_SHADOW = (PATH_RAY_SHADOW_OPAQUE|PATH_RAY_SHADOW_TRANSPARENT), + + PATH_RAY_MIS_SKIP = 512, + + PATH_RAY_ALL = (1|2|4|8|16|32|64|128|256|512) }; /* Closure Label */ -- cgit v1.2.3