[Bf-blender-cvs] [77a4bb02cc9] master: Fix T100697: Curve nodes change colors at identity settings

Omar Emara noreply at git.blender.org
Fri Sep 9 13:05:37 CEST 2022


Commit: 77a4bb02cc99bfd581c6bb9e35ca3fe53389915e
Author: Omar Emara
Date:   Fri Sep 9 13:03:53 2022 +0200
Branches: master
https://developer.blender.org/rB77a4bb02cc99bfd581c6bb9e35ca3fe53389915e

Fix T100697: Curve nodes change colors at identity settings

Shader and compositor curve nodes change their inputs even if they are
at identity settings.

That is because shader and compositor curve nodes evaluate their curve
map texture samplers at the normalized input directly, disregarding the
fact that the samplers are evaluated using linear interpolation. This
causes the output to be slightly different that it should be.

This patch remaps the evaluation parameters such that the texture
sampler is evaluated at the center of the pixels.

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

Reviewed By: Clement Foucault

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

M	source/blender/gpu/shaders/common/gpu_shader_common_curves.glsl

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

diff --git a/source/blender/gpu/shaders/common/gpu_shader_common_curves.glsl b/source/blender/gpu/shaders/common/gpu_shader_common_curves.glsl
index db8e114ec7a..e68c173c055 100644
--- a/source/blender/gpu/shaders/common/gpu_shader_common_curves.glsl
+++ b/source/blender/gpu/shaders/common/gpu_shader_common_curves.glsl
@@ -26,9 +26,29 @@ vec3 extrapolate_if_needed(vec3 parameters, vec3 values, vec3 start_slopes, vec3
   return values + parameters * slopes;
 }
 
