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. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to