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:
authorPatrick Mours <pmours@nvidia.com>2019-08-25 19:11:41 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2019-08-26 11:26:53 +0300
commitfd52dc58ddea642b7162b01538c0c6c48abb0507 (patch)
tree21df79cee59c14c0cada5c4bc49da3824d4c8a4b
parentf491c23f1e104998752380b930307e7abc4597b3 (diff)
Cycles: GPU code generation optimizations for direct lighting
Use a single loop to iterate over all lights, reducing divergence and amount of code to generate. Moving ray intersection calls out of conditionals will also help the Optix compiler. Ref D5363
-rw-r--r--intern/cycles/kernel/kernel_light.h61
-rw-r--r--intern/cycles/kernel/kernel_path.h10
-rw-r--r--intern/cycles/kernel/kernel_path_surface.h241
-rw-r--r--intern/cycles/kernel/kernel_path_volume.h244
-rw-r--r--intern/cycles/kernel/split/kernel_direct_lighting.h3
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;