diff options
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/kernel/kernel_light.h | 61 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path.h | 10 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path_surface.h | 241 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path_volume.h | 244 | ||||
-rw-r--r-- | intern/cycles/kernel/split/kernel_direct_lighting.h | 3 |
5 files changed, 234 insertions, 325 deletions
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 758e91159b6..ce908ce0fe2 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -1076,7 +1076,7 @@ ccl_device int light_distribution_sample(KernelGlobals *kg, float *randu) int len = kernel_data.integrator.num_distribution + 1; float r = *randu; - while (len > 0) { + do { int half_len = len >> 1; int middle = first + half_len; @@ -1087,7 +1087,7 @@ ccl_device int light_distribution_sample(KernelGlobals *kg, float *randu) first = middle + 1; len = len - half_len - 1; } - } + } while (len > 0); /* Clamping should not be needed but float rounding errors seem to * make this fail on rare occasions. */ @@ -1104,42 +1104,49 @@ ccl_device int light_distribution_sample(KernelGlobals *kg, float *randu) /* Generic Light */ -ccl_device bool light_select_reached_max_bounces(KernelGlobals *kg, int index, int bounce) +ccl_device_inline bool light_select_reached_max_bounces(KernelGlobals *kg, int index, int bounce) { return (bounce > kernel_tex_fetch(__lights, index).max_bounces); } -ccl_device_noinline bool light_sample( - KernelGlobals *kg, float randu, float randv, float time, float3 P, int bounce, LightSample *ls) +ccl_device_noinline bool light_sample(KernelGlobals *kg, + int lamp, + float randu, + float randv, + float time, + float3 P, + int bounce, + LightSample *ls) { - /* sample index */ - int index = light_distribution_sample(kg, &randu); - - /* fetch light data */ - const ccl_global KernelLightDistribution *kdistribution = &kernel_tex_fetch(__light_distribution, - index); - int prim = kdistribution->prim; - - if (prim >= 0) { - int object = kdistribution->mesh_light.object_id; - int shader_flag = kdistribution->mesh_light.shader_flag; + if (lamp < 0) { + /* sample index */ + int index = light_distribution_sample(kg, &randu); + + /* fetch light data */ + const ccl_global KernelLightDistribution *kdistribution = &kernel_tex_fetch( + __light_distribution, index); + int prim = kdistribution->prim; + + if (prim >= 0) { + int object = kdistribution->mesh_light.object_id; + int shader_flag = kdistribution->mesh_light.shader_flag; + + triangle_light_sample(kg, prim, object, randu, randv, time, ls, P); + ls->shader |= shader_flag; + return (ls->pdf > 0.0f); + } - triangle_light_sample(kg, prim, object, randu, randv, time, ls, P); - ls->shader |= shader_flag; - return (ls->pdf > 0.0f); + lamp = -prim - 1; } - else { - int lamp = -prim - 1; - if (UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) { - return false; - } - - return lamp_light_sample(kg, lamp, randu, randv, P, ls); + if (UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) { + return false; } + + return lamp_light_sample(kg, lamp, randu, randv, P, ls); } -ccl_device int light_select_num_samples(KernelGlobals *kg, int index) +ccl_device_inline int light_select_num_samples(KernelGlobals *kg, int index) { return kernel_tex_fetch(__lights, index).samples; } diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 1e8d54a23bf..63be0a7f505 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -474,12 +474,10 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, # endif /* __SUBSURFACE__ */ # if defined(__EMISSION__) - if (kernel_data.integrator.use_direct_light) { - int all = (kernel_data.integrator.sample_all_lights_indirect) || - (state->flag & PATH_RAY_SHADOW_CATCHER); - kernel_branched_path_surface_connect_light( - kg, sd, emission_sd, state, throughput, 1.0f, L, all); - } + int all = (kernel_data.integrator.sample_all_lights_indirect) || + (state->flag & PATH_RAY_SHADOW_CATCHER); + kernel_branched_path_surface_connect_light( + kg, sd, emission_sd, state, throughput, 1.0f, L, all); # endif /* defined(__EMISSION__) */ # ifdef __VOLUME__ diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h index 07444a98d82..d299106ea96 100644 --- a/intern/cycles/kernel/kernel_path_surface.h +++ b/intern/cycles/kernel/kernel_path_surface.h @@ -32,140 +32,100 @@ ccl_device_noinline_cpu void kernel_branched_path_surface_connect_light( { # ifdef __EMISSION__ /* sample illumination from lights to find path contribution */ - if (!(sd->flag & SD_BSDF_HAS_EVAL)) - return; - - Ray light_ray; BsdfEval L_light; - bool is_lamp; - -# ifdef __OBJECT_MOTION__ - light_ray.time = sd->time; -# endif - - if (sample_all_lights) { - /* lamp sampling */ - for (int i = 0; i < kernel_data.integrator.num_all_lights; i++) { - if (UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce))) - continue; - - int num_samples = ceil_to_int(num_samples_adjust * light_select_num_samples(kg, i)); - float num_samples_inv = num_samples_adjust / - (num_samples * kernel_data.integrator.num_all_lights); - uint lamp_rng_hash = cmj_hash(state->rng_hash, i); - - for (int j = 0; j < num_samples; j++) { - float light_u, light_v; - path_branched_rng_2D( - kg, lamp_rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v); - float terminate = path_branched_rng_light_termination( - kg, lamp_rng_hash, state, j, num_samples); - LightSample ls; - if (lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) { - /* The sampling probability returned by lamp_light_sample assumes that all lights were - * sampled. - * However, this code only samples lamps, so if the scene also had mesh lights, the real - * probability is twice as high. */ - if (kernel_data.integrator.pdf_triangles != 0.0f) - ls.pdf *= 2.0f; + int num_lights = 0; + if (kernel_data.integrator.use_direct_light) { + if (sample_all_lights) { + num_lights = kernel_data.integrator.num_all_lights; + if (kernel_data.integrator.pdf_triangles != 0.0f) { + num_lights += 1; + } + } + else { + num_lights = 1; + } + } - if (direct_emission( - kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) { - /* trace shadow ray */ - float3 shadow; - - if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) { - /* accumulate */ - path_radiance_accum_light(L, - state, - throughput * num_samples_inv, - &L_light, - shadow, - num_samples_inv, - is_lamp); - } - else { - path_radiance_accum_total_light(L, state, throughput * num_samples_inv, &L_light); - } - } + for (int i = 0; i < num_lights; i++) { + /* sample one light at random */ + int num_samples = 1; + int num_all_lights = 1; + uint lamp_rng_hash = state->rng_hash; + bool double_pdf = false; + bool is_mesh_light = false; + bool is_lamp = false; + + if (sample_all_lights) { + /* lamp sampling */ + is_lamp = i < kernel_data.integrator.num_all_lights; + if (is_lamp) { + if (UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce))) { + continue; } + num_samples = ceil_to_int(num_samples_adjust * light_select_num_samples(kg, i)); + num_all_lights = kernel_data.integrator.num_all_lights; + lamp_rng_hash = cmj_hash(state->rng_hash, i); + double_pdf = kernel_data.integrator.pdf_triangles != 0.0f; + } + /* mesh light sampling */ + else { + num_samples = ceil_to_int(num_samples_adjust * kernel_data.integrator.mesh_light_samples); + double_pdf = kernel_data.integrator.num_all_lights != 0; + is_mesh_light = true; } } - /* mesh light sampling */ - if (kernel_data.integrator.pdf_triangles != 0.0f) { - int num_samples = ceil_to_int(num_samples_adjust * - kernel_data.integrator.mesh_light_samples); - float num_samples_inv = num_samples_adjust / num_samples; + float num_samples_inv = num_samples_adjust / (num_samples * num_all_lights); - for (int j = 0; j < num_samples; j++) { + for (int j = 0; j < num_samples; j++) { + Ray light_ray; + light_ray.t = 0.0f; /* reset ray */ +# ifdef __OBJECT_MOTION__ + light_ray.time = sd->time; +# endif + bool has_emission = false; + + if (kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL)) { float light_u, light_v; path_branched_rng_2D( - kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v); + kg, lamp_rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v); float terminate = path_branched_rng_light_termination( - kg, state->rng_hash, state, j, num_samples); + kg, lamp_rng_hash, state, j, num_samples); /* only sample triangle lights */ - if (kernel_data.integrator.num_all_lights) + if (is_mesh_light && double_pdf) { light_u = 0.5f * light_u; + } LightSample ls; - if (light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { - /* Same as above, probability needs to be corrected since the sampling was forced to - * select a mesh light. */ - if (kernel_data.integrator.num_all_lights) + const int lamp = is_lamp ? i : -1; + if (light_sample(kg, lamp, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { + /* The sampling probability returned by lamp_light_sample assumes that all lights were + * sampled. However, this code only samples lamps, so if the scene also had mesh lights, + * the real probability is twice as high. */ + if (double_pdf) { ls.pdf *= 2.0f; - - if (direct_emission( - kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) { - /* trace shadow ray */ - float3 shadow; - - if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) { - /* accumulate */ - path_radiance_accum_light(L, - state, - throughput * num_samples_inv, - &L_light, - shadow, - num_samples_inv, - is_lamp); - } - else { - path_radiance_accum_total_light(L, state, throughput * num_samples_inv, &L_light); - } } + + has_emission = direct_emission( + kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate); } } - } - } - else { - /* sample one light at random */ - float light_u, light_v; - path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v); - float terminate = path_state_rng_light_termination(kg, state); - LightSample ls; - if (light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { - /* sample random light */ - if (direct_emission( - kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) { - /* trace shadow ray */ - float3 shadow; - - if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) { + /* trace shadow ray */ + float3 shadow; + + const bool blocked = shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow); + + if (has_emission) { + if (!blocked) { /* accumulate */ - path_radiance_accum_light(L, - state, - throughput * num_samples_adjust, - &L_light, - shadow, - num_samples_adjust, - is_lamp); + path_radiance_accum_light( + L, state, throughput * num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp); } else { - path_radiance_accum_total_light(L, state, throughput * num_samples_adjust, &L_light); + path_radiance_accum_total_light(L, state, throughput * num_samples_inv, &L_light); } } } @@ -255,45 +215,48 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, PROFILING_INIT(kg, PROFILING_CONNECT_LIGHT); #ifdef __EMISSION__ - if (!(kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL))) - return; - # ifdef __SHADOW_TRICKS__ - if (state->flag & PATH_RAY_SHADOW_CATCHER) { - kernel_branched_path_surface_connect_light(kg, sd, emission_sd, state, throughput, 1.0f, L, 1); - return; - } -# endif - + int all = (state->flag & PATH_RAY_SHADOW_CATCHER); + kernel_branched_path_surface_connect_light(kg, sd, emission_sd, state, throughput, 1.0f, L, all); +# else /* sample illumination from lights to find path contribution */ - float light_u, light_v; - path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v); - Ray light_ray; BsdfEval L_light; - bool is_lamp; + bool is_lamp = false; + bool has_emission = false; -# ifdef __OBJECT_MOTION__ + light_ray.t = 0.0f; +# ifdef __OBJECT_MOTION__ light_ray.time = sd->time; -# endif +# endif - LightSample ls; - if (light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { - float terminate = path_state_rng_light_termination(kg, state); - if (direct_emission( - kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) { - /* trace shadow ray */ - float3 shadow; + if (kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL)) { + float light_u, light_v; + path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v); - if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) { - /* accumulate */ - path_radiance_accum_light(L, state, throughput, &L_light, shadow, 1.0f, is_lamp); - } - else { - path_radiance_accum_total_light(L, state, throughput, &L_light); - } + LightSample ls; + if (light_sample(kg, -1, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { + float terminate = path_state_rng_light_termination(kg, state); + has_emission = direct_emission( + kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate); + } + } + + /* trace shadow ray */ + float3 shadow; + + const bool blocked = shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow); + + if (has_emission) { + if (!blocked) { + /* accumulate */ + path_radiance_accum_light(L, state, throughput, &L_light, shadow, 1.0f, is_lamp); + } + else { + path_radiance_accum_total_light(L, state, throughput, &L_light); } } +# endif #endif } diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h index 82975c2ad26..6b62005d19a 100644 --- a/intern/cycles/kernel/kernel_path_volume.h +++ b/intern/cycles/kernel/kernel_path_volume.h @@ -26,34 +26,39 @@ ccl_device_inline void kernel_path_volume_connect_light(KernelGlobals *kg, PathRadiance *L) { # ifdef __EMISSION__ - if (!kernel_data.integrator.use_direct_light) - return; - /* sample illumination from lights to find path contribution */ - float light_u, light_v; - path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v); - Ray light_ray; BsdfEval L_light; - LightSample ls; - bool is_lamp; + bool is_lamp = false; + bool has_emission = false; + light_ray.t = 0.0f; +# ifdef __OBJECT_MOTION__ /* connect to light from given point where shader has been evaluated */ light_ray.time = sd->time; +# endif - if (light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { - float terminate = path_state_rng_light_termination(kg, state); - if (direct_emission( - kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) { - /* trace shadow ray */ - float3 shadow; + if (kernel_data.integrator.use_direct_light) { + float light_u, light_v; + path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v); - if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) { - /* accumulate */ - path_radiance_accum_light(L, state, throughput, &L_light, shadow, 1.0f, is_lamp); - } + LightSample ls; + if (light_sample(kg, -1, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { + float terminate = path_state_rng_light_termination(kg, state); + has_emission = direct_emission( + kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate); } } + + /* trace shadow ray */ + float3 shadow; + + const bool blocked = shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow); + + if (has_emission && !blocked) { + /* accumulate */ + path_radiance_accum_light(L, state, throughput, &L_light, shadow, 1.0f, is_lamp); + } # endif /* __EMISSION__ */ } @@ -122,7 +127,7 @@ ccl_device_noinline_cpu bool kernel_path_volume_bounce(KernelGlobals *kg, return true; } -# ifndef __SPLIT_KERNEL__ +# if !defined(__SPLIT_KERNEL__) && (defined(__BRANCHED_PATH__) || defined(__VOLUME_DECOUPLED__)) ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, ShaderData *sd, ShaderData *emission_sd, @@ -134,96 +139,71 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, const VolumeSegment *segment) { # ifdef __EMISSION__ - if (!kernel_data.integrator.use_direct_light) - return; - - Ray light_ray; BsdfEval L_light; - bool is_lamp; - - light_ray.time = sd->time; + int num_lights = 1; if (sample_all_lights) { - /* lamp sampling */ - for (int i = 0; i < kernel_data.integrator.num_all_lights; i++) { - if (UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce))) - continue; - - int num_samples = light_select_num_samples(kg, i); - float num_samples_inv = 1.0f / (num_samples * kernel_data.integrator.num_all_lights); - uint lamp_rng_hash = cmj_hash(state->rng_hash, i); - - for (int j = 0; j < num_samples; j++) { - /* sample random position on given light */ - float light_u, light_v; - path_branched_rng_2D( - kg, lamp_rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v); - - LightSample ls; - lamp_light_sample(kg, i, light_u, light_v, ray->P, &ls); - - float3 tp = throughput; - - /* sample position on volume segment */ - float rphase = path_branched_rng_1D( - kg, state->rng_hash, state, j, num_samples, PRNG_PHASE_CHANNEL); - float rscatter = path_branched_rng_1D( - kg, state->rng_hash, state, j, num_samples, PRNG_SCATTER_DISTANCE); - - VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg, - state, - ray, - sd, - &tp, - rphase, - rscatter, - segment, - (ls.t != FLT_MAX) ? &ls.P : - NULL, - false); + num_lights = kernel_data.integrator.num_all_lights; + if (kernel_data.integrator.pdf_triangles != 0.0f) { + num_lights += 1; + } + } - /* todo: split up light_sample so we don't have to call it again with new position */ - if (result == VOLUME_PATH_SCATTERED && - lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) { - if (kernel_data.integrator.pdf_triangles != 0.0f) - ls.pdf *= 2.0f; - - float terminate = path_branched_rng_light_termination( - kg, state->rng_hash, state, j, num_samples); - if (direct_emission( - kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) { - /* trace shadow ray */ - float3 shadow; - - if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) { - /* accumulate */ - path_radiance_accum_light( - L, state, tp * num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp); - } - } + for (int i = 0; i < num_lights; ++i) { + /* sample one light at random */ + int num_samples = 1; + int num_all_lights = 1; + uint lamp_rng_hash = state->rng_hash; + bool double_pdf = false; + bool is_mesh_light = false; + bool is_lamp = false; + + if (sample_all_lights) { + /* lamp sampling */ + is_lamp = i < kernel_data.integrator.num_all_lights; + if (is_lamp) { + if (UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce))) { + continue; } + num_samples = light_select_num_samples(kg, i); + num_all_lights = kernel_data.integrator.num_all_lights; + lamp_rng_hash = cmj_hash(state->rng_hash, i); + double_pdf = kernel_data.integrator.pdf_triangles != 0.0f; + } + /* mesh light sampling */ + else { + num_samples = kernel_data.integrator.mesh_light_samples; + double_pdf = kernel_data.integrator.num_all_lights != 0; + is_mesh_light = true; } } - /* mesh light sampling */ - if (kernel_data.integrator.pdf_triangles != 0.0f) { - int num_samples = kernel_data.integrator.mesh_light_samples; - float num_samples_inv = 1.0f / num_samples; + float num_samples_inv = 1.0f / (num_samples * num_all_lights); + + for (int j = 0; j < num_samples; j++) { + Ray light_ray; + light_ray.t = 0.0f; /* reset ray */ +# ifdef __OBJECT_MOTION__ + light_ray.time = sd->time; +# endif + bool has_emission = false; - for (int j = 0; j < num_samples; j++) { - /* sample random position on random triangle */ + float3 tp = throughput; + + if (kernel_data.integrator.use_direct_light) { + /* sample random position on random light/triangle */ float light_u, light_v; path_branched_rng_2D( - kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v); + kg, lamp_rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v); /* only sample triangle lights */ - if (kernel_data.integrator.num_all_lights) + if (is_mesh_light && double_pdf) { light_u = 0.5f * light_u; + } LightSample ls; - light_sample(kg, light_u, light_v, sd->time, ray->P, state->bounce, &ls); - - float3 tp = throughput; + const int lamp = is_lamp ? i : -1; + light_sample(kg, lamp, light_u, light_v, sd->time, ray->P, state->bounce, &ls); /* sample position on volume segment */ float rphase = path_branched_rng_1D( @@ -243,69 +223,31 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, NULL, false); - /* todo: split up light_sample so we don't have to call it again with new position */ - if (result == VOLUME_PATH_SCATTERED && - light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { - if (kernel_data.integrator.num_all_lights) - ls.pdf *= 2.0f; - - float terminate = path_branched_rng_light_termination( - kg, state->rng_hash, state, j, num_samples); - if (direct_emission( - kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) { - /* trace shadow ray */ - float3 shadow; - - if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) { - /* accumulate */ - path_radiance_accum_light( - L, state, tp * num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp); + if (result == VOLUME_PATH_SCATTERED) { + /* todo: split up light_sample so we don't have to call it again with new position */ + if (light_sample(kg, lamp, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { + if (double_pdf) { + ls.pdf *= 2.0f; } + + /* sample random light */ + float terminate = path_branched_rng_light_termination( + kg, state->rng_hash, state, j, num_samples); + has_emission = direct_emission( + kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate); } } } - } - } - else { - /* sample random position on random light */ - float light_u, light_v; - path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v); - LightSample ls; - light_sample(kg, light_u, light_v, sd->time, ray->P, state->bounce, &ls); - - float3 tp = throughput; - - /* sample position on volume segment */ - float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL); - float rscatter = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE); - - VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg, - state, - ray, - sd, - &tp, - rphase, - rscatter, - segment, - (ls.t != FLT_MAX) ? &ls.P : - NULL, - false); - - /* todo: split up light_sample so we don't have to call it again with new position */ - if (result == VOLUME_PATH_SCATTERED && - light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { - /* sample random light */ - float terminate = path_state_rng_light_termination(kg, state); - if (direct_emission( - kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) { - /* trace shadow ray */ - float3 shadow; - - if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) { - /* accumulate */ - path_radiance_accum_light(L, state, tp, &L_light, shadow, 1.0f, is_lamp); - } + /* trace shadow ray */ + float3 shadow; + + const bool blocked = shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow); + + if (has_emission && !blocked) { + /* accumulate */ + path_radiance_accum_light( + L, state, tp * num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp); } } } diff --git a/intern/cycles/kernel/split/kernel_direct_lighting.h b/intern/cycles/kernel/split/kernel_direct_lighting.h index b2ca59d60cc..3be2b35812f 100644 --- a/intern/cycles/kernel/split/kernel_direct_lighting.h +++ b/intern/cycles/kernel/split/kernel_direct_lighting.h @@ -86,8 +86,7 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg, float terminate = path_state_rng_light_termination(kg, state); LightSample ls; - if (light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { - + if (light_sample(kg, -1, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) { Ray light_ray; light_ray.time = sd->time; |