-/* Curve maps are stored in sampler objects that are evaluated in the [0, 1] range, so normalize
- * parameters accordingly. */
-#define NORMALIZE_PARAMETER(parameter, minimum, range) ((parameter - minimum) * range)
+/* Curve maps are stored in texture samplers that are evaluated in the [0, 1] range, so normalize
+ * the parameters accordingly. Additionally, ensure that the parameters evaluate the sampler at the
+ * center of the pixels, because samplers are evaluated using linear interpolation. */
+float normalize_parameter(float parameter, float minimum, float range_divider)
+{
+  float normalized_parameter = (parameter - minimum) * range_divider;
+
+  /* Curve maps have a fixed width of 257. We offset by the equivalent of half a pixel and scale
+   * down such that the normalized parameter 1.0 corresponds to the center of the last pixel. */
+  float sampler_offset = 0.5 / 257.0;
+  float sampler_scale = 1.0 - (1.0 / 257.0);
+  return normalized_parameter * sampler_scale + sampler_offset;
+}
+
+/* Same as normalize_parameter but vectorized. */
+vec3 normalize_parameters(vec3 parameters, vec3 minimums, vec3 range_dividers)
+{
+  vec3 normalized_parameters = (parameters - minimums) * range_dividers;
+
+  float sampler_offset = 0.5 / 257.0;
+  float sampler_scale = 1.0 - (1.0 / 257.0);
+  return normalized_parameters * sampler_scale + sampler_offset;
+}
 
 void curves_combined_rgb(float factor,
                          vec4 color,
@@ -46,7 +66,7 @@ void curves_combined_rgb(float factor,
 
   /* First, evaluate alpha curve map at all channels. The alpha curve is the Combined curve in the
    * UI. */
-  vec3 parameters = NORMALIZE_PARAMETER(balanced.rgb, range_minimums.aaa, range_dividers.aaa);
+  vec3 parameters = normalize_parameters(balanced.rgb, range_minimums.aaa, range_dividers.aaa);
   result.r = texture(curve_map, vec2(parameters.x, layer)).a;
   result.g = texture(curve_map, vec2(parameters.y, layer)).a;
   result.b = texture(curve_map, vec2(parameters.z, layer)).a;
@@ -55,13 +75,14 @@ void curves_combined_rgb(float factor,
   result.rgb = extrapolate_if_needed(parameters, result.rgb, start_slopes.aaa, end_slopes.aaa);
 
   /* Then, evaluate each channel on its curve map. */
-  parameters = NORMALIZE_PARAMETER(result.rgb, range_minimums.rgb, range_dividers.rgb);
+  parameters = normalize_parameters(result.rgb, range_minimums.rgb, range_dividers.rgb);
   result.r = texture(curve_map, vec2(parameters.r, layer)).r;
   result.g = texture(curve_map, vec2(parameters.g, layer)).g;
   result.b = texture(curve_map, vec2(parameters.b, layer)).b;
 
   /* Then, extrapolate again if needed. */
   result.rgb = extrapolate_if_needed(parameters, result.rgb, start_slopes.rgb, end_slopes.rgb);
+
   result.a = color.a;
 
   result = mix(color, result, factor);
@@ -83,13 +104,14 @@ void curves_combined_only(float factor,
 
   /* Evaluate alpha curve map at all channels. The alpha curve is the Combined curve in the
    * UI. */
-  vec3 parameters = NORMALIZE_PARAMETER(balanced.rgb, range_minimum, range_divider);
+  vec3 parameters = normalize_parameters(balanced.rgb, vec3(range_minimum), vec3(range_divider));
   result.r = texture(curve_map, vec2(parameters.x, layer)).a;
   result.g = texture(curve_map, vec2(parameters.y, layer)).a;
   result.b = texture(curve_map, vec2(parameters.z, layer)).a;
 
   /* Then, extrapolate if needed. */
   result.rgb = extrapolate_if_needed(parameters, result.rgb, vec3(start_slope), vec3(end_slope));
+
   result.a = color.a;
 
   result = mix(color, result, factor);
@@ -147,8 +169,8 @@ void curves_film_like(float factor,
 
   /* Evaluate alpha curve map at the maximum and minimum channels. The alpha curve is the Combined
    * curve in the UI. */
-  float min_parameter = NORMALIZE_PARAMETER(minimum, range_minimum, range_divider);
-  float max_parameter = NORMALIZE_PARAMETER(maximum, range_minimum, range_divider);
+  float min_parameter = normalize_parameter(minimum, range_minimum, range_divider);
+  float max_parameter = normalize_parameter(maximum, range_minimum, range_divider);
   float new_min = texture(curve_map, vec2(min_parameter, layer)).a;
   float new_max = texture(curve_map, vec2(max_parameter, layer)).a;
 
@@ -165,6 +187,7 @@ void curves_film_like(float factor,
   vec3 median_or_min = mix(vec3(new_median), vec3(new_min), channel_is_min);
   bvec3 channel_is_max = equal(balanced.rgb, vec3(maximum));
   result.rgb = mix(median_or_min, vec3(new_max), channel_is_max);
+
   result.a = color.a;
 
   result = mix(color, result, clamp(factor, 0.0, 1.0));
@@ -180,7 +203,7 @@ void curves_vector(vec3 vector,
                    out vec3 result)
 {
   /* Evaluate each component on its curve map. */
-  vec3 parameters = NORMALIZE_PARAMETER(vector, range_minimums, range_dividers);
+  vec3 parameters = normalize_parameters(vector, range_minimums, range_dividers);
   result.x = texture(curve_map, vec2(parameters.x, layer)).x;
   result.y = texture(curve_map, vec2(parameters.y, layer)).y;
   result.z = texture(curve_map, vec2(parameters.z, layer)).z;
@@ -214,7 +237,7 @@ void curves_float(float value,
                   out float result)
 {
   /* Evaluate the normalized value on the first curve map. */
-  float parameter = NORMALIZE_PARAMETER(value, range_minimum, range_divider);
+  float parameter = normalize_parameter(value, range_minimum, range_divider);
   result = texture(curve_map, vec2(parameter, layer)).x;
 
   /* Then, extrapolate if needed. */



More information about the Bf-blender-cvs mailing list