Blender V5.0
color_util.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#pragma once
6
7#include "kernel/svm/types.h"
8
9#include "util/color.h"
10
12
13ccl_device float3 svm_mix_blend(const float t, const float3 col1, const float3 col2)
14{
15 return interp(col1, col2, t);
16}
17
18ccl_device float3 svm_mix_add(const float t, const float3 col1, const float3 col2)
19{
20 return interp(col1, col1 + col2, t);
21}
22
23ccl_device float3 svm_mix_mul(const float t, const float3 col1, const float3 col2)
24{
25 return interp(col1, col1 * col2, t);
26}
27
28ccl_device float3 svm_mix_screen(const float t, const float3 col1, const float3 col2)
29{
30 const float tm = 1.0f - t;
31 const float3 one = make_float3(1.0f, 1.0f, 1.0f);
32 const float3 tm3 = make_float3(tm, tm, tm);
33
34 return one - (tm3 + t * (one - col2)) * (one - col1);
35}
36
37ccl_device float3 svm_mix_overlay(const float t, const float3 col1, const float3 col2)
38{
39 const float tm = 1.0f - t;
40
41 float3 outcol = col1;
42
43 if (outcol.x < 0.5f) {
44 outcol.x *= tm + 2.0f * t * col2.x;
45 }
46 else {
47 outcol.x = 1.0f - (tm + 2.0f * t * (1.0f - col2.x)) * (1.0f - outcol.x);
48 }
49
50 if (outcol.y < 0.5f) {
51 outcol.y *= tm + 2.0f * t * col2.y;
52 }
53 else {
54 outcol.y = 1.0f - (tm + 2.0f * t * (1.0f - col2.y)) * (1.0f - outcol.y);
55 }
56
57 if (outcol.z < 0.5f) {
58 outcol.z *= tm + 2.0f * t * col2.z;
59 }
60 else {
61 outcol.z = 1.0f - (tm + 2.0f * t * (1.0f - col2.z)) * (1.0f - outcol.z);
62 }
63
64 return outcol;
65}
66
67ccl_device float3 svm_mix_sub(const float t, const float3 col1, const float3 col2)
68{
69 return interp(col1, col1 - col2, t);
70}
71
72ccl_device float3 svm_mix_div(const float t, const float3 col1, const float3 col2)
73{
74 const float tm = 1.0f - t;
75
76 float3 outcol = col1;
77
78 if (col2.x != 0.0f) {
79 outcol.x = tm * outcol.x + t * outcol.x / col2.x;
80 }
81 if (col2.y != 0.0f) {
82 outcol.y = tm * outcol.y + t * outcol.y / col2.y;
83 }
84 if (col2.z != 0.0f) {
85 outcol.z = tm * outcol.z + t * outcol.z / col2.z;
86 }
87
88 return outcol;
89}
90
91ccl_device float3 svm_mix_diff(const float t, const float3 col1, const float3 col2)
92{
93 return interp(col1, fabs(col1 - col2), t);
94}
95
96ccl_device float3 svm_mix_exclusion(const float t, const float3 col1, const float3 col2)
97{
98 return max(interp(col1, col1 + col2 - 2.0f * col1 * col2, t), zero_float3());
99}
100
101ccl_device float3 svm_mix_dark(const float t, const float3 col1, const float3 col2)
102{
103 return interp(col1, min(col1, col2), t);
104}
105
106ccl_device float3 svm_mix_light(const float t, const float3 col1, const float3 col2)
107{
108 return interp(col1, max(col1, col2), t);
109}
110
111ccl_device float3 svm_mix_dodge(const float t, const float3 col1, const float3 col2)
112{
113 float3 outcol = col1;
114
115 if (outcol.x != 0.0f) {
116 float tmp = 1.0f - t * col2.x;
117 if (tmp <= 0.0f) {
118 outcol.x = 1.0f;
119 }
120 else {
121 tmp = outcol.x / tmp;
122 if (tmp > 1.0f) {
123 outcol.x = 1.0f;
124 }
125 else {
126 outcol.x = tmp;
127 }
128 }
129 }
130 if (outcol.y != 0.0f) {
131 float tmp = 1.0f - t * col2.y;
132 if (tmp <= 0.0f) {
133 outcol.y = 1.0f;
134 }
135 else {
136 tmp = outcol.y / tmp;
137 if (tmp > 1.0f) {
138 outcol.y = 1.0f;
139 }
140 else {
141 outcol.y = tmp;
142 }
143 }
144 }
145 if (outcol.z != 0.0f) {
146 float tmp = 1.0f - t * col2.z;
147 if (tmp <= 0.0f) {
148 outcol.z = 1.0f;
149 }
150 else {
151 tmp = outcol.z / tmp;
152 if (tmp > 1.0f) {
153 outcol.z = 1.0f;
154 }
155 else {
156 outcol.z = tmp;
157 }
158 }
159 }
160
161 return outcol;
162}
163
164ccl_device float3 svm_mix_burn(const float t, const float3 col1, const float3 col2)
165{
166 float tmp;
167 const float tm = 1.0f - t;
168
169 float3 outcol = col1;
170
171 tmp = tm + t * col2.x;
172 if (tmp <= 0.0f) {
173 outcol.x = 0.0f;
174 }
175 else {
176 tmp = (1.0f - (1.0f - outcol.x) / tmp);
177 if (tmp < 0.0f) {
178 outcol.x = 0.0f;
179 }
180 else if (tmp > 1.0f) {
181 outcol.x = 1.0f;
182 }
183 else {
184 outcol.x = tmp;
185 }
186 }
187
188 tmp = tm + t * col2.y;
189 if (tmp <= 0.0f) {
190 outcol.y = 0.0f;
191 }
192 else {
193 tmp = (1.0f - (1.0f - outcol.y) / tmp);
194 if (tmp < 0.0f) {
195 outcol.y = 0.0f;
196 }
197 else if (tmp > 1.0f) {
198 outcol.y = 1.0f;
199 }
200 else {
201 outcol.y = tmp;
202 }
203 }
204
205 tmp = tm + t * col2.z;
206 if (tmp <= 0.0f) {
207 outcol.z = 0.0f;
208 }
209 else {
210 tmp = (1.0f - (1.0f - outcol.z) / tmp);
211 if (tmp < 0.0f) {
212 outcol.z = 0.0f;
213 }
214 else if (tmp > 1.0f) {
215 outcol.z = 1.0f;
216 }
217 else {
218 outcol.z = tmp;
219 }
220 }
221
222 return outcol;
223}
224
225ccl_device float3 svm_mix_hue(const float t, const float3 col1, const float3 col2)
226{
227 float3 outcol = col1;
228
229 const float3 hsv2 = rgb_to_hsv(col2);
230
231 if (hsv2.y != 0.0f) {
232 float3 hsv = rgb_to_hsv(outcol);
233 hsv.x = hsv2.x;
234 const float3 tmp = hsv_to_rgb(hsv);
235
236 outcol = interp(outcol, tmp, t);
237 }
238
239 return outcol;
240}
241
242ccl_device float3 svm_mix_sat(const float t, const float3 col1, const float3 col2)
243{
244 const float tm = 1.0f - t;
245
246 float3 outcol = col1;
247
248 float3 hsv = rgb_to_hsv(outcol);
249
250 if (hsv.y != 0.0f) {
251 const float3 hsv2 = rgb_to_hsv(col2);
252
253 hsv.y = tm * hsv.y + t * hsv2.y;
254 outcol = hsv_to_rgb(hsv);
255 }
256
257 return outcol;
258}
259
260ccl_device float3 svm_mix_val(const float t, const float3 col1, const float3 col2)
261{
262 const float tm = 1.0f - t;
263
264 float3 hsv = rgb_to_hsv(col1);
265 const float3 hsv2 = rgb_to_hsv(col2);
266
267 hsv.z = tm * hsv.z + t * hsv2.z;
268
269 return hsv_to_rgb(hsv);
270}
271
272ccl_device float3 svm_mix_color(const float t, const float3 col1, const float3 col2)
273{
274 float3 outcol = col1;
275 const float3 hsv2 = rgb_to_hsv(col2);
276
277 if (hsv2.y != 0.0f) {
278 float3 hsv = rgb_to_hsv(outcol);
279 hsv.x = hsv2.x;
280 hsv.y = hsv2.y;
281 const float3 tmp = hsv_to_rgb(hsv);
282
283 outcol = interp(outcol, tmp, t);
284 }
285
286 return outcol;
287}
288
289ccl_device float3 svm_mix_soft(const float t, const float3 col1, const float3 col2)
290{
291 const float tm = 1.0f - t;
292
293 const float3 one = make_float3(1.0f, 1.0f, 1.0f);
294 const float3 scr = one - (one - col2) * (one - col1);
295
296 return tm * col1 + t * ((one - col1) * col2 * col1 + col1 * scr);
297}
298
299ccl_device float3 svm_mix_linear(const float t, const float3 col1, const float3 col2)
300{
301 return col1 + t * (2.0f * col2 + make_float3(-1.0f, -1.0f, -1.0f));
302}
303
305{
306 return saturate(col);
307}
308
310 const float t,
311 const float3 c1,
312 const float3 c2)
313{
314 switch (type) {
315 case NODE_MIX_BLEND:
316 return svm_mix_blend(t, c1, c2);
317 case NODE_MIX_ADD:
318 return svm_mix_add(t, c1, c2);
319 case NODE_MIX_MUL:
320 return svm_mix_mul(t, c1, c2);
321 case NODE_MIX_SCREEN:
322 return svm_mix_screen(t, c1, c2);
323 case NODE_MIX_OVERLAY:
324 return svm_mix_overlay(t, c1, c2);
325 case NODE_MIX_SUB:
326 return svm_mix_sub(t, c1, c2);
327 case NODE_MIX_DIV:
328 return svm_mix_div(t, c1, c2);
329 case NODE_MIX_DIFF:
330 return svm_mix_diff(t, c1, c2);
332 return svm_mix_exclusion(t, c1, c2);
333 case NODE_MIX_DARK:
334 return svm_mix_dark(t, c1, c2);
335 case NODE_MIX_LIGHT:
336 return svm_mix_light(t, c1, c2);
337 case NODE_MIX_DODGE:
338 return svm_mix_dodge(t, c1, c2);
339 case NODE_MIX_BURN:
340 return svm_mix_burn(t, c1, c2);
341 case NODE_MIX_HUE:
342 return svm_mix_hue(t, c1, c2);
343 case NODE_MIX_SAT:
344 return svm_mix_sat(t, c1, c2);
345 case NODE_MIX_VAL:
346 return svm_mix_val(t, c1, c2);
347 case NODE_MIX_COL:
348 return svm_mix_color(t, c1, c2);
349 case NODE_MIX_SOFT:
350 return svm_mix_soft(t, c1, c2);
351 case NODE_MIX_LINEAR:
352 return svm_mix_linear(t, c1, c2);
353 case NODE_MIX_CLAMP:
354 return svm_mix_clamp(c1);
355 }
356
357 return make_float3(0.0f, 0.0f, 0.0f);
358}
359
361 const float t,
362 const float3 c1,
363 const float3 c2)
364{
365 const float fac = saturatef(t);
366 return svm_mix(type, fac, c1, c2);
367}
368
370 const float brightness,
371 const float contrast)
372{
373 const float a = 1.0f + contrast;
374 const float b = brightness - contrast * 0.5f;
375
376 color.x = max(a * color.x + b, 0.0f);
377 color.y = max(a * color.y + b, 0.0f);
378 color.z = max(a * color.z + b, 0.0f);
379
380 return color;
381}
382
384{
385 switch (type) {
387 return hsv_to_rgb(color);
389 return hsl_to_rgb(color);
391 default:
392 return color;
393 }
394}
395
397{
398 switch (type) {
400 return rgb_to_hsv(color);
402 return rgb_to_hsl(color);
404 default:
405 return color;
406 }
407}
408
void rgb_to_hsl(float r, float g, float b, float *r_h, float *r_s, float *r_l)
void rgb_to_hsv(float r, float g, float b, float *r_h, float *r_s, float *r_v)
void hsv_to_rgb(float h, float s, float v, float *r_r, float *r_g, float *r_b)
Definition math_color.cc:21
void hsl_to_rgb(float h, float s, float l, float *r_r, float *r_g, float *r_b)
Definition math_color.cc:38
@ NODE_COMBSEP_COLOR_RGB
@ NODE_COMBSEP_COLOR_HSV
@ NODE_COMBSEP_COLOR_HSL
ccl_device float3 svm_mix_color(const float t, const float3 col1, const float3 col2)
Definition color_util.h:272
ccl_device float3 svm_mix_light(const float t, const float3 col1, const float3 col2)
Definition color_util.h:106
ccl_device float3 svm_separate_color(NodeCombSepColorType type, const float3 color)
Definition color_util.h:396
ccl_device float3 svm_mix_div(const float t, const float3 col1, const float3 col2)
Definition color_util.h:72
ccl_device float3 svm_mix_clamp(const float3 col)
Definition color_util.h:304
ccl_device float3 svm_mix_sub(const float t, const float3 col1, const float3 col2)
Definition color_util.h:67
ccl_device_noinline_cpu float3 svm_mix(NodeMix type, const float t, const float3 c1, const float3 c2)
Definition color_util.h:309
ccl_device float3 svm_mix_add(const float t, const float3 col1, const float3 col2)
Definition color_util.h:18
CCL_NAMESPACE_BEGIN ccl_device float3 svm_mix_blend(const float t, const float3 col1, const float3 col2)
Definition color_util.h:13
ccl_device float3 svm_mix_sat(const float t, const float3 col1, const float3 col2)
Definition color_util.h:242
ccl_device float3 svm_mix_exclusion(const float t, const float3 col1, const float3 col2)
Definition color_util.h:96
ccl_device float3 svm_combine_color(NodeCombSepColorType type, const float3 color)
Definition color_util.h:383
ccl_device_noinline_cpu float3 svm_mix_clamped_factor(NodeMix type, const float t, const float3 c1, const float3 c2)
Definition color_util.h:360
ccl_device float3 svm_mix_hue(const float t, const float3 col1, const float3 col2)
Definition color_util.h:225
ccl_device_inline float3 svm_brightness_contrast(float3 color, const float brightness, const float contrast)
Definition color_util.h:369
ccl_device float3 svm_mix_diff(const float t, const float3 col1, const float3 col2)
Definition color_util.h:91
ccl_device float3 svm_mix_mul(const float t, const float3 col1, const float3 col2)
Definition color_util.h:23
ccl_device float3 svm_mix_linear(const float t, const float3 col1, const float3 col2)
Definition color_util.h:299
ccl_device float3 svm_mix_burn(const float t, const float3 col1, const float3 col2)
Definition color_util.h:164
ccl_device float3 svm_mix_dodge(const float t, const float3 col1, const float3 col2)
Definition color_util.h:111
ccl_device float3 svm_mix_val(const float t, const float3 col1, const float3 col2)
Definition color_util.h:260
ccl_device float3 svm_mix_dark(const float t, const float3 col1, const float3 col2)
Definition color_util.h:101
ccl_device float3 svm_mix_overlay(const float t, const float3 col1, const float3 col2)
Definition color_util.h:37
ccl_device float3 svm_mix_soft(const float t, const float3 col1, const float3 col2)
Definition color_util.h:289
ccl_device float3 svm_mix_screen(const float t, const float3 col1, const float3 col2)
Definition color_util.h:28
#define ccl_device_noinline_cpu
#define ccl_device_inline
#define CCL_NAMESPACE_END
#define saturatef(x)
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
uint col
@ NODE_MIX_DIV
@ NODE_MIX_SOFT
@ NODE_MIX_CLAMP
@ NODE_MIX_COL
@ NODE_MIX_LIGHT
@ NODE_MIX_MUL
@ NODE_MIX_DIFF
@ NODE_MIX_BURN
@ NODE_MIX_SUB
@ NODE_MIX_LINEAR
@ NODE_MIX_DARK
@ NODE_MIX_SAT
@ NODE_MIX_EXCLUSION
@ NODE_MIX_SCREEN
@ NODE_MIX_HUE
@ NODE_MIX_BLEND
@ NODE_MIX_OVERLAY
@ NODE_MIX_DODGE
@ NODE_MIX_VAL
@ NODE_MIX_ADD
NodeCombSepColorType
ccl_device_inline float interp(const float a, const float b, const float t)
Definition math_base.h:502
ccl_device_inline float2 fabs(const float2 a)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:17
#define ccl_device
#define saturate(a)
Definition smaa.cc:315
#define min(a, b)
Definition sort.cc:36
float z
Definition sky_math.h:136
float y
Definition sky_math.h:136
float x
Definition sky_math.h:136
max
Definition text_draw.cc:251