Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorOmar Emara <mail@OmarEmara.dev>2022-09-09 14:03:53 +0300
committerOmar Emara <mail@OmarEmara.dev>2022-09-09 14:03:53 +0300
commit77a4bb02cc99bfd581c6bb9e35ca3fe53389915e (patch)
tree4d9368551f8ce90e20a72658b80629e0058edc31 /source
parentfa0f18b37d1154dcb3c1d3fcc9075f68f79c8631 (diff)
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
Diffstat (limited to 'source')
-rw-r--r--source/blender/gpu/shaders/common/gpu_shader_common_curves.glsl43
1 files changed, 33 insertions, 10 deletions
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. */