[Bf-blender-cvs] [e29a45b] master: Cycles: Separation of Indirect and Direct clamping.

Thomas Dinges noreply at git.blender.org
Mon Feb 10 21:46:23 CET 2014


Commit: e29a45b396ccf507d858ec4afc301bdaf816b328
Author: Thomas Dinges
Date:   Mon Feb 10 21:44:49 2014 +0100
https://developer.blender.org/rBe29a45b396ccf507d858ec4afc301bdaf816b328

Cycles: Separation of Indirect and Direct clamping.

Indirect and Direct samples can now be clamped individually. This way we can clamp the indirect samples (fireflies), while keeping the direct highlights.
Example render: http://www.pasteall.org/pic/show.php?id=66586

WARNING: This breaks backwards compatibility. If you had Clamping enabled in an old file, you must re-enable either Direct/Indirect clamping or both again.

Reviewed by: brecht
Differential Revision: https://developer.blender.org/D303

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

M	intern/cycles/app/cycles_xml.cpp
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_accumulate.h
M	intern/cycles/kernel/kernel_path.h
M	intern/cycles/kernel/kernel_types.h
M	intern/cycles/render/film.cpp
M	intern/cycles/render/integrator.cpp
M	intern/cycles/render/integrator.h

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

diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 3c8e484..efd7e5e 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -276,7 +276,8 @@ static void xml_read_integrator(const XMLReadState& state, pugi::xml_node node)
 	xml_read_float(&integrator->filter_glossy, node, "filter_glossy");
 	
 	xml_read_int(&integrator->seed, node, "seed");
-	xml_read_float(&integrator->sample_clamp, node, "sample_clamp");
+	xml_read_float(&integrator->sample_clamp_direct, node, "sample_clamp_direct");
+	xml_read_float(&integrator->sample_clamp_indirect, node, "sample_clamp_indirect");
 }
 
 /* Camera */
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 5adcbc6..0f0bff2 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -363,9 +363,18 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
                 default=0,
                 )
 
-        cls.sample_clamp = FloatProperty(
-                name="Clamp",
-                description="If non-zero, the maximum value for a sample, "
+        cls.sample_clamp_direct = FloatProperty(
+                name="Clamp Direct",
+                description="If non-zero, the maximum value for a direct sample, "
+                            "higher values will be scaled down to avoid too "
+                            "much noise and slow convergence at the cost of accuracy",
+                min=0.0, max=1e8,
+                default=0.0,
+                )
+                
+        cls.sample_clamp_indirect = FloatProperty(
+                name="Clamp Indirect",
+                description="If non-zero, the maximum value for an indirect sample, "
                             "higher values will be scaled down to avoid too "
                             "much noise and slow convergence at the cost of accuracy",
                 min=0.0, max=1e8,
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 3217a96..65eb75a 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -120,7 +120,8 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
         sub = col.column(align=True)
         sub.label("Settings:")
         sub.prop(cscene, "seed")
-        sub.prop(cscene, "sample_clamp")
+        sub.prop(cscene, "sample_clamp_direct")
+        sub.prop(cscene, "sample_clamp_indirect")
 
         if cscene.progressive == 'PATH':
             col = split.column()
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 68ef209..4415940 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -182,7 +182,8 @@ void BlenderSync::sync_integrator()
 
 	integrator->layer_flag = render_layer.layer;
 
-	integrator->sample_clamp = get_float(cscene, "sample_clamp");
+	integrator->sample_clamp_direct = get_float(cscene, "sample_clamp_direct");
+	integrator->sample_clamp_indirect = get_float(cscene, "sample_clamp_indirect");
 #ifdef __CAMERA_MOTION__
 	if(!preview) {
 		if(integrator->motion_blur != r.use_motion_blur()) {
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index 24e9d7b..80f3bfd 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -316,15 +316,50 @@ ccl_device_inline void path_radiance_reset_indirect(PathRadiance *L)
 #endif
 }
 
-ccl_device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L)
+ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadiance *L)
 {
 #ifdef __PASSES__
 	if(L->use_light_pass) {
 		path_radiance_sum_indirect(L);
 
-		float3 L_sum = L->emission
-			+ L->direct_diffuse + L->direct_glossy + L->direct_transmission + L->direct_subsurface
-			+ L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission + L->indirect_subsurface;
+		float3 L_direct = L->direct_diffuse + L->direct_glossy + L->direct_transmission + L->direct_subsurface + L->emission;
+		float3 L_indirect = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission + L->indirect_subsurface;
+
+#ifdef __CLAMP_SAMPLE__ 
+		float clamp_direct = kernel_data.integrator.sample_clamp_direct;
+		float clamp_indirect = kernel_data.integrator.sample_clamp_indirect;
+
+		if(clamp_direct != FLT_MAX || clamp_indirect != FLT_MAX) {
+			float scale;
+
+			/* Direct */
+			float sum_direct = fabsf(L_direct.x) + fabsf(L_direct.y) + fabsf(L_direct.z);
+			if(sum_direct > clamp_direct) {
+				scale = clamp_direct/sum_direct;
+				L_direct *= scale;
+
+				L->direct_diffuse *= scale;
+				L->direct_glossy *= scale;
+				L->direct_transmission *= scale;
+				L->direct_subsurface *= scale;
+				L->emission *= scale;
+			}
+
+			/* Indirect */
+			float sum_indirect = fabsf(L_indirect.x) + fabsf(L_indirect.y) + fabsf(L_indirect.z);
+			if(sum_indirect > clamp_indirect) {
+				scale = clamp_indirect/sum_indirect;
+				L_indirect *= scale;
+
+				L->indirect_diffuse *= scale;
+				L->indirect_glossy *= scale;
+				L->indirect_transmission *= scale;
+				L->indirect_subsurface *= scale;
+			}
+		}
+#endif
+		/* Combine */
+		float3 L_sum = L_direct + L_indirect;
 
 		if(!kernel_data.background.transparent)
 			L_sum += L->background;
@@ -338,7 +373,7 @@ ccl_device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L)
 #endif
 }
 
-ccl_device_inline void path_radiance_clamp(PathRadiance *L, float3 *L_sum, float clamp)
+ccl_device_inline void path_radiance_reject(PathRadiance *L, float3 *L_sum)
 {
 	float sum = fabsf((*L_sum).x) + fabsf((*L_sum).y) + fabsf((*L_sum).z);
 
@@ -362,28 +397,6 @@ ccl_device_inline void path_radiance_clamp(PathRadiance *L, float3 *L_sum, float
 		}
 #endif
 	}
-	else if(sum > clamp) {
-		/* value to high, scale down */
-		float scale = clamp/sum;
-
-		*L_sum *= scale;
-
-#ifdef __PASSES__
-		if(L->use_light_pass) {
-			L->direct_diffuse *= scale;
-			L->direct_glossy *= scale;
-			L->direct_transmission *= scale;
-			L->direct_subsurface *= scale;
-
-			L->indirect_diffuse *= scale;
-			L->indirect_glossy *= scale;
-			L->indirect_transmission *= scale;
-			L->indirect_subsurface *= scale;
-
-			L->emission *= scale;
-		}
-#endif
-	}
 }
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index aabac2e..77bc204 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -884,10 +884,10 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
 			ray.t = FLT_MAX;
 	}
 
