[Bf-blender-cvs] [fd94e033446] master: Blenlib: Explicit Colors.

Jeroen Bakker noreply at git.blender.org
Tue May 25 17:01:51 CEST 2021


Commit: fd94e033446c72fb92048a9864c1d539fccde59a
Author: Jeroen Bakker
Date:   Tue May 25 17:00:14 2021 +0200
Branches: master
https://developer.blender.org/rBfd94e033446c72fb92048a9864c1d539fccde59a

Blenlib: Explicit Colors.

Colors are often thought of as being 4 values that make up that can make any color.
But that is of course too limited. In C we didn’t spend time to annotate what we meant
when using colors.

Recently `BLI_color.hh` was made to facilitate color structures in CPP. CPP has possibilities to
enforce annotating structures during compilation and can adds conversions between them using
function overloading and explicit constructors.

The storage structs can hold 4 channels (r, g, b and a).

Usage:

Convert a theme byte color to a linearrgb premultiplied.
```
ColorTheme4b theme_color;
ColorSceneLinear4f<eAlpha::Premultiplied> linearrgb_color =
    BLI_color_convert_to_scene_linear(theme_color).premultiply_alpha();
```

The API is structured to make most use of inlining. Most notable are space
conversions done via `BLI_color_convert_to*` functions.

- Conversions between spaces (theme <=> scene linear) should always be done by
  invoking the `BLI_color_convert_to*` methods.
- Encoding colors (compressing to store colors inside a less precision storage)
  should be done by invoking the `encode` and `decode` methods.
- Changing alpha association should be done by invoking `premultiply_alpha` or
  `unpremultiply_alpha` methods.

# Encoding.

Color encoding is used to store colors with less precision as in using `uint8_t` in
stead of `float`. This encoding is supported for `eSpace::SceneLinear`.
To make this clear to the developer the `eSpace::SceneLinearByteEncoded`
space is added.

# Precision

Colors can be stored using `uint8_t` or `float` colors. The conversion
between the two precisions are available as methods. (`to_4b` and
`to_4f`).

# Alpha conversion

Alpha conversion is only supported in SceneLinear space.

Extending:
- This file can be extended with `ColorHex/Hsl/Hsv` for different representations
  of rgb based colors. `ColorHsl4f<eSpace::SceneLinear, eAlpha::Premultiplied>`
- Add non RGB spaces/storages ColorXyz.

Reviewed By: JacquesLucke, brecht

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

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

M	source/blender/blenkernel/BKE_attribute_math.hh
M	source/blender/blenkernel/intern/attribute_access.cc
M	source/blender/blenkernel/intern/attribute_math.cc
M	source/blender/blenkernel/intern/geometry_component_mesh.cc
M	source/blender/blenlib/BLI_color.hh
M	source/blender/blenlib/CMakeLists.txt
A	source/blender/blenlib/intern/BLI_color.cc
A	source/blender/blenlib/tests/BLI_color_test.cc
M	source/blender/draw/intern/draw_cache_impl.h
M	source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh
M	source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
M	source/blender/editors/space_spreadsheet/spreadsheet_layout.cc
M	source/blender/functions/intern/cpp_types.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc
M	source/blender/nodes/geometry/nodes/node_geo_switch.cc
M	source/blender/nodes/intern/node_geometry_exec.cc
M	source/blender/nodes/intern/node_socket.cc
M	source/blender/nodes/intern/type_conversions.cc
M	source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc
M	source/blender/nodes/shader/nodes/node_shader_valToRgb.cc

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

