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.
This commit is contained in:
@@ -174,6 +174,13 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
|||||||
default=0,
|
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(
|
cls.debug_tile_size = IntProperty(
|
||||||
name="Tile Size",
|
name="Tile Size",
|
||||||
description="",
|
description="",
|
||||||
|
@@ -67,6 +67,7 @@ class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel):
|
|||||||
sub.prop(cscene, "samples", text="Render")
|
sub.prop(cscene, "samples", text="Render")
|
||||||
sub.prop(cscene, "preview_samples", text="Preview")
|
sub.prop(cscene, "preview_samples", text="Preview")
|
||||||
sub.prop(cscene, "seed")
|
sub.prop(cscene, "seed")
|
||||||
|
sub.prop(cscene, "sample_clamp")
|
||||||
|
|
||||||
sub = col.column(align=True)
|
sub = col.column(align=True)
|
||||||
sub.label("Transparency:")
|
sub.label("Transparency:")
|
||||||
|
@@ -157,6 +157,8 @@ void BlenderSync::sync_integrator()
|
|||||||
|
|
||||||
integrator->layer_flag = render_layer.layer;
|
integrator->layer_flag = render_layer.layer;
|
||||||
|
|
||||||
|
integrator->sample_clamp = get_float(cscene, "sample_clamp");
|
||||||
|
|
||||||
if(integrator->modified(previntegrator))
|
if(integrator->modified(previntegrator))
|
||||||
integrator->tag_update(scene);
|
integrator->tag_update(scene);
|
||||||
}
|
}
|
||||||
|
@@ -294,5 +294,49 @@ __device_inline float3 path_radiance_sum(PathRadiance *L)
|
|||||||
#endif
|
#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
|
CCL_NAMESPACE_END
|
||||||
|
|
||||||
|
@@ -396,6 +396,10 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
|
|||||||
|
|
||||||
float3 L_sum = path_radiance_sum(&L);
|
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);
|
kernel_write_light_passes(kg, buffer, &L, sample);
|
||||||
|
|
||||||
return make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - L_transparent);
|
return make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - L_transparent);
|
||||||
|
@@ -60,6 +60,7 @@ CCL_NAMESPACE_BEGIN
|
|||||||
#define __RAY_DIFFERENTIALS__
|
#define __RAY_DIFFERENTIALS__
|
||||||
#define __CAMERA_CLIPPING__
|
#define __CAMERA_CLIPPING__
|
||||||
#define __INTERSECTION_REFINE__
|
#define __INTERSECTION_REFINE__
|
||||||
|
#define __CLAMP_SAMPLE__
|
||||||
|
|
||||||
#ifdef __KERNEL_SHADING__
|
#ifdef __KERNEL_SHADING__
|
||||||
#define __SVM__
|
#define __SVM__
|
||||||
@@ -521,7 +522,12 @@ typedef struct KernelIntegrator {
|
|||||||
|
|
||||||
/* render layer */
|
/* render layer */
|
||||||
int layer_flag;
|
int layer_flag;
|
||||||
int pad1, pad2;
|
|
||||||
|
/* clamp */
|
||||||
|
float sample_clamp;
|
||||||
|
|
||||||
|
/* padding */
|
||||||
|
int pad;
|
||||||
} KernelIntegrator;
|
} KernelIntegrator;
|
||||||
|
|
||||||
typedef struct KernelBVH {
|
typedef struct KernelBVH {
|
||||||
|
@@ -43,6 +43,7 @@ Integrator::Integrator()
|
|||||||
no_caustics = false;
|
no_caustics = false;
|
||||||
seed = 0;
|
seed = 0;
|
||||||
layer_flag = ~0;
|
layer_flag = ~0;
|
||||||
|
sample_clamp = 0.0f;
|
||||||
|
|
||||||
need_update = true;
|
need_update = true;
|
||||||
}
|
}
|
||||||
@@ -85,6 +86,8 @@ void Integrator::device_update(Device *device, DeviceScene *dscene)
|
|||||||
|
|
||||||
kintegrator->use_ambient_occlusion =
|
kintegrator->use_ambient_occlusion =
|
||||||
((dscene->data.film.pass_flag & PASS_AO) || dscene->data.background.ao_factor != 0.0f);
|
((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 */
|
/* sobol directions table */
|
||||||
int dimensions = PRNG_BASE_NUM + (max_bounce + transparent_max_bounce + 2)*PRNG_BOUNCE_NUM;
|
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 &&
|
transparent_shadows == integrator.transparent_shadows &&
|
||||||
no_caustics == integrator.no_caustics &&
|
no_caustics == integrator.no_caustics &&
|
||||||
layer_flag == integrator.layer_flag &&
|
layer_flag == integrator.layer_flag &&
|
||||||
seed == integrator.seed);
|
seed == integrator.seed &&
|
||||||
|
sample_clamp == integrator.sample_clamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Integrator::tag_update(Scene *scene)
|
void Integrator::tag_update(Scene *scene)
|
||||||
|
@@ -45,6 +45,8 @@ public:
|
|||||||
int seed;
|
int seed;
|
||||||
int layer_flag;
|
int layer_flag;
|
||||||
|
|
||||||
|
float sample_clamp;
|
||||||
|
|
||||||
bool need_update;
|
bool need_update;
|
||||||
|
|
||||||
Integrator();
|
Integrator();
|
||||||
|
Reference in New Issue
Block a user