Blender  V3.3
BLI_color_mix.hh
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
10 #include "BLI_color.hh"
11 #include "BLI_math_base.h"
12 #include "BLI_math_color.h"
13 #include "BLI_sys_types.h"
14 
15 #include "IMB_colormanagement.h"
16 #include "IMB_imbuf.h"
17 
18 #include <type_traits>
19 
20 namespace blender::color {
21 
22 struct ByteTraits {
23  using ValueType = uchar;
24  using BlendType = int;
25 
26  inline static const uchar range = 255; /* Zero-based maximum value. */
27  inline static const float frange = 255.0f; /* Convenient floating-point version of range. */
28  inline static const int cmpRange = 254;
29  inline static const int expandedRange = 256; /* One-based maximum value. */
30 
31  inline static const int bytes = 1;
32  inline static const float unit = 255.0f;
33 
35  {
36  return divide_round_i(a, b);
37  }
38 
39  static inline BlendType min(BlendType a, BlendType b)
40  {
41  return min_ii(a, b);
42  }
43 
44  static inline BlendType max(BlendType a, BlendType b)
45  {
46  return max_ii(a, b);
47  }
48  /* Discretizes in steps of 1.0 / range */
49  static inline ValueType round(float f)
50  {
51  return round_fl_to_uchar(f);
52  }
53 };
54 
55 struct FloatTraits {
56  using ValueType = float;
57  using BlendType = float;
58 
59  inline const static float range = 1.0f;
60  inline const static float frange = 1.0f;
61  inline const static float cmpRange = 0.9999f;
62  inline static const int expandedRange = 1.0f;
63 
64  inline const static float unit = 1.0f;
65  inline const static int bytes = 4;
66 
68  {
69  return a / b;
70  }
71 
72  static inline BlendType min(BlendType a, BlendType b)
73  {
74  return min_ff(a, b);
75  }
76 
77  static inline BlendType max(BlendType a, BlendType b)
78  {
79  return min_ff(a, b);
80  }
81 
82  /* Discretizes in steps of 1.0 / range */
83  static inline ValueType round(float f)
84  {
85  return f;
86  }
87 };
88 
90 {
92 }
93 
95 {
97 }
98 
99 #define EPS_SATURATION 0.0005f
100 
101 /* -------------------------------------------------------------------- */
105 template<typename Color, typename Traits>
106 static Color mix_blend(Color col_src, Color col_dst, typename Traits::BlendType fac)
107 {
108  using Value = typename Traits::ValueType;
109  using Blend = typename Traits::BlendType;
110 
111  Value *cp_src, *cp_dst, *cp_mix;
112  Color col_mix(0, 0, 0, 0);
113  Blend mfac;
114 
115  if (fac == 0) {
116  return col_src;
117  }
118 
119  if (fac >= Traits::range) {
120  return col_dst;
121  }
122 
123  mfac = Traits::range - fac;
124 
125  cp_src = &col_src.r;
126  cp_dst = &col_dst.r;
127  cp_mix = &col_mix.r;
128 
129  /* Updated to use the rgb squared color model which blends nicer. */
130  Blend r1 = cp_src[0] * cp_src[0];
131  Blend g1 = cp_src[1] * cp_src[1];
132  Blend b1 = cp_src[2] * cp_src[2];
133  Blend a1 = cp_src[3] * cp_src[3];
134 
135  Blend r2 = cp_dst[0] * cp_dst[0];
136  Blend g2 = cp_dst[1] * cp_dst[1];
137  Blend b2 = cp_dst[2] * cp_dst[2];
138  Blend a2 = cp_dst[3] * cp_dst[3];
139 
140  cp_mix[0] = Traits::round(sqrtf(Traits::divide_round((mfac * r1 + fac * r2), Traits::range)));
141  cp_mix[1] = Traits::round(sqrtf(Traits::divide_round((mfac * g1 + fac * g2), Traits::range)));
142  cp_mix[2] = Traits::round(sqrtf(Traits::divide_round((mfac * b1 + fac * b2), Traits::range)));
143  cp_mix[3] = Traits::round(sqrtf(Traits::divide_round((mfac * a1 + fac * a2), Traits::range)));
144  return Color(col_mix[0], col_mix[1], col_mix[2], col_mix[3]);
145 
146  return col_mix;
147 }
148 
149 template<typename Color, typename Traits>
150 static Color mix_add(Color col_src, Color col_dst, typename Traits::BlendType fac)
151 {
152  using Value = typename Traits::ValueType;
153  using Blend = typename Traits::BlendType;
154 
155  Value *cp_src, *cp_dst, *cp_mix;
156  Blend temp;
157  Color col_mix(0, 0, 0, 0);
158 
159  if (fac == 0) {
160  return col_src;
161  }
162 
163  cp_src = (Value *)&col_src.r;
164  cp_dst = (Value *)&col_dst.r;
165  cp_mix = (Value *)&col_mix.r;
166 
167  temp = cp_src[0] + Traits::divide_round((fac * cp_dst[0]), Traits::range);
168  cp_mix[0] = (temp > Traits::cmpRange) ? Traits::range : temp;
169  temp = cp_src[1] + Traits::divide_round((fac * cp_dst[1]), Traits::range);
170  cp_mix[1] = (temp > Traits::cmpRange) ? Traits::range : temp;
171  temp = cp_src[2] + Traits::divide_round((fac * cp_dst[2]), Traits::range);
172  cp_mix[2] = (temp > Traits::cmpRange) ? Traits::range : temp;
173  temp = cp_src[3] + Traits::divide_round((fac * cp_dst[3]), Traits::range);
174  cp_mix[3] = (temp > Traits::cmpRange) ? Traits::range : temp;
175 
176  return col_mix;
177 }
178 
179 template<typename Color, typename Traits>
180 static Color mix_sub(Color col_src, Color col_dst, typename Traits::BlendType fac)
181 {
182  using Value = typename Traits::ValueType;
183  using Blend = typename Traits::BlendType;
184 
185  Value *cp_src, *cp_dst, *cp_mix;
186  Blend temp;
187  Color col_mix(0, 0, 0, 0);
188 
189  cp_src = (Value *)&col_src.r;
190  cp_dst = (Value *)&col_dst.r;
191  cp_mix = (Value *)&col_mix.r;
192 
193  temp = cp_src[0] - Traits::divide_round((fac * cp_dst[0]), Traits::range);
194  cp_mix[0] = (temp < 0) ? 0 : temp;
195  temp = cp_src[1] - Traits::divide_round((fac * cp_dst[1]), Traits::range);
196  cp_mix[1] = (temp < 0) ? 0 : temp;
197  temp = cp_src[2] - Traits::divide_round((fac * cp_dst[2]), Traits::range);
198  cp_mix[2] = (temp < 0) ? 0 : temp;
199  temp = cp_src[3] - Traits::divide_round((fac * cp_dst[3]), Traits::range);
200  cp_mix[3] = (temp < 0) ? 0 : temp;
201 
202  return col_mix;
203 }
204 
205 template<typename Color, typename Traits>
206 static Color mix_mul(Color col_src, Color col_dst, typename Traits::BlendType fac)
207 {
208  using Value = typename Traits::ValueType;
209  using Blend = typename Traits::BlendType;
210 
211  Value *cp_src, *cp_dst, *cp_mix;
212  Blend mfac;
213  Color col_mix(0, 0, 0, 0);
214 
215  if (fac == 0) {
216  return col_src;
217  }
218 
219  mfac = Traits::range - fac;
220 
221  cp_src = (Value *)&col_src;
222  cp_dst = (Value *)&col_dst;
223  cp_mix = (Value *)&col_mix;
224 
225  /* first mul, then blend the fac */
226  cp_mix[0] = Traits::divide_round(mfac * cp_src[0] * Traits::range + fac * cp_dst[0] * cp_src[0],
227  Traits::range * Traits::range);
228  cp_mix[1] = Traits::divide_round(mfac * cp_src[1] * Traits::range + fac * cp_dst[1] * cp_src[1],
229  Traits::range * Traits::range);
230  cp_mix[2] = Traits::divide_round(mfac * cp_src[2] * Traits::range + fac * cp_dst[2] * cp_src[2],
231  Traits::range * Traits::range);
232  cp_mix[3] = Traits::divide_round(mfac * cp_src[3] * Traits::range + fac * cp_dst[3] * cp_src[3],
233  Traits::range * Traits::range);
234 
235  return col_mix;
236 }
237 
238 template<typename Color, typename Traits>
239 static Color mix_lighten(Color col_src, Color col_dst, typename Traits::BlendType fac)
240 {
241  using Value = typename Traits::ValueType;
242  using Blend = typename Traits::BlendType;
243 
244  Value *cp_src, *cp_dst, *cp_mix;
245  Blend mfac;
246  Color col_mix(0, 0, 0, 0);
247 
248  if (fac == 0) {
249  return col_src;
250  }
251  if (fac >= Traits::range) {
252  return col_dst;
253  }
254 
255  mfac = Traits::range - fac;
256 
257  cp_src = (Value *)&col_src;
258  cp_dst = (Value *)&col_dst;
259  cp_mix = (Value *)&col_mix;
260 
261  /* See if we're lighter, if so mix, else don't do anything.
262  * if the paint color is darker then the original, then ignore */
263  if (get_luminance(cp_src) > get_luminance(cp_dst)) {
264  return col_src;
265  }
266 
267  cp_mix[0] = Traits::divide_round(mfac * cp_src[0] + fac * cp_dst[0], Traits::range);
268  cp_mix[1] = Traits::divide_round(mfac * cp_src[1] + fac * cp_dst[1], Traits::range);
269  cp_mix[2] = Traits::divide_round(mfac * cp_src[2] + fac * cp_dst[2], Traits::range);
270  cp_mix[3] = Traits::divide_round(mfac * cp_src[3] + fac * cp_dst[3], Traits::range);
271 
272  return col_mix;
273 }
274 
275 template<typename Color, typename Traits>
276 static Color mix_darken(Color col_src, Color col_dst, typename Traits::BlendType fac)
277 {
278  using Value = typename Traits::ValueType;
279  using Blend = typename Traits::BlendType;
280 
281  Value *cp_src, *cp_dst, *cp_mix;
282  Blend mfac;
283  Color col_mix(0, 0, 0, 0);
284 
285  if (fac == 0) {
286  return col_src;
287  }
288  if (fac >= Traits::range) {
289  return col_dst;
290  }
291 
292  mfac = Traits::range - fac;
293 
294  cp_src = (Value *)&col_src;
295  cp_dst = (Value *)&col_dst;
296  cp_mix = (Value *)&col_mix;
297 
298  /* See if we're darker, if so mix, else don't do anything.
299  * if the paint color is brighter then the original, then ignore */
300  if (get_luminance(cp_src) < get_luminance(cp_dst)) {
301  return col_src;
302  }
303 
304  cp_mix[0] = Traits::divide_round((mfac * cp_src[0] + fac * cp_dst[0]), Traits::range);
305  cp_mix[1] = Traits::divide_round((mfac * cp_src[1] + fac * cp_dst[1]), Traits::range);
306  cp_mix[2] = Traits::divide_round((mfac * cp_src[2] + fac * cp_dst[2]), Traits::range);
307  cp_mix[3] = Traits::divide_round((mfac * cp_src[3] + fac * cp_dst[3]), Traits::range);
308  return col_mix;
309 }
310 
311 template<typename Color, typename Traits>
312 static Color mix_colordodge(Color col_src, Color col_dst, typename Traits::BlendType fac)
313 {
314  using Value = typename Traits::ValueType;
315  using Blend = typename Traits::BlendType;
316 
317  Value *cp_src, *cp_dst, *cp_mix;
318  Blend mfac, temp;
319  Color col_mix(0, 0, 0, 0);
320 
321  if (fac == 0) {
322  return col_src;
323  }
324 
325  mfac = Traits::range - fac;
326 
327  cp_src = (Value *)&col_src;
328  cp_dst = (Value *)&col_dst;
329  cp_mix = (Value *)&col_mix;
330 
331  Blend dodgefac = (Blend)((float)Traits::range * 0.885f); /* ~225/255 */
332 
333  temp = (cp_dst[0] == Traits::range) ?
334  Traits::range :
335  Traits::min((cp_src[0] * dodgefac) / (Traits::range - cp_dst[0]), Traits::range);
336  cp_mix[0] = (mfac * cp_src[0] + temp * fac) / Traits::range;
337  temp = (cp_dst[1] == Traits::range) ?
338  Traits::range :
339  Traits::min((cp_src[1] * dodgefac) / (Traits::range - cp_dst[1]), Traits::range);
340  cp_mix[1] = (mfac * cp_src[1] + temp * fac) / Traits::range;
341  temp = (cp_dst[2] == Traits::range) ?
342  Traits::range :
343  Traits::min((cp_src[2] * dodgefac) / (Traits::range - cp_dst[2]), Traits::range);
344  cp_mix[2] = (mfac * cp_src[2] + temp * fac) / Traits::range;
345  temp = (cp_dst[3] == Traits::range) ?
346  Traits::range :
347  Traits::min((cp_src[3] * dodgefac) / (Traits::range - cp_dst[3]), Traits::range);
348  cp_mix[3] = (mfac * cp_src[3] + temp * fac) / Traits::range;
349  return col_mix;
350 }
351 
352 template<typename Color, typename Traits>
353 static Color mix_difference(Color col_src, Color col_dst, typename Traits::BlendType fac)
354 {
355  using Value = typename Traits::ValueType;
356  using Blend = typename Traits::BlendType;
357 
358  Value *cp_src, *cp_dst, *cp_mix;
359  Blend mfac, temp;
360  Color col_mix(0, 0, 0, 0);
361 
362  if (fac == 0) {
363  return col_src;
364  }
365 
366  mfac = Traits::range - fac;
367 
368  cp_src = (Value *)&col_src;
369  cp_dst = (Value *)&col_dst;
370  cp_mix = (Value *)&col_mix;
371 
372  temp = abs(cp_src[0] - cp_dst[0]);
373  cp_mix[0] = (mfac * cp_src[0] + temp * fac) / Traits::range;
374  temp = abs(cp_src[1] - cp_dst[1]);
375  cp_mix[1] = (mfac * cp_src[1] + temp * fac) / Traits::range;
376  temp = abs(cp_src[2] - cp_dst[2]);
377  cp_mix[2] = (mfac * cp_src[2] + temp * fac) / Traits::range;
378  temp = abs(cp_src[3] - cp_dst[3]);
379  cp_mix[3] = (mfac * cp_src[3] + temp * fac) / Traits::range;
380  return col_mix;
381 }
382 
383 template<typename Color, typename Traits>
384 static Color mix_screen(Color col_src, Color col_dst, typename Traits::BlendType fac)
385 {
386  using Value = typename Traits::ValueType;
387  using Blend = typename Traits::BlendType;
388 
389  Value *cp_src, *cp_dst, *cp_mix;
390  Blend mfac, temp;
391  Color col_mix(0, 0, 0, 0);
392 
393  if (fac == 0) {
394  return col_src;
395  }
396 
397  mfac = Traits::range - fac;
398 
399  cp_src = (Value *)&col_src;
400  cp_dst = (Value *)&col_dst;
401  cp_mix = (Value *)&col_mix;
402 
403  temp = Traits::max(Traits::range - (((Traits::range - cp_src[0]) * (Traits::range - cp_dst[0])) /
404  Traits::range),
405  0);
406  cp_mix[0] = (mfac * cp_src[0] + temp * fac) / Traits::range;
407  temp = Traits::max(Traits::range - (((Traits::range - cp_src[1]) * (Traits::range - cp_dst[1])) /
408  Traits::range),
409  0);
410  cp_mix[1] = (mfac * cp_src[1] + temp * fac) / Traits::range;
411  temp = Traits::max(Traits::range - (((Traits::range - cp_src[2]) * (Traits::range - cp_dst[2])) /
412  Traits::range),
413  0);
414  cp_mix[2] = (mfac * cp_src[2] + temp * fac) / Traits::range;
415  temp = Traits::max(Traits::range - (((Traits::range - cp_src[3]) * (Traits::range - cp_dst[3])) /
416  Traits::range),
417  0);
418  cp_mix[3] = (mfac * cp_src[3] + temp * fac) / Traits::range;
419  return col_mix;
420 }
421 
422 template<typename Color, typename Traits>
423 static Color mix_hardlight(Color col_src, Color col_dst, typename Traits::BlendType fac)
424 {
425  using Value = typename Traits::ValueType;
426  using Blend = typename Traits::BlendType;
427 
428  Value *cp_src, *cp_dst, *cp_mix;
429  Blend mfac, temp;
430  Color col_mix(0, 0, 0, 0);
431 
432  if (fac == 0) {
433  return col_src;
434  }
435 
436  mfac = Traits::range - fac;
437 
438  cp_src = (Value *)&col_src;
439  cp_dst = (Value *)&col_dst;
440  cp_mix = (Value *)&col_mix;
441 
442  int i = 0;
443 
444  for (i = 0; i < 4; i++) {
445  if (cp_dst[i] > (Traits::range / 2)) {
446  temp = Traits::range - ((Traits::range - 2 * (cp_dst[i] - (Traits::range / 2))) *
447  (Traits::range - cp_src[i]) / Traits::range);
448  }
449  else {
450  temp = (2 * cp_dst[i] * cp_src[i]) / Traits::expandedRange;
451  }
452  cp_mix[i] = Traits::min((mfac * cp_src[i] + temp * fac) / Traits::range, Traits::range);
453  }
454  return col_mix;
455 }
456 
457 template<typename Color, typename Traits>
458 static Color mix_overlay(Color col_src, Color col_dst, typename Traits::BlendType fac)
459 {
460  using Value = typename Traits::ValueType;
461  using Blend = typename Traits::BlendType;
462 
463  Value *cp_src, *cp_dst, *cp_mix;
464  Blend mfac, temp;
465  Color col_mix(0, 0, 0, 0);
466 
467  if (fac == 0) {
468  return col_src;
469  }
470 
471  mfac = Traits::range - fac;
472 
473  cp_src = (Value *)&col_src;
474  cp_dst = (Value *)&col_dst;
475  cp_mix = (Value *)&col_mix;
476 
477  int i = 0;
478 
479  for (i = 0; i < 4; i++) {
480  if (cp_src[i] > (Traits::range / 2)) {
481  temp = Traits::range - ((Traits::range - 2 * (cp_src[i] - (Traits::range / 2))) *
482  (Traits::range - cp_dst[i]) / Traits::range);
483  }
484  else {
485  temp = (2 * cp_dst[i] * cp_src[i]) / Traits::expandedRange;
486  }
487  cp_mix[i] = Traits::min((mfac * cp_src[i] + temp * fac) / Traits::range, Traits::range);
488  }
489  return col_mix;
490 }
491 
492 template<typename Color, typename Traits>
493 static Color mix_softlight(Color col_src, Color col_dst, typename Traits::BlendType fac)
494 {
495  using Value = typename Traits::ValueType;
496  using Blend = typename Traits::BlendType;
497 
498  Value *cp_src, *cp_dst, *cp_mix;
499  Blend mfac, temp;
500  Color col_mix(0, 0, 0, 0);
501 
502  if (fac == 0) {
503  return col_src;
504  }
505 
506  mfac = Traits::range - fac;
507 
508  cp_src = (Value *)&col_src;
509  cp_dst = (Value *)&col_dst;
510  cp_mix = (Value *)&col_mix;
511 
512  /* Use divide_round so we don't alter original byte equations. */
513  const int add = Traits::divide_round(Traits::range, 4);
514 
515  for (int i = 0; i < 4; i++) {
516  if (cp_src[i] < (Traits::range / 2)) {
517  temp = ((2 * ((cp_dst[i] / 2) + add)) * cp_src[i]) / Traits::range;
518  }
519  else {
520  temp = Traits::range - (2 * (Traits::range - ((cp_dst[i] / 2) + add)) *
521  (Traits::range - cp_src[i]) / Traits::range);
522  }
523  cp_mix[i] = (temp * fac + cp_src[i] * mfac) / Traits::range;
524  }
525  return col_mix;
526 }
527 
528 template<typename Color, typename Traits>
529 static Color mix_exclusion(Color col_src, Color col_dst, typename Traits::BlendType fac)
530 {
531  using Value = typename Traits::ValueType;
532  using Blend = typename Traits::BlendType;
533 
534  Value *cp_src, *cp_dst, *cp_mix;
535  Blend mfac, temp;
536  Color col_mix(0, 0, 0, 0);
537 
538  if (fac == 0) {
539  return col_src;
540  }
541 
542  mfac = Traits::range - fac;
543 
544  cp_src = (Value *)&col_src;
545  cp_dst = (Value *)&col_dst;
546  cp_mix = (Value *)&col_mix;
547 
548  int i = 0;
549 
550  for (i = 0; i < 4; i++) {
551  temp = (Traits::range / 2) -
552  ((2 * (cp_src[i] - (Traits::range / 2)) * (cp_dst[i] - (Traits::range / 2))) /
553  Traits::range);
554  cp_mix[i] = (temp * fac + cp_src[i] * mfac) / Traits::range;
555  }
556  return col_mix;
557 }
558 
559 template<typename Color, typename Traits>
560 static Color mix_luminosity(Color col_src, Color col_dst, typename Traits::BlendType fac)
561 {
562  using Value = typename Traits::ValueType;
563  using Blend = typename Traits::BlendType;
564 
565  Value *cp_src, *cp_dst, *cp_mix;
566  Blend mfac;
567  Color col_mix(0, 0, 0, 0);
568 
569  if (fac == 0) {
570  return col_src;
571  }
572 
573  mfac = Traits::range - fac;
574 
575  cp_src = (Value *)&col_src;
576  cp_dst = (Value *)&col_dst;
577  cp_mix = (Value *)&col_mix;
578 
579  float h1, s1, v1;
580  float h2, s2, v2;
581  float r, g, b;
582  rgb_to_hsv(cp_src[0] / Traits::frange,
583  cp_src[1] / Traits::frange,
584  cp_src[2] / Traits::frange,
585  &h1,
586  &s1,
587  &v1);
588  rgb_to_hsv(cp_dst[0] / Traits::frange,
589  cp_dst[1] / Traits::frange,
590  cp_dst[2] / Traits::frange,
591  &h2,
592  &s2,
593  &v2);
594 
595  v1 = v2;
596 
597  hsv_to_rgb(h1, s1, v1, &r, &g, &b);
598 
599  cp_mix[0] = ((Blend)(r * Traits::frange) * fac + mfac * cp_src[0]) / Traits::range;
600  cp_mix[1] = ((Blend)(g * Traits::frange) * fac + mfac * cp_src[1]) / Traits::range;
601  cp_mix[2] = ((Blend)(b * Traits::frange) * fac + mfac * cp_src[2]) / Traits::range;
602  cp_mix[3] = ((Blend)(cp_dst[3]) * fac + mfac * cp_src[3]) / Traits::range;
603  return col_mix;
604 }
605 
606 template<typename Color, typename Traits>
607 static Color mix_saturation(Color col_src, Color col_dst, typename Traits::BlendType fac)
608 {
609  using Value = typename Traits::ValueType;
610  using Blend = typename Traits::BlendType;
611 
612  Value *cp_src, *cp_dst, *cp_mix;
613  Blend mfac;
614  Color col_mix(0, 0, 0, 0);
615 
616  if (fac == 0) {
617  return col_src;
618  }
619 
620  mfac = Traits::range - fac;
621 
622  cp_src = (Value *)&col_src;
623  cp_dst = (Value *)&col_dst;
624  cp_mix = (Value *)&col_mix;
625 
626  float h1, s1, v1;
627  float h2, s2, v2;
628  float r, g, b;
629  rgb_to_hsv(cp_src[0] / Traits::frange,
630  cp_src[1] / Traits::frange,
631  cp_src[2] / Traits::frange,
632  &h1,
633  &s1,
634  &v1);
635  rgb_to_hsv(cp_dst[0] / Traits::frange,
636  cp_dst[1] / Traits::frange,
637  cp_dst[2] / Traits::frange,
638  &h2,
639  &s2,
640  &v2);
641 
642  if (s1 > EPS_SATURATION) {
643  s1 = s2;
644  }
645 
646  hsv_to_rgb(h1, s1, v1, &r, &g, &b);
647 
648  cp_mix[0] = ((Blend)(r * Traits::frange) * fac + mfac * cp_src[0]) / Traits::range;
649  cp_mix[1] = ((Blend)(g * Traits::frange) * fac + mfac * cp_src[1]) / Traits::range;
650  cp_mix[2] = ((Blend)(b * Traits::frange) * fac + mfac * cp_src[2]) / Traits::range;
651  return col_mix;
652 }
653 
654 template<typename Color, typename Traits>
655 static Color mix_hue(Color col_src, Color col_dst, typename Traits::BlendType fac)
656 {
657  using Value = typename Traits::ValueType;
658  using Blend = typename Traits::BlendType;
659 
660  Value *cp_src, *cp_dst, *cp_mix;
661  Blend mfac;
662  Color col_mix(0, 0, 0, 0);
663 
664  if (fac == 0) {
665  return col_src;
666  }
667 
668  mfac = Traits::range - fac;
669 
670  cp_src = (Value *)&col_src;
671  cp_dst = (Value *)&col_dst;
672  cp_mix = (Value *)&col_mix;
673 
674  float h1, s1, v1;
675  float h2, s2, v2;
676  float r, g, b;
677  rgb_to_hsv(cp_src[0] / Traits::frange,
678  cp_src[1] / Traits::frange,
679  cp_src[2] / Traits::frange,
680  &h1,
681  &s1,
682  &v1);
683  rgb_to_hsv(cp_dst[0] / Traits::frange,
684  cp_dst[1] / Traits::frange,
685  cp_dst[2] / Traits::frange,
686  &h2,
687  &s2,
688  &v2);
689 
690  h1 = h2;
691 
692  hsv_to_rgb(h1, s1, v1, &r, &g, &b);
693 
694  cp_mix[0] = ((Blend)(r * Traits::frange) * fac + mfac * cp_src[0]) / Traits::range;
695  cp_mix[1] = ((Blend)(g * Traits::frange) * fac + mfac * cp_src[1]) / Traits::range;
696  cp_mix[2] = ((Blend)(b * Traits::frange) * fac + mfac * cp_src[2]) / Traits::range;
697  cp_mix[3] = ((Blend)(cp_dst[3]) * fac + mfac * cp_src[3]) / Traits::range;
698  return col_mix;
699 }
700 
701 template<typename Color, typename Traits>
702 static Color mix_alpha_add(Color col_src, typename Traits::BlendType fac)
703 {
704  using Value = typename Traits::ValueType;
705  using Blend = typename Traits::BlendType;
706 
707  Value *cp_src, *cp_mix;
708  Blend temp;
709  Color col_mix = col_src;
710 
711  if (fac == 0) {
712  return col_src;
713  }
714 
715  cp_src = (Value *)&col_src;
716  cp_mix = (Value *)&col_mix;
717 
718  temp = cp_src[3] + fac;
719  cp_mix[3] = (temp > Traits::cmpRange) ? Traits::range : temp;
720 
721  return col_mix;
722 }
723 
724 template<typename Color, typename Traits>
725 static Color mix_alpha_sub(Color col_src, typename Traits::BlendType fac)
726 {
727  using Value = typename Traits::ValueType;
728  using Blend = typename Traits::BlendType;
729 
730  Value *cp_src, *cp_mix;
731  Blend temp;
732  Color col_mix = col_src;
733 
734  if (fac == 0) {
735  return col_src;
736  }
737 
738  cp_src = (Value *)&col_src;
739  cp_mix = (Value *)&col_mix;
740 
741  temp = cp_src[3] - fac;
742  cp_mix[3] = temp < 0 ? 0 : temp;
743 
744  return col_mix;
745 }
746 
747 template<typename Color, typename Traits>
748 static Color mix_pinlight(Color col_src, Color col_dst, typename Traits::BlendType fac)
749 {
750  using Value = typename Traits::ValueType;
751  using Blend = typename Traits::BlendType;
752 
753  Value *cp_src, *cp_dst, *cp_mix;
754  Blend mfac;
755  Color col_mix(0, 0, 0, 0);
756 
757  if (fac == 0) {
758  return col_src;
759  }
760 
761  mfac = Traits::range - fac;
762 
763  cp_src = (Value *)&col_src;
764  cp_dst = (Value *)&col_dst;
765  cp_mix = (Value *)&col_mix;
766 
767  const Blend cmp = Traits::range / 2;
768 
769  int i = 3;
770  Blend temp;
771 
772  while (i--) {
773  if (cp_dst[i] > cmp) {
774  temp = Traits::max(2 * (cp_dst[i] - cmp), cp_src[i]);
775  }
776  else {
777  temp = Traits::min(2 * cp_dst[i], cp_src[i]);
778  }
779  cp_mix[i] = (Value)((Traits::min(temp, Traits::range) * fac + cp_src[i] * mfac) /
780  Traits::range);
781  }
782 
783  col_mix.a = col_src.a;
784  return col_mix;
785 }
786 
787 template<typename Color, typename Traits>
788 static Color mix_linearlight(Color col_src, Color col_dst, typename Traits::BlendType fac)
789 {
790  using Value = typename Traits::ValueType;
791  using Blend = typename Traits::BlendType;
792 
793  Value *cp_src, *cp_dst, *cp_mix;
794  Blend mfac;
795  Color col_mix(0, 0, 0, 0);
796 
797  if (fac == 0) {
798  return col_src;
799  }
800 
801  mfac = Traits::range - fac;
802 
803  cp_src = (Value *)&col_src;
804  cp_dst = (Value *)&col_dst;
805  cp_mix = (Value *)&col_mix;
806 
807  const Blend cmp = Traits::range / 2;
808 
809  int i = 3;
810  while (i--) {
811  Blend temp;
812 
813  if (cp_dst[i] > cmp) {
814  temp = Traits::min(cp_src[i] + 2 * (cp_dst[i] - cmp), Traits::range);
815  }
816  else {
817  temp = Traits::max(cp_src[i] + 2 * cp_dst[i] - Traits::range, 0);
818  }
819 
820  cp_mix[i] = (Value)((temp * fac + cp_src[i] * mfac) / Traits::range);
821  }
822 
823  col_mix.a = col_src.a;
824  return col_mix;
825 }
826 
827 template<typename Color, typename Traits>
828 static Color mix_vividlight(Color col_src, Color col_dst, typename Traits::BlendType fac)
829 {
830  using Value = typename Traits::ValueType;
831  using Blend = typename Traits::BlendType;
832 
833  Value *cp_src, *cp_dst;
834  Blend mfac;
835  Color col_mix(0, 0, 0, 0);
836 
837  if (fac == 0) {
838  return col_src;
839  }
840 
841  mfac = Traits::range - fac;
842 
843  cp_src = (Value *)&col_src;
844  cp_dst = (Value *)&col_dst;
845 
846  const Blend cmp = Traits::range / 2;
847 
848  int i = 3;
849 
850  while (i--) {
851  Blend temp;
852 
853  if (cp_dst[i] == Traits::range) {
854  temp = (cp_src[i] == 0) ? cmp : Traits::range;
855  }
856  else if (cp_dst[i] == 0) {
857  temp = (cp_src[i] == Traits::range) ? cmp : 0;
858  }
859  else if (cp_dst[i] > cmp) {
860  temp = Traits::min(((cp_src[i]) * Traits::range) / (2 * (Traits::range - cp_dst[i])),
861  Traits::range);
862  }
863  else {
864  temp = Traits::max(
865  Traits::range - ((Traits::range - cp_src[i]) * Traits::range / (2 * cp_dst[i])), 0);
866  }
867  col_mix[i] = (Value)((temp * fac + cp_src[i] * mfac) / Traits::range);
868  }
869 
870  col_mix.a = col_src.a;
871  return col_mix;
872 }
873 
874 template<typename Color, typename Traits>
875 static Color mix_color(Color col_src, Color col_dst, typename Traits::BlendType fac)
876 {
877  using Value = typename Traits::ValueType;
878  using Blend = typename Traits::BlendType;
879 
880  Value *cp_src, *cp_dst, *cp_mix;
881  Blend mfac;
882  Color col_mix(0, 0, 0, 0);
883 
884  if (fac == 0) {
885  return col_src;
886  }
887 
888  mfac = Traits::range - fac;
889 
890  cp_src = (Value *)&col_src;
891  cp_dst = (Value *)&col_dst;
892  cp_mix = (Value *)&col_mix;
893 
894  float h1, s1, v1;
895  float h2, s2, v2;
896  float r, g, b;
897 
898  rgb_to_hsv(cp_src[0] / Traits::frange,
899  cp_src[1] / Traits::frange,
900  cp_src[2] / Traits::frange,
901  &h1,
902  &s1,
903  &v1);
904  rgb_to_hsv(cp_dst[0] / Traits::frange,
905  cp_dst[1] / Traits::frange,
906  cp_dst[2] / Traits::frange,
907  &h2,
908  &s2,
909  &v2);
910 
911  h1 = h2;
912  s1 = s2;
913 
914  hsv_to_rgb(h1, s1, v1, &r, &g, &b);
915 
916  cp_mix[0] = (Value)(((Blend)(r * Traits::frange) * fac + cp_src[0] * mfac) / Traits::range);
917  cp_mix[1] = (Value)(((Blend)(g * Traits::frange) * fac + cp_src[1] * mfac) / Traits::range);
918  cp_mix[2] = (Value)(((Blend)(b * Traits::frange) * fac + cp_src[2] * mfac) / Traits::range);
919 
920  col_mix.a = col_src.a;
921  return col_mix;
922 }
923 
924 template<typename Color, typename Traits>
925 static Color mix_colorburn(Color col_src, Color col_dst, typename Traits::BlendType fac)
926 {
927  using Value = typename Traits::ValueType;
928  using Blend = typename Traits::BlendType;
929 
930  Value *cp_src, *cp_dst, *cp_mix;
931  Blend mfac;
932  Color col_mix(0, 0, 0, 0);
933 
934  if (fac == 0) {
935  return col_src;
936  }
937 
938  mfac = Traits::range - fac;
939 
940  cp_src = (Value *)&col_src;
941  cp_dst = (Value *)&col_dst;
942  cp_mix = (Value *)&col_mix;
943 
944  int i = 3;
945 
946  while (i--) {
947  const Blend temp =
948  (cp_dst[i] == 0) ?
949  0 :
950  Traits::max(Traits::range - ((Traits::range - cp_src[i]) * Traits::range) / cp_dst[i],
951  0);
952  cp_mix[i] = (Value)((temp * fac + cp_src[i] * mfac) / Traits::range);
953  }
954 
955  col_mix.a = col_src.a;
956  return col_mix;
957 }
958 
959 template<typename Color, typename Traits>
960 static Color mix_linearburn(Color col_src, Color col_dst, typename Traits::BlendType fac)
961 {
962  using Value = typename Traits::ValueType;
963  using Blend = typename Traits::BlendType;
964 
965  Value *cp_src, *cp_dst, *cp_mix;
966  Blend mfac;
967  Color col_mix(0, 0, 0, 0);
968 
969  if (fac == 0) {
970  return col_src;
971  }
972 
973  mfac = Traits::range - fac;
974 
975  cp_src = (Value *)&col_src;
976  cp_dst = (Value *)&col_dst;
977  cp_mix = (Value *)&col_mix;
978 
979  int i = 3;
980 
981  while (i--) {
982  const Blend temp = Traits::max(cp_src[i] + cp_dst[i] - Traits::range, 0);
983  cp_mix[i] = (Value)((temp * fac + cp_src[i] * mfac) / Traits::range);
984  }
985 
986  col_mix.a = col_src.a;
987  return col_mix;
988 }
989 
990 template<typename Color, typename Traits>
992  const Color a,
993  const Color b,
994  const typename Traits::BlendType alpha)
995 {
996  switch ((IMB_BlendMode)tool) {
997  case IMB_BLEND_MIX:
998  return mix_blend<Color, Traits>(a, b, alpha);
999  case IMB_BLEND_ADD:
1000  return mix_add<Color, Traits>(a, b, alpha);
1001  case IMB_BLEND_SUB:
1002  return mix_sub<Color, Traits>(a, b, alpha);
1003  case IMB_BLEND_MUL:
1004  return mix_mul<Color, Traits>(a, b, alpha);
1005  case IMB_BLEND_LIGHTEN:
1006  return mix_lighten<Color, Traits>(a, b, alpha);
1007  case IMB_BLEND_DARKEN:
1008  return mix_darken<Color, Traits>(a, b, alpha);
1009  case IMB_BLEND_COLORDODGE:
1010  return mix_colordodge<Color, Traits>(a, b, alpha);
1011  case IMB_BLEND_COLORBURN:
1012  return mix_colorburn<Color, Traits>(a, b, alpha);
1013  case IMB_BLEND_DIFFERENCE:
1014  return mix_difference<Color, Traits>(a, b, alpha);
1015  case IMB_BLEND_SCREEN:
1016  return mix_screen<Color, Traits>(a, b, alpha);
1017  case IMB_BLEND_HARDLIGHT:
1018  return mix_hardlight<Color, Traits>(a, b, alpha);
1019  case IMB_BLEND_OVERLAY:
1020  return mix_overlay<Color, Traits>(a, b, alpha);
1021  case IMB_BLEND_SOFTLIGHT:
1022  return mix_softlight<Color, Traits>(a, b, alpha);
1023  case IMB_BLEND_EXCLUSION:
1024  return mix_exclusion<Color, Traits>(a, b, alpha);
1025  case IMB_BLEND_LUMINOSITY:
1026  return mix_luminosity<Color, Traits>(a, b, alpha);
1027  case IMB_BLEND_SATURATION:
1028  return mix_saturation<Color, Traits>(a, b, alpha);
1029  case IMB_BLEND_HUE:
1030  return mix_hue<Color, Traits>(a, b, alpha);
1031  /* non-color */
1032  case IMB_BLEND_ERASE_ALPHA:
1033  return mix_alpha_sub<Color, Traits>(a, alpha);
1034  case IMB_BLEND_ADD_ALPHA:
1035  return mix_alpha_add<Color, Traits>(a, alpha);
1036  case IMB_BLEND_PINLIGHT:
1037  return mix_pinlight<Color, Traits>(a, b, alpha);
1038  case IMB_BLEND_LINEARLIGHT:
1039  return mix_linearlight<Color, Traits>(a, b, alpha);
1040  case IMB_BLEND_VIVIDLIGHT:
1041  return mix_vividlight<Color, Traits>(a, b, alpha);
1042  case IMB_BLEND_COLOR:
1043  return mix_color<Color, Traits>(a, b, alpha);
1044  default:
1046  return Color(0, 0, 0, 0);
1047  }
1048 }
1051 } // namespace blender::color
typedef float(TangentPoint)[2]
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define EPS_SATURATION
#define BLI_INLINE
MINLINE unsigned char round_fl_to_uchar(float a)
MINLINE int min_ii(int a, int b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
MINLINE int divide_round_i(int a, int b)
void rgb_to_hsv(float r, float g, float b, float *r_h, float *r_s, float *r_v)
Definition: math_color.c:208
void hsv_to_rgb(float h, float s, float v, float *r_r, float *r_g, float *r_b)
Definition: math_color.c:13
unsigned char uchar
Definition: BLI_sys_types.h:70
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
BLI_INLINE unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char[3])
BLI_INLINE float IMB_colormanagement_get_luminance(const float rgb[3])
IMB_BlendMode
Definition: IMB_imbuf.h:209
@ IMB_BLEND_EXCLUSION
Definition: IMB_imbuf.h:229
@ IMB_BLEND_DIFFERENCE
Definition: IMB_imbuf.h:228
@ IMB_BLEND_HARDLIGHT
Definition: IMB_imbuf.h:219
@ IMB_BLEND_COLORBURN
Definition: IMB_imbuf.h:220
@ IMB_BLEND_COLORDODGE
Definition: IMB_imbuf.h:222
@ IMB_BLEND_ERASE_ALPHA
Definition: IMB_imbuf.h:216
@ IMB_BLEND_SCREEN
Definition: IMB_imbuf.h:223
@ IMB_BLEND_HUE
Definition: IMB_imbuf.h:230
@ IMB_BLEND_MUL
Definition: IMB_imbuf.h:213
@ IMB_BLEND_ADD_ALPHA
Definition: IMB_imbuf.h:217
@ IMB_BLEND_DARKEN
Definition: IMB_imbuf.h:215
@ IMB_BLEND_OVERLAY
Definition: IMB_imbuf.h:218
@ IMB_BLEND_SATURATION
Definition: IMB_imbuf.h:231
@ IMB_BLEND_VIVIDLIGHT
Definition: IMB_imbuf.h:226
@ IMB_BLEND_LUMINOSITY
Definition: IMB_imbuf.h:232
@ IMB_BLEND_LIGHTEN
Definition: IMB_imbuf.h:214
@ IMB_BLEND_SOFTLIGHT
Definition: IMB_imbuf.h:224
@ IMB_BLEND_COLOR
Definition: IMB_imbuf.h:233
@ IMB_BLEND_LINEARLIGHT
Definition: IMB_imbuf.h:227
@ IMB_BLEND_PINLIGHT
Definition: IMB_imbuf.h:225
@ IMB_BLEND_MIX
Definition: IMB_imbuf.h:210
@ IMB_BLEND_ADD
Definition: IMB_imbuf.h:211
@ IMB_BLEND_SUB
Definition: IMB_imbuf.h:212
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color or the default fallback if none is specified Separate Split a vector into its and Z components Generates normals with round corners and may slow down renders Vector Displace the surface along an arbitrary direction White Return a random value or color based on an input seed Float Map an input float to a curve and outputs a float value Separate Color
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue Hue Saturation Value
ATTR_WARN_UNUSED_RESULT const BMVert * v2
#define sqrtf(x)
Definition: metal/compat.h:243
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
bool add(void *owner, const AttributeIDRef &attribute_id, eAttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer)
static Color mix_pinlight(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_difference(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_alpha_sub(Color col_src, typename Traits::BlendType fac)
static float get_luminance(ColorPaint4f c)
static Color mix_screen(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_alpha_add(Color col_src, typename Traits::BlendType fac)
static Color mix_colorburn(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_colordodge(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_hardlight(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_vividlight(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_linearburn(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_sub(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_luminosity(Color col_src, Color col_dst, typename Traits::BlendType fac)
BLI_INLINE Color BLI_mix_colors(const IMB_BlendMode tool, const Color a, const Color b, const typename Traits::BlendType alpha)
static Color mix_softlight(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_color(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_overlay(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_mul(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_add(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_lighten(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_darken(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_linearlight(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_hue(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_blend(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_saturation(Color col_src, Color col_dst, typename Traits::BlendType fac)
static Color mix_exclusion(Color col_src, Color col_dst, typename Traits::BlendType fac)
T abs(const T &a)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static const pxr::TfToken g("g", pxr::TfToken::Immortal)
#define min(a, b)
Definition: sort.c:35
static const float frange
static BlendType max(BlendType a, BlendType b)
static const int expandedRange
static const uchar range
static const float unit
static BlendType min(BlendType a, BlendType b)
static ValueType round(float f)
static BlendType divide_round(BlendType a, BlendType b)
static const int cmpRange
static const float unit
static const float frange
static ValueType round(float f)
static const float cmpRange
static BlendType min(BlendType a, BlendType b)
static const int expandedRange
static BlendType max(BlendType a, BlendType b)
static const float range
static BlendType divide_round(BlendType a, BlendType b)
float max