From 6e93e3329427390c35fb93b2c5add8a639671bb6 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 5 Apr 2012 15:17:45 +0000 Subject: Cycles: add rejection of inf/nan samples, in principle these should not happen but this makes it more reliable for now. Also add an integrator "Clamp" option, to clamp very light samples to a maximum value. This will reduce accuracy but may help reducing noise and speed up convergence. --- intern/cycles/blender/addon/properties.py | 7 +++++ intern/cycles/blender/addon/ui.py | 1 + intern/cycles/blender/blender_sync.cpp | 2 ++ intern/cycles/kernel/kernel_accumulate.h | 44 +++++++++++++++++++++++++++++++ intern/cycles/kernel/kernel_path.h | 4 +++ intern/cycles/kernel/kernel_types.h | 8 +++++- intern/cycles/render/integrator.cpp | 6 ++++- intern/cycles/render/integrator.h | 2 ++ 8 files changed, 72 insertions(+), 2 deletions(-) (limited to 'intern') diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index da4de1aeafd..d20507427b4 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -174,6 +174,13 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): default=0, ) + cls.sample_clamp = FloatProperty( + name="Clamp", + description="If non-zero, the maximum value for a 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.debug_tile_size = IntProperty( name="Tile Size", description="", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index f22e298f52d..47aba845ba3 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -67,6 +67,7 @@ class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel): sub.prop(cscene, "samples", text="Render") sub.prop(cscene, "preview_samples", text="Preview") sub.prop(cscene, "seed") + sub.prop(cscene, "sample_clamp") sub = col.column(align=True) sub.label("Transparency:") diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index e88f74eea68..066e5b776b8 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -157,6 +157,8 @@ void BlenderSync::sync_integrator() integrator->layer_flag = render_layer.layer; + integrator->sample_clamp = get_float(cscene, "sample_clamp"); + if(integrator->modified(previntegrator)) integrator->tag_update(scene); } diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 7ba50973444..a78cfc4dfb7 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -294,5 +294,49 @@ __device_inline float3 path_radiance_sum(PathRadiance *L) #endif } +__device_inline void path_radiance_clamp(PathRadiance *L, float3 *L_sum, float clamp) +{ + float sum = fabsf(L_sum->x) + fabsf(L_sum->y) + fabsf(L_sum->z); + + if(!isfinite(sum)) { + /* invalid value, reject */ + *L_sum = make_float3(0.0f, 0.0f, 0.0f); + +#ifdef __PASSES__ + if(L->use_light_pass) { + L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f); + L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f); + L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f); + + L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f); + L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f); + L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f); + + L->emission = make_float3(0.0f, 0.0f, 0.0f); + } +#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->indirect_diffuse *= scale; + L->indirect_glossy *= scale; + L->indirect_transmission *= 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 f9eeccb1f11..53ce374e150 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -396,6 +396,10 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R float3 L_sum = path_radiance_sum(&L); +#ifdef __CLAMP_SAMPLE__ + path_radiance_clamp(&L, &L_sum, kernel_data.integrator.sample_clamp); +#endif + kernel_write_light_passes(kg, buffer, &L, sample); return make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - L_transparent); diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 453d5c826e6..391dcd12dad 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -60,6 +60,7 @@ CCL_NAMESPACE_BEGIN #define __RAY_DIFFERENTIALS__ #define __CAMERA_CLIPPING__ #define __INTERSECTION_REFINE__ +#define __CLAMP_SAMPLE__ #ifdef __KERNEL_SHADING__ #define __SVM__ @@ -521,7 +522,12 @@ typedef struct KernelIntegrator { /* render layer */ int layer_flag; - int pad1, pad2; + + /* clamp */ + float sample_clamp; + + /* padding */ + int pad; } KernelIntegrator; typedef struct KernelBVH { diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index ff2afc7119b..6e6d30f3879 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -43,6 +43,7 @@ Integrator::Integrator() no_caustics = false; seed = 0; layer_flag = ~0; + sample_clamp = 0.0f; need_update = true; } @@ -85,6 +86,8 @@ void Integrator::device_update(Device *device, DeviceScene *dscene) 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; /* sobol directions table */ int dimensions = PRNG_BASE_NUM + (max_bounce + transparent_max_bounce + 2)*PRNG_BOUNCE_NUM; @@ -117,7 +120,8 @@ bool Integrator::modified(const Integrator& integrator) transparent_shadows == integrator.transparent_shadows && no_caustics == integrator.no_caustics && layer_flag == integrator.layer_flag && - seed == integrator.seed); + seed == integrator.seed && + sample_clamp == integrator.sample_clamp); } void Integrator::tag_update(Scene *scene) diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h index e610d670142..abbbaca894c 100644 --- a/intern/cycles/render/integrator.h +++ b/intern/cycles/render/integrator.h @@ -45,6 +45,8 @@ public: int seed; int layer_flag; + float sample_clamp; + bool need_update; Integrator(); -- cgit v1.2.3