diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index e8845e03acb..a2ff6a05706 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -69,7 +69,9 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian path_radiance_accum_emission(&L_sample, throughput, emission, state.bounce); } - if(kernel_path_integrate_lighting(kg, &rng, sd, &throughput, &state, &L_sample, &ray)) { + kernel_path_surface_connect_light(kg, &rng, sd, throughput, &state, &L_sample); + + if(kernel_path_surface_bounce(kg, &rng, sd, &throughput, &state, &L_sample, &ray)) { #ifdef __LAMP_MIS__ state.ray_t = 0.0f; #endif @@ -107,7 +109,17 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian path_radiance_accum_emission(&L_sample, throughput, emission, state.bounce); } - kernel_branched_path_integrate_lighting(kg, &rng, +#if defined(__EMISSION__) + /* direct light */ + if(kernel_data.integrator.use_direct_light) { + bool all = kernel_data.integrator.sample_all_lights_direct; + kernel_branched_path_surface_connect_light(kg, &rng, + sd, &state, throughput, 1.0f, &L_sample, all); + } +#endif + + /* indirect light */ + kernel_branched_path_surface_indirect_light(kg, &rng, sd, throughput, 1.0f, &state, &L_sample); } } diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 70366eaac90..f5606c003d1 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -47,40 +47,45 @@ CCL_NAMESPACE_BEGIN #ifdef __VOLUME__ -ccl_device_inline bool kernel_path_integrate_scatter_lighting(KernelGlobals *kg, RNG *rng, - ShaderData *sd, float3 *throughput, PathState *state, PathRadiance *L, Ray *ray, - float num_samples_adjust) +ccl_device_inline void kernel_path_volume_connect_light(KernelGlobals *kg, RNG *rng, + ShaderData *sd, float3 throughput, PathState *state, PathRadiance *L, float num_samples_adjust) { #ifdef __EMISSION__ - if(kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL)) { - /* sample illumination from lights to find path contribution */ - float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT); - float light_u, light_v; - path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v); + if(!(kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL))) + return; - Ray light_ray; - BsdfEval L_light; - bool is_lamp; + /* sample illumination from lights to find path contribution */ + float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT); + float light_u, light_v; + path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v); + + Ray light_ray; + BsdfEval L_light; + bool is_lamp; #ifdef __OBJECT_MOTION__ - light_ray.time = sd->time; + light_ray.time = sd->time; #endif - LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); + LightSample ls; + light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); - if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) { - /* trace shadow ray */ - float3 shadow; + if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) { + /* trace shadow ray */ + float3 shadow; - if(!shadow_blocked(kg, state, &light_ray, &shadow)) { - /* accumulate */ - path_radiance_accum_light(L, *throughput * num_samples_adjust, &L_light, shadow, 1.0f, state->bounce, is_lamp); - } + if(!shadow_blocked(kg, state, &light_ray, &shadow)) { + /* accumulate */ + path_radiance_accum_light(L, throughput * num_samples_adjust, &L_light, shadow, 1.0f, state->bounce, is_lamp); } } #endif +} +ccl_device_inline bool kernel_path_volume_bounce(KernelGlobals *kg, RNG *rng, + ShaderData *sd, float3 *throughput, PathState *state, PathRadiance *L, Ray *ray, + float num_samples_adjust) +{ /* sample phase function */ float phase_pdf; BsdfEval phase_eval; @@ -126,7 +131,8 @@ ccl_device_inline bool kernel_path_integrate_scatter_lighting(KernelGlobals *kg, #if defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__) -ccl_device void kernel_branched_path_integrate_direct_lighting(KernelGlobals *kg, RNG *rng, +/* branched path tracing: connect path directly to position on one or more lights and add it to L */ +ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RNG *rng, ShaderData *sd, PathState *state, float3 throughput, float num_samples_adjust, PathRadiance *L, bool sample_all_lights) { /* sample illumination from lights to find path contribution */ @@ -224,6 +230,122 @@ ccl_device void kernel_branched_path_integrate_direct_lighting(KernelGlobals *kg #endif +/* path tracing: connect path directly to position on a light and add it to L */ +ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG *rng, + ShaderData *sd, float3 throughput, PathState *state, PathRadiance *L) +{ +#ifdef __EMISSION__ + if(!(kernel_data.integrator.use_direct_light) && (sd->flag & SD_BSDF_HAS_EVAL)) + return; + + float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT); + float light_u, light_v; + path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v); + + Ray light_ray; + BsdfEval L_light; + bool is_lamp; + +#ifdef __OBJECT_MOTION__ + light_ray.time = sd->time; +#endif + + LightSample ls; + light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); + + if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) { + /* trace shadow ray */ + float3 shadow; + + if(!shadow_blocked(kg, state, &light_ray, &shadow)) { + /* accumulate */ + path_radiance_accum_light(L, throughput, &L_light, shadow, 1.0f, state->bounce, is_lamp); + } + } +#endif +} + +/* path tracing: bounce off or through surface to with new direction stored in ray */ +ccl_device_inline bool kernel_path_surface_bounce(KernelGlobals *kg, RNG *rng, + ShaderData *sd, float3 *throughput, PathState *state, PathRadiance *L, Ray *ray) +{ + /* no BSDF? we can stop here */ + if(sd->flag & SD_BSDF) { + /* sample BSDF */ + float bsdf_pdf; + BsdfEval bsdf_eval; + float3 bsdf_omega_in; + differential3 bsdf_domega_in; + float bsdf_u, bsdf_v; + path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v); + int label; + + label = shader_bsdf_sample(kg, sd, bsdf_u, bsdf_v, &bsdf_eval, + &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf); + + if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval)) + return false; + + /* modify throughput */ + path_radiance_bsdf_bounce(L, throughput, &bsdf_eval, bsdf_pdf, state->bounce, label); + + /* set labels */ + if(!(label & LABEL_TRANSPARENT)) { + state->ray_pdf = bsdf_pdf; +#ifdef __LAMP_MIS__ + state->ray_t = 0.0f; +#endif + state->min_ray_pdf = fminf(bsdf_pdf, state->min_ray_pdf); + } + + /* update path state */ + path_state_next(kg, state, label); + + /* setup ray */ + ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT)? -sd->Ng: sd->Ng); + ray->D = bsdf_omega_in; + + if(state->bounce == 0) + ray->t -= sd->ray_length; /* clipping works through transparent */ + else + ray->t = FLT_MAX; + +#ifdef __RAY_DIFFERENTIALS__ + ray->dP = sd->dP; + ray->dD = bsdf_domega_in; +#endif + +#ifdef __VOLUME__ + /* enter/exit volume */ + if(label & LABEL_TRANSMIT) + kernel_volume_stack_enter_exit(kg, sd, state->volume_stack); +#endif + return true; + } +#ifdef __VOLUME__ + else if(sd->flag & SD_HAS_ONLY_VOLUME) { + /* no surface shader but have a volume shader? act transparent */ + + /* update path state, count as transparent */ + path_state_next(kg, state, LABEL_TRANSPARENT); + + /* setup ray position, direction stays unchanged */ + ray->P = ray_offset(sd->P, -sd->Ng); +#ifdef __RAY_DIFFERENTIALS__ + ray->dP = sd->dP; +#endif + + /* enter/exit volume */ + kernel_volume_stack_enter_exit(kg, sd, state->volume_stack); + return true; + } +#endif + else { + /* no bsdf or volume? */ + return false; + } +} + ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, float3 throughput, int num_samples, PathState state, PathRadiance *L) { @@ -270,7 +392,9 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, &volume_sd, &volume_ray, L, &throughput, rng); if(result == VOLUME_PATH_SCATTERED) { - if(kernel_path_integrate_scatter_lighting(kg, rng, &volume_sd, &throughput, &state, L, &ray, 1.0f)) + kernel_path_volume_connect_light(kg, rng, &volume_sd, throughput, &state, L, 1.0f); + + if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, &state, L, &ray, 1.0f)) continue; else break; @@ -393,190 +517,12 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, #if defined(__EMISSION__) && defined(__BRANCHED_PATH__) if(kernel_data.integrator.use_direct_light) { bool all = kernel_data.integrator.sample_all_lights_indirect; - kernel_branched_path_integrate_direct_lighting(kg, rng, &sd, &state, throughput, 1.0f, L, all); + kernel_branched_path_surface_connect_light(kg, rng, &sd, &state, throughput, 1.0f, L, all); } #endif - /* no BSDF? we can stop here */ - if(sd.flag & SD_BSDF) { - /* sample BSDF */ - float bsdf_pdf; - BsdfEval bsdf_eval; - float3 bsdf_omega_in; - differential3 bsdf_domega_in; - float bsdf_u, bsdf_v; - path_state_rng_2D(kg, rng, &state, PRNG_BSDF_U, &bsdf_u, &bsdf_v); - int label; - - label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval, - &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf); - - if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval)) - break; - - /* modify throughput */ - path_radiance_bsdf_bounce(L, &throughput, &bsdf_eval, bsdf_pdf, state.bounce, label); - - /* set labels */ - if(!(label & LABEL_TRANSPARENT)) { - state.ray_pdf = bsdf_pdf; -#ifdef __LAMP_MIS__ - state.ray_t = 0.0f; -#endif - state.min_ray_pdf = fminf(bsdf_pdf, state.min_ray_pdf); - } - - /* update path state */ - path_state_next(kg, &state, label); - - /* setup ray */ - ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng); - ray.D = bsdf_omega_in; - ray.t = FLT_MAX; -#ifdef __RAY_DIFFERENTIALS__ - ray.dP = sd.dP; - ray.dD = bsdf_domega_in; -#endif - -#ifdef __VOLUME__ - /* enter/exit volume */ - if(label & LABEL_TRANSMIT) - kernel_volume_stack_enter_exit(kg, &sd, state.volume_stack); -#endif - } -#ifdef __VOLUME__ - else if(sd.flag & SD_HAS_ONLY_VOLUME) { - /* no surface shader but have a volume shader? act transparent */ - - /* update path state, count as transparent */ - path_state_next(kg, &state, LABEL_TRANSPARENT); - - /* setup ray position, direction stays unchanged */ - ray.P = ray_offset(sd.P, -sd.Ng); -#ifdef __RAY_DIFFERENTIALS__ - ray.dP = sd.dP; -#endif - - /* enter/exit volume */ - kernel_volume_stack_enter_exit(kg, &sd, state.volume_stack); - } -#endif - else { - /* no bsdf or volume? we're done */ + if(!kernel_path_surface_bounce(kg, rng, &sd, &throughput, &state, L, &ray)) break; - } - } -} - -ccl_device_inline bool kernel_path_integrate_lighting(KernelGlobals *kg, RNG *rng, - ShaderData *sd, float3 *throughput, PathState *state, PathRadiance *L, Ray *ray) -{ -#ifdef __EMISSION__ - if(kernel_data.integrator.use_direct_light) { - /* sample illumination from lights to find path contribution */ - if(sd->flag & SD_BSDF_HAS_EVAL) { - float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT); - float light_u, light_v; - path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v); - - Ray light_ray; - BsdfEval L_light; - bool is_lamp; - -#ifdef __OBJECT_MOTION__ - light_ray.time = sd->time; -#endif - - LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); - - if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) { - /* trace shadow ray */ - float3 shadow; - - if(!shadow_blocked(kg, state, &light_ray, &shadow)) { - /* accumulate */ - path_radiance_accum_light(L, *throughput, &L_light, shadow, 1.0f, state->bounce, is_lamp); - } - } - } - } -#endif - - /* no BSDF? we can stop here */ - if(sd->flag & SD_BSDF) { - /* sample BSDF */ - float bsdf_pdf; - BsdfEval bsdf_eval; - float3 bsdf_omega_in; - differential3 bsdf_domega_in; - float bsdf_u, bsdf_v; - path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v); - int label; - - label = shader_bsdf_sample(kg, sd, bsdf_u, bsdf_v, &bsdf_eval, - &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf); - - if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval)) - return false; - - /* modify throughput */ - path_radiance_bsdf_bounce(L, throughput, &bsdf_eval, bsdf_pdf, state->bounce, label); - - /* set labels */ - if(!(label & LABEL_TRANSPARENT)) { - state->ray_pdf = bsdf_pdf; -#ifdef __LAMP_MIS__ - state->ray_t = 0.0f; -#endif - state->min_ray_pdf = fminf(bsdf_pdf, state->min_ray_pdf); - } - - /* update path state */ - path_state_next(kg, state, label); - - /* setup ray */ - ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT)? -sd->Ng: sd->Ng); - ray->D = bsdf_omega_in; - - if(state->bounce == 0) - ray->t -= sd->ray_length; /* clipping works through transparent */ - else - ray->t = FLT_MAX; - -#ifdef __RAY_DIFFERENTIALS__ - ray->dP = sd->dP; - ray->dD = bsdf_domega_in; -#endif - -#ifdef __VOLUME__ - /* enter/exit volume */ - if(label & LABEL_TRANSMIT) - kernel_volume_stack_enter_exit(kg, sd, state->volume_stack); -#endif - return true; - } -#ifdef __VOLUME__ - else if(sd->flag & SD_HAS_ONLY_VOLUME) { - /* no surface shader but have a volume shader? act transparent */ - - /* update path state, count as transparent */ - path_state_next(kg, state, LABEL_TRANSPARENT); - - /* setup ray position, direction stays unchanged */ - ray->P = ray_offset(sd->P, -sd->Ng); -#ifdef __RAY_DIFFERENTIALS__ - ray->dP = sd->dP; -#endif - - /* enter/exit volume */ - kernel_volume_stack_enter_exit(kg, sd, state->volume_stack); - return true; - } -#endif - else { - /* no bsdf or volume? */ - return false; } } @@ -677,8 +623,10 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd hit_state.flag |= PATH_RAY_BSSRDF_ANCESTOR; hit_state.rng_offset += PRNG_BOUNCE_NUM; + + kernel_path_surface_connect_light(kg, rng, &bssrdf_sd[hit], tp, state, L); - if(kernel_path_integrate_lighting(kg, rng, &bssrdf_sd[hit], &tp, &hit_state, L, &hit_ray)) { + if(kernel_path_surface_bounce(kg, rng, &bssrdf_sd[hit], &tp, &hit_state, L, &hit_ray)) { #ifdef __LAMP_MIS__ hit_state.ray_t = 0.0f; #endif @@ -767,7 +715,9 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, &volume_sd, &volume_ray, &L, &throughput, rng); if(result == VOLUME_PATH_SCATTERED) { - if(kernel_path_integrate_scatter_lighting(kg, rng, &volume_sd, &throughput, &state, &L, &ray, 1.0f)) + kernel_path_volume_connect_light(kg, rng, &volume_sd, throughput, &state, &L, 1.0f); + + if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, &state, &L, &ray, 1.0f)) continue; else break; @@ -876,115 +826,13 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, break; } #endif - - /* Same as kernel_path_integrate_lighting(kg, rng, &sd, &throughput, &state, &L, &ray), - but for CUDA the function call is slower. */ -#ifdef __EMISSION__ - if(kernel_data.integrator.use_direct_light) { - /* sample illumination from lights to find path contribution */ - if(sd.flag & SD_BSDF_HAS_EVAL) { - float light_t = path_state_rng_1D(kg, rng, &state, PRNG_LIGHT); - float light_u, light_v; - path_state_rng_2D(kg, rng, &state, PRNG_LIGHT_U, &light_u, &light_v); - Ray light_ray; - BsdfEval L_light; - bool is_lamp; + /* direct lighting */ + kernel_path_surface_connect_light(kg, rng, &sd, throughput, &state, &L); -#ifdef __OBJECT_MOTION__ - light_ray.time = sd.time; -#endif - - LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd.time, sd.P, &ls); - - if(direct_emission(kg, &sd, &ls, &light_ray, &L_light, &is_lamp, state.bounce, state.transparent_bounce)) { - /* trace shadow ray */ - float3 shadow; - - if(!shadow_blocked(kg, &state, &light_ray, &shadow)) { - /* accumulate */ - path_radiance_accum_light(&L, throughput, &L_light, shadow, 1.0f, state.bounce, is_lamp); - } - } - } - } -#endif - - if(sd.flag & SD_BSDF) { - /* sample BSDF */ - float bsdf_pdf; - BsdfEval bsdf_eval; - float3 bsdf_omega_in; - differential3 bsdf_domega_in; - float bsdf_u, bsdf_v; - path_state_rng_2D(kg, rng, &state, PRNG_BSDF_U, &bsdf_u, &bsdf_v); - int label; - - label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval, - &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf); - - if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval)) - break; - - /* modify throughput */ - path_radiance_bsdf_bounce(&L, &throughput, &bsdf_eval, bsdf_pdf, state.bounce, label); - - /* set labels */ - if(!(label & LABEL_TRANSPARENT)) { - state.ray_pdf = bsdf_pdf; -#ifdef __LAMP_MIS__ - state.ray_t = 0.0f; -#endif - state.min_ray_pdf = fminf(bsdf_pdf, state.min_ray_pdf); - } - - /* update path state */ - path_state_next(kg, &state, label); - - /* setup ray */ - ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng); - ray.D = bsdf_omega_in; - -#ifdef __RAY_DIFFERENTIALS__ - ray.dP = sd.dP; - ray.dD = bsdf_domega_in; -#endif - -#ifdef __VOLUME__ - /* enter/exit volume */ - if(label & LABEL_TRANSMIT) - kernel_volume_stack_enter_exit(kg, &sd, state.volume_stack); -#endif - - } -#ifdef __VOLUME__ - else if(sd.flag & SD_HAS_ONLY_VOLUME) { - /* no surface shader but have a volume shader? act transparent */ - - /* update path state, count as transparent */ - path_state_next(kg, &state, LABEL_TRANSPARENT); - - /* setup ray position, direction stays unchanged */ - ray.P = ray_offset(sd.P, -sd.Ng); -#ifdef __RAY_DIFFERENTIALS__ - ray.dP = sd.dP; -#endif - - /* enter/exit volume */ - kernel_volume_stack_enter_exit(kg, &sd, state.volume_stack); - } -#endif - else { - /* no bsdf or volume? we're done */ + /* compute direct lighting and next bounce */ + if(!kernel_path_surface_bounce(kg, rng, &sd, &throughput, &state, &L, &ray)) break; - } - - /* adjust ray distance for clipping */ - if(state.bounce == 0) - ray.t -= sd.ray_length; /* clipping works through transparent */ - else - ray.t = FLT_MAX; } float3 L_sum = path_radiance_clamp_and_sum(kg, &L); @@ -996,17 +844,11 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, #ifdef __BRANCHED_PATH__ -ccl_device_noinline void kernel_branched_path_integrate_lighting(KernelGlobals *kg, +/* branched path tracing: bounce off surface and integrate indirect light */ +ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGlobals *kg, RNG *rng, ShaderData *sd, float3 throughput, float num_samples_adjust, PathState *state, PathRadiance *L) { -#ifdef __EMISSION__ - if(kernel_data.integrator.use_direct_light) { - bool all = kernel_data.integrator.sample_all_lights_direct; - kernel_branched_path_integrate_direct_lighting(kg, rng, sd, state, throughput, num_samples_adjust, L, all); - } -#endif - for(int i = 0; i< sd->num_closure; i++) { const ShaderClosure *sc = &sd->closure[i]; @@ -1127,15 +969,24 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, Shade path_state_branch(&hit_state, j, num_samples); - kernel_branched_path_integrate_lighting(kg, rng, - &bssrdf_sd[hit], throughput, num_samples_inv, - &hit_state, L); +#if defined(__EMISSION__) && defined(__BRANCHED_PATH__) + /* direct light */ + if(kernel_data.integrator.use_direct_light) { + bool all = kernel_data.integrator.sample_all_lights_direct; + kernel_branched_path_surface_connect_light(kg, rng, + &bssrdf_sd[hit], &hit_state, throughput, num_samples_inv, L, all); + } +#endif + + /* indirect light */ + kernel_branched_path_surface_indirect_light(kg, rng, + &bssrdf_sd[hit], throughput, num_samples_inv, + &hit_state, L); } } state->flag &= ~PATH_RAY_BSSRDF_ANCESTOR; } - } #endif @@ -1216,7 +1067,9 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in if(result == VOLUME_PATH_SCATTERED) { /* todo: use all-light sampling */ - if(kernel_path_integrate_scatter_lighting(kg, rng, &volume_sd, &tp, &ps, &L, &pray, num_samples_inv)) { + kernel_path_volume_connect_light(kg, rng, &volume_sd, tp, &state, &L, 1.0f); + + if(kernel_path_volume_bounce(kg, rng, &volume_sd, &tp, &ps, &L, &pray, num_samples_inv)) { kernel_path_indirect(kg, rng, pray, tp*num_samples_inv, num_samples, ps, &L); /* for render passes, sum and reset indirect light pass variables @@ -1367,8 +1220,17 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in if(!(sd.flag & SD_HAS_ONLY_VOLUME)) { PathState hit_state = state; - /* lighting */ - kernel_branched_path_integrate_lighting(kg, rng, +#ifdef __EMISSION__ + /* direct light */ + if(kernel_data.integrator.use_direct_light) { + bool all = kernel_data.integrator.sample_all_lights_direct; + kernel_branched_path_surface_connect_light(kg, rng, + &sd, &hit_state, throughput, 1.0f, &L, all); + } +#endif + + /* indirect light */ + kernel_branched_path_surface_indirect_light(kg, rng, &sd, throughput, 1.0f, &hit_state, &L); /* continue in case of transparency */