[Bf-blender-cvs] [99e20d7] master: Cycles: Option to Sample all Lights in the Branched Path integrator for indirect samples

Thomas Dinges noreply at git.blender.org
Sun Mar 9 22:20:55 CET 2014


Commit: 99e20d7b8930479edfacae246a529e03b84264ae
Author: Thomas Dinges
Date:   Sun Mar 9 22:19:27 2014 +0100
https://developer.blender.org/rB99e20d7b8930479edfacae246a529e03b84264ae

Cycles: Option to Sample all Lights in the Branched Path integrator for indirect samples

This adds a new option "Sample All Lights" to the Sampling panel in Cycles (Branched Path). When enabled, Cycles will sample all the lights in the scene for the indirect samples, instead of randomly picking one. This is already happening for direct samples, now you can optionally enable it for indirect.

Example file and renders:
Blend file: http://www.pasteall.org/blend/27411
Random: http://www.pasteall.org/pic/show.php?id=68033
All: http://www.pasteall.org/pic/show.php?id=68034

Sampling all lights is a bit slower, but there is less variance, so it should help in situations with many lights.

Patch by myself with some tweaks by Brecht.
Differential Revision: https://developer.blender.org/D391

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

M	intern/cycles/blender/addon/properties.py
M	intern/cycles/blender/addon/ui.py
M	intern/cycles/blender/blender_sync.cpp
M	intern/cycles/kernel/kernel_path.h
M	intern/cycles/kernel/kernel_types.h
M	intern/cycles/render/integrator.cpp
M	intern/cycles/render/integrator.h

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

diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index e267ea4..875f9d3 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -252,6 +252,11 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
                 items=enum_use_layer_samples,
                 default='USE',
                 )
+        cls.sample_all_lights_indirect = BoolProperty(
+                name="Sample All Lights",
+                description="Sample all lights (for indirect samples), rather than randomly picking one",
+                default=False,
+                )
 
         cls.no_caustics = BoolProperty(
                 name="No Caustics",
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index a313826..da334e2 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -133,6 +133,8 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
             sub.label(text="AA Samples:")
             sub.prop(cscene, "aa_samples", text="Render")
             sub.prop(cscene, "preview_aa_samples", text="Preview")
+            sub.separator()
+            sub.prop(cscene, "sample_all_lights_indirect")
 
             col = split.column()
             sub = col.column(align=True)
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 1d507ed..202eff4 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -197,6 +197,8 @@ void BlenderSync::sync_integrator()
 #endif
 
 	integrator->method = (Integrator::Method)get_enum(cscene, "progressive");
+	
+	integrator->sample_all_lights_indirect = get_boolean(cscene, "sample_all_lights_indirect");
 
 	int diffuse_samples = get_int(cscene, "diffuse_samples");
 	int glossy_samples = get_int(cscene, "glossy_samples");
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 6352014..000b241 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -133,6 +133,93 @@ ccl_device_inline bool kernel_path_integrate_scatter_lighting(KernelGlobals *kg,
 
 #if defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__)
 
+ccl_device void kernel_branched_path_integrate_direct_lighting(KernelGlobals *kg, RNG *rng,
+	ShaderData *sd, PathState *state, float3 throughput, float num_samples_adjust, PathRadiance *L, bool sample_all_lights)
+{
+	/* sample illumination from lights to find path contribution */
+	if(sd->flag & SD_BSDF_HAS_EVAL) {
+		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++) {
+				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);
+				RNG lamp_rng = cmj_hash(*rng, i);
+
+				if(kernel_data.integrator.pdf_triangles != 0.0f)
+					num_samples_inv *= 0.5f;
+
+				for(int j = 0; j < num_samples; j++) {
+					float light_u, light_v;
+					path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
+
+					if(direct_emission(kg, sd, i, 0.0f, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce)) {
+						/* trace shadow ray */
+						float3 shadow;
+
+						if(!shadow_blocked(kg, state, &light_ray, &shadow)) {
+							/* accumulate */
+							path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
+						}
+					}
+				}
+			}
+
+			/* 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;
+
+				if(kernel_data.integrator.num_all_lights)
+					num_samples_inv *= 0.5f;
+
+				for(int j = 0; j < num_samples; j++) {
+					float light_t = path_branched_rng_1D(kg, rng, state, j, num_samples, PRNG_LIGHT);
+					float light_u, light_v;
+					path_branched_rng_2D(kg, rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
+
+					/* only sample triangle lights */
+					if(kernel_data.integrator.num_all_lights)
+						light_t = 0.5f*light_t;
+
+					if(direct_emission(kg, sd, -1, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce)) {
+						/* trace shadow ray */
+						float3 shadow;
+
+						if(!shadow_blocked(kg, state, &light_ray, &shadow)) {
+							/* accumulate */
+							path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
+						}
+					}
+				}
+			}
+		}
+		else {
+			float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
+			float light_u, light_v;
+			path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
+
+			/* sample random light */
+			if(direct_emission(kg, sd, -1, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce)) {
+				/* trace shadow ray */
+				float3 shadow;
+
+				if(!shadow_blocked(kg, state, &light_ray, &shadow)) {
+					/* accumulate */
+					path_radiance_accum_light(L, throughput, &L_light, shadow, 1.0f, state->bounce, is_lamp);
+				}
+			}
+		}
+	}
+}
+
 ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, ccl_global float *buffer,
 	float3 throughput, int num_samples, PathState state, PathRadiance *L)
 {
@@ -302,36 +389,8 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, ccl_g
 
 #ifdef __EMISSION__
 		if(kernel_data.integrator.use_direct_light) {
-			/* sample illumination from lights to find path contribution */
-			if(sd.flag & SD_BSDF_HAS_EVAL) {
-				float light_t = path_state_rng_1D(kg, rng, &state, PRNG_LIGHT);
-#ifdef __MULTI_CLOSURE__
-				float light_o = 0.0f;
-#else
-				float light_o = path_state_rng_1D(kg, rng, &state, PRNG_LIGHT_F);
-#endif
-				float light_u, light_v;
-				path_state_rng_2D(kg, rng, &state, PRNG_LIGHT_U, &light_u, &light_v);
-
-				Ray light_ray;
-				BsdfEval L_light;
-				bool is_lamp;
-
-#ifdef __OBJECT_MOTION__
-				light_ray.time = sd.time;
-#endif
-
-				/* sample random light */
-				if(direct_emission(kg, &sd, -1, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp, state.bounce)) {
-					/* trace shadow ray */
-					float3 shadow;
-
-					if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
-						/* accumulate */
-						path_radiance_accum_light(L, throughput, &L_light, shadow, 1.0f, state.bounce, is_lamp);
-					}
-				}
-			}
+			bool all = kernel_data.integrator.sample_all_lights_indirect;
+			kernel_branched_path_integrate_direct_lighting(kg, rng, &sd, &state, throughput, 1.0f, L, all);
 		}
 #endif
 
