From b05b814cb6d84f7cc2b4592d43d58ef1a5994c7b Mon Sep 17 00:00:00 2001 From: Valtteri Koskivuori Date: Sat, 4 Nov 2023 00:35:03 +0200 Subject: [PATCH] Try to clamp out fireflies (bright dots in image) These sometimes happen - Somewhere in the renderer, something divides by zero in some exceedingly unlikely case, and the resulting sample contains NaNs. It's fairly common to just clamp these out, but a proper approach would be to actually trace where the goof happens, and fix that. --- src/datatypes/color.h | 5 +++++ src/renderer/renderer.c | 5 +++++ src/utils/protocol/worker.c | 2 ++ 3 files changed, 12 insertions(+) diff --git a/src/datatypes/color.h b/src/datatypes/color.h index c0367809..0dbc719e 100644 --- a/src/datatypes/color.h +++ b/src/datatypes/color.h @@ -103,6 +103,11 @@ static inline bool colorEquals(struct color a, struct color b) { return a.red == b.red && a.green == b.green && a.blue == b.blue && a.alpha == b.alpha; } +static inline void nan_clamp(struct color *a, struct color *b) { + if (a->red != a->red || a->green != a->green || a->blue != a->blue || a->alpha != a->alpha) + *a = *b; +} + struct color colorForKelvin(float kelvin); struct color color_from_hsl(float hue, float saturation, float lightness); diff --git a/src/renderer/renderer.c b/src/renderer/renderer.c index ae4c3e16..444e3a71 100644 --- a/src/renderer/renderer.c +++ b/src/renderer/renderer.c @@ -225,6 +225,8 @@ void *renderThreadInteractive(void *arg) { struct color output = textureGetPixel(r->state.renderBuffer, x, y, false); struct lightRay incidentRay = cam_get_ray(cam, x, y, sampler); struct color sample = path_trace(&incidentRay, r->scene, r->prefs.bounces, sampler); + + nan_clamp(&sample, &output); //And process the running average output = colorCoef((float)(r->state.finishedPasses - 1), output); @@ -304,6 +306,9 @@ void *renderThread(void *arg) { struct lightRay incidentRay = cam_get_ray(cam, x, y, sampler); struct color sample = path_trace(&incidentRay, r->scene, r->prefs.bounces, sampler); + // Clamp out fireflies - This is probably not a good way to do that. + nan_clamp(&sample, &output); + //And process the running average output = colorCoef((float)(threadState->completedSamples - 1), output); output = colorAdd(output, sample); diff --git a/src/utils/protocol/worker.c b/src/utils/protocol/worker.c index c1d5c2f8..8eba337f 100644 --- a/src/utils/protocol/worker.c +++ b/src/utils/protocol/worker.c @@ -171,6 +171,8 @@ static void *workerThread(void *arg) { struct color output = textureGetPixel(r->state.renderBuffer, x, y, false); struct lightRay incidentRay = cam_get_ray(cam, x, y, sampler); struct color sample = path_trace(&incidentRay, r->scene, r->prefs.bounces, sampler); + + nan_clamp(&sample, &output); //And process the running average output = colorCoef((float)(thread->completedSamples - 1), output);