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,
|
||||
)
|
||||
|
||||
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="",
|
||||
|
@@ -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:")
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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 {
|
||||
|
@@ -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)
|
||||
|
@@ -45,6 +45,8 @@ public:
|
||||
int seed;
|
||||
int layer_flag;
|
||||
|
||||
float sample_clamp;
|
||||
|
||||
bool need_update;
|
||||
|
||||
Integrator();
|
||||
|
Reference in New Issue
Block a user