Commit: b459d9f46c5355841aae3048c27cf778c0291566
Author: Lukas Stockner
Date:   Fri Sep 9 15:51:40 2016 +0200
Branches: master
https://developer.blender.org/rBb459d9f46c5355841aae3048c27cf778c0291566

Cycles: Stop lamp sampling if the lamp isn't visible

Both spot and area light have large areas where they're not visible.
Therefore, this patch stops the light sampling code when one of these cases 
(outside of the spotlight cone or behind the area light) occurs, before the 
lamp shader is evaluated.
In the case of the area light, the solid angle sampling can also be skipped.

In a test scene with Sample All Lights and 18 Area lamps and 9 Spot lamps that 
all point away from the area that the camera sees, render time drops from 12sec 
to 5sec.

Reviewers: brecht, sergey, dingto, juicyfruit

Differential Revision: https://developer.blender.org/D2216

===================================================================

M       intern/cycles/kernel/kernel_light.h
M       intern/cycles/kernel/kernel_path_surface.h
M       intern/cycles/kernel/kernel_path_volume.h
M       intern/cycles/kernel/split/kernel_direct_lighting.h

===================================================================

diff --git a/intern/cycles/kernel/kernel_light.h 
b/intern/cycles/kernel/kernel_light.h
index 1e99f2c..fffa9af 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -510,7 +510,7 @@ ccl_device float lamp_light_pdf(KernelGlobals *kg, const 
float3 Ng, const float3
        return t*t/cos_pi;
 }
 
-ccl_device_inline void lamp_light_sample(KernelGlobals *kg,
+ccl_device_inline bool lamp_light_sample(KernelGlobals *kg,
                                          int lamp,
                                          float randu, float randv,
                                          float3 P,
@@ -581,6 +581,9 @@ ccl_device_inline void lamp_light_sample(KernelGlobals *kg,
                                /* spot light attenuation */
                                float4 data2 = kernel_tex_fetch(__light_data, 
lamp*LIGHT_SIZE + 2);
                                ls->eval_fac *= spot_light_attenuation(data1, 
data2, ls);
+                               if(ls->eval_fac == 0.0f) {
+                                       return false;
+                               }
                        }
                        ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
                }
@@ -593,6 +596,10 @@ ccl_device_inline void lamp_light_sample(KernelGlobals *kg,
                        float3 axisv = make_float3(data2.y, data2.z, data2.w);
                        float3 D = make_float3(data3.y, data3.z, data3.w);
 
+                       if(dot(ls->P - P, D) > 0.0f) {
+                               return false;
+                       }
+
                        ls->pdf = area_light_sample(P, &ls->P,
                                                  axisu, axisv,
                                                  randu, randv,
@@ -603,13 +610,12 @@ ccl_device_inline void lamp_light_sample(KernelGlobals 
*kg,
 
                        float invarea = data2.x;
                        ls->eval_fac = 0.25f*invarea;
-
-                       if(dot(ls->D, D) > 0.0f)
-                               ls->pdf = 0.0f;
                }
 
                ls->eval_fac *= kernel_data.integrator.inv_pdf_lights;
        }
+
+       return (ls->pdf > 0.0f);
 }
 
 ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 
D, float t, LightSample *ls)
@@ -836,7 +842,7 @@ ccl_device bool 
light_select_reached_max_bounces(KernelGlobals *kg, int index, i
        return (bounce > __float_as_int(data4.x));
 }
 
