From 9856615813ab137d0abd4baca847c7a2362bb794 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 2 Sep 2025 11:37:56 +0200 Subject: [PATCH] Color Management: Change byte color attributes to always be sRGB These don't really work as scene linear with sRGB transfer function for e.g. ACEScg, there are not enough bits. If you want wide gamut you need to use float colors. Pull Request: https://projects.blender.org/blender/blender/pulls/145763 --- intern/cycles/kernel/geom/attribute.h | 4 +++- source/blender/blenlib/BLI_color.hh | 11 ++++++++- .../blender/draw/intern/attribute_convert.hh | 12 +++++++--- .../draw/intern/draw_cache_impl_particles.cc | 23 ++++++++++++------- .../blender/makesrna/intern/rna_attribute.cc | 12 ++++++++-- 5 files changed, 47 insertions(+), 15 deletions(-) diff --git a/intern/cycles/kernel/geom/attribute.h b/intern/cycles/kernel/geom/attribute.h index e82fc06605f..fb41492779b 100644 --- a/intern/cycles/kernel/geom/attribute.h +++ b/intern/cycles/kernel/geom/attribute.h @@ -6,6 +6,7 @@ #include "kernel/globals.h" #include "kernel/types.h" +#include "kernel/util/colorspace.h" #include "util/color.h" @@ -123,8 +124,9 @@ ccl_device_inline T attribute_data_fetch_bytecolor(KernelGlobals /*kg*/, int /*o ccl_device_template_spec float4 attribute_data_fetch_bytecolor(KernelGlobals kg, int offset) { - return color_srgb_to_linear_v4( + const float4 rec709 = color_srgb_to_linear_v4( color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, offset))); + return make_float4(rec709_to_rgb(kg, make_float3(rec709)), rec709.w); } ccl_device_template_spec Transform attribute_data_fetch(KernelGlobals kg, int offset) diff --git a/source/blender/blenlib/BLI_color.hh b/source/blender/blenlib/BLI_color.hh index ba43332f691..fd3f29eef94 100644 --- a/source/blender/blenlib/BLI_color.hh +++ b/source/blender/blenlib/BLI_color.hh @@ -11,8 +11,10 @@ #include #include "BLI_color_types.hh" +#include "BLI_colorspace.hh" #include "BLI_compiler_compat.h" #include "BLI_math_color.h" +#include "BLI_math_vector.h" namespace blender { @@ -47,8 +49,12 @@ BLI_INLINE ColorTheme4b to_byte(const ColorTheme4b &theme4b) template BLI_INLINE ColorSceneLinearByteEncoded4b encode(const ColorSceneLinear4f &color) { + float4 value = static_cast(color); + if (!colorspace::scene_linear_is_rec709) { + copy_v3_v3(value, colorspace::scene_linear_to_rec709 * value.xyz()); + } ColorSceneLinearByteEncoded4b encoded; - linearrgb_to_srgb_uchar4(encoded, color); + linearrgb_to_srgb_uchar4(encoded, value); return encoded; } @@ -72,6 +78,9 @@ BLI_INLINE ColorSceneLinear4f decode(const ColorSceneLinearByteEncoded4b< { ColorSceneLinear4f decoded; srgb_to_linearrgb_uchar4(decoded, color); + if (!blender::colorspace::scene_linear_is_rec709) { + copy_v3_v3(decoded, blender::colorspace::rec709_to_scene_linear * blender::float3(decoded)); + } return decoded; } diff --git a/source/blender/draw/intern/attribute_convert.hh b/source/blender/draw/intern/attribute_convert.hh index 7b94fa12536..6b2d31618c7 100644 --- a/source/blender/draw/intern/attribute_convert.hh +++ b/source/blender/draw/intern/attribute_convert.hh @@ -15,6 +15,8 @@ #include "GPU_vertex_format.hh" +#include "IMB_colormanagement.hh" + namespace blender::gpu { class VertBuf; } @@ -117,9 +119,13 @@ template<> struct AttributeConverter { static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT_UNIT; static VBOType convert(const ColorGeometry4b &value) { - return {unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.r]), - unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.g]), - unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.b]), + blender::float3 rgb = {BLI_color_from_srgb_table[value.r], + BLI_color_from_srgb_table[value.g], + BLI_color_from_srgb_table[value.b]}; + IMB_colormanagement_rec709_to_scene_linear(rgb, rgb); + return {unit_float_to_ushort_clamp(rgb[0]), + unit_float_to_ushort_clamp(rgb[1]), + unit_float_to_ushort_clamp(rgb[2]), ushort(value.a * 257)}; } }; diff --git a/source/blender/draw/intern/draw_cache_impl_particles.cc b/source/blender/draw/intern/draw_cache_impl_particles.cc index 0ef67ce2906..e85c8e6f903 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.cc +++ b/source/blender/draw/intern/draw_cache_impl_particles.cc @@ -43,6 +43,8 @@ #include "DEG_depsgraph_query.hh" +#include "IMB_colormanagement.hh" + #include "draw_attributes.hh" #include "draw_cache_impl.hh" /* own include */ #include "draw_hair_private.hh" @@ -354,9 +356,13 @@ static void ensure_seg_pt_count(PTCacheEdit *edit, static void particle_pack_mcol(MCol *mcol, ushort r_scol[3]) { /* Convert to linear ushort and swizzle */ - r_scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]); - r_scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]); - r_scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]); + float3 col = {BLI_color_from_srgb_table[mcol->r], + BLI_color_from_srgb_table[mcol->g], + BLI_color_from_srgb_table[mcol->b]}; + IMB_colormanagement_rec709_to_scene_linear(col, col); + r_scol[0] = unit_float_to_ushort_clamp(col[2]); + r_scol[1] = unit_float_to_ushort_clamp(col[1]); + r_scol[2] = unit_float_to_ushort_clamp(col[0]); } /* Used by parent particles and simple children. */ @@ -1309,12 +1315,13 @@ static int particle_mface_index(const ChildParticle &particle, int /*face_count_ static float4 particle_mcol_convert(const MCol &mcol) { - float4 col; /* Convert to linear ushort and swizzle */ - col[0] = BLI_color_from_srgb_table[mcol.b]; - col[1] = BLI_color_from_srgb_table[mcol.g]; - col[2] = BLI_color_from_srgb_table[mcol.r]; - col[3] = mcol.a / 255.0f; + float4 col = {BLI_color_from_srgb_table[mcol.r], + BLI_color_from_srgb_table[mcol.g], + BLI_color_from_srgb_table[mcol.b], + mcol.a / 255.0f}; + IMB_colormanagement_rec709_to_scene_linear(col, col); + std::swap(col[0], col[2]); return col; } diff --git a/source/blender/makesrna/intern/rna_attribute.cc b/source/blender/makesrna/intern/rna_attribute.cc index abf410638d4..d4fb0c9a9ad 100644 --- a/source/blender/makesrna/intern/rna_attribute.cc +++ b/source/blender/makesrna/intern/rna_attribute.cc @@ -203,6 +203,8 @@ const EnumPropertyItem rna_enum_attribute_curves_domain_items[] = { # include "BLT_translation.hh" +# include "IMB_colormanagement.hh" + # include "WM_api.hh" using blender::StringRef; @@ -577,11 +579,15 @@ static void rna_ByteColorAttributeValue_color_get(PointerRNA *ptr, float *values { MLoopCol *mlcol = (MLoopCol *)ptr->data; srgb_to_linearrgb_uchar4(values, &mlcol->r); + IMB_colormanagement_rec709_to_scene_linear(values, values); } static void rna_ByteColorAttributeValue_color_set(PointerRNA *ptr, const float *values) { MLoopCol *mlcol = (MLoopCol *)ptr->data; + float rec709[4]; + IMB_colormanagement_scene_linear_to_rec709(rec709, values); + rec709[3] = values[3]; linearrgb_to_srgb_uchar4(&mlcol->r, values); } @@ -606,13 +612,15 @@ static void rna_ByteColorAttributeValue_color_srgb_set(PointerRNA *ptr, const fl static void rna_FloatColorAttributeValue_color_srgb_get(PointerRNA *ptr, float *values) { MPropCol *col = (MPropCol *)ptr->data; - linearrgb_to_srgb_v4(values, col->color); + IMB_colormanagement_scene_linear_to_srgb_v3(values, col->color); + values[3] = col->color[3]; } static void rna_FloatColorAttributeValue_color_srgb_set(PointerRNA *ptr, const float *values) { MPropCol *col = (MPropCol *)ptr->data; - srgb_to_linearrgb_v4(col->color, values); + IMB_colormanagement_srgb_to_scene_linear_v3(col->color, values); + col->color[3] = values[3]; } /* String Attribute */