[Bf-blender-cvs] [b459d9f] master: Cycles: Stop lamp sampling if the lamp isn't visible

Lukas Stockner noreply at git.blender.org
Wed Sep 14 19:51:02 CEST 2016


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




More information about the Bf-blender-cvs mailing list