[Bf-blender-cvs] [bdfee6d8318] master: EEVEE: Refactor curve nodes

Omar Emara noreply at git.blender.org
Fri May 6 13:34:00 CEST 2022


Commit: bdfee6d8318b6dd261adbb08ea2323784f088140
Author: Omar Emara
Date:   Fri May 6 13:33:23 2022 +0200
Branches: master
https://developer.blender.org/rBbdfee6d8318b6dd261adbb08ea2323784f088140

EEVEE: Refactor curve nodes

This patches rewrites the GPU shaders of curve nodes for easier future
development. This is a non-functional change. The new code avoids code
duplication by moving common code into BKE curve mapping functions. It
also avoids ambiguous data embedding into the gradient vectors that are
passed to vectors and reduces the size of uniforms uploaded to the
shader by avoiding redundancies.

This is needed in preparation for the viewport compositor, which will
utilize and extend this implementation.

Reviewed By: fclem

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

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

M	source/blender/blenkernel/BKE_colortools.h
M	source/blender/blenkernel/intern/colortools.c
M	source/blender/gpu/CMakeLists.txt
A	source/blender/gpu/shaders/common/gpu_shader_common_curves.glsl
D	source/blender/gpu/shaders/material/gpu_shader_material_float_curve.glsl
D	source/blender/gpu/shaders/material/gpu_shader_material_rgb_curves.glsl
D	source/blender/gpu/shaders/material/gpu_shader_material_vector_curves.glsl
M	source/blender/nodes/shader/nodes/node_shader_curves.cc

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

diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h
index 0d4560207ea..d52fd91ccdd 100644
--- a/source/blender/blenkernel/BKE_colortools.h
+++ b/source/blender/blenkernel/BKE_colortools.h
@@ -129,6 +129,36 @@ bool BKE_curvemapping_RGBA_does_something(const struct CurveMapping *cumap);
 void BKE_curvemapping_table_F(const struct CurveMapping *cumap, float **array, int *size);
 void BKE_curvemapping_table_RGBA(const struct CurveMapping *cumap, float **array, int *size);
 
