[Bf-blender-cvs] [852cdd476b5] master: ColorManagement: Dithering Improvement

Clément Foucault noreply at git.blender.org
Mon Feb 17 15:47:24 CET 2020


Commit: 852cdd476b5572b56418d377e379c07253363eff
Author: Clément Foucault
Date:   Mon Feb 17 14:14:30 2020 +0100
Branches: master
https://developer.blender.org/rB852cdd476b5572b56418d377e379c07253363eff

ColorManagement: Dithering Improvement

- Unlock property range.
- Use triangular noise to keep perceptual noise error more uniform.
  Remap range to preserve perceptual intensity.
- Center noise distribution around 0 for GPU implementation because of
  rounding.
- Do dithering after merging overlays.

Effect of using triangular noise is not really noticeable if you don't use
really low bitdepth. But doing a test in the shader were we artificially
reduce the bitdepth (`col = (col * 16) / 16;`) reveals the real difference.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D6850

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

M	intern/opencolorio/gpu_shader_display_transform.glsl
M	source/blender/blenlib/intern/math_color_inline.c
M	source/blender/imbuf/intern/divers.c
M	source/blender/makesrna/intern/rna_scene.c

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

diff --git a/intern/opencolorio/gpu_shader_display_transform.glsl b/intern/opencolorio/gpu_shader_display_transform.glsl
index f1f77cf7df2..f7c64244dd6 100644
--- a/intern/opencolorio/gpu_shader_display_transform.glsl
+++ b/intern/opencolorio/gpu_shader_display_transform.glsl
@@ -115,9 +115,20 @@ vec4 curvemapping_evaluate_premulRGBF(vec4 col)
   return result;
 }
 
+/* Using a triangle distribution which gives a more final uniform noise.
+ * See Banding in Games:A Noisy Rant(revision 5) Mikkel Gjøl, Playdead (slide 27) */
+/* GPUs are rounding before writting to framebuffer so we center the distribution around 0.0. */
+/* Return triangle noise in [-1..1[ range */
 float dither_random_value(vec2 co)
 {
-  return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453) * 0.005 * dither;
+  /* Original code from https://www.shadertoy.com/view/4t2SDh */
+  /* Uniform noise in [0..1[ range */
+  float nrnd0 = fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
+  /* Convert uniform distribution into triangle-shaped distribution. */
+  float orig = nrnd0 * 2.0 - 1.0;
+  nrnd0 = orig * inversesqrt(abs(orig));
+  nrnd0 = max(-1.0, nrnd0); /* Removes nan's */
+  return nrnd0 - sign(orig);
 }
 
 vec2 round_to_pixel(sampler2D tex, vec2 uv)
@@ -128,7 +139,7 @@ vec2 round_to_pixel(sampler2D tex, vec2 uv)
 
 vec4 apply_dither(vec4 col, vec2 uv)
 {
-  col.rgb += dither_random_value(uv);
+  col.rgb += dither_random_value(uv) * 0.0033 * dither;
   return col;
 }
 
@@ -151,10 +162,6 @@ vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay, vec2 noise_uv)
 
   col = OCIO_to_display_linear_with_look(col, lut3d_texture);
 
-  if (dither > 0.0) {
-    col = apply_dither(col, noise_uv);
-  }
-
   if (overlay) {
     col *= 1.0 - col_overlay.a;
     col += col_overlay; /* Assumed unassociated alpha. */
@@ -162,6 +169,10 @@ vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay, vec2 noise_uv)
 
   col = OCIO_to_display_encoded(col, lut3d_display_texture);
 
+  if (dither > 0.0) {
+    col = apply_dither(col, noise_uv);
+  }
+
   return col;
 }
 
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index f5aaddc0ea3..52ca229fe27 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -317,19 +317,27 @@ MINLINE int compare_rgb_uchar(const unsigned char col_a[3],
   return 0;
 }
 
+/* Using a triangle distribution which gives a more final uniform noise.
+ * See Banding in Games:A Noisy Rant(revision 5) Mikkel Gjøl, Playdead (slide 27) */
+/* Return triangle noise in [-0.5..1.5[ range */
 MINLINE float dither_random_value(float s, float t)
 {
-  static float vec[2] = {12.9898f, 78.233f};
-  float value;
-
-  value = sinf(s * vec[0] + t * vec[1]) * 43758.5453f;
-  return value - floorf(value);
+  /* Original code from https://www.shadertoy.com/view/4t2SDh */
+  /* The nois reshaping technique does not work on CPU.
+   * We generate and merge two distribution instead */
+  /* Uniform noise in [0..1[ range */
+  float nrnd0 = sinf(s * 12.9898f + t * 78.233f) * 43758.5453f;
+  float nrnd1 = sinf(s * 19.9898f + t * 119.233f) * 43798.5453f;
+  nrnd0 -= floorf(nrnd0);
+  nrnd1 -= floorf(nrnd1);
+  /* Convert uniform distribution into triangle-shaped distribution. */
+  return nrnd0 + nrnd1 - 0.5f;
 }
 
 MINLINE void float_to_byte_dither_v3(
     unsigned char b[3], const float f[3], float dither, float s, float t)
 {
-  float dither_value = dither_random_value(s, t) * 0.005f * dither;
+  float dither_value = dither_random_value(s, t) * 0.0033f * dither;
 
   b[0] = unit_float_to_uchar_clamp(dither_value + f[0]);
   b[1] = unit_float_to_uchar_clamp(dither_value + f[1]);
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index aa49453d68c..07bbec9e15c 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -75,7 +75,7 @@ MINLINE void ushort_to_byte_dither_v4(
     uchar b[4], const unsigned short us[4], DitherContext *di, float s, float t)
 {
 #define USHORTTOFLOAT(val) ((float)val / 65535.0f)
-  float dither_value = dither_random_value(s, t) * 0.005f * di->dither;
+  float dither_value = dither_random_value(s, t) * 0.0033f * di->dither;
 
   b[0] = ftochar(dither_value + USHORTTOFLOAT(us[0]));
   b[1] = ftochar(dither_value + USHORTTOFLOAT(us[1]));
@@ -88,7 +88,7 @@ MINLINE void ushort_to_byte_dither_v4(
 MINLINE void float_to_byte_dither_v4(
     uchar b[4], const float f[4], DitherContext *di, float s, float t)
 {
-  float dither_value = dither_random_value(s, t) * 0.005f * di->dither;
+  float dither_value = dither_random_value(s, t) * 0.0033f * di->dither;
 
   b[0] = ftochar(dither_value + f[0]);
   b[1] = ftochar(dither_value + f[1]);
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index cc0903ed2c8..5e5bafdc178 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -5683,7 +5683,8 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
 
   prop = RNA_def_property(srna, "dither_intensity", PROP_FLOAT, PROP_NONE);
   RNA_def_property_float_sdna(prop, NULL, "dither_intensity");
-  RNA_def_property_range(prop, 0.0f, 2.0f);
+  RNA_def_property_range(prop, 0.0, FLT_MAX);
+  RNA_def_property_ui_range(prop, 0.0, 2.0, 0.1, 2);
   RNA_def_property_ui_text(
       prop,
       "Dither Intensity",



More information about the Bf-blender-cvs mailing list