diff --git a/source/blender/blenkernel/BKE_attribute_math.hh b/source/blender/blenkernel/BKE_attribute_math.hh
index 0afdc436415..ba683362e69 100644
--- a/source/blender/blenkernel/BKE_attribute_math.hh
+++ b/source/blender/blenkernel/BKE_attribute_math.hh
@@ -52,7 +52,7 @@ inline void convert_to_static_type(const CustomDataType data_type, const Func &f
       func(bool());
       break;
     case CD_PROP_COLOR:
-      func(Color4f());
+      func(ColorGeometry4f());
       break;
     default:
       BLI_assert_unreachable();
@@ -78,8 +78,8 @@ inline void convert_to_static_type(const fn::CPPType &cpp_type, const Func &func
   else if (cpp_type.is<bool>()) {
     func(bool());
   }
-  else if (cpp_type.is<Color4f>()) {
-    func(Color4f());
+  else if (cpp_type.is<ColorGeometry4f>()) {
+    func(ColorGeometry4f());
   }
   else {
     BLI_assert_unreachable();
@@ -123,9 +123,12 @@ inline float3 mix3(const float3 &weights, const float3 &v0, const float3 &v1, co
 }
 
 template<>
-inline Color4f mix3(const float3 &weights, const Color4f &v0, const Color4f &v1, const Color4f &v2)
+inline ColorGeometry4f mix3(const float3 &weights,
+                            const ColorGeometry4f &v0,
+                            const ColorGeometry4f &v1,
+                            const ColorGeometry4f &v2)
 {
-  Color4f result;
+  ColorGeometry4f result;
   interp_v4_v4v4v4(result, v0, v1, v2, weights);
   return result;
 }
@@ -165,9 +168,10 @@ template<> inline float3 mix2(const float factor, const float3 &a, const float3
   return float3::interpolate(a, b, factor);
 }
 
-template<> inline Color4f mix2(const float factor, const Color4f &a, const Color4f &b)
+template<>
+inline ColorGeometry4f mix2(const float factor, const ColorGeometry4f &a, const ColorGeometry4f &b)
 {
-  Color4f result;
+  ColorGeometry4f result;
   interp_v4_v4v4(result, a, b, factor);
   return result;
 }
@@ -274,15 +278,16 @@ class SimpleMixerWithAccumulationType {
   }
 };
 
-class Color4fMixer {
+class ColorGeometryMixer {
  private:
-  MutableSpan<Color4f> buffer_;
-  Color4f default_color_;
+  MutableSpan<ColorGeometry4f> buffer_;
+  ColorGeometry4f default_color_;
   Array<float> total_weights_;
 
  public:
-  Color4fMixer(MutableSpan<Color4f> buffer, Color4f default_color = {0, 0, 0, 1});
-  void mix_in(const int64_t index, const Color4f &color, const float weight = 1.0f);
+  ColorGeometryMixer(MutableSpan<ColorGeometry4f> buffer,
+                     ColorGeometry4f default_color = ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f));
+  void mix_in(const int64_t index, const ColorGeometry4f &color, const float weight = 1.0f);
   void finalize();
 };
 
@@ -299,10 +304,10 @@ template<> struct DefaultMixerStruct<float2> {
 template<> struct DefaultMixerStruct<float3> {
   using type = SimpleMixer<float3>;
 };
-template<> struct DefaultMixerStruct<Color4f> {
-  /* Use a special mixer for colors. Color4f can't be added/multiplied, because this is not
+template<> struct DefaultMixerStruct<ColorGeometry4f> {
+  /* Use a special mixer for colors. ColorGeometry4f can't be added/multiplied, because this is not
    * something one should usually do with colors.  */
-  using type = Color4fMixer;
+  using type = ColorGeometryMixer;
 };
 template<> struct DefaultMixerStruct<int> {
   static int double_to_int(const double &value)
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 62833e10438..d36e9ed3e86 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -61,7 +61,7 @@ const blender::fn::CPPType *custom_data_type_to_cpp_type(const CustomDataType ty
     case CD_PROP_INT32:
       return &CPPType::get<int>();
     case CD_PROP_COLOR:
-      return &CPPType::get<Color4f>();
+      return &CPPType::get<ColorGeometry4f>();
     case CD_PROP_BOOL:
       return &CPPType::get<bool>();
     default:
@@ -84,7 +84,7 @@ CustomDataType cpp_type_to_custom_data_type(const blender::fn::CPPType &type)
   if (type.is<int>()) {
     return CD_PROP_INT32;
   }
-  if (type.is<Color4f>()) {
+  if (type.is<ColorGeometry4f>()) {
     return CD_PROP_COLOR;
   }
   if (type.is<bool>()) {
@@ -355,7 +355,7 @@ ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read(
       case CD_PROP_INT32:
         return this->layer_to_read_attribute<int>(layer, domain_size);
       case CD_PROP_COLOR:
-        return this->layer_to_read_attribute<Color4f>(layer, domain_size);
+        return this->layer_to_read_attribute<ColorGeometry4f>(layer, domain_size);
       case CD_PROP_BOOL:
         return this->layer_to_read_attribute<bool>(layer, domain_size);
       default:
@@ -389,7 +389,7 @@ WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write(
       case CD_PROP_INT32:
         return this->layer_to_write_attribute<int>(layer, domain_size);
       case CD_PROP_COLOR:
-        return this->layer_to_write_attribute<Color4f>(layer, domain_size);
+        return this->layer_to_write_attribute<ColorGeometry4f>(layer, domain_size);
       case CD_PROP_BOOL:
         return this->layer_to_write_attribute<bool>(layer, domain_size);
       default:
diff --git a/source/blender/blenkernel/intern/attribute_math.cc b/source/blender/blenkernel/intern/attribute_math.cc
index 4ff3a6ceff5..5cdf329effb 100644
--- a/source/blender/blenkernel/intern/attribute_math.cc
+++ b/source/blender/blenkernel/intern/attribute_math.cc
@@ -18,18 +18,21 @@
 
 namespace blender::attribute_math {
 
-Color4fMixer::Color4fMixer(MutableSpan<Color4f> output_buffer, Color4f default_color)
+ColorGeometryMixer::ColorGeometryMixer(MutableSpan<ColorGeometry4f> output_buffer,
+                                       ColorGeometry4f default_color)
     : buffer_(output_buffer),
       default_color_(default_color),
       total_weights_(output_buffer.size(), 0.0f)
 {
-  buffer_.fill(Color4f(0, 0, 0, 0));
+  buffer_.fill(ColorGeometry4f(0.0f, 0.0f, 0.0f, 0.0f));
 }
 
-void Color4fMixer::mix_in(const int64_t index, const Color4f &color, const float weight)
+void ColorGeometryMixer::mix_in(const int64_t index,
+                                const ColorGeometry4f &color,
+                                const float weight)
 {
   BLI_assert(weight >= 0.0f);
-  Color4f &output_color = buffer_[index];
+  ColorGeometry4f &output_color = buffer_[index];
   output_color.r += color.r * weight;
   output_color.g += color.g * weight;
   output_color.b += color.b * weight;
@@ -37,11 +40,11 @@ void Color4fMixer::mix_in(const int64_t index, const Color4f &color, const float
   total_weights_[index] += weight;
 }
 
-void Color4fMixer::finalize()
+void ColorGeometryMixer::finalize()
 {
   for (const int64_t i : buffer_.index_range()) {
     const float weight = total_weights_[i];
-    Color4f &output_color = buffer_[i];
+    ColorGeometry4f &output_color = buffer_[i];
     if (weight > 0.0f) {
       const float weight_inv = 1.0f / weight;
       output_color.r *= weight_inv;
diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc
index 9e622ab2cdf..42f3a854aec 100644
--- a/source/blender/blenkernel/intern/geometry_component_mesh.cc
+++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc
@@ -773,18 +773,20 @@ static void set_loop_uv(MLoopUV &uv, float2 co)
   copy_v2_v2(uv.uv, co);
 }
 
-static Color4f get_loop_color(const MLoopCol &col)
+static ColorGeometry4f get_loop_color(const MLoopCol &col)
 {
-  Color4f srgb_color;
-  rgba_uchar_to_float(srgb_color, &col.r);
-  Color4f linear_color;
-  srgb_to_linearrgb_v4(linear_color, srgb_color);
+  ColorGeometry4b encoded_color = ColorGeometry4b(col.r, col.g, col.b, col.a);
+  ColorGeometry4f linear_color = encoded_color.decode();
   return linear_color;
 }
 
-static void set_loop_color(MLoopCol &col, Color4f linear_color)
+static void set_loop_color(MLoopCol &col, ColorGeometry4f linear_color)
 {
-  linearrgb_to_srgb_uchar4(&col.r, linear_color);
+  ColorGeometry4b encoded_color = linear_color.encode();
+  col.r = encoded_color.r;
+  col.g = encoded_color.g;
+  col.b = encoded_color.b;
+  col.a = encoded_color.a;
 }
 
 static float get_crease(const MEdge &edge)
@@ -1121,8 +1123,8 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
       CD_PROP_COLOR,
       CD_MLOOPCOL,
       corner_access,
-      make_derived_read_attribute<MLoopCol, Color4f, get_loop_color>,
-      make_derived_write_attribute<MLoopCol, Color4f, get_loop_color, set_loop_color>);
+      make_derived_read_attribute<MLoopCol, ColorGeometry4f, get_loop_color>,
+      make_derived_write_attribute<MLoopCol, ColorGeometry4f, get_loop_color, set_loop_color>);
 
   static VertexGroupsAttributeProvider vertex_groups;
   static CustomDataAttributeProvider corner_custom_data(ATTR_DOMAIN_CORNER, corner_access);
diff --git a/source/blender/blenlib/BLI_color.hh b/source/blender/blenlib/BLI_color.hh
index e57a5109a66..287587e04be 100644
--- a/source/blender/blenlib/BLI_color.hh
+++ b/source/blender/blenlib/BLI_color.hh
@@ -22,41 +22,122 @@
 
 namespace blender {
 
-struct Color4f {
-  float r, g, b, a;
+/**
+ * CPP based color structures.
+ *
+ * Strongly typed color storage structures with space and alpha association.
+ * Will increase readability and visibility of typical mistakes when
+ * working with colors.
+ *
+ * The storage structs can hold 4 channels (r, g, b and a).
+ *
+ * Usage:
+ *
+ * Convert a theme byte color to a linearrgb premultiplied.
+ * ```
+ * ColorTheme4b theme_color;
+ * ColorSceneLinear4f<eAlpha::Premultiplied> linearrgb_color =
+ *     BLI_color_convert_to_scene_linear(theme_color).premultiply_alpha();
+ * ```
+ *
+ * The API is structured to make most use of inlining. Most notable are space
+ * conversions done via `BLI_color_convert_to*` functions.
+ *
+ * - Conversions between spaces (theme <=> scene linear) should always be done by
+ *   invoking the `BLI_color_convert_to*` methods.
+ * - Encoding colors (compressing to store colors inside a less precision storage)
+ *   should be done by invoking the `encode` and `decode` methods.
+ * - Changing alpha association should be done by invo

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list