-	float3 L_sum = path_radiance_sum(kg, &L);
+	float3 L_sum = path_radiance_clamp_and_sum(kg, &L);
 
 #ifdef __CLAMP_SAMPLE__
-	path_radiance_clamp(&L, &L_sum, kernel_data.integrator.sample_clamp);
+	path_radiance_reject(&L, &L_sum);
 #endif
 
 	kernel_write_light_passes(kg, buffer, &L, sample);
@@ -1320,10 +1320,10 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
 #endif
 	}
 
-	float3 L_sum = path_radiance_sum(kg, &L);
+	float3 L_sum = path_radiance_clamp_and_sum(kg, &L);
 
 #ifdef __CLAMP_SAMPLE__
-	path_radiance_clamp(&L, &L_sum, kernel_data.integrator.sample_clamp);
+	path_radiance_reject(&L, &L_sum);
 #endif
 
 	kernel_write_light_passes(kg, buffer, &L, sample);
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 06bf6b7..5ee25a6 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -822,7 +822,9 @@ typedef struct KernelIntegrator {
 	int layer_flag;
 
 	/* clamp */
-	float sample_clamp;
+	float sample_clamp_direct;
+	float sample_clamp_indirect;
+	float pad1, pad2, pad3;
 
 	/* branched path */
 	int branched;
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index 23a7030..0a1a88e 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -288,12 +288,15 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
 	device_free(device, dscene, scene);
 
 	KernelFilm *kfilm = &dscene->data.film;
+	KernelIntegrator *kintegrator = &dscene->data.integrator;
+	
+	bool use_clamping = (kintegrator->sample_clamp_direct != FLT_MAX) || (kintegrator->sample_clamp_indirect != FLT_MAX);
 
 	/* update __data */
 	kfilm->exposure = exposure;
 	kfilm->pass_flag = 0;
 	kfilm->pass_stride = 0;
-	kfilm->use_light_pass = use_light_visibility;
+	kfilm->use_light_pass = use_light_visibility || use_clamping;
 
 	foreach(Pass& pass, passes) {
 		kfilm->pass_flag |= pass.type;
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index 1042a5c..f48e04f 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -48,7 +48,8 @@ Integrator::Integrator()
 	filter_glossy = 0.0f;
 	seed = 0;
 	layer_flag = ~0;
-	sample_clamp = 0.0f;
+	sample_clamp_direct = 0.0f;
+	sample_clamp_indirect = 0.0f;
 	motion_blur = false;
 
 	aa_samples = 0;
@@ -115,7 +116,8 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
 	kintegrator->use_ambient_occlusion =
 		((dscene->data.film.pass_flag & PASS_AO) || dscene->data.background.ao_factor != 0.0f);
 	
-	kintegrator->sample_clamp = (sample_clamp == 0.0f)? FLT_MAX: sample_clamp*3.0f;
+	kintegrator->sample_clamp_direct = (sample_clamp_direct == 0.0f)? FLT_MAX: sample_clamp_direct*3.0f;
+	kintegrator->sample_clamp_indirect = (sample_clamp_indirect == 0.0f)? FLT_MAX: sample_clamp_indirect*3.0f;
 
 	kintegrator->branched = (method == BRANCHED_PATH);
 	kintegrator->aa_samples = aa_samples;
@@ -180,7 +182,8 @@ bool Integrator::modified(const Integrator& integrator)
 		filter_glossy == integrator.filter_glossy &&
 		layer_flag == integrator.layer_flag &&
 		seed == integrator.seed &&
-		sample_clamp == integrator.sample_clamp &&
+		sample_clamp_direct == integrator.sample_clamp_direct &&
+		sample_clamp_indirect == integrator.sample_clamp_indirect &&
 		method == integrator.method &&
 		aa_samples == integrator.aa_samples &&
 		diffuse_samples == integrator.diffuse_samples &&
diff --git a/in

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list