Page MenuHome

Blenlib: Explicit Colors.
ClosedPublic

Authored by Jeroen Bakker (jbakker) on Apr 14 2021, 4:14 PM.

Details

Summary

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.

Diff Detail

Repository
rB Blender
Branch
temp-explicit-colors
Build Status
Buildable 14075
Build 14075: arc lint + arc unit

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes
source/blender/blenlib/BLI_color.hh
66

That is a good one. In the gpu/draw module it is also confusing when we mean sRGB (themes) and when it is linear, but with byte encoding. What happens to be implemented as srgb.

I prefer the term SceneLinearByteEncoded. A bit long, but gives clarity.

Would this then also be the time to link this to actual ocio config. I do see some challenges there and would suggest to do it as a separate project after this one is completed due to the tight relation with srgb buffers and different goals (code deconfussion vs more flexible color pipeline).

source/blender/blenlib/BLI_color.hh
66

ByteEncoded sounds good to me.

I'm not sure what linking to the OCIO config means exactly, but I think just naming the colors after the roles they correspond to in the OCIO config is most important.

135–145

I don't think this kind of automatic conversion in a constructor is good.

These conversions can be lossy. For example you would not want a function that has a temporary variable with a different alpha mode than the data it is operating on, because you will lose data.

What I think is helpful is communicating intent and type safety. I'd rather have specific functions that associate/unassociate alpha, decode/encode byte colors, etc.

source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc
73

In this design ColorGeometry always has exactly four floats, right?
I think having the 4f suffix is useful, just to better understand what the type is when looking at the name.

  • Merge branch 'master' into temp-explicit-colors
  • Renamed ColorGeometry to ColorGeometry4f.
  • Color encoding + alpha conversions are not done automatically.
  • Use encode/decode for geometry colors.

In general this looks good to me now. I'll leave the discussion about color space specific stuff to you.
There is still some code that is commented out, that should be removed before merging.

source/blender/blenlib/BLI_color.hh
108

I think this name should be a bit more specific, like convert_color_space. Also it might make sense to take src as a reference, just for consistency.

NOTE: I am not satisfied with the current patch, but want some feedback on how to proceed.

Although I tried to do no conversion at all in constructors, it wasn't working for me. The compiler wasn't smart enough to select the correct template function (convert_space). Hence it is commented out.

When using specific conversion methods introduces more bugs as you really need to be specific. When not specific done the compiler will select float* or uint8_t* constructor what isn't expected by the developer. See SrgbStraightToSceneLinearPremultiplied for example where every step needs to be specified.

We could simplify this for common transformations, but I think the current setup is too error-prone.

Another solution would be to make the color space + storage as a single class with concrete methods eg Srgb4b/SceneLinear4f as subclasses from abstract classes Color4b and Color4f

source/blender/blenlib/BLI_color.hh
135–145

Although I tried to do no conversion in constructor at all, it wasn't working for me. The compiler wasn't smart enough to select the correct template function. Hence it is commented out.

When using specific conversion methods introduces more bugs as you really need to specify the correct constructor. When this isn't done the compiler will select float* or uint8_t* constructor what isn't expected by the developer. See SrgbStraightToSceneLinearPremultiplied for example where every step needs to be specified.

We could simplify this for common transformations, but I think the current setup is too error-prone.

Another solution would be to make the color space + storage as a single class with concrete methods eg Srgb4b/SceneLinear4f as subclasses from abstract classes Color4b and Color4f

source/blender/blenlib/BLI_color.hh
135–145

I think it's fine to do no color space conversion in constructors and only use standalone functions with descriptive names instead. That should make things more explicit indeed.

I can see the issue with the float/uint8_t * constructor. The issue here is not really the constructor though but the implicit conversion to a pointer. This was causing issues for float3 as well sometimes. The best solution might be to just remove operator float *() and similar conversion operators. Instead people could use &color.r or something like color.ptr(). It's not pretty but at least it does not have these issues.