-ccl_device_noinline void light_sample(KernelGlobals *kg,
+ccl_device_noinline bool light_sample(KernelGlobals *kg,
                                       float randt,
                                       float randu,
                                       float randv,
@@ -857,21 +863,20 @@ ccl_device_noinline void light_sample(KernelGlobals *kg,
                int shader_flag = __float_as_int(l.z);
 
                triangle_light_sample(kg, prim, object, randu, randv, time, ls);
-
                /* compute incoming direction, distance and pdf */
                ls->D = normalize_len(ls->P - P, &ls->t);
                ls->pdf = triangle_light_pdf(kg, ls->Ng, -ls->D, ls->t);
                ls->shader |= shader_flag;
+               return (ls->pdf > 0.0f);
        }
        else {
                int lamp = -prim-1;
 
                if(UNLIKELY(light_select_reached_max_bounces(kg, lamp, 
bounce))) {
-                       ls->pdf = 0.0f;
-                       return;
+                       return false;
                }
 
-               lamp_light_sample(kg, lamp, randu, randv, P, ls);
+               return lamp_light_sample(kg, lamp, randu, randv, P, ls);
        }
 }
 
diff --git a/intern/cycles/kernel/kernel_path_surface.h 
b/intern/cycles/kernel/kernel_path_surface.h
index 250b8e9..27acf81 100644
--- a/intern/cycles/kernel/kernel_path_surface.h
+++ b/intern/cycles/kernel/kernel_path_surface.h
@@ -54,15 +54,15 @@ ccl_device_noinline void 
kernel_branched_path_surface_connect_light(KernelGlobal
                                path_branched_rng_2D(kg, &lamp_rng, state, j, 
num_samples, PRNG_LIGHT_U, &light_u, &light_v);
 
                                LightSample ls;
-                               lamp_light_sample(kg, i, light_u, light_v, 
ccl_fetch(sd, P), &ls);
-
-                               if(direct_emission(kg, sd, emission_sd, &ls, 
state, &light_ray, &L_light, &is_lamp)) {
-                                       /* trace shadow ray */
-                                       float3 shadow;
-
-                                       if(!shadow_blocked(kg, emission_sd, 
state, &light_ray, &shadow)) {
-                                               /* accumulate */
-                                               path_radiance_accum_light(L, 
throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, 
is_lamp);
+                               if(lamp_light_sample(kg, i, light_u, light_v, 
ccl_fetch(sd, P), &ls)) {
+                                       if(direct_emission(kg, sd, emission_sd, 
&ls, state, &light_ray, &L_light, &is_lamp)) {
+                                               /* trace shadow ray */
+                                               float3 shadow;
+
+                                               if(!shadow_blocked(kg, 
emission_sd, state, &light_ray, &shadow)) {
+                                                       /* accumulate */
+                                                       
path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, 
num_samples_inv, state->bounce, is_lamp);
+                                               }
                                        }
                                }
                        }
@@ -86,15 +86,15 @@ ccl_device_noinline void 
kernel_branched_path_surface_connect_light(KernelGlobal
                                        light_t = 0.5f*light_t;
 
                                LightSample ls;
-                               light_sample(kg, light_t, light_u, light_v, 
ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls);
-
-                               if(direct_emission(kg, sd, emission_sd, &ls, 
state, &light_ray, &L_light, &is_lamp)) {
-                                       /* trace shadow ray */
-                                       float3 shadow;
-
-                                       if(!shadow_blocked(kg, emission_sd, 
state, &light_ray, &shadow)) {
-                                               /* accumulate */
-                                               path_radiance_accum_light(L, 
throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, 
is_lamp);
+                               if(light_sample(kg, light_t, light_u, light_v, 
ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls)) {
+                                       if(direct_emission(kg, sd, emission_sd, 
&ls, state, &light_ray, &L_light, &is_lamp)) {
+                                               /* trace shadow ray */
+                                               float3 shadow;
+
+                                               if(!shadow_blocked(kg, 
emission_sd, state, &light_ray, &shadow)) {
+                                                       /* accumulate */
+                                                       
path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, 
num_samples_inv, state->bounce, is_lamp);
+                                               }
                                        }
                                }
                        }
@@ -107,16 +107,16 @@ ccl_device_noinline void 
kernel_branched_path_surface_connect_light(KernelGlobal
                path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, 
&light_v);
 
                LightSample ls;
-               light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, 
time), ccl_fetch(sd, P), state->bounce, &ls);
-
-               /* sample random light */
-               if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, 
&L_light, &is_lamp)) {
-                       /* trace shadow ray */
-                       float3 shadow;
-
-                       if(!shadow_blocked(kg, emission_sd, state, &light_ray, 
&shadow)) {
-                               /* accumulate */
-                               path_radiance_accum_light(L, 
throughput*num_samples_adjust, &L_light, shadow, num_samples_adjust, 
state->bounce, is_lamp);
+               if(light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, 
time), ccl_fetch(sd, P), state->bounce, &ls)) {
+                       /* sample random light */
+                       if(direct_emission(kg, sd, emission_sd, &ls, state, 
&light_ray, &L_light, &is_lamp)) {
+                               /* trace shadow ray */
+                               float3 shadow;
+
+                               if(!shadow_blocked(kg, emission_sd, state, 
&light_ray, &shadow)) {
+                                       /* accumulate */
+                                       path_radiance_accum_light(L, 
throughput*num_samples_adjust, &L_light, shadow, num_samples_adjust, 
state->bounce, is_lamp);
+                               }
                        }
                }
        }