+/** Get the minimum x value of each curve map table. */
+void BKE_curvemapping_get_range_minimums(const struct CurveMapping *curve_mapping,
+                                         float minimums[4]);
+
+/** Get the reciprocal of the difference between the maximum and the minimum x value of each curve
+ * map table. Evaluation parameters can be multiplied by this value to be normalized. If the
+ * difference is zero, 1^8 is returned. */
+void BKE_curvemapping_compute_range_dividers(const struct CurveMapping *curve_mapping,
+                                             float dividers[4]);
+
+/** Compute the slopes at the start and end points of each curve map. The slopes are multiplied by
+ * the range of the curve map to compensate for parameter normalization. If the slope is vertical,
+ * 1^8 is returned.  */
+void BKE_curvemapping_compute_slopes(const struct CurveMapping *curve_mapping,
+                                     float start_slopes[4],
+                                     float end_slopes[4]);
+
+/** Check if the curve map at the index is identity, that is, does nothing. A curve map is said to
+ * be identity if:
+ * - The curve mapping uses extrapolation.
+ * - Its range is 1.
+ * - The slope at its start point is 1.
+ * - The slope at its end point is 1.
+ * - The number of points is 2.
+ * - The start point is at (0, 0).
+ * - The end point is at (1, 1).
+ * Note that this could return false even if the curve map is identity, this happens in the case
+ * when more than 2 points exist in the curve map but all points are collinear. */
+bool BKE_curvemapping_is_map_identity(const struct CurveMapping *curve_mapping, int index);
+
 /**
  * Call when you do images etc, needs restore too. also verifies tables.
  * non-const (these modify the curve).
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index c3d66d4463d..e4c46703f8a 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -1158,6 +1158,80 @@ bool BKE_curvemapping_RGBA_does_something(const CurveMapping *cumap)
   return false;
 }
 
+void BKE_curvemapping_get_range_minimums(const CurveMapping *curve_mapping, float minimums[CM_TOT])
+{
+  for (int i = 0; i < CM_TOT; i++) {
+    minimums[i] = curve_mapping->cm[i].mintable;
+  }
+}
+
+void BKE_curvemapping_compute_range_dividers(const CurveMapping *curve_mapping,
+                                             float dividers[CM_TOT])
+{
+  for (int i = 0; i < CM_TOT; i++) {
+    const CurveMap *curve_map = &curve_mapping->cm[i];
+    dividers[i] = 1.0f / max_ff(1e-8f, curve_map->maxtable - curve_map->mintable);
+  }
+}
+
+void BKE_curvemapping_compute_slopes(const CurveMapping *curve_mapping,
+                                     float start_slopes[CM_TOT],
+                                     float end_slopes[CM_TOT])
+{
+  float range_dividers[CM_TOT];
+  BKE_curvemapping_compute_range_dividers(curve_mapping, range_dividers);
+  for (int i = 0; i < CM_TOT; i++) {
+    const CurveMap *curve_map = &curve_mapping->cm[i];
+    /* If extrapolation is not enabled, the slopes are horizontal. */
+    if (!(curve_mapping->flag & CUMA_EXTEND_EXTRAPOLATE)) {
+      start_slopes[i] = 0.0f;
+      end_slopes[i] = 0.0f;
+      continue;
+    }
+
+    if (curve_map->ext_in[0] != 0.0f) {
+      start_slopes[i] = curve_map->ext_in[1] / (curve_map->ext_in[0] * range_dividers[i]);
+    }
+    else {
+      start_slopes[i] = 1e8f;
+    }
+
+    if (curve_map->ext_out[0] != 0.0f) {
+      end_slopes[i] = curve_map->ext_out[1] / (curve_map->ext_out[0] * range_dividers[i]);
+    }
+    else {
+      end_slopes[i] = 1e8f;
+    }
+  }
+}
+
+bool BKE_curvemapping_is_map_identity(const CurveMapping *curve_mapping, int index)
+{
+  if (!(curve_mapping->flag & CUMA_EXTEND_EXTRAPOLATE)) {
+    return false;
+  }
+  const CurveMap *curve_map = &curve_mapping->cm[index];
+  if (curve_map->maxtable - curve_map->mintable != 1.0f) {
+    return false;
+  }
+  if (curve_map->ext_in[0] != curve_map->ext_in[1]) {
+    return false;
+  }
+  if (curve_map->ext_out[0] != curve_map->ext_out[1]) {
+    return false;
+  }
+  if (curve_map->totpoint != 2) {
+    return false;
+  }
+  if (curve_map->curve[0].x != 0 || curve_map->curve[0].y != 0) {
+    return false;
+  }
+  if (curve_map->curve[1].x != 0 || curve_map->curve[1].y != 0) {
+    return false;
+  }
+  return true;
+}
+
 void BKE_curvemapping_init(CurveMapping *cumap)
 {
   int a;
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index dc542411596..5fee9167362 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -305,6 +305,7 @@ set(GLSL_SRC
 
   shaders/common/gpu_shader_common_color_ramp.glsl
   shaders/common/gpu_shader_common_color_utils.glsl
+  shaders/common/gpu_shader_common_curves.glsl
   shaders/common/gpu_shader_common_hash.glsl
   shaders/common/gpu_shader_common_math.glsl
   shaders/common/gpu_shader_common_math_utils.glsl
@@ -330,7 +331,6 @@ set(GLSL_SRC
   shaders/material/gpu_shader_material_displacement.glsl
   shaders/material/gpu_shader_material_eevee_specular.glsl
   shaders/material/gpu_shader_material_emission.glsl
-  shaders/material/gpu_shader_material_float_curve.glsl
   shaders/material/gpu_shader_material_fractal_noise.glsl
   shaders/material/gpu_shader_material_fresnel.glsl
   shaders/material/gpu_shader_material_gamma.glsl
@@ -359,7 +359,6 @@ set(GLSL_SRC
   shaders/material/gpu_shader_material_point_info.glsl
   shaders/material/gpu_shader_material_principled.glsl
   shaders/material/gpu_shader_material_refraction.glsl
-  shaders/material/gpu_shader_material_rgb_curves.glsl
   shaders/material/gpu_shader_material_rgb_to_bw.glsl
   shaders/material/gpu_shader_material_separate_color.glsl
   shaders/material/gpu_shader_material_separate_hsv.glsl
@@ -388,7 +387,6 @@ set(GLSL_SRC
   shaders/material/gpu_shader_material_translucent.glsl
   shaders/material/gpu_shader_material_transparent.glsl
   shaders/material/gpu_shader_material_uv_map.glsl
-  shaders/material/gpu_shader_material_vector_curves.glsl
   shaders/material/gpu_shader_material_vector_displacement.glsl
   shaders/material/gpu_shader_material_vector_math.glsl
   shaders/material/gpu_shader_material_vector_rotate.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
new file mode 100644
index 00000000000..8948ed77557
--- /dev/null
+++ b/source/blender/gpu/shaders/common/gpu_shader_common_curves.glsl
@@ -0,0 +1,162 @@
+vec4 white_balance(vec4 color, vec4 black_level, vec4 white_level)
+{
+  vec4 range = max(white_level - black_level, vec4(1e-5f));
+  return (color - black_level) / range;
+}
+
+float extrapolate_if_needed(float parameter, float value, float start_slope, float end_slope)
+{
+  if (parameter < 0.0) {
+    return value + parameter * start_slope;
+  }
+
+  if (parameter > 1.0) {
+    return value + (parameter - 1.0) * end_slope;
+  }
+
+  return value;
+}
+
+/* Same as extrapolate_if_needed but vectorized. */
+vec3 extrapolate_if_needed(vec3 parameters, vec3 values, vec3 start_slopes, vec3 end_slopes)
+{
+  vec3 end_or_zero_slopes = mix(vec3(0.0), end_slopes, greaterThan(parameters, vec3(1.0)));
+  vec3 slopes = mix(end_or_zero_slopes, start_slopes, lessThan(parameters, vec3(0.0)));
+  parameters = parameters - mix(vec3(0.0), vec3(1.0), greaterThan(parameters, vec3(1.0)));
+  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)
+
+void curves_combined_rgb(float factor,
+                         vec4 color,
+                         vec4 black_level,
+                         vec4 white_level,
+                         sampler1DArray curve_map,
+                         const float layer,
+                         vec4 range_minimums,
+                         vec4 range_dividers,
+                         vec4 start_slopes,
+                         vec4 end_slopes,
+                         out vec4 result)
+{
+  vec4 balanced = white_balance(color, black_level, white_level);
+
+  /* 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);
+  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, 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);
+  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);
+}
+
+void curves_combined_only(float factor,
+                          vec4 color,
+                          vec4 black_level,
+                          vec4 white_level,
+                          sampler1DArray curve_map,
+                          const float layer,
+                  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list