Jeroen Bakker (jbakker) planned changes to this revision.Apr 19 2021, 7:42 PM

Use concrete classes for spaces including storage, Only alpha will be templated.

  • Merge branch 'master' into temp-explicit-colors
  • Changed templates to concrete classes.
  • Added final keyword to concrete color classes.
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)Apr 20 2021, 2:33 PM
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)Apr 20 2021, 2:38 PM
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)
Jeroen Bakker (jbakker) marked 8 inline comments as done.Apr 20 2021, 2:43 PM
Jeroen Bakker (jbakker) added inline comments.
source/blender/blenlib/BLI_color.hh
326

new line

source/blender/blenlib/intern/BLI_color.cc
55 ↗(On Diff #36325)

Add newline.

source/blender/blenlib/tests/BLI_color_test.cc
134

Add newline.

source/blender/blenlib/intern/BLI_color.cc
40 ↗(On Diff #36325)

sRGB

This comment was removed by Jeroen Bakker (jbakker).
  • Merge branch 'master' into temp-explicit-colors
Brecht Van Lommel (brecht) requested changes to this revision.May 17 2021, 2:13 PM
Brecht Van Lommel (brecht) added inline comments.
source/blender/blenlib/BLI_color.hh
127–128

I would not add an sRGB color space when the implementation is known to not take into account what the scene linear color space is.

Any code using this may introduce bugs, so I would recommend having it.

282

I would not use "scene reference" terminology. "Reference" has a specific meaning in OpenColorIO, and it's different.

Maybe giving the ColorSceneLinear4f template a default value of eAlpha::Premultiplied works? Then we don't have to introduce a new term.

source/blender/draw/CMakeLists.txt
483 ↗(On Diff #37158)

I guess the drawing performance test was not meant to be part of this patch.

This revision now requires changes to proceed.May 17 2021, 2:13 PM
Jacques Lucke (JacquesLucke) requested changes to this revision.May 17 2021, 3:05 PM

Requesting changes because the patch changed since I last looked at it, and I want to have another look.

Revert "Performance: GPU Batch Baseline TestCase."

Jeroen Bakker (jbakker) planned changes to this revision.May 17 2021, 3:21 PM
Jeroen Bakker (jbakker) marked an inline comment as done.May 17 2021, 3:24 PM
source/blender/blenlib/BLI_color.hh
127–128

I am a bit between two solutions here. Theme colors are in sRGB. when removing sRGB and not changing the current logic users would do the conversion the old way that is error prone.

 char theme_color[4];
 float linear_color[4];
 srgb_to_linearrgb_v4(linear_color, srgb_color)
ColorSceneLinear4f<eAlpha::Straight> scene_linear(linear_color)

A future proof solution would be to use OCIO for the conversion between known color spaces and roles.

I think you're right to remove the confusion from start and only add it when we have connected it to color management.

282

Both premultiplied and straight is used in blender (compositor and selected operations).
My proposal would be to remove ColorSceneReference4f and ColorSceneReference4b and use the actual classes

using ColorGeometry4f = ColorSceneLinear4f<eAlpha::Premultiplied>;
using ColorGeometry4b = ColorSceneLinearByteEncoded4b<eAlpha::Premultiplied>;
source/blender/blenlib/BLI_color.hh
127–128

I think it's fine to have a color space for theme colors. And a case I forgot is the usage of theme colors in the viewport background, which needs a conversion to scene linear.

Maybe we can rename ColorSrgb to ColorTheme or ColorUI?

282

Fine with me too.

  • Changed Srgb to Theme.
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)May 18 2021, 9:16 AM
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)
  • Fixed comments still mentioning srgb.

This seems to include the drawing performance test again, but I assume that will be left out on commit.

Jacques Lucke (JacquesLucke) requested changes to this revision.May 19 2021, 1:46 PM
Jacques Lucke (JacquesLucke) added inline comments.
source/blender/blenkernel/intern/geometry_component_mesh.cc
821

Somehow I find the name to_byte_decoded confusing. Maybe it should be decode_bytes or to_float_encoded or something like that?

source/blender/blenlib/BLI_color.hh
127

typo (typically)

134

typo (an)

138

This seems to be outdated, the BLI_color_convert_to_linear function does not exist.

148

typo (to_(pre)multiplied_alpha)

155

typo (a)

208

It feels like either (1) this method should not exist when when Alpha != Straight or (2) it should just return the value unchanged in this case.

  1. This could be done by moving the method out of ColorSceneLinear4f into a standalone function. Alternatively, one could use some SFINAE to disable the method based on template parameters, this would look quite ugly though.
  2. This could be done with a simple if constexpr (Alpha == eAlpha::Straight) ....

The same applies to the method below of course.

211

typo (..)

220

Should this constructor and the one below take uint8_ts as argument?

226

typo (**)

238

Not sure I understand that last sentence.

265

This doesn't compile for me.
Use BLI_assert((std::is_same_v<ChannelStorageType, uint8_t>)); instead (note the double parenthesis).
The same applies to the method below.
Also the same arguments I mentioned in to_premultiplied_alpha apply here.

This revision now requires changes to proceed.May 19 2021, 1:46 PM
Jeroen Bakker (jbakker) marked 15 inline comments as done.
  • Merge branch 'master' into temp-explicit-colors
  • Fix compile issue introduced by merge.
  • Cleanup: to_byte_encoded => encode.
  • Cleanup: to_byte_decoded => decode
  • Cleanup: to_premultiplied_alpha => premultiply_alpha.
  • Cleanup: to_straight_alpha => unpremultiply_alpha.
  • Cleanup: Typos in comment.
  • Do nothing when method doesn't make any sense. (used to be asserts).
  • Revert "Performance: GPU Batch Baseline TestCase."
Jeroen Bakker (jbakker) marked an inline comment as done.May 25 2021, 9:01 AM
Jeroen Bakker (jbakker) added inline comments.
source/blender/blenkernel/intern/geometry_component_mesh.cc
821

I change it to encode/decode.

Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)May 25 2021, 9:03 AM
This revision is now accepted and ready to land.May 25 2021, 12:45 PM
This revision was automatically updated to reflect the committed changes.
This revision is now accepted and ready to land.May 25 2021, 5:12 PM
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)
  • Merge branch 'temp-explicit-colors' of git.blender.org:blender into temp-explicit-colors
  • Merge branch 'master' into temp-explicit-colors
  • Make constructors explicit.
  • Merge branch 'master' into temp-explicit-colors
  • Cleaned up the patch before first review.
  • Merge branch 'master' into temp-explicit-colors
  • Renamed ColorGeometry to ColorGeometry4f.
  • Color encoding + alpha conversions are not done automatically.
  • Use encode/decode for geometry colors.
  • Merge branch 'master' into temp-explicit-colors
  • Changed templates to concrete classes.
  • Added final keyword to concrete color classes.
  • Merge branch 'master' into temp-explicit-colors
  • Revert "Performance: GPU Batch Baseline TestCase."
  • Changed Srgb to Theme.
  • Merge branch 'master' into temp-explicit-colors
  • Fixed comments still mentioning srgb.
  • Merge branch 'master' into temp-explicit-colors
  • Fix compile issue introduced by merge.
  • Cleanup: to_byte_encoded => encode.
  • Cleanup: to_byte_decoded => decode
  • Cleanup: to_premultiplied_alpha => premultiply_alpha.
  • Cleanup: to_straight_alpha => unpremultiply_alpha.
  • Cleanup: Typos in comment.
  • Do nothing when method doesn't make any sense. (used to be asserts).
  • Revert "Performance: GPU Batch Baseline TestCase."
  • Merge branch 'master' into temp-explicit-colors
This revision was automatically updated to reflect the committed changes.