Blender  V3.3
COM_MixOperation.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2011 Blender Foundation. */
3 
4 #include "COM_MixOperation.h"
5 
6 namespace blender::compositor {
7 
8 /* ******** Mix Base Operation ******** */
9 
11 {
16  input_value_operation_ = nullptr;
17  input_color1_operation_ = nullptr;
18  input_color2_operation_ = nullptr;
19  this->set_use_value_alpha_multiply(false);
20  this->set_use_clamp(false);
21  flags_.can_be_constant = true;
22 }
23 
25 {
29 }
30 
32  float x,
33  float y,
35 {
36  float input_color1[4];
37  float input_color2[4];
38  float input_value[4];
39 
43 
44  float value = input_value[0];
45  if (this->use_value_alpha_multiply()) {
46  value *= input_color2[3];
47  }
48  float valuem = 1.0f - value;
49  output[0] = valuem * (input_color1[0]) + value * (input_color2[0]);
50  output[1] = valuem * (input_color1[1]) + value * (input_color2[1]);
51  output[2] = valuem * (input_color1[2]) + value * (input_color2[2]);
52  output[3] = input_color1[3];
53 }
54 
55 void MixBaseOperation::determine_canvas(const rcti &preferred_area, rcti &r_area)
56 {
57  NodeOperationInput *socket;
58  rcti temp_area = COM_AREA_NONE;
59 
60  socket = this->get_input_socket(1);
61  bool determined = socket->determine_canvas(COM_AREA_NONE, temp_area);
62  if (determined) {
63  this->set_canvas_input_index(1);
64  }
65  else {
66  socket = this->get_input_socket(2);
67  determined = socket->determine_canvas(COM_AREA_NONE, temp_area);
68  if (determined) {
69  this->set_canvas_input_index(2);
70  }
71  else {
72  this->set_canvas_input_index(0);
73  }
74  }
75  NodeOperation::determine_canvas(preferred_area, r_area);
76 }
77 
79 {
80  input_value_operation_ = nullptr;
81  input_color1_operation_ = nullptr;
82  input_color2_operation_ = nullptr;
83 }
84 
86  const rcti &area,
88 {
89  const MemoryBuffer *input_value = inputs[0];
90  const MemoryBuffer *input_color1 = inputs[1];
91  const MemoryBuffer *input_color2 = inputs[2];
92  const int width = BLI_rcti_size_x(&area);
93  PixelCursor p;
94  p.out_stride = output->elem_stride;
95  p.value_stride = input_value->elem_stride;
96  p.color1_stride = input_color1->elem_stride;
97  p.color2_stride = input_color2->elem_stride;
98  for (int y = area.ymin; y < area.ymax; y++) {
99  p.out = output->get_elem(area.xmin, y);
100  p.row_end = p.out + width * output->elem_stride;
101  p.value = input_value->get_elem(area.xmin, y);
102  p.color1 = input_color1->get_elem(area.xmin, y);
103  p.color2 = input_color2->get_elem(area.xmin, y);
105  }
106 }
107 
109 {
110  while (p.out < p.row_end) {
111  float value = p.value[0];
112  if (this->use_value_alpha_multiply()) {
113  value *= p.color2[3];
114  }
115  const float value_m = 1.0f - value;
116  p.out[0] = value_m * p.color1[0] + value * p.color2[0];
117  p.out[1] = value_m * p.color1[1] + value * p.color2[1];
118  p.out[2] = value_m * p.color1[2] + value * p.color2[2];
119  p.out[3] = p.color1[3];
120  p.next();
121  }
122 }
123 
124 /* ******** Mix Add Operation ******** */
125 
127  float x,
128  float y,
130 {
131  float input_color1[4];
132  float input_color2[4];
133  float input_value[4];
134 
135  input_value_operation_->read_sampled(input_value, x, y, sampler);
136  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
137  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
138 
139  float value = input_value[0];
140  if (this->use_value_alpha_multiply()) {
141  value *= input_color2[3];
142  }
143  output[0] = input_color1[0] + value * input_color2[0];
144  output[1] = input_color1[1] + value * input_color2[1];
145  output[2] = input_color1[2] + value * input_color2[2];
146  output[3] = input_color1[3];
147 
149 }
150 
152 {
153  while (p.out < p.row_end) {
154  float value = p.value[0];
155  if (this->use_value_alpha_multiply()) {
156  value *= p.color2[3];
157  }
158  p.out[0] = p.color1[0] + value * p.color2[0];
159  p.out[1] = p.color1[1] + value * p.color2[1];
160  p.out[2] = p.color1[2] + value * p.color2[2];
161  p.out[3] = p.color1[3];
162 
163  clamp_if_needed(p.out);
164  p.next();
165  }
166 }
167 
168 /* ******** Mix Blend Operation ******** */
169 
171  float x,
172  float y,
174 {
175  float input_color1[4];
176  float input_color2[4];
177  float input_value[4];
178  float value;
179 
180  input_value_operation_->read_sampled(input_value, x, y, sampler);
181  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
182  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
183  value = input_value[0];
184 
185  if (this->use_value_alpha_multiply()) {
186  value *= input_color2[3];
187  }
188  float valuem = 1.0f - value;
189  output[0] = valuem * (input_color1[0]) + value * (input_color2[0]);
190  output[1] = valuem * (input_color1[1]) + value * (input_color2[1]);
191  output[2] = valuem * (input_color1[2]) + value * (input_color2[2]);
192  output[3] = input_color1[3];
193 
195 }
196 
198 {
199  while (p.out < p.row_end) {
200  float value = p.value[0];
201  if (this->use_value_alpha_multiply()) {
202  value *= p.color2[3];
203  }
204  float value_m = 1.0f - value;
205  p.out[0] = value_m * p.color1[0] + value * p.color2[0];
206  p.out[1] = value_m * p.color1[1] + value * p.color2[1];
207  p.out[2] = value_m * p.color1[2] + value * p.color2[2];
208  p.out[3] = p.color1[3];
209 
210  clamp_if_needed(p.out);
211  p.next();
212  }
213 }
214 
215 /* ******** Mix Burn Operation ******** */
216 
218  float x,
219  float y,
221 {
222  float input_color1[4];
223  float input_color2[4];
224  float input_value[4];
225  float tmp;
226 
227  input_value_operation_->read_sampled(input_value, x, y, sampler);
228  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
229  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
230 
231  float value = input_value[0];
232  if (this->use_value_alpha_multiply()) {
233  value *= input_color2[3];
234  }
235  float valuem = 1.0f - value;
236 
237  tmp = valuem + value * input_color2[0];
238  if (tmp <= 0.0f) {
239  output[0] = 0.0f;
240  }
241  else {
242  tmp = 1.0f - (1.0f - input_color1[0]) / tmp;
243  if (tmp < 0.0f) {
244  output[0] = 0.0f;
245  }
246  else if (tmp > 1.0f) {
247  output[0] = 1.0f;
248  }
249  else {
250  output[0] = tmp;
251  }
252  }
253 
254  tmp = valuem + value * input_color2[1];
255  if (tmp <= 0.0f) {
256  output[1] = 0.0f;
257  }
258  else {
259  tmp = 1.0f - (1.0f - input_color1[1]) / tmp;
260  if (tmp < 0.0f) {
261  output[1] = 0.0f;
262  }
263  else if (tmp > 1.0f) {
264  output[1] = 1.0f;
265  }
266  else {
267  output[1] = tmp;
268  }
269  }
270 
271  tmp = valuem + value * input_color2[2];
272  if (tmp <= 0.0f) {
273  output[2] = 0.0f;
274  }
275  else {
276  tmp = 1.0f - (1.0f - input_color1[2]) / tmp;
277  if (tmp < 0.0f) {
278  output[2] = 0.0f;
279  }
280  else if (tmp > 1.0f) {
281  output[2] = 1.0f;
282  }
283  else {
284  output[2] = tmp;
285  }
286  }
287 
288  output[3] = input_color1[3];
289 
291 }
292 
294 {
295  while (p.out < p.row_end) {
296  float value = p.value[0];
297  if (this->use_value_alpha_multiply()) {
298  value *= p.color2[3];
299  }
300  const float value_m = 1.0f - value;
301 
302  float tmp = value_m + value * p.color2[0];
303  if (tmp <= 0.0f) {
304  p.out[0] = 0.0f;
305  }
306  else {
307  tmp = 1.0f - (1.0f - p.color1[0]) / tmp;
308  p.out[0] = CLAMPIS(tmp, 0.0f, 1.0f);
309  }
310 
311  tmp = value_m + value * p.color2[1];
312  if (tmp <= 0.0f) {
313  p.out[1] = 0.0f;
314  }
315  else {
316  tmp = 1.0f - (1.0f - p.color1[1]) / tmp;
317  p.out[1] = CLAMPIS(tmp, 0.0f, 1.0f);
318  }
319 
320  tmp = value_m + value * p.color2[2];
321  if (tmp <= 0.0f) {
322  p.out[2] = 0.0f;
323  }
324  else {
325  tmp = 1.0f - (1.0f - p.color1[2]) / tmp;
326  p.out[2] = CLAMPIS(tmp, 0.0f, 1.0f);
327  }
328  p.out[3] = p.color1[3];
329 
330  clamp_if_needed(p.out);
331  p.next();
332  }
333 }
334 
335 /* ******** Mix Color Operation ******** */
336 
338  float x,
339  float y,
341 {
342  float input_color1[4];
343  float input_color2[4];
344  float input_value[4];
345 
346  input_value_operation_->read_sampled(input_value, x, y, sampler);
347  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
348  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
349 
350  float value = input_value[0];
351  if (this->use_value_alpha_multiply()) {
352  value *= input_color2[3];
353  }
354  float valuem = 1.0f - value;
355 
356  float colH, colS, colV;
357  rgb_to_hsv(input_color2[0], input_color2[1], input_color2[2], &colH, &colS, &colV);
358  if (colS != 0.0f) {
359  float rH, rS, rV;
360  float tmpr, tmpg, tmpb;
361  rgb_to_hsv(input_color1[0], input_color1[1], input_color1[2], &rH, &rS, &rV);
362  hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb);
363  output[0] = (valuem * input_color1[0]) + (value * tmpr);
364  output[1] = (valuem * input_color1[1]) + (value * tmpg);
365  output[2] = (valuem * input_color1[2]) + (value * tmpb);
366  }
367  else {
368  copy_v3_v3(output, input_color1);
369  }
370  output[3] = input_color1[3];
371 
373 }
374 
376 {
377  while (p.out < p.row_end) {
378  float value = p.value[0];
379  if (this->use_value_alpha_multiply()) {
380  value *= p.color2[3];
381  }
382  const float value_m = 1.0f - value;
383 
384  float colH, colS, colV;
385  rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV);
386  if (colS != 0.0f) {
387  float rH, rS, rV;
388  float tmpr, tmpg, tmpb;
389  rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV);
390  hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb);
391  p.out[0] = (value_m * p.color1[0]) + (value * tmpr);
392  p.out[1] = (value_m * p.color1[1]) + (value * tmpg);
393  p.out[2] = (value_m * p.color1[2]) + (value * tmpb);
394  }
395  else {
396  copy_v3_v3(p.out, p.color1);
397  }
398  p.out[3] = p.color1[3];
399 
400  clamp_if_needed(p.out);
401  p.next();
402  }
403 }
404 
405 /* ******** Mix Darken Operation ******** */
406 
408  float x,
409  float y,
411 {
412  float input_color1[4];
413  float input_color2[4];
414  float input_value[4];
415 
416  input_value_operation_->read_sampled(input_value, x, y, sampler);
417  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
418  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
419 
420  float value = input_value[0];
421  if (this->use_value_alpha_multiply()) {
422  value *= input_color2[3];
423  }
424  float valuem = 1.0f - value;
425  output[0] = min_ff(input_color1[0], input_color2[0]) * value + input_color1[0] * valuem;
426  output[1] = min_ff(input_color1[1], input_color2[1]) * value + input_color1[1] * valuem;
427  output[2] = min_ff(input_color1[2], input_color2[2]) * value + input_color1[2] * valuem;
428  output[3] = input_color1[3];
429 
431 }
432 
434 {
435  while (p.out < p.row_end) {
436  float value = p.value[0];
437  if (this->use_value_alpha_multiply()) {
438  value *= p.color2[3];
439  }
440  float value_m = 1.0f - value;
441  p.out[0] = min_ff(p.color1[0], p.color2[0]) * value + p.color1[0] * value_m;
442  p.out[1] = min_ff(p.color1[1], p.color2[1]) * value + p.color1[1] * value_m;
443  p.out[2] = min_ff(p.color1[2], p.color2[2]) * value + p.color1[2] * value_m;
444  p.out[3] = p.color1[3];
445 
446  clamp_if_needed(p.out);
447  p.next();
448  }
449 }
450 
451 /* ******** Mix Difference Operation ******** */
452 
454  float x,
455  float y,
457 {
458  float input_color1[4];
459  float input_color2[4];
460  float input_value[4];
461 
462  input_value_operation_->read_sampled(input_value, x, y, sampler);
463  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
464  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
465 
466  float value = input_value[0];
467  if (this->use_value_alpha_multiply()) {
468  value *= input_color2[3];
469  }
470  float valuem = 1.0f - value;
471  output[0] = valuem * input_color1[0] + value * fabsf(input_color1[0] - input_color2[0]);
472  output[1] = valuem * input_color1[1] + value * fabsf(input_color1[1] - input_color2[1]);
473  output[2] = valuem * input_color1[2] + value * fabsf(input_color1[2] - input_color2[2]);
474  output[3] = input_color1[3];
475 
477 }
478 
480 {
481  while (p.out < p.row_end) {
482  float value = p.value[0];
483  if (this->use_value_alpha_multiply()) {
484  value *= p.color2[3];
485  }
486  const float value_m = 1.0f - value;
487  p.out[0] = value_m * p.color1[0] + value * fabsf(p.color1[0] - p.color2[0]);
488  p.out[1] = value_m * p.color1[1] + value * fabsf(p.color1[1] - p.color2[1]);
489  p.out[2] = value_m * p.color1[2] + value * fabsf(p.color1[2] - p.color2[2]);
490  p.out[3] = p.color1[3];
491 
492  clamp_if_needed(p.out);
493  p.next();
494  }
495 }
496 
497 /* ******** Mix Difference Operation ******** */
498 
500  float x,
501  float y,
503 {
504  float input_color1[4];
505  float input_color2[4];
506  float input_value[4];
507 
508  input_value_operation_->read_sampled(input_value, x, y, sampler);
509  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
510  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
511 
512  float value = input_value[0];
513  if (this->use_value_alpha_multiply()) {
514  value *= input_color2[3];
515  }
516  float valuem = 1.0f - value;
517 
518  if (input_color2[0] != 0.0f) {
519  output[0] = valuem * (input_color1[0]) + value * (input_color1[0]) / input_color2[0];
520  }
521  else {
522  output[0] = 0.0f;
523  }
524  if (input_color2[1] != 0.0f) {
525  output[1] = valuem * (input_color1[1]) + value * (input_color1[1]) / input_color2[1];
526  }
527  else {
528  output[1] = 0.0f;
529  }
530  if (input_color2[2] != 0.0f) {
531  output[2] = valuem * (input_color1[2]) + value * (input_color1[2]) / input_color2[2];
532  }
533  else {
534  output[2] = 0.0f;
535  }
536 
537  output[3] = input_color1[3];
538 
540 }
541 
543 {
544  while (p.out < p.row_end) {
545  float value = p.value[0];
546  if (this->use_value_alpha_multiply()) {
547  value *= p.color2[3];
548  }
549  const float value_m = 1.0f - value;
550 
551  if (p.color2[0] != 0.0f) {
552  p.out[0] = value_m * (p.color1[0]) + value * (p.color1[0]) / p.color2[0];
553  }
554  else {
555  p.out[0] = 0.0f;
556  }
557  if (p.color2[1] != 0.0f) {
558  p.out[1] = value_m * (p.color1[1]) + value * (p.color1[1]) / p.color2[1];
559  }
560  else {
561  p.out[1] = 0.0f;
562  }
563  if (p.color2[2] != 0.0f) {
564  p.out[2] = value_m * (p.color1[2]) + value * (p.color1[2]) / p.color2[2];
565  }
566  else {
567  p.out[2] = 0.0f;
568  }
569 
570  p.out[3] = p.color1[3];
571 
572  clamp_if_needed(p.out);
573  p.next();
574  }
575 }
576 
577 /* ******** Mix Dodge Operation ******** */
578 
580  float x,
581  float y,
583 {
584  float input_color1[4];
585  float input_color2[4];
586  float input_value[4];
587  float tmp;
588 
589  input_value_operation_->read_sampled(input_value, x, y, sampler);
590  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
591  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
592 
593  float value = input_value[0];
594  if (this->use_value_alpha_multiply()) {
595  value *= input_color2[3];
596  }
597 
598  if (input_color1[0] != 0.0f) {
599  tmp = 1.0f - value * input_color2[0];
600  if (tmp <= 0.0f) {
601  output[0] = 1.0f;
602  }
603  else {
604  tmp = input_color1[0] / tmp;
605  if (tmp > 1.0f) {
606  output[0] = 1.0f;
607  }
608  else {
609  output[0] = tmp;
610  }
611  }
612  }
613  else {
614  output[0] = 0.0f;
615  }
616 
617  if (input_color1[1] != 0.0f) {
618  tmp = 1.0f - value * input_color2[1];
619  if (tmp <= 0.0f) {
620  output[1] = 1.0f;
621  }
622  else {
623  tmp = input_color1[1] / tmp;
624  if (tmp > 1.0f) {
625  output[1] = 1.0f;
626  }
627  else {
628  output[1] = tmp;
629  }
630  }
631  }
632  else {
633  output[1] = 0.0f;
634  }
635 
636  if (input_color1[2] != 0.0f) {
637  tmp = 1.0f - value * input_color2[2];
638  if (tmp <= 0.0f) {
639  output[2] = 1.0f;
640  }
641  else {
642  tmp = input_color1[2] / tmp;
643  if (tmp > 1.0f) {
644  output[2] = 1.0f;
645  }
646  else {
647  output[2] = tmp;
648  }
649  }
650  }
651  else {
652  output[2] = 0.0f;
653  }
654 
655  output[3] = input_color1[3];
656 
658 }
659 
661 {
662  while (p.out < p.row_end) {
663  float value = p.value[0];
664  if (this->use_value_alpha_multiply()) {
665  value *= p.color2[3];
666  }
667 
668  float tmp;
669  if (p.color1[0] != 0.0f) {
670  tmp = 1.0f - value * p.color2[0];
671  if (tmp <= 0.0f) {
672  p.out[0] = 1.0f;
673  }
674  else {
675  p.out[0] = p.color1[0] / tmp;
676  CLAMP_MAX(p.out[0], 1.0f);
677  }
678  }
679  else {
680  p.out[0] = 0.0f;
681  }
682 
683  if (p.color1[1] != 0.0f) {
684  tmp = 1.0f - value * p.color2[1];
685  if (tmp <= 0.0f) {
686  p.out[1] = 1.0f;
687  }
688  else {
689  p.out[1] = p.color1[1] / tmp;
690  CLAMP_MAX(p.out[1], 1.0f);
691  }
692  }
693  else {
694  p.out[1] = 0.0f;
695  }
696 
697  if (p.color1[2] != 0.0f) {
698  tmp = 1.0f - value * p.color2[2];
699  if (tmp <= 0.0f) {
700  p.out[2] = 1.0f;
701  }
702  else {
703  p.out[2] = p.color1[2] / tmp;
704  CLAMP_MAX(p.out[2], 1.0f);
705  }
706  }
707  else {
708  p.out[2] = 0.0f;
709  }
710 
711  p.out[3] = p.color1[3];
712 
713  clamp_if_needed(p.out);
714  p.next();
715  }
716 }
717 
718 /* ******** Mix Glare Operation ******** */
719 
721  float x,
722  float y,
724 {
725  float input_color1[4];
726  float input_color2[4];
727  float input_value[4];
728  float value, input_weight, glare_weight;
729 
730  input_value_operation_->read_sampled(input_value, x, y, sampler);
731  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
732  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
733  value = input_value[0];
734  /* Linear interpolation between 3 cases:
735  * value=-1:output=input value=0:output=input+glare value=1:output=glare
736  */
737  if (value < 0.0f) {
738  input_weight = 1.0f;
739  glare_weight = 1.0f + value;
740  }
741  else {
742  input_weight = 1.0f - value;
743  glare_weight = 1.0f;
744  }
745  output[0] = input_weight * MAX2(input_color1[0], 0.0f) + glare_weight * input_color2[0];
746  output[1] = input_weight * MAX2(input_color1[1], 0.0f) + glare_weight * input_color2[1];
747  output[2] = input_weight * MAX2(input_color1[2], 0.0f) + glare_weight * input_color2[2];
748  output[3] = input_color1[3];
749 
751 }
752 
754 {
755  while (p.out < p.row_end) {
756  const float value = p.value[0];
757  /* Linear interpolation between 3 cases:
758  * value=-1:output=input value=0:output=input+glare value=1:output=glare
759  */
760  float input_weight;
761  float glare_weight;
762  if (value < 0.0f) {
763  input_weight = 1.0f;
764  glare_weight = 1.0f + value;
765  }
766  else {
767  input_weight = 1.0f - value;
768  glare_weight = 1.0f;
769  }
770  p.out[0] = input_weight * MAX2(p.color1[0], 0.0f) + glare_weight * p.color2[0];
771  p.out[1] = input_weight * MAX2(p.color1[1], 0.0f) + glare_weight * p.color2[1];
772  p.out[2] = input_weight * MAX2(p.color1[2], 0.0f) + glare_weight * p.color2[2];
773  p.out[3] = p.color1[3];
774 
775  clamp_if_needed(p.out);
776  p.next();
777  }
778 }
779 
780 /* ******** Mix Hue Operation ******** */
781 
783  float x,
784  float y,
786 {
787  float input_color1[4];
788  float input_color2[4];
789  float input_value[4];
790 
791  input_value_operation_->read_sampled(input_value, x, y, sampler);
792  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
793  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
794 
795  float value = input_value[0];
796  if (this->use_value_alpha_multiply()) {
797  value *= input_color2[3];
798  }
799  float valuem = 1.0f - value;
800 
801  float colH, colS, colV;
802  rgb_to_hsv(input_color2[0], input_color2[1], input_color2[2], &colH, &colS, &colV);
803  if (colS != 0.0f) {
804  float rH, rS, rV;
805  float tmpr, tmpg, tmpb;
806  rgb_to_hsv(input_color1[0], input_color1[1], input_color1[2], &rH, &rS, &rV);
807  hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb);
808  output[0] = valuem * (input_color1[0]) + value * tmpr;
809  output[1] = valuem * (input_color1[1]) + value * tmpg;
810  output[2] = valuem * (input_color1[2]) + value * tmpb;
811  }
812  else {
813  copy_v3_v3(output, input_color1);
814  }
815  output[3] = input_color1[3];
816 
818 }
819 
821 {
822  while (p.out < p.row_end) {
823  float value = p.value[0];
824  if (this->use_value_alpha_multiply()) {
825  value *= p.color2[3];
826  }
827  const float value_m = 1.0f - value;
828 
829  float colH, colS, colV;
830  rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV);
831  if (colS != 0.0f) {
832  float rH, rS, rV;
833  float tmpr, tmpg, tmpb;
834  rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV);
835  hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb);
836  p.out[0] = value_m * p.color1[0] + value * tmpr;
837  p.out[1] = value_m * p.color1[1] + value * tmpg;
838  p.out[2] = value_m * p.color1[2] + value * tmpb;
839  }
840  else {
841  copy_v3_v3(p.out, p.color1);
842  }
843  p.out[3] = p.color1[3];
844 
845  clamp_if_needed(p.out);
846  p.next();
847  }
848 }
849 
850 /* ******** Mix Lighten Operation ******** */
851 
853  float x,
854  float y,
856 {
857  float input_color1[4];
858  float input_color2[4];
859  float input_value[4];
860 
861  input_value_operation_->read_sampled(input_value, x, y, sampler);
862  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
863  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
864 
865  float value = input_value[0];
866  if (this->use_value_alpha_multiply()) {
867  value *= input_color2[3];
868  }
869  float tmp;
870  tmp = value * input_color2[0];
871  if (tmp > input_color1[0]) {
872  output[0] = tmp;
873  }
874  else {
875  output[0] = input_color1[0];
876  }
877  tmp = value * input_color2[1];
878  if (tmp > input_color1[1]) {
879  output[1] = tmp;
880  }
881  else {
882  output[1] = input_color1[1];
883  }
884  tmp = value * input_color2[2];
885  if (tmp > input_color1[2]) {
886  output[2] = tmp;
887  }
888  else {
889  output[2] = input_color1[2];
890  }
891  output[3] = input_color1[3];
892 
894 }
895 
897 {
898  while (p.out < p.row_end) {
899  float value = p.value[0];
900  if (this->use_value_alpha_multiply()) {
901  value *= p.color2[3];
902  }
903 
904  float tmp = value * p.color2[0];
905  p.out[0] = MAX2(tmp, p.color1[0]);
906 
907  tmp = value * p.color2[1];
908  p.out[1] = MAX2(tmp, p.color1[1]);
909 
910  tmp = value * p.color2[2];
911  p.out[2] = MAX2(tmp, p.color1[2]);
912 
913  p.out[3] = p.color1[3];
914 
915  clamp_if_needed(p.out);
916  p.next();
917  }
918 }
919 
920 /* ******** Mix Linear Light Operation ******** */
921 
923  float x,
924  float y,
926 {
927  float input_color1[4];
928  float input_color2[4];
929  float input_value[4];
930 
931  input_value_operation_->read_sampled(input_value, x, y, sampler);
932  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
933  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
934 
935  float value = input_value[0];
936  if (this->use_value_alpha_multiply()) {
937  value *= input_color2[3];
938  }
939  if (input_color2[0] > 0.5f) {
940  output[0] = input_color1[0] + value * (2.0f * (input_color2[0] - 0.5f));
941  }
942  else {
943  output[0] = input_color1[0] + value * (2.0f * (input_color2[0]) - 1.0f);
944  }
945  if (input_color2[1] > 0.5f) {
946  output[1] = input_color1[1] + value * (2.0f * (input_color2[1] - 0.5f));
947  }
948  else {
949  output[1] = input_color1[1] + value * (2.0f * (input_color2[1]) - 1.0f);
950  }
951  if (input_color2[2] > 0.5f) {
952  output[2] = input_color1[2] + value * (2.0f * (input_color2[2] - 0.5f));
953  }
954  else {
955  output[2] = input_color1[2] + value * (2.0f * (input_color2[2]) - 1.0f);
956  }
957 
958  output[3] = input_color1[3];
959 
961 }
962 
964 {
965  while (p.out < p.row_end) {
966  float value = p.value[0];
967  if (this->use_value_alpha_multiply()) {
968  value *= p.color2[3];
969  }
970  if (p.color2[0] > 0.5f) {
971  p.out[0] = p.color1[0] + value * (2.0f * (p.color2[0] - 0.5f));
972  }
973  else {
974  p.out[0] = p.color1[0] + value * (2.0f * (p.color2[0]) - 1.0f);
975  }
976  if (p.color2[1] > 0.5f) {
977  p.out[1] = p.color1[1] + value * (2.0f * (p.color2[1] - 0.5f));
978  }
979  else {
980  p.out[1] = p.color1[1] + value * (2.0f * (p.color2[1]) - 1.0f);
981  }
982  if (p.color2[2] > 0.5f) {
983  p.out[2] = p.color1[2] + value * (2.0f * (p.color2[2] - 0.5f));
984  }
985  else {
986  p.out[2] = p.color1[2] + value * (2.0f * (p.color2[2]) - 1.0f);
987  }
988 
989  p.out[3] = p.color1[3];
990 
991  clamp_if_needed(p.out);
992  p.next();
993  }
994 }
995 
996 /* ******** Mix Multiply Operation ******** */
997 
999  float x,
1000  float y,
1002 {
1003  float input_color1[4];
1004  float input_color2[4];
1005  float input_value[4];
1006 
1007  input_value_operation_->read_sampled(input_value, x, y, sampler);
1008  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
1009  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
1010 
1011  float value = input_value[0];
1012  if (this->use_value_alpha_multiply()) {
1013  value *= input_color2[3];
1014  }
1015  float valuem = 1.0f - value;
1016  output[0] = input_color1[0] * (valuem + value * input_color2[0]);
1017  output[1] = input_color1[1] * (valuem + value * input_color2[1]);
1018  output[2] = input_color1[2] * (valuem + value * input_color2[2]);
1019  output[3] = input_color1[3];
1020 
1022 }
1023 
1025 {
1026  while (p.out < p.row_end) {
1027  float value = p.value[0];
1028  if (this->use_value_alpha_multiply()) {
1029  value *= p.color2[3];
1030  }
1031  const float value_m = 1.0f - value;
1032  p.out[0] = p.color1[0] * (value_m + value * p.color2[0]);
1033  p.out[1] = p.color1[1] * (value_m + value * p.color2[1]);
1034  p.out[2] = p.color1[2] * (value_m + value * p.color2[2]);
1035 
1036  p.out[3] = p.color1[3];
1037 
1038  clamp_if_needed(p.out);
1039  p.next();
1040  }
1041 }
1042 
1043 /* ******** Mix Overlay Operation ******** */
1044 
1046  float x,
1047  float y,
1049 {
1050  float input_color1[4];
1051  float input_color2[4];
1052  float input_value[4];
1053 
1054  input_value_operation_->read_sampled(input_value, x, y, sampler);
1055  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
1056  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
1057 
1058  float value = input_value[0];
1059  if (this->use_value_alpha_multiply()) {
1060  value *= input_color2[3];
1061  }
1062 
1063  float valuem = 1.0f - value;
1064 
1065  if (input_color1[0] < 0.5f) {
1066  output[0] = input_color1[0] * (valuem + 2.0f * value * input_color2[0]);
1067  }
1068  else {
1069  output[0] = 1.0f -
1070  (valuem + 2.0f * value * (1.0f - input_color2[0])) * (1.0f - input_color1[0]);
1071  }
1072  if (input_color1[1] < 0.5f) {
1073  output[1] = input_color1[1] * (valuem + 2.0f * value * input_color2[1]);
1074  }
1075  else {
1076  output[1] = 1.0f -
1077  (valuem + 2.0f * value * (1.0f - input_color2[1])) * (1.0f - input_color1[1]);
1078  }
1079  if (input_color1[2] < 0.5f) {
1080  output[2] = input_color1[2] * (valuem + 2.0f * value * input_color2[2]);
1081  }
1082  else {
1083  output[2] = 1.0f -
1084  (valuem + 2.0f * value * (1.0f - input_color2[2])) * (1.0f - input_color1[2]);
1085  }
1086  output[3] = input_color1[3];
1087 
1089 }
1090 
1092 {
1093  while (p.out < p.row_end) {
1094  float value = p.value[0];
1095  if (this->use_value_alpha_multiply()) {
1096  value *= p.color2[3];
1097  }
1098  const float value_m = 1.0f - value;
1099  if (p.color1[0] < 0.5f) {
1100  p.out[0] = p.color1[0] * (value_m + 2.0f * value * p.color2[0]);
1101  }
1102  else {
1103  p.out[0] = 1.0f - (value_m + 2.0f * value * (1.0f - p.color2[0])) * (1.0f - p.color1[0]);
1104  }
1105  if (p.color1[1] < 0.5f) {
1106  p.out[1] = p.color1[1] * (value_m + 2.0f * value * p.color2[1]);
1107  }
1108  else {
1109  p.out[1] = 1.0f - (value_m + 2.0f * value * (1.0f - p.color2[1])) * (1.0f - p.color1[1]);
1110  }
1111  if (p.color1[2] < 0.5f) {
1112  p.out[2] = p.color1[2] * (value_m + 2.0f * value * p.color2[2]);
1113  }
1114  else {
1115  p.out[2] = 1.0f - (value_m + 2.0f * value * (1.0f - p.color2[2])) * (1.0f - p.color1[2]);
1116  }
1117 
1118  p.out[3] = p.color1[3];
1119 
1120  clamp_if_needed(p.out);
1121  p.next();
1122  }
1123 }
1124 
1125 /* ******** Mix Saturation Operation ******** */
1126 
1128  float x,
1129  float y,
1131 {
1132  float input_color1[4];
1133  float input_color2[4];
1134  float input_value[4];
1135 
1136  input_value_operation_->read_sampled(input_value, x, y, sampler);
1137  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
1138  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
1139 
1140  float value = input_value[0];
1141  if (this->use_value_alpha_multiply()) {
1142  value *= input_color2[3];
1143  }
1144  float valuem = 1.0f - value;
1145 
1146  float rH, rS, rV;
1147  rgb_to_hsv(input_color1[0], input_color1[1], input_color1[2], &rH, &rS, &rV);
1148  if (rS != 0.0f) {
1149  float colH, colS, colV;
1150  rgb_to_hsv(input_color2[0], input_color2[1], input_color2[2], &colH, &colS, &colV);
1151  hsv_to_rgb(rH, (valuem * rS + value * colS), rV, &output[0], &output[1], &output[2]);
1152  }
1153  else {
1154  copy_v3_v3(output, input_color1);
1155  }
1156 
1157  output[3] = input_color1[3];
1158 
1160 }
1161 
1163 {
1164  while (p.out < p.row_end) {
1165  float value = p.value[0];
1166  if (this->use_value_alpha_multiply()) {
1167  value *= p.color2[3];
1168  }
1169  const float value_m = 1.0f - value;
1170 
1171  float rH, rS, rV;
1172  rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV);
1173  if (rS != 0.0f) {
1174  float colH, colS, colV;
1175  rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV);
1176  hsv_to_rgb(rH, (value_m * rS + value * colS), rV, &p.out[0], &p.out[1], &p.out[2]);
1177  }
1178  else {
1179  copy_v3_v3(p.out, p.color1);
1180  }
1181 
1182  p.out[3] = p.color1[3];
1183 
1184  clamp_if_needed(p.out);
1185  p.next();
1186  }
1187 }
1188 
1189 /* ******** Mix Screen Operation ******** */
1190 
1192  float x,
1193  float y,
1195 {
1196  float input_color1[4];
1197  float input_color2[4];
1198  float input_value[4];
1199 
1200  input_value_operation_->read_sampled(input_value, x, y, sampler);
1201  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
1202  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
1203 
1204  float value = input_value[0];
1205  if (this->use_value_alpha_multiply()) {
1206  value *= input_color2[3];
1207  }
1208  float valuem = 1.0f - value;
1209 
1210  output[0] = 1.0f - (valuem + value * (1.0f - input_color2[0])) * (1.0f - input_color1[0]);
1211  output[1] = 1.0f - (valuem + value * (1.0f - input_color2[1])) * (1.0f - input_color1[1]);
1212  output[2] = 1.0f - (valuem + value * (1.0f - input_color2[2])) * (1.0f - input_color1[2]);
1213  output[3] = input_color1[3];
1214 
1216 }
1217 
1219 {
1220  while (p.out < p.row_end) {
1221  float value = p.value[0];
1222  if (this->use_value_alpha_multiply()) {
1223  value *= p.color2[3];
1224  }
1225  const float value_m = 1.0f - value;
1226 
1227  p.out[0] = 1.0f - (value_m + value * (1.0f - p.color2[0])) * (1.0f - p.color1[0]);
1228  p.out[1] = 1.0f - (value_m + value * (1.0f - p.color2[1])) * (1.0f - p.color1[1]);
1229  p.out[2] = 1.0f - (value_m + value * (1.0f - p.color2[2])) * (1.0f - p.color1[2]);
1230  p.out[3] = p.color1[3];
1231 
1232  clamp_if_needed(p.out);
1233  p.next();
1234  }
1235 }
1236 
1237 /* ******** Mix Soft Light Operation ******** */
1238 
1240  float x,
1241  float y,
1243 {
1244  float input_color1[4];
1245  float input_color2[4];
1246  float input_value[4];
1247 
1248  input_value_operation_->read_sampled(input_value, x, y, sampler);
1249  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
1250  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
1251 
1252  float value = input_value[0];
1253  if (this->use_value_alpha_multiply()) {
1254  value *= input_color2[3];
1255  }
1256  float valuem = 1.0f - value;
1257  float scr, scg, scb;
1258 
1259  /* first calculate non-fac based Screen mix */
1260  scr = 1.0f - (1.0f - input_color2[0]) * (1.0f - input_color1[0]);
1261  scg = 1.0f - (1.0f - input_color2[1]) * (1.0f - input_color1[1]);
1262  scb = 1.0f - (1.0f - input_color2[2]) * (1.0f - input_color1[2]);
1263 
1264  output[0] = valuem * (input_color1[0]) +
1265  value * (((1.0f - input_color1[0]) * input_color2[0] * (input_color1[0])) +
1266  (input_color1[0] * scr));
1267  output[1] = valuem * (input_color1[1]) +
1268  value * (((1.0f - input_color1[1]) * input_color2[1] * (input_color1[1])) +
1269  (input_color1[1] * scg));
1270  output[2] = valuem * (input_color1[2]) +
1271  value * (((1.0f - input_color1[2]) * input_color2[2] * (input_color1[2])) +
1272  (input_color1[2] * scb));
1273  output[3] = input_color1[3];
1274 
1276 }
1277 
1279 {
1280  while (p.out < p.row_end) {
1281  float value = p.value[0];
1282  if (this->use_value_alpha_multiply()) {
1283  value *= p.color2[3];
1284  }
1285  const float value_m = 1.0f - value;
1286  float scr, scg, scb;
1287 
1288  /* First calculate non-fac based Screen mix. */
1289  scr = 1.0f - (1.0f - p.color2[0]) * (1.0f - p.color1[0]);
1290  scg = 1.0f - (1.0f - p.color2[1]) * (1.0f - p.color1[1]);
1291  scb = 1.0f - (1.0f - p.color2[2]) * (1.0f - p.color1[2]);
1292 
1293  p.out[0] = value_m * p.color1[0] +
1294  value * ((1.0f - p.color1[0]) * p.color2[0] * p.color1[0] + p.color1[0] * scr);
1295  p.out[1] = value_m * p.color1[1] +
1296  value * ((1.0f - p.color1[1]) * p.color2[1] * p.color1[1] + p.color1[1] * scg);
1297  p.out[2] = value_m * p.color1[2] +
1298  value * ((1.0f - p.color1[2]) * p.color2[2] * p.color1[2] + p.color1[2] * scb);
1299  p.out[3] = p.color1[3];
1300 
1301  clamp_if_needed(p.out);
1302  p.next();
1303  }
1304 }
1305 
1306 /* ******** Mix Subtract Operation ******** */
1307 
1309  float x,
1310  float y,
1312 {
1313  float input_color1[4];
1314  float input_color2[4];
1315  float input_value[4];
1316 
1317  input_value_operation_->read_sampled(input_value, x, y, sampler);
1318  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
1319  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
1320 
1321  float value = input_value[0];
1322  if (this->use_value_alpha_multiply()) {
1323  value *= input_color2[3];
1324  }
1325  output[0] = input_color1[0] - value * (input_color2[0]);
1326  output[1] = input_color1[1] - value * (input_color2[1]);
1327  output[2] = input_color1[2] - value * (input_color2[2]);
1328  output[3] = input_color1[3];
1329 
1331 }
1332 
1334 {
1335  while (p.out < p.row_end) {
1336  float value = p.value[0];
1337  if (this->use_value_alpha_multiply()) {
1338  value *= p.color2[3];
1339  }
1340  p.out[0] = p.color1[0] - value * p.color2[0];
1341  p.out[1] = p.color1[1] - value * p.color2[1];
1342  p.out[2] = p.color1[2] - value * p.color2[2];
1343  p.out[3] = p.color1[3];
1344 
1345  clamp_if_needed(p.out);
1346  p.next();
1347  }
1348 }
1349 
1350 /* ******** Mix Value Operation ******** */
1351 
1353  float x,
1354  float y,
1356 {
1357  float input_color1[4];
1358  float input_color2[4];
1359  float input_value[4];
1360 
1361  input_value_operation_->read_sampled(input_value, x, y, sampler);
1362  input_color1_operation_->read_sampled(input_color1, x, y, sampler);
1363  input_color2_operation_->read_sampled(input_color2, x, y, sampler);
1364 
1365  float value = input_value[0];
1366  if (this->use_value_alpha_multiply()) {
1367  value *= input_color2[3];
1368  }
1369  float valuem = 1.0f - value;
1370 
1371  float rH, rS, rV;
1372  float colH, colS, colV;
1373  rgb_to_hsv(input_color1[0], input_color1[1], input_color1[2], &rH, &rS, &rV);
1374  rgb_to_hsv(input_color2[0], input_color2[1], input_color2[2], &colH, &colS, &colV);
1375  hsv_to_rgb(rH, rS, (valuem * rV + value * colV), &output[0], &output[1], &output[2]);
1376  output[3] = input_color1[3];
1377 
1379 }
1380 
1382 {
1383  while (p.out < p.row_end) {
1384  float value = p.value[0];
1385  if (this->use_value_alpha_multiply()) {
1386  value *= p.color2[3];
1387  }
1388  float value_m = 1.0f - value;
1389 
1390  float rH, rS, rV;
1391  float colH, colS, colV;
1392  rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV);
1393  rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV);
1394  hsv_to_rgb(rH, rS, (value_m * rV + value * colV), &p.out[0], &p.out[1], &p.out[2]);
1395  p.out[3] = p.color1[3];
1396 
1397  clamp_if_needed(p.out);
1398  p.next();
1399  }
1400 }
1401 
1402 } // 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: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
MINLINE void copy_v3_v3(float r[3], const float a[3])
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
#define CLAMP_MAX(a, c)
#define CLAMPIS(a, b, c)
#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
_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 width
a MemoryBuffer contains access to the data of a chunk
void update_memory_buffer_row(PixelCursor &p) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void update_memory_buffer_partial(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) final
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void determine_canvas(const rcti &preferred_area, rcti &r_area) override
virtual void update_memory_buffer_row(PixelCursor &p)
void set_use_value_alpha_multiply(const bool value)
void update_memory_buffer_row(PixelCursor &p) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void update_memory_buffer_row(PixelCursor &p) override
void update_memory_buffer_row(PixelCursor &p) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void update_memory_buffer_row(PixelCursor &p) override
void update_memory_buffer_row(PixelCursor &p) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void update_memory_buffer_row(PixelCursor &p) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void update_memory_buffer_row(PixelCursor &p) override
void update_memory_buffer_row(PixelCursor &p) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void update_memory_buffer_row(PixelCursor &p) override
void update_memory_buffer_row(PixelCursor &p) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void update_memory_buffer_row(PixelCursor &p) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void update_memory_buffer_row(PixelCursor &p) override
void update_memory_buffer_row(PixelCursor &p) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void update_memory_buffer_row(PixelCursor &p) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void update_memory_buffer_row(PixelCursor &p) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void update_memory_buffer_row(PixelCursor &p) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void update_memory_buffer_row(PixelCursor &p) override
void update_memory_buffer_row(PixelCursor &p) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
bool determine_canvas(const rcti &preferred_area, rcti &r_area)
void add_output_socket(DataType datatype)
SocketReader * get_input_socket_reader(unsigned int index)
NodeOperationInput * get_input_socket(unsigned int index)
void read_sampled(float result[4], float x, float y, PixelSampler sampler)
void add_input_socket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
void set_canvas_input_index(unsigned int index)
set the index of the input socket that will determine the canvas of this operation
virtual void determine_canvas(const rcti &preferred_area, rcti &r_area)
depth_tx sampler(1, ImageType::FLOAT_2D, "combined_tx") .sampler(2
ccl_global KernelShaderEvalInput ccl_global float * output
#define fabsf(x)
Definition: metal/compat.h:219
static void area(int d1, int d2, int e1, int e2, float weights[2])
constexpr rcti COM_AREA_NONE
Definition: COM_defines.h:112
static bNodeSocketTemplate inputs[]