@@ -898,70 +957,7 @@ ccl_device_noinline void kernel_branched_path_integrate_lighting(KernelGlobals *
 	PathState *state, PathRadiance *L, ccl_global float *buffer)
 {
 #ifdef __EMISSION__
-	/* sample illumination from lights to find path contribution */
-	if(sd->flag & SD_BSDF_HAS_EVAL) {
-		Ray light_ray;
-		BsdfEval L_light;
-		bool is_lamp;
-
-#ifdef __OBJECT_MOTION__
-		light_ray.time = sd->time;
-#endif
-
-		/* lamp sampling */
-		for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) {
-			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);
-			RNG lamp_rng = cmj_hash(*rng, i);
-
-			if(kernel_data.integrator.pdf_triangles != 0.0f)
-				num_samples_inv *= 0.5f;
-
-			for(int j = 0; j < num_samples; j++) {
-				float light_u, light_v;
-				path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
-
-				if(direct_emission(kg, sd, i, 0.0f, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce)) {
-					/* trace shadow ray */
-					float3 shadow;
-
-					if(!shadow_blocked(kg, state, &light_ray, &shadow)) {
-						/* accumulate */
-						path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
-					}
-				}
-			}
-		}
-
-		/* 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;
-
-			if(kernel_data.integrator.num_all_lights)
-				num_samples_inv *= 0.5f;
-
-			for(int j = 0; j < num_samples; j++) {
-				float light_t = path_branched_rng_1D(kg, rng, state, j, num_samples, PRNG_LIGHT);
-				float light_u, light_v;
-				path_branched_rng_2D(kg, rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
-
-				/* only sample triangle lights */
-				if(kernel_data.integrator.num_all_lights)
-					light_t = 0.5f*light_t;
-
-				if(direct_emission(kg, sd, -1, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce)) {
-					/* trace shadow ray */
-					float3 shadow;
-
-					if(!shadow_blocked(kg, state, &light_ray, &shadow)) {
-						/* accumulate */
-						path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
-					}
-				}
-			}
-		}
-	}
+	kernel_branched_path_integrate_direct_lighting(kg, rng, sd, state, throughput, num_samples_adjust, L, true);
 #endif
 
 	for(int i = 0; i< sd->num_closure; i++) {
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index fc3e273..bf79b0a 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -834,6 +834,7 @@ typedef struct KernelIntegrator {
 	int ao_samples;
 	int mesh_light_samples;
 	int subsurface_samples;
+	int sample_all_lights_indirect;
 	
 	/* mis */
 	int use_lamp_mis;
@@ -847,7 +848,7 @@ typedef struct KernelIntegrator {
 	int volume_max_steps;
 	float volume_step_size;
 	int volume_samples;
-	int pad1, pad2;
+	int pad1;
 } KernelIntegrator;
 
 typedef struct KernelBVH {
diff --git a/intern/cycles/render/i

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list