diff options
Diffstat (limited to 'intern/cycles/kernel/kernel_path.h')
-rw-r--r-- | intern/cycles/kernel/kernel_path.h | 99 |
1 files changed, 94 insertions, 5 deletions
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index b073cd49a8c..815eb4a1d53 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -162,6 +162,86 @@ __device_inline float path_state_terminate_probability(KernelGlobals *kg, PathSt return average(throughput); } +#ifdef __TRANSPARENT_SHADOWS__ +__device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect) +{ + int prim = kernel_tex_fetch(__prim_index, isect->prim); + float4 Ns = kernel_tex_fetch(__tri_normal, prim); + int shader = __float_as_int(Ns.w); + + /* todo: add shader flag to check this */ + + return true; +} +#endif + +__device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, Intersection *isect, float3 *light_L) +{ + if(ray->t == 0.0f) + return false; + + bool result = scene_intersect(kg, ray, PATH_RAY_SHADOW, isect); + +#ifdef __TRANSPARENT_SHADOWS__ + if(result && kernel_data.integrator.transparent_shadows) { + /* transparent shadows work in such a way to try to minimize overhead + 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 */ + 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; + + for(;;) { + if(bounce >= kernel_data.integrator.transparent_max_bounce) { + return true; + } + else if(bounce >= kernel_data.integrator.transparent_min_bounce) { + /* todo: get random number somewhere for probabilistic terminate */ +#if 0 + float probability = average(throughput); + float terminate = 0.0f; /* todo: get this random number */ + + if(terminate >= probability) + return true; + + throughput /= probability; +#endif + } + + /* todo: fix it so we get first hit */ + if(!scene_intersect(kg, ray, PATH_RAY_SHADOW, 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? */ + + throughput *= shader_bsdf_transparency(kg, &sd); + + ray->P = ray_offset(sd.P, -sd.Ng); + ray->t = len(Pend - ray->P); + + bounce++; + } + + return true; + } + } +#endif + + return result; +} + __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray ray, float3 throughput) { /* initialize */ @@ -247,13 +327,22 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray Ray light_ray; float3 light_L; - /* todo: use visbility flag to skip lights */ +#ifdef __MULTI_LIGHT__ + /* index -1 means randomly sample from distribution */ + int i = (kernel_data.integrator.num_distribution)? -1: 0; - if(direct_emission(kg, &sd, light_t, light_o, light_u, light_v, &light_ray, &light_L)) { - /* trace shadow ray */ - if(!scene_intersect(kg, &light_ray, PATH_RAY_SHADOW, &isect)) - L += throughput*light_L; + for(; i < kernel_data.integrator.num_all_lights; i++) { +#else + const int i = -1; +#endif + if(direct_emission(kg, &sd, i, light_t, light_o, light_u, light_v, &light_ray, &light_L)) { + /* trace shadow ray */ + if(!shadow_blocked(kg, &state, &light_ray, &isect, &light_L)) + L += throughput*light_L; + } +#ifdef __MULTI_LIGHT__ } +#endif } } #endif |