@@ -206,15 +206,15 @@ ccl_device_inline void 
kernel_path_surface_connect_light(KernelGlobals *kg, ccl_
 #endif
 
        LightSample ls;
-       light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), 
ccl_fetch(sd, P), state->bounce, &ls);
-
-       if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, 
&L_light, &is_lamp)) {
-               /* trace shadow ray */
-               float3 shadow;
+       if(light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), 
ccl_fetch(sd, P), state->bounce, &ls)) {
+               if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, 
&L_light, &is_lamp)) {
+                       /* trace shadow ray */
+                       float3 shadow;
 
-               if(!shadow_blocked(kg, emission_sd, state, &light_ray, 
&shadow)) {
-                       /* accumulate */
-                       path_radiance_accum_light(L, throughput, &L_light, 
shadow, 1.0f, state->bounce, is_lamp);
+                       if(!shadow_blocked(kg, emission_sd, state, &light_ray, 
&shadow)) {
+                               /* accumulate */
+                               path_radiance_accum_light(L, throughput, 
&L_light, shadow, 1.0f, state->bounce, is_lamp);
+                       }
                }
        }
 #endif
diff --git a/intern/cycles/kernel/kernel_path_volume.h 
b/intern/cycles/kernel/kernel_path_volume.h
index 5fd4f2f..0bb8f1c 100644
--- a/intern/cycles/kernel/kernel_path_volume.h
+++ b/intern/cycles/kernel/kernel_path_volume.h
@@ -46,17 +46,16 @@ ccl_device_inline void kernel_path_volume_connect_light(
        light_ray.time = sd->time;
 #  endif
 
-       light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, 
state->bounce, &ls);
-       if(ls.pdf == 0.0f)
-               return;
-       
-       if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, 
&L_light, &is_lamp)) {
-               /* trace shadow ray */
-               float3 shadow;
+       if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, 
state->bounce, &ls))
+       {
+               if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, 
&L_light, &is_lamp)) {
+                       /* trace shadow ray */
+                       float3 shadow;
 
-               if(!shadow_blocked(kg, emission_sd, state, &light_ray, 
&shadow)) {
-                       /* accumulate */
-                       path_radiance_accum_light(L, throughput, &L_light, 
shadow, 1.0f, state->bounce, is_lamp);
+                       if(!shadow_blocked(kg, emission_sd, state, &light_ray, 
&shadow)) {
+                               /* accumulate */
+                               path_radiance_accum_light(L, throughput, 
&L_light, shadow, 1.0f, state->bounce, is_lamp);
+                       }
                }
        }
 #endif
@@ -146,7 +145,7 @@ ccl_device void 
kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
                                path_branched_rng_2D(kg, &lamp_rng, 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);                
+                               lamp_light_sample(kg, i, light_u, light_v, 
ray->P, &ls);
 
                                float3 tp = throughput;
 
@@ -156,23 +155,20 @@ ccl_device void 
kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
 
                                VolumeIntegrateResult result = 
kernel_volume_decoupled_scatter(kg,
                                        state, ray, sd, &tp, rphase, rscatter, 
segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
-                                       
+
                                (void)result;
                                kernel_assert(result == VOLUME_PATH_SCATTERED);
 
                                /* todo: split up light_sample so we don't have 
to call it again with new position */
-                               lamp_light_sample(kg, i, light_u, light_v, 
sd->P, &ls);
-
-                               if(ls.pdf == 0.0f)
-                                       continue;
-
-                               if(direct_emission(kg, sd, emission_sd, &ls, 
state, &light_ray, &L_light, &is_lamp)) {
-                                       /* trace shadow ray */
-                                       float3 shadow;
-
-                                       if(!shadow_blocked(kg, emission_sd, 
state, &light_ray, &shadow)) {
-                                               /* accumulate */
-                                               path_radiance_accum_light(L, 
tp*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
+                               if(lamp_light_sample(kg, i, light_u, light_v, 
sd->P, 

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to