Blender  V2.93
COM_MixOperation.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2011, Blender Foundation.
17  */
18 
19 #include "COM_MixOperation.h"
20 
21 #include "BLI_math.h"
22 
23 namespace blender::compositor {
24 
25 /* ******** Mix Base Operation ******** */
26 
28 {
33  this->m_inputValueOperation = nullptr;
34  this->m_inputColor1Operation = nullptr;
35  this->m_inputColor2Operation = nullptr;
36  this->setUseValueAlphaMultiply(false);
37  this->setUseClamp(false);
38 }
39 
41 {
45 }
46 
47 void MixBaseOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
48 {
49  float inputColor1[4];
50  float inputColor2[4];
51  float inputValue[4];
52 
53  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
54  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
55  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
56 
57  float value = inputValue[0];
58  if (this->useValueAlphaMultiply()) {
59  value *= inputColor2[3];
60  }
61  float valuem = 1.0f - value;
62  output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]);
63  output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]);
64  output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]);
65  output[3] = inputColor1[3];
66 }
67 
68 void MixBaseOperation::determineResolution(unsigned int resolution[2],
69  unsigned int preferredResolution[2])
70 {
71  NodeOperationInput *socket;
72  unsigned int tempPreferredResolution[2] = {0, 0};
73  unsigned int tempResolution[2];
74 
75  socket = this->getInputSocket(1);
76  socket->determineResolution(tempResolution, tempPreferredResolution);
77  if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) {
79  }
80  else {
81  socket = this->getInputSocket(2);
82  socket->determineResolution(tempResolution, tempPreferredResolution);
83  if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) {
85  }
86  else {
88  }
89  }
90  NodeOperation::determineResolution(resolution, preferredResolution);
91 }
92 
94 {
95  this->m_inputValueOperation = nullptr;
96  this->m_inputColor1Operation = nullptr;
97  this->m_inputColor2Operation = nullptr;
98 }
99 
100 /* ******** Mix Add Operation ******** */
101 
102 void MixAddOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
103 {
104  float inputColor1[4];
105  float inputColor2[4];
106  float inputValue[4];
107 
108  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
109  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
110  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
111 
112  float value = inputValue[0];
113  if (this->useValueAlphaMultiply()) {
114  value *= inputColor2[3];
115  }
116  output[0] = inputColor1[0] + value * inputColor2[0];
117  output[1] = inputColor1[1] + value * inputColor2[1];
118  output[2] = inputColor1[2] + value * inputColor2[2];
119  output[3] = inputColor1[3];
120 
122 }
123 
124 /* ******** Mix Blend Operation ******** */
125 
127  float x,
128  float y,
129  PixelSampler sampler)
130 {
131  float inputColor1[4];
132  float inputColor2[4];
133  float inputValue[4];
134  float value;
135 
136  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
137  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
138  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
139  value = inputValue[0];
140 
141  if (this->useValueAlphaMultiply()) {
142  value *= inputColor2[3];
143  }
144  float valuem = 1.0f - value;
145  output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]);
146  output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]);
147  output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]);
148  output[3] = inputColor1[3];
149 
151 }
152 
153 /* ******** Mix Burn Operation ******** */
154 
156  float x,
157  float y,
158  PixelSampler sampler)
159 {
160  float inputColor1[4];
161  float inputColor2[4];
162  float inputValue[4];
163  float tmp;
164 
165  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
166  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
167  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
168 
169  float value = inputValue[0];
170  if (this->useValueAlphaMultiply()) {
171  value *= inputColor2[3];
172  }
173  float valuem = 1.0f - value;
174 
175  tmp = valuem + value * inputColor2[0];
176  if (tmp <= 0.0f) {
177  output[0] = 0.0f;
178  }
179  else {
180  tmp = 1.0f - (1.0f - inputColor1[0]) / tmp;
181  if (tmp < 0.0f) {
182  output[0] = 0.0f;
183  }
184  else if (tmp > 1.0f) {
185  output[0] = 1.0f;
186  }
187  else {
188  output[0] = tmp;
189  }
190  }
191 
192  tmp = valuem + value * inputColor2[1];
193  if (tmp <= 0.0f) {
194  output[1] = 0.0f;
195  }
196  else {
197  tmp = 1.0f - (1.0f - inputColor1[1]) / tmp;
198  if (tmp < 0.0f) {
199  output[1] = 0.0f;
200  }
201  else if (tmp > 1.0f) {
202  output[1] = 1.0f;
203  }
204  else {
205  output[1] = tmp;
206  }
207  }
208 
209  tmp = valuem + value * inputColor2[2];
210  if (tmp <= 0.0f) {
211  output[2] = 0.0f;
212  }
213  else {
214  tmp = 1.0f - (1.0f - inputColor1[2]) / tmp;
215  if (tmp < 0.0f) {
216  output[2] = 0.0f;
217  }
218  else if (tmp > 1.0f) {
219  output[2] = 1.0f;
220  }
221  else {
222  output[2] = tmp;
223  }
224  }
225 
226  output[3] = inputColor1[3];
227 
229 }
230 
231 /* ******** Mix Color Operation ******** */
232 
234  float x,
235  float y,
236  PixelSampler sampler)
237 {
238  float inputColor1[4];
239  float inputColor2[4];
240  float inputValue[4];
241 
242  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
243  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
244  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
245 
246  float value = inputValue[0];
247  if (this->useValueAlphaMultiply()) {
248  value *= inputColor2[3];
249  }
250  float valuem = 1.0f - value;
251 
252  float colH, colS, colV;
253  rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
254  if (colS != 0.0f) {
255  float rH, rS, rV;
256  float tmpr, tmpg, tmpb;
257  rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
258  hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb);
259  output[0] = (valuem * inputColor1[0]) + (value * tmpr);
260  output[1] = (valuem * inputColor1[1]) + (value * tmpg);
261  output[2] = (valuem * inputColor1[2]) + (value * tmpb);
262  }
263  else {
264  copy_v3_v3(output, inputColor1);
265  }
266  output[3] = inputColor1[3];
267 
269 }
270 
271 /* ******** Mix Darken Operation ******** */
272 
274  float x,
275  float y,
276  PixelSampler sampler)
277 {
278  float inputColor1[4];
279  float inputColor2[4];
280  float inputValue[4];
281 
282  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
283  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
284  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
285 
286  float value = inputValue[0];
287  if (this->useValueAlphaMultiply()) {
288  value *= inputColor2[3];
289  }
290  float valuem = 1.0f - value;
291  output[0] = min_ff(inputColor1[0], inputColor2[0]) * value + inputColor1[0] * valuem;
292  output[1] = min_ff(inputColor1[1], inputColor2[1]) * value + inputColor1[1] * valuem;
293  output[2] = min_ff(inputColor1[2], inputColor2[2]) * value + inputColor1[2] * valuem;
294  output[3] = inputColor1[3];
295 
297 }
298 
299 /* ******** Mix Difference Operation ******** */
300 
302  float x,
303  float y,
304  PixelSampler sampler)
305 {
306  float inputColor1[4];
307  float inputColor2[4];
308  float inputValue[4];
309 
310  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
311  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
312  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
313 
314  float value = inputValue[0];
315  if (this->useValueAlphaMultiply()) {
316  value *= inputColor2[3];
317  }
318  float valuem = 1.0f - value;
319  output[0] = valuem * inputColor1[0] + value * fabsf(inputColor1[0] - inputColor2[0]);
320  output[1] = valuem * inputColor1[1] + value * fabsf(inputColor1[1] - inputColor2[1]);
321  output[2] = valuem * inputColor1[2] + value * fabsf(inputColor1[2] - inputColor2[2]);
322  output[3] = inputColor1[3];
323 
325 }
326 
327 /* ******** Mix Difference Operation ******** */
328 
330  float x,
331  float y,
332  PixelSampler sampler)
333 {
334  float inputColor1[4];
335  float inputColor2[4];
336  float inputValue[4];
337 
338  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
339  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
340  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
341 
342  float value = inputValue[0];
343  if (this->useValueAlphaMultiply()) {
344  value *= inputColor2[3];
345  }
346  float valuem = 1.0f - value;
347 
348  if (inputColor2[0] != 0.0f) {
349  output[0] = valuem * (inputColor1[0]) + value * (inputColor1[0]) / inputColor2[0];
350  }
351  else {
352  output[0] = 0.0f;
353  }
354  if (inputColor2[1] != 0.0f) {
355  output[1] = valuem * (inputColor1[1]) + value * (inputColor1[1]) / inputColor2[1];
356  }
357  else {
358  output[1] = 0.0f;
359  }
360  if (inputColor2[2] != 0.0f) {
361  output[2] = valuem * (inputColor1[2]) + value * (inputColor1[2]) / inputColor2[2];
362  }
363  else {
364  output[2] = 0.0f;
365  }
366 
367  output[3] = inputColor1[3];
368 
370 }
371 
372 /* ******** Mix Dodge Operation ******** */
373 
375  float x,
376  float y,
377  PixelSampler sampler)
378 {
379  float inputColor1[4];
380  float inputColor2[4];
381  float inputValue[4];
382  float tmp;
383 
384  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
385  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
386  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
387 
388  float value = inputValue[0];
389  if (this->useValueAlphaMultiply()) {
390  value *= inputColor2[3];
391  }
392 
393  if (inputColor1[0] != 0.0f) {
394  tmp = 1.0f - value * inputColor2[0];
395  if (tmp <= 0.0f) {
396  output[0] = 1.0f;
397  }
398  else {
399  tmp = inputColor1[0] / tmp;
400  if (tmp > 1.0f) {
401  output[0] = 1.0f;
402  }
403  else {
404  output[0] = tmp;
405  }
406  }
407  }
408  else {
409  output[0] = 0.0f;
410  }
411 
412  if (inputColor1[1] != 0.0f) {
413  tmp = 1.0f - value * inputColor2[1];
414  if (tmp <= 0.0f) {
415  output[1] = 1.0f;
416  }
417  else {
418  tmp = inputColor1[1] / tmp;
419  if (tmp > 1.0f) {
420  output[1] = 1.0f;
421  }
422  else {
423  output[1] = tmp;
424  }
425  }
426  }
427  else {
428  output[1] = 0.0f;
429  }
430 
431  if (inputColor1[2] != 0.0f) {
432  tmp = 1.0f - value * inputColor2[2];
433  if (tmp <= 0.0f) {
434  output[2] = 1.0f;
435  }
436  else {
437  tmp = inputColor1[2] / tmp;
438  if (tmp > 1.0f) {
439  output[2] = 1.0f;
440  }
441  else {
442  output[2] = tmp;
443  }
444  }
445  }
446  else {
447  output[2] = 0.0f;
448  }
449 
450  output[3] = inputColor1[3];
451 
453 }
454 
455 /* ******** Mix Glare Operation ******** */
456 
458  float x,
459  float y,
460  PixelSampler sampler)
461 {
462  float inputColor1[4];
463  float inputColor2[4];
464  float inputValue[4];
465  float value, input_weight, glare_weight;
466 
467  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
468  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
469  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
470  value = inputValue[0];
471  /* Linear interpolation between 3 cases:
472  * value=-1:output=input value=0:output=input+glare value=1:output=glare
473  */
474  if (value < 0.0f) {
475  input_weight = 1.0f;
476  glare_weight = 1.0f + value;
477  }
478  else {
479  input_weight = 1.0f - value;
480  glare_weight = 1.0f;
481  }
482  output[0] = input_weight * MAX2(inputColor1[0], 0.0f) + glare_weight * inputColor2[0];
483  output[1] = input_weight * MAX2(inputColor1[1], 0.0f) + glare_weight * inputColor2[1];
484  output[2] = input_weight * MAX2(inputColor1[2], 0.0f) + glare_weight * inputColor2[2];
485  output[3] = inputColor1[3];
486 
488 }
489 
490 /* ******** Mix Hue Operation ******** */
491 
492 void MixHueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
493 {
494  float inputColor1[4];
495  float inputColor2[4];
496  float inputValue[4];
497 
498  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
499  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
500  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
501 
502  float value = inputValue[0];
503  if (this->useValueAlphaMultiply()) {
504  value *= inputColor2[3];
505  }
506  float valuem = 1.0f - value;
507 
508  float colH, colS, colV;
509  rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
510  if (colS != 0.0f) {
511  float rH, rS, rV;
512  float tmpr, tmpg, tmpb;
513  rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
514  hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb);
515  output[0] = valuem * (inputColor1[0]) + value * tmpr;
516  output[1] = valuem * (inputColor1[1]) + value * tmpg;
517  output[2] = valuem * (inputColor1[2]) + value * tmpb;
518  }
519  else {
520  copy_v3_v3(output, inputColor1);
521  }
522  output[3] = inputColor1[3];
523 
525 }
526 
527 /* ******** Mix Lighten Operation ******** */
528 
530  float x,
531  float y,
532  PixelSampler sampler)
533 {
534  float inputColor1[4];
535  float inputColor2[4];
536  float inputValue[4];
537 
538  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
539  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
540  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
541 
542  float value = inputValue[0];
543  if (this->useValueAlphaMultiply()) {
544  value *= inputColor2[3];
545  }
546  float tmp;
547  tmp = value * inputColor2[0];
548  if (tmp > inputColor1[0]) {
549  output[0] = tmp;
550  }
551  else {
552  output[0] = inputColor1[0];
553  }
554  tmp = value * inputColor2[1];
555  if (tmp > inputColor1[1]) {
556  output[1] = tmp;
557  }
558  else {
559  output[1] = inputColor1[1];
560  }
561  tmp = value * inputColor2[2];
562  if (tmp > inputColor1[2]) {
563  output[2] = tmp;
564  }
565  else {
566  output[2] = inputColor1[2];
567  }
568  output[3] = inputColor1[3];
569 
571 }
572 
573 /* ******** Mix Linear Light Operation ******** */
574 
576  float x,
577  float y,
578  PixelSampler sampler)
579 {
580  float inputColor1[4];
581  float inputColor2[4];
582  float inputValue[4];
583 
584  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
585  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
586  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
587 
588  float value = inputValue[0];
589  if (this->useValueAlphaMultiply()) {
590  value *= inputColor2[3];
591  }
592  if (inputColor2[0] > 0.5f) {
593  output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0] - 0.5f));
594  }
595  else {
596  output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0]) - 1.0f);
597  }
598  if (inputColor2[1] > 0.5f) {
599  output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1] - 0.5f));
600  }
601  else {
602  output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1]) - 1.0f);
603  }
604  if (inputColor2[2] > 0.5f) {
605  output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2] - 0.5f));
606  }
607  else {
608  output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2]) - 1.0f);
609  }
610 
611  output[3] = inputColor1[3];
612 
614 }
615 
616 /* ******** Mix Multiply Operation ******** */
617 
619  float x,
620  float y,
621  PixelSampler sampler)
622 {
623  float inputColor1[4];
624  float inputColor2[4];
625  float inputValue[4];
626 
627  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
628  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
629  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
630 
631  float value = inputValue[0];
632  if (this->useValueAlphaMultiply()) {
633  value *= inputColor2[3];
634  }
635  float valuem = 1.0f - value;
636  output[0] = inputColor1[0] * (valuem + value * inputColor2[0]);
637  output[1] = inputColor1[1] * (valuem + value * inputColor2[1]);
638  output[2] = inputColor1[2] * (valuem + value * inputColor2[2]);
639  output[3] = inputColor1[3];
640 
642 }
643 
644 /* ******** Mix Overlay Operation ******** */
645 
647  float x,
648  float y,
649  PixelSampler sampler)
650 {
651  float inputColor1[4];
652  float inputColor2[4];
653  float inputValue[4];
654 
655  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
656  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
657  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
658 
659  float value = inputValue[0];
660  if (this->useValueAlphaMultiply()) {
661  value *= inputColor2[3];
662  }
663 
664  float valuem = 1.0f - value;
665 
666  if (inputColor1[0] < 0.5f) {
667  output[0] = inputColor1[0] * (valuem + 2.0f * value * inputColor2[0]);
668  }
669  else {
670  output[0] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]);
671  }
672  if (inputColor1[1] < 0.5f) {
673  output[1] = inputColor1[1] * (valuem + 2.0f * value * inputColor2[1]);
674  }
675  else {
676  output[1] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]);
677  }
678  if (inputColor1[2] < 0.5f) {
679  output[2] = inputColor1[2] * (valuem + 2.0f * value * inputColor2[2]);
680  }
681  else {
682  output[2] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]);
683  }
684  output[3] = inputColor1[3];
685 
687 }
688 
689 /* ******** Mix Saturation Operation ******** */
690 
692  float x,
693  float y,
694  PixelSampler sampler)
695 {
696  float inputColor1[4];
697  float inputColor2[4];
698  float inputValue[4];
699 
700  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
701  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
702  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
703 
704  float value = inputValue[0];
705  if (this->useValueAlphaMultiply()) {
706  value *= inputColor2[3];
707  }
708  float valuem = 1.0f - value;
709 
710  float rH, rS, rV;
711  rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
712  if (rS != 0.0f) {
713  float colH, colS, colV;
714  rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
715  hsv_to_rgb(rH, (valuem * rS + value * colS), rV, &output[0], &output[1], &output[2]);
716  }
717  else {
718  copy_v3_v3(output, inputColor1);
719  }
720 
721  output[3] = inputColor1[3];
722 
724 }
725 
726 /* ******** Mix Screen Operation ******** */
727 
729  float x,
730  float y,
731  PixelSampler sampler)
732 {
733  float inputColor1[4];
734  float inputColor2[4];
735  float inputValue[4];
736 
737  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
738  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
739  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
740 
741  float value = inputValue[0];
742  if (this->useValueAlphaMultiply()) {
743  value *= inputColor2[3];
744  }
745  float valuem = 1.0f - value;
746 
747  output[0] = 1.0f - (valuem + value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]);
748  output[1] = 1.0f - (valuem + value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]);
749  output[2] = 1.0f - (valuem + value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]);
750  output[3] = inputColor1[3];
751 
753 }
754 
755 /* ******** Mix Soft Light Operation ******** */
756 
758  float x,
759  float y,
760  PixelSampler sampler)
761 {
762  float inputColor1[4];
763  float inputColor2[4];
764  float inputValue[4];
765 
766  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
767  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
768  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
769 
770  float value = inputValue[0];
771  if (this->useValueAlphaMultiply()) {
772  value *= inputColor2[3];
773  }
774  float valuem = 1.0f - value;
775  float scr, scg, scb;
776 
777  /* first calculate non-fac based Screen mix */
778  scr = 1.0f - (1.0f - inputColor2[0]) * (1.0f - inputColor1[0]);
779  scg = 1.0f - (1.0f - inputColor2[1]) * (1.0f - inputColor1[1]);
780  scb = 1.0f - (1.0f - inputColor2[2]) * (1.0f - inputColor1[2]);
781 
782  output[0] = valuem * (inputColor1[0]) +
783  value * (((1.0f - inputColor1[0]) * inputColor2[0] * (inputColor1[0])) +
784  (inputColor1[0] * scr));
785  output[1] = valuem * (inputColor1[1]) +
786  value * (((1.0f - inputColor1[1]) * inputColor2[1] * (inputColor1[1])) +
787  (inputColor1[1] * scg));
788  output[2] = valuem * (inputColor1[2]) +
789  value * (((1.0f - inputColor1[2]) * inputColor2[2] * (inputColor1[2])) +
790  (inputColor1[2] * scb));
791  output[3] = inputColor1[3];
792 
794 }
795 
796 /* ******** Mix Subtract Operation ******** */
797 
799  float x,
800  float y,
801  PixelSampler sampler)
802 {
803  float inputColor1[4];
804  float inputColor2[4];
805  float inputValue[4];
806 
807  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
808  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
809  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
810 
811  float value = inputValue[0];
812  if (this->useValueAlphaMultiply()) {
813  value *= inputColor2[3];
814  }
815  output[0] = inputColor1[0] - value * (inputColor2[0]);
816  output[1] = inputColor1[1] - value * (inputColor2[1]);
817  output[2] = inputColor1[2] - value * (inputColor2[2]);
818  output[3] = inputColor1[3];
819 
821 }
822 
823 /* ******** Mix Value Operation ******** */
824 
826  float x,
827  float y,
828  PixelSampler sampler)
829 {
830  float inputColor1[4];
831  float inputColor2[4];
832  float inputValue[4];
833 
834  this->m_inputValueOperation->readSampled(inputValue, x, y, sampler);
835  this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler);
836  this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler);
837 
838  float value = inputValue[0];
839  if (this->useValueAlphaMultiply()) {
840  value *= inputColor2[3];
841  }
842  float valuem = 1.0f - value;
843 
844  float rH, rS, rV;
845  float colH, colS, colV;
846  rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
847  rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
848  hsv_to_rgb(rH, rS, (valuem * rV + value * colV), &output[0], &output[1], &output[2]);
849  output[3] = inputColor1[3];
850 
852 }
853 
854 } // namespace blender::compositor
MINLINE float min_ff(float a, float b)
void rgb_to_hsv(float r, float g, float b, float *r_h, float *r_s, float *r_v)
Definition: math_color.c:229
void hsv_to_rgb(float h, float s, float v, float *r_r, float *r_g, float *r_b)
Definition: math_color.c:31
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define MAX2(a, b)
_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 y
#define output
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void setUseValueAlphaMultiply(const bool value)
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) override
determine the resolution of this node
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
void readSampled(float result[4], float x, float y, PixelSampler sampler)
NodeOperationInput * getInputSocket(unsigned int index)
void addInputSocket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
void addOutputSocket(DataType datatype)
void setResolutionInputSocketIndex(unsigned int index)
set the index of the input socket that will determine the resolution of this operation
virtual void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
determine the resolution of this node
SocketReader * getInputSocketReader(unsigned int inputSocketindex)
#define fabsf(x)