Blender V4.3
util/color.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#ifndef __UTIL_COLOR_H__
6#define __UTIL_COLOR_H__
7
8#include "util/math.h"
9#include "util/types.h"
10
11#if !defined(__KERNEL_GPU__) && defined(__KERNEL_SSE2__)
12# include "util/simd.h"
13#endif
14
16
18{
19 return ((val <= 0.0f) ? 0 :
20 ((val > (1.0f - 0.5f / 255.0f)) ? 255 : (uchar)((255.0f * val) + 0.5f)));
21}
22
24{
25 return val * (1.0f / 255.0f);
26}
27
29{
30 uchar r, g, b;
31
32 r = float_to_byte(c.x);
33 g = float_to_byte(c.y);
34 b = float_to_byte(c.z);
35
36 return make_uchar4(r, g, b, 0);
37}
38
40{
41 uchar r, g, b, a;
42
43 r = float_to_byte(c.x);
44 g = float_to_byte(c.y);
45 b = float_to_byte(c.z);
46 a = float_to_byte(c.w);
47
48 return make_uchar4(r, g, b, a);
49}
50
52{
53 return make_float3(c.x * (1.0f / 255.0f), c.y * (1.0f / 255.0f), c.z * (1.0f / 255.0f));
54}
55
57{
58 return make_float4(
59 c.x * (1.0f / 255.0f), c.y * (1.0f / 255.0f), c.z * (1.0f / 255.0f), c.w * (1.0f / 255.0f));
60}
61
63{
64 if (c < 0.04045f) {
65 return (c < 0.0f) ? 0.0f : c * (1.0f / 12.92f);
66 }
67 else {
68 return powf((c + 0.055f) * (1.0f / 1.055f), 2.4f);
69 }
70}
71
73{
74 if (c < 0.0031308f) {
75 return (c < 0.0f) ? 0.0f : c * 12.92f;
76 }
77 else {
78 return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f;
79 }
80}
81
83{
84 float cmax, cmin, h, s, v, cdelta;
85 float3 c;
86
87 cmax = fmaxf(rgb.x, fmaxf(rgb.y, rgb.z));
88 cmin = min(rgb.x, min(rgb.y, rgb.z));
89 cdelta = cmax - cmin;
90
91 v = cmax;
92
93 if (cmax != 0.0f) {
94 s = cdelta / cmax;
95 }
96 else {
97 s = 0.0f;
98 h = 0.0f;
99 }
100
101 if (s != 0.0f) {
102 float3 cmax3 = make_float3(cmax, cmax, cmax);
103 c = (cmax3 - rgb) / cdelta;
104
105 if (rgb.x == cmax) {
106 h = c.z - c.y;
107 }
108 else if (rgb.y == cmax) {
109 h = 2.0f + c.x - c.z;
110 }
111 else {
112 h = 4.0f + c.y - c.x;
113 }
114
115 h /= 6.0f;
116
117 if (h < 0.0f) {
118 h += 1.0f;
119 }
120 }
121 else {
122 h = 0.0f;
123 }
124
125 return make_float3(h, s, v);
126}
127
129{
130 float i, f, p, q, t, h, s, v;
131 float3 rgb;
132
133 h = hsv.x;
134 s = hsv.y;
135 v = hsv.z;
136
137 if (s != 0.0f) {
138 if (h == 1.0f) {
139 h = 0.0f;
140 }
141
142 h *= 6.0f;
143 i = floorf(h);
144 f = h - i;
145 rgb = make_float3(f, f, f);
146 p = v * (1.0f - s);
147 q = v * (1.0f - (s * f));
148 t = v * (1.0f - (s * (1.0f - f)));
149
150 if (i == 0.0f) {
151 rgb = make_float3(v, t, p);
152 }
153 else if (i == 1.0f) {
154 rgb = make_float3(q, v, p);
155 }
156 else if (i == 2.0f) {
157 rgb = make_float3(p, v, t);
158 }
159 else if (i == 3.0f) {
160 rgb = make_float3(p, q, v);
161 }
162 else if (i == 4.0f) {
163 rgb = make_float3(t, p, v);
164 }
165 else {
166 rgb = make_float3(v, p, q);
167 }
168 }
169 else {
170 rgb = make_float3(v, v, v);
171 }
172
173 return rgb;
174}
175
177{
178 float cmax, cmin, h, s, l;
179
180 cmax = fmaxf(rgb.x, fmaxf(rgb.y, rgb.z));
181 cmin = min(rgb.x, min(rgb.y, rgb.z));
182 l = min(1.0f, (cmax + cmin) / 2.0f);
183
184 if (cmax == cmin) {
185 h = s = 0.0f; /* achromatic */
186 }
187 else {
188 float cdelta = cmax - cmin;
189 s = l > 0.5f ? cdelta / (2.0f - cmax - cmin) : cdelta / (cmax + cmin);
190 if (cmax == rgb.x) {
191 h = (rgb.y - rgb.z) / cdelta + (rgb.y < rgb.z ? 6.0f : 0.0f);
192 }
193 else if (cmax == rgb.y) {
194 h = (rgb.z - rgb.x) / cdelta + 2.0f;
195 }
196 else {
197 h = (rgb.x - rgb.y) / cdelta + 4.0f;
198 }
199 }
200 h /= 6.0f;
201
202 return make_float3(h, s, l);
203}
204
206{
207 float nr, ng, nb, chroma, h, s, l;
208
209 h = hsl.x;
210 s = hsl.y;
211 l = hsl.z;
212
213 nr = fabsf(h * 6.0f - 3.0f) - 1.0f;
214 ng = 2.0f - fabsf(h * 6.0f - 2.0f);
215 nb = 2.0f - fabsf(h * 6.0f - 4.0f);
216
217 nr = clamp(nr, 0.0f, 1.0f);
218 nb = clamp(nb, 0.0f, 1.0f);
219 ng = clamp(ng, 0.0f, 1.0f);
220
221 chroma = (1.0f - fabsf(2.0f * l - 1.0f)) * s;
222
223 return make_float3((nr - 0.5f) * chroma + l, (ng - 0.5f) * chroma + l, (nb - 0.5f) * chroma + l);
224}
225
226ccl_device float3 xyY_to_xyz(float x, float y, float Y)
227{
228 float X, Z;
229
230 if (y != 0.0f) {
231 X = (x / y) * Y;
232 }
233 else {
234 X = 0.0f;
235 }
236
237 if (y != 0.0f && Y != 0.0f) {
238 Z = (1.0f - x - y) / y * Y;
239 }
240 else {
241 Z = 0.0f;
242 }
243
244 return make_float3(X, Y, Z);
245}
246
247#ifdef __KERNEL_SSE2__
248/*
249 * Calculate initial guess for arg^exp based on float representation
250 * This method gives a constant bias,
251 * which can be easily compensated by multiplication with bias_coeff.
252 * Gives better results for exponents near 1 (e. g. 4/5).
253 * exp = exponent, encoded as uint32_t
254 * e2coeff = 2^(127/exponent - 127) * bias_coeff^(1/exponent), encoded as uint32_t
255 */
256template<unsigned exp, unsigned e2coeff> ccl_device_inline float4 fastpow_sse2(const float4 &arg)
257{
258 float4 ret = arg * cast(make_int4(e2coeff));
260 ret = ret * cast(make_int4(exp));
261 ret = cast(make_int4(ret));
262 return ret;
263}
264
265/* Improve x ^ 1.0f/5.0f solution with Newton-Raphson method */
266ccl_device_inline float4 improve_5throot_solution_sse2(const float4 &old_result, const float4 &x)
267{
268 float4 approx2 = old_result * old_result;
269 float4 approx4 = approx2 * approx2;
270 float4 t = x / approx4;
271 float4 summ = madd(make_float4(4.0f), old_result, t);
272 return summ * make_float4(1.0f / 5.0f);
273}
274
275/* Calculate powf(x, 2.4). Working domain: 1e-10 < x < 1e+10 */
276ccl_device_inline float4 fastpow24_sse2(const float4 &arg)
277{
278 /* `max`, `avg` and |avg| errors were calculated in GCC without FMA instructions.
279 * The final precision should be better than `powf` in GLIBC. */
280
281 /* Calculate x^4/5, coefficient 0.994 was constructed manually to minimize avg error */
282 /* 0x3F4CCCCD = 4/5 */
283 /* 0x4F55A7FB = 2^(127/(4/5) - 127) * 0.994^(1/(4/5)) */
284 float4 x = fastpow_sse2<0x3F4CCCCD, 0x4F55A7FB>(
285 arg); // error max = 0.17 avg = 0.0018 |avg| = 0.05
286 float4 arg2 = arg * arg;
287 float4 arg4 = arg2 * arg2;
288
289 /* error max = 0.018 avg = 0.0031 |avg| = 0.0031 */
290 x = improve_5throot_solution_sse2(x, arg4);
291 /* error max = 0.00021 avg = 1.6e-05 |avg| = 1.6e-05 */
292 x = improve_5throot_solution_sse2(x, arg4);
293 /* error max = 6.1e-07 avg = 5.2e-08 |avg| = 1.1e-07 */
294 x = improve_5throot_solution_sse2(x, arg4);
295
296 return x * (x * x);
297}
298
299ccl_device float4 color_srgb_to_linear_sse2(const float4 &c)
300{
301 int4 cmp = c < make_float4(0.04045f);
302 float4 lt = max(c * make_float4(1.0f / 12.92f), make_float4(0.0f));
303 float4 gtebase = (c + make_float4(0.055f)) * make_float4(1.0f / 1.055f); /* fma */
304 float4 gte = fastpow24_sse2(gtebase);
305 return select(cmp, lt, gte);
306}
307#endif /* __KERNEL_SSE2__ */
308
314
320
322{
323 return make_float4(
325}
326
328{
329#ifdef __KERNEL_SSE2__
330 float4 r = c;
331 r = color_srgb_to_linear_sse2(r);
332 r.w = c.w;
333 return r;
334#else
335 return make_float4(
337#endif
338}
339
341{
342 color += one_float3();
343 if (variance) {
344 *variance *= sqr(one_float3() / color);
345 }
346 return log(color);
347}
348
350{
351 return exp(color) - one_float3();
352}
353
355
356#endif /* __UTIL_COLOR_H__ */
unsigned char uchar
#define X
#define Z
#define Y
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
local_group_size(16, 16) .push_constant(Type b
#define ccl_device
#define ccl_private
#define ccl_device_inline
#define powf(x, y)
#define CCL_NAMESPACE_END
ccl_device_forceinline float4 make_float4(const float x, const float y, const float z, const float w)
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
ccl_device_forceinline uchar4 make_uchar4(const uchar x, const uchar y, const uchar z, const uchar w)
#define fmaxf(x, y)
#define floorf(x)
#define fabsf(x)
ccl_device_forceinline int4 make_int4(const int x, const int y, const int z, const int w)
CCL_NAMESPACE_BEGIN ccl_device_inline float madd(const float a, const float b, const float c)
Definition math_fast.h:29
ccl_device_inline float3 one_float3()
Definition math_float3.h:24
ccl_device_inline float3 exp(float3 v)
ccl_device_inline float3 log(float3 v)
ccl_device_inline int4 cast(const float4 a)
Definition math_float4.h:29
ccl_device_inline float4 select(const int4 mask, const float4 a, const float4 b)
VecBase< float, 4 > float4
return ret
#define min(a, b)
Definition sort.c:32
float z
Definition sky_float3.h:27
float y
Definition sky_float3.h:27
float x
Definition sky_float3.h:27
uchar z
uchar w
uchar x
uchar y
float max
ccl_device float3 hsl_to_rgb(float3 hsl)
Definition util/color.h:205
ccl_device float color_linear_to_srgb(float c)
Definition util/color.h:72
ccl_device float3 color_highlight_compress(float3 color, ccl_private float3 *variance)
Definition util/color.h:340
ccl_device float3 xyY_to_xyz(float x, float y, float Y)
Definition util/color.h:226
ccl_device_inline float4 color_uchar4_to_float4(uchar4 c)
Definition util/color.h:56
ccl_device uchar4 color_float4_to_uchar4(float4 c)
Definition util/color.h:39
ccl_device float3 color_srgb_to_linear_v3(float3 c)
Definition util/color.h:309
ccl_device float4 color_linear_to_srgb_v4(float4 c)
Definition util/color.h:321
ccl_device float3 rgb_to_hsv(float3 rgb)
Definition util/color.h:82
ccl_device float3 color_highlight_uncompress(float3 color)
Definition util/color.h:349
ccl_device float4 color_srgb_to_linear_v4(float4 c)
Definition util/color.h:327
ccl_device float3 color_linear_to_srgb_v3(float3 c)
Definition util/color.h:315
ccl_device float3 hsv_to_rgb(float3 hsv)
Definition util/color.h:128
ccl_device float color_srgb_to_linear(float c)
Definition util/color.h:62
ccl_device float byte_to_float(uchar val)
Definition util/color.h:23
ccl_device float3 rgb_to_hsl(float3 rgb)
Definition util/color.h:176
ccl_device_inline float3 color_byte_to_float(uchar4 c)
Definition util/color.h:51
ccl_device uchar4 color_float_to_byte(float3 c)
Definition util/color.h:28
CCL_NAMESPACE_BEGIN ccl_device uchar float_to_byte(float val)
Definition util/color.h:17
ccl_device_inline float sqr(float a)
Definition util/math.h:782
ccl_device_inline int clamp(int a, int mn, int mx)
Definition util/math.h:379