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
This commit is contained in:
Patrick Mours
2019-08-25 18:11:41 +02:00
committed by Brecht Van Lommel
parent f491c23f1e
commit fd52dc58dd
5 changed files with 233 additions and 324 deletions

View File

@@ -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);
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;
/* 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 (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);
}
else {
int lamp = -prim - 1;
if (UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) {
return false;
triangle_light_sample(kg, prim, object, randu, randv, time, ls, P);
ls->shader |= shader_flag;
return (ls->pdf > 0.0f);
}
return lamp_light_sample(kg, lamp, randu, randv, P, ls);
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);
}
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;
}

View File

@@ -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__

View File

@@ -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;
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;
}
}
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;
}
}
float num_samples_inv = num_samples_adjust / (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;
light_ray.time = sd->time;
# endif
bool has_emission = false;
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++) {
if (kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL)) {
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;
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);
}
}
}
}
}
/* 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;
for (int j = 0; j < num_samples; j++) {
float light_u, light_v;
path_branched_rng_2D(
kg, state->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);
/* 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;
/* trace shadow ray */
float3 shadow;
if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &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
}

View File

@@ -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;
num_lights = kernel_data.integrator.num_all_lights;
if (kernel_data.integrator.pdf_triangles != 0.0f) {
num_lights += 1;
}
}
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 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;
for (int j = 0; j < num_samples; j++) {
/* sample random position on given light */
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;
}
}
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;
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, 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);
/* 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);
}
}
}
}
}
/* 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;
for (int j = 0; j < num_samples; j++) {
/* sample random position on random 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);
/* 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);
/* trace shadow ray */
float3 shadow;
float3 tp = throughput;
const bool blocked = shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow);
/* 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);
}
if (has_emission && !blocked) {
/* accumulate */
path_radiance_accum_light(
L, state, tp * num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp);
}
}
}

View File

@@ -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;