Blender  V3.3
texture_image.c
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 
8 #include <fcntl.h>
9 #include <float.h>
10 #include <math.h>
11 #include <stdio.h>
12 #include <string.h>
13 #ifndef WIN32
14 # include <unistd.h>
15 #else
16 # include <io.h>
17 #endif
18 
19 #include "IMB_imbuf.h"
20 #include "IMB_imbuf_types.h"
21 
22 #include "DNA_image_types.h"
23 #include "DNA_scene_types.h"
24 #include "DNA_texture_types.h"
25 
26 #include "BLI_blenlib.h"
27 #include "BLI_math.h"
28 #include "BLI_threads.h"
29 #include "BLI_utildefines.h"
30 
31 #include "BKE_image.h"
32 
33 #include "RE_texture.h"
34 
35 #include "render_types.h"
36 #include "texture_common.h"
37 
38 static void boxsample(ImBuf *ibuf,
39  float minx,
40  float miny,
41  float maxx,
42  float maxy,
43  TexResult *texres,
44  const short imaprepeat,
45  const short imapextend);
46 
47 /* *********** IMAGEWRAPPING ****************** */
48 
49 /* x and y have to be checked for image size */
50 static void ibuf_get_color(float col[4], struct ImBuf *ibuf, int x, int y)
51 {
52  int ofs = y * ibuf->x + x;
53 
54  if (ibuf->rect_float) {
55  if (ibuf->channels == 4) {
56  const float *fp = ibuf->rect_float + 4 * ofs;
57  copy_v4_v4(col, fp);
58  }
59  else if (ibuf->channels == 3) {
60  const float *fp = ibuf->rect_float + 3 * ofs;
61  copy_v3_v3(col, fp);
62  col[3] = 1.0f;
63  }
64  else {
65  const float *fp = ibuf->rect_float + ofs;
66  col[0] = col[1] = col[2] = col[3] = *fp;
67  }
68  }
69  else {
70  const char *rect = (char *)(ibuf->rect + ofs);
71 
72  col[0] = ((float)rect[0]) * (1.0f / 255.0f);
73  col[1] = ((float)rect[1]) * (1.0f / 255.0f);
74  col[2] = ((float)rect[2]) * (1.0f / 255.0f);
75  col[3] = ((float)rect[3]) * (1.0f / 255.0f);
76 
77  /* bytes are internally straight, however render pipeline seems to expect premul */
78  col[0] *= col[3];
79  col[1] *= col[3];
80  col[2] *= col[3];
81  }
82 }
83 
85  Image *ima,
86  const float texvec[3],
87  TexResult *texres,
88  struct ImagePool *pool,
89  const bool skip_load_image)
90 {
91  float fx, fy;
92  int x, y, retval;
93  int xi, yi; /* original values */
94 
95  texres->tin = texres->trgba[3] = texres->trgba[0] = texres->trgba[1] = texres->trgba[2] = 0.0f;
96 
97  retval = TEX_RGB;
98 
99  /* quick tests */
100  if (ima == NULL) {
101  return retval;
102  }
103 
104  /* hack for icon render */
105  if (skip_load_image && !BKE_image_has_loaded_ibuf(ima)) {
106  return retval;
107  }
108 
109  ImageUser *iuser = &tex->iuser;
110  ImageUser local_iuser;
111  if (ima->source == IMA_SRC_TILED) {
112  /* tex->iuser might be shared by threads, so create a local copy. */
113  local_iuser = tex->iuser;
114  iuser = &local_iuser;
115 
116  float new_uv[2];
117  iuser->tile = BKE_image_get_tile_from_pos(ima, texvec, new_uv, NULL);
118  fx = new_uv[0];
119  fy = new_uv[1];
120  }
121  else {
122  fx = texvec[0];
123  fy = texvec[1];
124  }
125 
126  ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, iuser, pool);
127 
128  ima->flag |= IMA_USED_FOR_RENDER;
129 
130  if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) {
131  BKE_image_pool_release_ibuf(ima, ibuf, pool);
132  return retval;
133  }
134 
135  /* setup mapping */
136  if (tex->imaflag & TEX_IMAROT) {
137  SWAP(float, fx, fy);
138  }
139 
140  if (tex->extend == TEX_CHECKER) {
141  int xs, ys;
142 
143  xs = (int)floor(fx);
144  ys = (int)floor(fy);
145  fx -= xs;
146  fy -= ys;
147 
148  if ((tex->flag & TEX_CHECKER_ODD) == 0) {
149  if ((xs + ys) & 1) {
150  /* pass */
151  }
152  else {
153  if (ima) {
154  BKE_image_pool_release_ibuf(ima, ibuf, pool);
155  }
156  return retval;
157  }
158  }
159  if ((tex->flag & TEX_CHECKER_EVEN) == 0) {
160  if ((xs + ys) & 1) {
161  if (ima) {
162  BKE_image_pool_release_ibuf(ima, ibuf, pool);
163  }
164  return retval;
165  }
166  }
167  /* scale around center, (0.5, 0.5) */
168  if (tex->checkerdist < 1.0f) {
169  fx = (fx - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
170  fy = (fy - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
171  }
172  }
173 
174  x = xi = (int)floorf(fx * ibuf->x);
175  y = yi = (int)floorf(fy * ibuf->y);
176 
177  if (tex->extend == TEX_CLIPCUBE) {
178  if (x < 0 || y < 0 || x >= ibuf->x || y >= ibuf->y || texvec[2] < -1.0f || texvec[2] > 1.0f) {
179  if (ima) {
180  BKE_image_pool_release_ibuf(ima, ibuf, pool);
181  }
182  return retval;
183  }
184  }
185  else if (ELEM(tex->extend, TEX_CLIP, TEX_CHECKER)) {
186  if (x < 0 || y < 0 || x >= ibuf->x || y >= ibuf->y) {
187  if (ima) {
188  BKE_image_pool_release_ibuf(ima, ibuf, pool);
189  }
190  return retval;
191  }
192  }
193  else {
194  if (tex->extend == TEX_EXTEND) {
195  if (x >= ibuf->x) {
196  x = ibuf->x - 1;
197  }
198  else if (x < 0) {
199  x = 0;
200  }
201  }
202  else {
203  x = x % ibuf->x;
204  if (x < 0) {
205  x += ibuf->x;
206  }
207  }
208  if (tex->extend == TEX_EXTEND) {
209  if (y >= ibuf->y) {
210  y = ibuf->y - 1;
211  }
212  else if (y < 0) {
213  y = 0;
214  }
215  }
216  else {
217  y = y % ibuf->y;
218  if (y < 0) {
219  y += ibuf->y;
220  }
221  }
222  }
223 
224  /* Keep this before interpolation T29761. */
225  if (ima) {
226  if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) {
227  if ((tex->imaflag & TEX_CALCALPHA) == 0) {
228  texres->talpha = true;
229  }
230  }
231  }
232 
233  /* interpolate */
234  if (tex->imaflag & TEX_INTERPOL) {
235  float filterx, filtery;
236  filterx = (0.5f * tex->filtersize) / ibuf->x;
237  filtery = (0.5f * tex->filtersize) / ibuf->y;
238 
239  /* Important that this value is wrapped T27782.
240  * this applies the modifications made by the checks above,
241  * back to the floating point values */
242  fx -= (float)(xi - x) / (float)ibuf->x;
243  fy -= (float)(yi - y) / (float)ibuf->y;
244 
245  boxsample(ibuf,
246  fx - filterx,
247  fy - filtery,
248  fx + filterx,
249  fy + filtery,
250  texres,
251  (tex->extend == TEX_REPEAT),
252  (tex->extend == TEX_EXTEND));
253  }
254  else { /* no filtering */
255  ibuf_get_color(texres->trgba, ibuf, x, y);
256  }
257 
258  if (texres->talpha) {
259  texres->tin = texres->trgba[3];
260  }
261  else if (tex->imaflag & TEX_CALCALPHA) {
262  texres->trgba[3] = texres->tin = max_fff(texres->trgba[0], texres->trgba[1], texres->trgba[2]);
263  }
264  else {
265  texres->trgba[3] = texres->tin = 1.0;
266  }
267 
268  if (tex->flag & TEX_NEGALPHA) {
269  texres->trgba[3] = 1.0f - texres->trgba[3];
270  }
271 
272  /* de-premul, this is being pre-multiplied in shade_input_do_shade()
273  * do not de-premul for generated alpha, it is already in straight */
274  if (texres->trgba[3] != 1.0f && texres->trgba[3] > 1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
275  fx = 1.0f / texres->trgba[3];
276  texres->trgba[0] *= fx;
277  texres->trgba[1] *= fx;
278  texres->trgba[2] *= fx;
279  }
280 
281  if (ima) {
282  BKE_image_pool_release_ibuf(ima, ibuf, pool);
283  }
284 
285  BRICONTRGB;
286 
287  return retval;
288 }
289 
290 static void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2)
291 {
292  rctf *rf, *newrct;
293  short a;
294 
295  a = *count;
296  rf = stack;
297  for (; a > 0; a--) {
298  if (rf->xmin < x1) {
299  if (rf->xmax < x1) {
300  rf->xmin += (x2 - x1);
301  rf->xmax += (x2 - x1);
302  }
303  else {
304  if (rf->xmax > x2) {
305  rf->xmax = x2;
306  }
307  newrct = stack + *count;
308  (*count)++;
309 
310  newrct->xmax = x2;
311  newrct->xmin = rf->xmin + (x2 - x1);
312  newrct->ymin = rf->ymin;
313  newrct->ymax = rf->ymax;
314 
315  if (newrct->xmin == newrct->xmax) {
316  (*count)--;
317  }
318 
319  rf->xmin = x1;
320  }
321  }
322  else if (rf->xmax > x2) {
323  if (rf->xmin > x2) {
324  rf->xmin -= (x2 - x1);
325  rf->xmax -= (x2 - x1);
326  }
327  else {
328  if (rf->xmin < x1) {
329  rf->xmin = x1;
330  }
331  newrct = stack + *count;
332  (*count)++;
333 
334  newrct->xmin = x1;
335  newrct->xmax = rf->xmax - (x2 - x1);
336  newrct->ymin = rf->ymin;
337  newrct->ymax = rf->ymax;
338 
339  if (newrct->xmin == newrct->xmax) {
340  (*count)--;
341  }
342 
343  rf->xmax = x2;
344  }
345  }
346  rf++;
347  }
348 }
349 
350 static void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2)
351 {
352  rctf *rf, *newrct;
353  short a;
354 
355  a = *count;
356  rf = stack;
357  for (; a > 0; a--) {
358  if (rf->ymin < y1) {
359  if (rf->ymax < y1) {
360  rf->ymin += (y2 - y1);
361  rf->ymax += (y2 - y1);
362  }
363  else {
364  if (rf->ymax > y2) {
365  rf->ymax = y2;
366  }
367  newrct = stack + *count;
368  (*count)++;
369 
370  newrct->ymax = y2;
371  newrct->ymin = rf->ymin + (y2 - y1);
372  newrct->xmin = rf->xmin;
373  newrct->xmax = rf->xmax;
374 
375  if (newrct->ymin == newrct->ymax) {
376  (*count)--;
377  }
378 
379  rf->ymin = y1;
380  }
381  }
382  else if (rf->ymax > y2) {
383  if (rf->ymin > y2) {
384  rf->ymin -= (y2 - y1);
385  rf->ymax -= (y2 - y1);
386  }
387  else {
388  if (rf->ymin < y1) {
389  rf->ymin = y1;
390  }
391  newrct = stack + *count;
392  (*count)++;
393 
394  newrct->ymin = y1;
395  newrct->ymax = rf->ymax - (y2 - y1);
396  newrct->xmin = rf->xmin;
397  newrct->xmax = rf->xmax;
398 
399  if (newrct->ymin == newrct->ymax) {
400  (*count)--;
401  }
402 
403  rf->ymax = y2;
404  }
405  }
406  rf++;
407  }
408 }
409 
410 static float square_rctf(rctf *rf)
411 {
412  float x, y;
413 
414  x = BLI_rctf_size_x(rf);
415  y = BLI_rctf_size_y(rf);
416  return x * y;
417 }
418 
419 static float clipx_rctf(rctf *rf, float x1, float x2)
420 {
421  float size;
422 
423  size = BLI_rctf_size_x(rf);
424 
425  if (rf->xmin < x1) {
426  rf->xmin = x1;
427  }
428  if (rf->xmax > x2) {
429  rf->xmax = x2;
430  }
431  if (rf->xmin > rf->xmax) {
432  rf->xmin = rf->xmax;
433  return 0.0;
434  }
435  if (size != 0.0f) {
436  return BLI_rctf_size_x(rf) / size;
437  }
438  return 1.0;
439 }
440 
441 static float clipy_rctf(rctf *rf, float y1, float y2)
442 {
443  float size;
444 
445  size = BLI_rctf_size_y(rf);
446 
447  if (rf->ymin < y1) {
448  rf->ymin = y1;
449  }
450  if (rf->ymax > y2) {
451  rf->ymax = y2;
452  }
453 
454  if (rf->ymin > rf->ymax) {
455  rf->ymin = rf->ymax;
456  return 0.0;
457  }
458  if (size != 0.0f) {
459  return BLI_rctf_size_y(rf) / size;
460  }
461  return 1.0;
462 }
463 
464 static void boxsampleclip(struct ImBuf *ibuf, rctf *rf, TexResult *texres)
465 {
466  /* Sample box, is clipped already, and minx etc. have been set at ibuf size.
467  * Enlarge with anti-aliased edges of the pixels. */
468 
469  float muly, mulx, div, col[4];
470  int x, y, startx, endx, starty, endy;
471 
472  startx = (int)floor(rf->xmin);
473  endx = (int)floor(rf->xmax);
474  starty = (int)floor(rf->ymin);
475  endy = (int)floor(rf->ymax);
476 
477  if (startx < 0) {
478  startx = 0;
479  }
480  if (starty < 0) {
481  starty = 0;
482  }
483  if (endx >= ibuf->x) {
484  endx = ibuf->x - 1;
485  }
486  if (endy >= ibuf->y) {
487  endy = ibuf->y - 1;
488  }
489 
490  if (starty == endy && startx == endx) {
491  ibuf_get_color(texres->trgba, ibuf, startx, starty);
492  }
493  else {
494  div = texres->trgba[0] = texres->trgba[1] = texres->trgba[2] = texres->trgba[3] = 0.0;
495  for (y = starty; y <= endy; y++) {
496 
497  muly = 1.0;
498 
499  if (starty == endy) {
500  /* pass */
501  }
502  else {
503  if (y == starty) {
504  muly = 1.0f - (rf->ymin - y);
505  }
506  if (y == endy) {
507  muly = (rf->ymax - y);
508  }
509  }
510 
511  if (startx == endx) {
512  mulx = muly;
513 
514  ibuf_get_color(col, ibuf, startx, y);
515  madd_v4_v4fl(texres->trgba, col, mulx);
516  div += mulx;
517  }
518  else {
519  for (x = startx; x <= endx; x++) {
520  mulx = muly;
521  if (x == startx) {
522  mulx *= 1.0f - (rf->xmin - x);
523  }
524  if (x == endx) {
525  mulx *= (rf->xmax - x);
526  }
527 
528  ibuf_get_color(col, ibuf, x, y);
529  /* TODO(jbakker): No need to do manual optimization. Branching is slower than multiplying
530  * with 1. */
531  if (mulx == 1.0f) {
532  add_v4_v4(texres->trgba, col);
533  div += 1.0f;
534  }
535  else {
536  madd_v4_v4fl(texres->trgba, col, mulx);
537  div += mulx;
538  }
539  }
540  }
541  }
542 
543  if (div != 0.0f) {
544  div = 1.0f / div;
545  mul_v4_fl(texres->trgba, div);
546  }
547  else {
548  zero_v4(texres->trgba);
549  }
550  }
551 }
552 
553 static void boxsample(ImBuf *ibuf,
554  float minx,
555  float miny,
556  float maxx,
557  float maxy,
558  TexResult *texres,
559  const short imaprepeat,
560  const short imapextend)
561 {
562  /* Sample box, performs clip. minx etc are in range 0.0 - 1.0 .
563  * Enlarge with anti-aliased edges of pixels.
564  * If variable 'imaprepeat' has been set, the
565  * clipped-away parts are sampled as well.
566  */
567  /* NOTE: actually minx etc isn't in the proper range...
568  * this due to filter size and offset vectors for bump. */
569  /* NOTE: talpha must be initialized. */
570  /* NOTE: even when 'imaprepeat' is set, this can only repeat once in any direction.
571  * the point which min/max is derived from is assumed to be wrapped. */
572  TexResult texr;
573  rctf *rf, stack[8];
574  float opp, tot, alphaclip = 1.0;
575  short count = 1;
576 
577  rf = stack;
578  rf->xmin = minx * (ibuf->x);
579  rf->xmax = maxx * (ibuf->x);
580  rf->ymin = miny * (ibuf->y);
581  rf->ymax = maxy * (ibuf->y);
582 
583  texr.talpha = texres->talpha; /* is read by boxsample_clip */
584 
585  if (imapextend) {
586  CLAMP(rf->xmin, 0.0f, ibuf->x - 1);
587  CLAMP(rf->xmax, 0.0f, ibuf->x - 1);
588  }
589  else if (imaprepeat) {
590  clipx_rctf_swap(stack, &count, 0.0, (float)(ibuf->x));
591  }
592  else {
593  alphaclip = clipx_rctf(rf, 0.0, (float)(ibuf->x));
594 
595  if (alphaclip <= 0.0f) {
596  texres->trgba[0] = texres->trgba[2] = texres->trgba[1] = texres->trgba[3] = 0.0;
597  return;
598  }
599  }
600 
601  if (imapextend) {
602  CLAMP(rf->ymin, 0.0f, ibuf->y - 1);
603  CLAMP(rf->ymax, 0.0f, ibuf->y - 1);
604  }
605  else if (imaprepeat) {
606  clipy_rctf_swap(stack, &count, 0.0, (float)(ibuf->y));
607  }
608  else {
609  alphaclip *= clipy_rctf(rf, 0.0, (float)(ibuf->y));
610 
611  if (alphaclip <= 0.0f) {
612  texres->trgba[0] = texres->trgba[2] = texres->trgba[1] = texres->trgba[3] = 0.0;
613  return;
614  }
615  }
616 
617  if (count > 1) {
618  tot = texres->trgba[0] = texres->trgba[2] = texres->trgba[1] = texres->trgba[3] = 0.0;
619  while (count--) {
620  boxsampleclip(ibuf, rf, &texr);
621 
622  opp = square_rctf(rf);
623  tot += opp;
624 
625  texres->trgba[0] += opp * texr.trgba[0];
626  texres->trgba[1] += opp * texr.trgba[1];
627  texres->trgba[2] += opp * texr.trgba[2];
628  if (texres->talpha) {
629  texres->trgba[3] += opp * texr.trgba[3];
630  }
631  rf++;
632  }
633  if (tot != 0.0f) {
634  texres->trgba[0] /= tot;
635  texres->trgba[1] /= tot;
636  texres->trgba[2] /= tot;
637  if (texres->talpha) {
638  texres->trgba[3] /= tot;
639  }
640  }
641  }
642  else {
643  boxsampleclip(ibuf, rf, texres);
644  }
645 
646  if (texres->talpha == 0) {
647  texres->trgba[3] = 1.0;
648  }
649 
650  if (alphaclip != 1.0f) {
651  /* premul it all */
652  texres->trgba[0] *= alphaclip;
653  texres->trgba[1] *= alphaclip;
654  texres->trgba[2] *= alphaclip;
655  texres->trgba[3] *= alphaclip;
656  }
657 }
658 
659 /* -------------------------------------------------------------------- */
660 /* from here, some functions only used for the new filtering */
661 
662 /* anisotropic filters, data struct used instead of long line of (possibly unused) func args */
663 typedef struct afdata_t {
664  float dxt[2], dyt[2];
666  /* feline only */
667  float majrad, minrad, theta;
668  int iProbes;
669  float dusc, dvsc;
671 
672 /* this only used here to make it easier to pass extend flags as single int */
674 
679 static int ibuf_get_color_clip(float col[4], ImBuf *ibuf, int x, int y, int extflag)
680 {
681  int clip = 0;
682  switch (extflag) {
683  case TXC_XMIR: /* y rep */
684  x %= 2 * ibuf->x;
685  x += x < 0 ? 2 * ibuf->x : 0;
686  x = x >= ibuf->x ? 2 * ibuf->x - x - 1 : x;
687  y %= ibuf->y;
688  y += y < 0 ? ibuf->y : 0;
689  break;
690  case TXC_YMIR: /* x rep */
691  x %= ibuf->x;
692  x += x < 0 ? ibuf->x : 0;
693  y %= 2 * ibuf->y;
694  y += y < 0 ? 2 * ibuf->y : 0;
695  y = y >= ibuf->y ? 2 * ibuf->y - y - 1 : y;
696  break;
697  case TXC_EXTD:
698  x = (x < 0) ? 0 : ((x >= ibuf->x) ? (ibuf->x - 1) : x);
699  y = (y < 0) ? 0 : ((y >= ibuf->y) ? (ibuf->y - 1) : y);
700  break;
701  case TXC_REPT:
702  x %= ibuf->x;
703  x += (x < 0) ? ibuf->x : 0;
704  y %= ibuf->y;
705  y += (y < 0) ? ibuf->y : 0;
706  break;
707  default: { /* as extend, if clipped, set alpha to 0.0 */
708  if (x < 0) {
709  x = 0;
710  } /* TXF alpha: clip = 1; } */
711  if (x >= ibuf->x) {
712  x = ibuf->x - 1;
713  } /* TXF alpha: clip = 1; } */
714  if (y < 0) {
715  y = 0;
716  } /* TXF alpha: clip = 1; } */
717  if (y >= ibuf->y) {
718  y = ibuf->y - 1;
719  } /* TXF alpha: clip = 1; } */
720  }
721  }
722 
723  if (ibuf->rect_float) {
724  const float *fp = ibuf->rect_float + (x + y * ibuf->x) * ibuf->channels;
725  if (ibuf->channels == 1) {
726  col[0] = col[1] = col[2] = col[3] = *fp;
727  }
728  else {
729  col[0] = fp[0];
730  col[1] = fp[1];
731  col[2] = fp[2];
732  col[3] = clip ? 0.0f : (ibuf->channels == 4 ? fp[3] : 1.0f);
733  }
734  }
735  else {
736  const char *rect = (char *)(ibuf->rect + x + y * ibuf->x);
737  float inv_alpha_fac = (1.0f / 255.0f) * rect[3] * (1.0f / 255.0f);
738  col[0] = rect[0] * inv_alpha_fac;
739  col[1] = rect[1] * inv_alpha_fac;
740  col[2] = rect[2] * inv_alpha_fac;
741  col[3] = clip ? 0.0f : rect[3] * (1.0f / 255.0f);
742  }
743  return clip;
744 }
745 
746 /* as above + bilerp */
748  float col[4], ImBuf *ibuf, float u, float v, int intpol, int extflag)
749 {
750  if (intpol) {
751  float c00[4], c01[4], c10[4], c11[4];
752  const float ufl = floorf(u -= 0.5f), vfl = floorf(v -= 0.5f);
753  const float uf = u - ufl, vf = v - vfl;
754  const float w00 = (1.0f - uf) * (1.0f - vf), w10 = uf * (1.0f - vf), w01 = (1.0f - uf) * vf,
755  w11 = uf * vf;
756  const int x1 = (int)ufl, y1 = (int)vfl, x2 = x1 + 1, y2 = y1 + 1;
757  int clip = ibuf_get_color_clip(c00, ibuf, x1, y1, extflag);
758  clip |= ibuf_get_color_clip(c10, ibuf, x2, y1, extflag);
759  clip |= ibuf_get_color_clip(c01, ibuf, x1, y2, extflag);
760  clip |= ibuf_get_color_clip(c11, ibuf, x2, y2, extflag);
761  col[0] = w00 * c00[0] + w10 * c10[0] + w01 * c01[0] + w11 * c11[0];
762  col[1] = w00 * c00[1] + w10 * c10[1] + w01 * c01[1] + w11 * c11[1];
763  col[2] = w00 * c00[2] + w10 * c10[2] + w01 * c01[2] + w11 * c11[2];
764  col[3] = clip ? 0.0f : w00 * c00[3] + w10 * c10[3] + w01 * c01[3] + w11 * c11[3];
765  return clip;
766  }
767  return ibuf_get_color_clip(col, ibuf, (int)u, (int)v, extflag);
768 }
769 
770 static void area_sample(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
771 {
772  int xs, ys, clip = 0;
773  float tc[4], xsd, ysd, cw = 0.0f;
774  const float ux = ibuf->x * AFD->dxt[0], uy = ibuf->y * AFD->dxt[1];
775  const float vx = ibuf->x * AFD->dyt[0], vy = ibuf->y * AFD->dyt[1];
776  int xsam = (int)(0.5f * sqrtf(ux * ux + uy * uy) + 0.5f);
777  int ysam = (int)(0.5f * sqrtf(vx * vx + vy * vy) + 0.5f);
778  const int minsam = AFD->intpol ? 2 : 4;
779  xsam = CLAMPIS(xsam, minsam, ibuf->x * 2);
780  ysam = CLAMPIS(ysam, minsam, ibuf->y * 2);
781  xsd = 1.0f / xsam;
782  ysd = 1.0f / ysam;
783  texr->trgba[0] = texr->trgba[1] = texr->trgba[2] = texr->trgba[3] = 0.0f;
784  for (ys = 0; ys < ysam; ys++) {
785  for (xs = 0; xs < xsam; xs++) {
786  const float su = (xs + ((ys & 1) + 0.5f) * 0.5f) * xsd - 0.5f;
787  const float sv = (ys + ((xs & 1) + 0.5f) * 0.5f) * ysd - 0.5f;
788  const float pu = fx + su * AFD->dxt[0] + sv * AFD->dyt[0];
789  const float pv = fy + su * AFD->dxt[1] + sv * AFD->dyt[1];
790  const int out = ibuf_get_color_clip_bilerp(
791  tc, ibuf, pu * ibuf->x, pv * ibuf->y, AFD->intpol, AFD->extflag);
792  clip |= out;
793  cw += out ? 0.0f : 1.0f;
794  texr->trgba[0] += tc[0];
795  texr->trgba[1] += tc[1];
796  texr->trgba[2] += tc[2];
797  texr->trgba[3] += texr->talpha ? tc[3] : 0.0f;
798  }
799  }
800  xsd *= ysd;
801  texr->trgba[0] *= xsd;
802  texr->trgba[1] *= xsd;
803  texr->trgba[2] *= xsd;
804  /* clipping can be ignored if alpha used, texr->trgba[3] already includes filtered edge */
805  texr->trgba[3] = texr->talpha ? texr->trgba[3] * xsd : (clip ? cw * xsd : 1.0f);
806 }
807 
808 typedef struct ReadEWAData {
812 
813 static void ewa_read_pixel_cb(void *userdata, int x, int y, float result[4])
814 {
815  ReadEWAData *data = (ReadEWAData *)userdata;
816  ibuf_get_color_clip(result, data->ibuf, x, y, data->AFD->extflag);
817 }
818 
819 static void ewa_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
820 {
822  const float uv[2] = {fx, fy};
823  data.ibuf = ibuf;
824  data.AFD = AFD;
825  BLI_ewa_filter(ibuf->x,
826  ibuf->y,
827  AFD->intpol != 0,
828  texr->talpha,
829  uv,
830  AFD->dxt,
831  AFD->dyt,
833  &data,
834  texr->trgba);
835 }
836 
837 static void feline_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
838 {
839  const int maxn = AFD->iProbes - 1;
840  const float ll = ((AFD->majrad == AFD->minrad) ? 2.0f * AFD->majrad :
841  2.0f * (AFD->majrad - AFD->minrad)) /
842  (maxn ? (float)maxn : 1.0f);
843  float du = maxn ? cosf(AFD->theta) * ll : 0.0f;
844  float dv = maxn ? sinf(AFD->theta) * ll : 0.0f;
845  // const float D = -0.5f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad);
846  const float D = (EWA_MAXIDX + 1) * 0.25f * (du * du + dv * dv) / (AFD->majrad * AFD->majrad);
847  float d; /* TXF alpha: cw = 0.0f; */
848  int n; /* TXF alpha: clip = 0; */
849  /* have to use same scaling for du/dv here as for Ux/Vx/Uy/Vy (*after* D calc.) */
850  du *= AFD->dusc;
851  dv *= AFD->dvsc;
852  d = texr->trgba[0] = texr->trgba[2] = texr->trgba[1] = texr->trgba[3] = 0.0f;
853  for (n = -maxn; n <= maxn; n += 2) {
854  float tc[4];
855  const float hn = n * 0.5f;
856  const float u = fx + hn * du, v = fy + hn * dv;
857  /* Can use ewa table here too. */
858 #if 0
859  const float wt = expf(n * n * D);
860 #else
861  const float wt = EWA_WTS[(int)(n * n * D)];
862 #endif
863  /* `const int out =` */ ibuf_get_color_clip_bilerp(
864  tc, ibuf, ibuf->x * u, ibuf->y * v, AFD->intpol, AFD->extflag);
865  /* TXF alpha: `clip |= out;`
866  * TXF alpha: `cw += out ? 0.0f : wt;` */
867  texr->trgba[0] += tc[0] * wt;
868  texr->trgba[1] += tc[1] * wt;
869  texr->trgba[2] += tc[2] * wt;
870  texr->trgba[3] += texr->talpha ? tc[3] * wt : 0.0f;
871  d += wt;
872  }
873 
874  d = 1.0f / d;
875  texr->trgba[0] *= d;
876  texr->trgba[1] *= d;
877  texr->trgba[2] *= d;
878  /* Clipping can be ignored if alpha used, `texr->trgba[3]` already includes filtered edge */
879  texr->trgba[3] = texr->talpha ? texr->trgba[3] * d :
880  1.0f; /* TXF alpha: `(clip ? cw*d : 1.0f);` */
881 }
882 #undef EWA_MAXIDX
883 
884 static void alpha_clip_aniso(
885  ImBuf *ibuf, float minx, float miny, float maxx, float maxy, int extflag, TexResult *texres)
886 {
887  float alphaclip;
888  rctf rf;
889 
890  /* TXF alpha: we're doing the same alpha-clip here as box-sample, but I'm doubting
891  * if this is actually correct for the all the filtering algorithms. */
892 
893  if (!(ELEM(extflag, TXC_REPT, TXC_EXTD))) {
894  rf.xmin = minx * (ibuf->x);
895  rf.xmax = maxx * (ibuf->x);
896  rf.ymin = miny * (ibuf->y);
897  rf.ymax = maxy * (ibuf->y);
898 
899  alphaclip = clipx_rctf(&rf, 0.0, (float)(ibuf->x));
900  alphaclip *= clipy_rctf(&rf, 0.0, (float)(ibuf->y));
901  alphaclip = max_ff(alphaclip, 0.0f);
902 
903  if (alphaclip != 1.0f) {
904  /* premul it all */
905  texres->trgba[0] *= alphaclip;
906  texres->trgba[1] *= alphaclip;
907  texres->trgba[2] *= alphaclip;
908  texres->trgba[3] *= alphaclip;
909  }
910  }
911 }
912 
913 static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
914 {
915  if (tex->imaflag & TEX_MIPMAP) {
916  if (ibuf->mipmap[0] && (ibuf->userflags & IB_MIPMAP_INVALID)) {
918  if (ibuf->userflags & IB_MIPMAP_INVALID) {
920  ibuf->userflags &= ~IB_MIPMAP_INVALID;
921  }
923  }
924  if (ibuf->mipmap[0] == NULL) {
926  if (ibuf->mipmap[0] == NULL) {
928  }
930  }
931  /* if no mipmap could be made, fall back on non-mipmap render */
932  if (ibuf->mipmap[0] == NULL) {
933  tex->imaflag &= ~TEX_MIPMAP;
934  }
935  }
936 }
937 
939  Image *ima,
940  ImBuf *ibuf,
941  const float texvec[3],
942  float dxt[2],
943  float dyt[2],
944  TexResult *texres,
945  struct ImagePool *pool,
946  const bool skip_load_image)
947 {
948  TexResult texr;
949  float fx, fy, minx, maxx, miny, maxy;
950  float maxd;
951  int curmap, retval, intpol, extflag = 0;
952  afdata_t AFD;
953 
954  void (*filterfunc)(TexResult *, ImBuf *, float, float, afdata_t *);
955  switch (tex->texfilter) {
956  case TXF_EWA:
957  filterfunc = ewa_eval;
958  break;
959  case TXF_FELINE:
960  filterfunc = feline_eval;
961  break;
962  case TXF_AREA:
963  default:
964  filterfunc = area_sample;
965  }
966 
967  texres->tin = texres->trgba[3] = texres->trgba[0] = texres->trgba[1] = texres->trgba[2] = 0.0f;
968 
969  retval = TEX_RGB;
970 
971  /* quick tests */
972  if (ibuf == NULL && ima == NULL) {
973  return retval;
974  }
975 
976  if (ima) { /* hack for icon render */
977  if (skip_load_image && !BKE_image_has_loaded_ibuf(ima)) {
978  return retval;
979  }
980  ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
981  }
982 
983  if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) {
984  if (ima) {
985  BKE_image_pool_release_ibuf(ima, ibuf, pool);
986  }
987  return retval;
988  }
989 
990  if (ima) {
991  ima->flag |= IMA_USED_FOR_RENDER;
992  }
993 
994  /* mipmap test */
995  image_mipmap_test(tex, ibuf);
996 
997  if (ima) {
998  if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) {
999  if ((tex->imaflag & TEX_CALCALPHA) == 0) {
1000  texres->talpha = true;
1001  }
1002  }
1003  }
1004  texr.talpha = texres->talpha;
1005 
1006  if (tex->imaflag & TEX_IMAROT) {
1007  fy = texvec[0];
1008  fx = texvec[1];
1009  }
1010  else {
1011  fx = texvec[0];
1012  fy = texvec[1];
1013  }
1014 
1015  /* pixel coordinates */
1016  minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
1017  maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
1018  miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
1019  maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
1020 
1021  /* tex_sharper has been removed */
1022  minx = (maxx - minx) * 0.5f;
1023  miny = (maxy - miny) * 0.5f;
1024 
1025  if (tex->imaflag & TEX_FILTER_MIN) {
1026  /* Make sure the filtersize is minimal in pixels
1027  * (normal, ref map can have miniature pixel dx/dy). */
1028  const float addval = (0.5f * tex->filtersize) / (float)MIN2(ibuf->x, ibuf->y);
1029  if (addval > minx) {
1030  minx = addval;
1031  }
1032  if (addval > miny) {
1033  miny = addval;
1034  }
1035  }
1036  else if (tex->filtersize != 1.0f) {
1037  minx *= tex->filtersize;
1038  miny *= tex->filtersize;
1039  dxt[0] *= tex->filtersize;
1040  dxt[1] *= tex->filtersize;
1041  dyt[0] *= tex->filtersize;
1042  dyt[1] *= tex->filtersize;
1043  }
1044 
1045  if (tex->imaflag & TEX_IMAROT) {
1046  float t;
1047  SWAP(float, minx, miny);
1048  /* must rotate dxt/dyt 90 deg
1049  * yet another blender problem is that swapping X/Y axes (or any tex projection switches)
1050  * should do something similar, but it doesn't, it only swaps coords,
1051  * so filter area will be incorrect in those cases. */
1052  t = dxt[0];
1053  dxt[0] = dxt[1];
1054  dxt[1] = -t;
1055  t = dyt[0];
1056  dyt[0] = dyt[1];
1057  dyt[1] = -t;
1058  }
1059 
1060  /* side faces of unit-cube */
1061  minx = (minx > 0.25f) ? 0.25f : ((minx < 1e-5f) ? 1e-5f : minx);
1062  miny = (miny > 0.25f) ? 0.25f : ((miny < 1e-5f) ? 1e-5f : miny);
1063 
1064  /* repeat and clip */
1065 
1066  if (tex->extend == TEX_REPEAT) {
1068  extflag = TXC_EXTD;
1069  }
1070  else if (tex->flag & TEX_REPEAT_XMIR) {
1071  extflag = TXC_XMIR;
1072  }
1073  else if (tex->flag & TEX_REPEAT_YMIR) {
1074  extflag = TXC_YMIR;
1075  }
1076  else {
1077  extflag = TXC_REPT;
1078  }
1079  }
1080  else if (tex->extend == TEX_EXTEND) {
1081  extflag = TXC_EXTD;
1082  }
1083 
1084  if (tex->extend == TEX_CHECKER) {
1085  int xs = (int)floorf(fx), ys = (int)floorf(fy);
1086  /* both checkers available, no boundary exceptions, checkerdist will eat aliasing */
1087  if ((tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN)) {
1088  fx -= xs;
1089  fy -= ys;
1090  }
1091  else if ((tex->flag & TEX_CHECKER_ODD) == 0 && (tex->flag & TEX_CHECKER_EVEN) == 0) {
1092  if (ima) {
1093  BKE_image_pool_release_ibuf(ima, ibuf, pool);
1094  }
1095  return retval;
1096  }
1097  else {
1098  int xs1 = (int)floorf(fx - minx);
1099  int ys1 = (int)floorf(fy - miny);
1100  int xs2 = (int)floorf(fx + minx);
1101  int ys2 = (int)floorf(fy + miny);
1102  if ((xs1 != xs2) || (ys1 != ys2)) {
1103  if (tex->flag & TEX_CHECKER_ODD) {
1104  fx -= ((xs1 + ys) & 1) ? xs2 : xs1;
1105  fy -= ((ys1 + xs) & 1) ? ys2 : ys1;
1106  }
1107  if (tex->flag & TEX_CHECKER_EVEN) {
1108  fx -= ((xs1 + ys) & 1) ? xs1 : xs2;
1109  fy -= ((ys1 + xs) & 1) ? ys1 : ys2;
1110  }
1111  }
1112  else {
1113  if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) {
1114  if (ima) {
1115  BKE_image_pool_release_ibuf(ima, ibuf, pool);
1116  }
1117  return retval;
1118  }
1119  if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) {
1120  if (ima) {
1121  BKE_image_pool_release_ibuf(ima, ibuf, pool);
1122  }
1123  return retval;
1124  }
1125  fx -= xs;
1126  fy -= ys;
1127  }
1128  }
1129  /* scale around center, (0.5, 0.5) */
1130  if (tex->checkerdist < 1.0f) {
1131  const float omcd = 1.0f / (1.0f - tex->checkerdist);
1132  fx = (fx - 0.5f) * omcd + 0.5f;
1133  fy = (fy - 0.5f) * omcd + 0.5f;
1134  minx *= omcd;
1135  miny *= omcd;
1136  }
1137  }
1138 
1139  if (tex->extend == TEX_CLIPCUBE) {
1140  if ((fx + minx) < 0.0f || (fy + miny) < 0.0f || (fx - minx) > 1.0f || (fy - miny) > 1.0f ||
1141  texvec[2] < -1.0f || texvec[2] > 1.0f) {
1142  if (ima) {
1143  BKE_image_pool_release_ibuf(ima, ibuf, pool);
1144  }
1145  return retval;
1146  }
1147  }
1148  else if (ELEM(tex->extend, TEX_CLIP, TEX_CHECKER)) {
1149  if ((fx + minx) < 0.0f || (fy + miny) < 0.0f || (fx - minx) > 1.0f || (fy - miny) > 1.0f) {
1150  if (ima) {
1151  BKE_image_pool_release_ibuf(ima, ibuf, pool);
1152  }
1153  return retval;
1154  }
1155  }
1156  else {
1157  if (tex->extend == TEX_EXTEND) {
1158  fx = (fx > 1.0f) ? 1.0f : ((fx < 0.0f) ? 0.0f : fx);
1159  fy = (fy > 1.0f) ? 1.0f : ((fy < 0.0f) ? 0.0f : fy);
1160  }
1161  else {
1162  fx -= floorf(fx);
1163  fy -= floorf(fy);
1164  }
1165  }
1166 
1167  intpol = tex->imaflag & TEX_INTERPOL;
1168 
1169  /* struct common data */
1170  copy_v2_v2(AFD.dxt, dxt);
1171  copy_v2_v2(AFD.dyt, dyt);
1172  AFD.intpol = intpol;
1173  AFD.extflag = extflag;
1174 
1175  /* NOTE(@brecht): added stupid clamping here, large dx/dy can give very large
1176  * filter sizes which take ages to render, it may be better to do this
1177  * more intelligently later in the code .. probably it's not noticeable */
1178  if (AFD.dxt[0] * AFD.dxt[0] + AFD.dxt[1] * AFD.dxt[1] > 2.0f * 2.0f) {
1179  mul_v2_fl(AFD.dxt, 2.0f / len_v2(AFD.dxt));
1180  }
1181  if (AFD.dyt[0] * AFD.dyt[0] + AFD.dyt[1] * AFD.dyt[1] > 2.0f * 2.0f) {
1182  mul_v2_fl(AFD.dyt, 2.0f / len_v2(AFD.dyt));
1183  }
1184 
1185  /* choice: */
1186  if (tex->imaflag & TEX_MIPMAP) {
1187  ImBuf *previbuf, *curibuf;
1188  float levf;
1189  int maxlev;
1190  ImBuf *mipmaps[IMB_MIPMAP_LEVELS + 1];
1191 
1192  /* Modify ellipse minor axis if too eccentric, use for area sampling as well
1193  * scaling `dxt/dyt` as done in PBRT is not the same
1194  * (as in `ewa_eval()`, scale by `sqrt(ibuf->x)` to maximize precision). */
1195  const float ff = sqrtf(ibuf->x), q = ibuf->y / ff;
1196  const float Ux = dxt[0] * ff, Vx = dxt[1] * q, Uy = dyt[0] * ff, Vy = dyt[1] * q;
1197  const float A = Vx * Vx + Vy * Vy;
1198  const float B = -2.0f * (Ux * Vx + Uy * Vy);
1199  const float C = Ux * Ux + Uy * Uy;
1200  const float F = A * C - B * B * 0.25f;
1201  float a, b, th, ecc;
1202  BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
1203  if (tex->texfilter == TXF_FELINE) {
1204  float fProbes;
1205  a *= ff;
1206  b *= ff;
1207  a = max_ff(a, 1.0f);
1208  b = max_ff(b, 1.0f);
1209  fProbes = 2.0f * (a / b) - 1.0f;
1210  AFD.iProbes = round_fl_to_int(fProbes);
1211  AFD.iProbes = MIN2(AFD.iProbes, tex->afmax);
1212  if (AFD.iProbes < fProbes) {
1213  b = 2.0f * a / (float)(AFD.iProbes + 1);
1214  }
1215  AFD.majrad = a / ff;
1216  AFD.minrad = b / ff;
1217  AFD.theta = th;
1218  AFD.dusc = 1.0f / ff;
1219  AFD.dvsc = ff / (float)ibuf->y;
1220  }
1221  else { /* EWA & area */
1222  if (ecc > (float)tex->afmax) {
1223  b = a / (float)tex->afmax;
1224  }
1225  b *= ff;
1226  }
1227  maxd = max_ff(b, 1e-8f);
1228  levf = ((float)M_LOG2E) * logf(maxd);
1229 
1230  curmap = 0;
1231  maxlev = 1;
1232  mipmaps[0] = ibuf;
1233  while (curmap < IMB_MIPMAP_LEVELS) {
1234  mipmaps[curmap + 1] = ibuf->mipmap[curmap];
1235  if (ibuf->mipmap[curmap]) {
1236  maxlev++;
1237  }
1238  curmap++;
1239  }
1240 
1241  /* mipmap level */
1242  if (levf < 0.0f) { /* original image only */
1243  previbuf = curibuf = mipmaps[0];
1244  levf = 0.0f;
1245  }
1246  else if (levf >= maxlev - 1) {
1247  previbuf = curibuf = mipmaps[maxlev - 1];
1248  levf = 0.0f;
1249  if (tex->texfilter == TXF_FELINE) {
1250  AFD.iProbes = 1;
1251  }
1252  }
1253  else {
1254  const int lev = isnan(levf) ? 0 : (int)levf;
1255  curibuf = mipmaps[lev];
1256  previbuf = mipmaps[lev + 1];
1257  levf -= floorf(levf);
1258  }
1259 
1260  /* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */
1261  filterfunc(texres, curibuf, fx, fy, &AFD);
1262  if (previbuf != curibuf) { /* interpolate */
1263  filterfunc(&texr, previbuf, fx, fy, &AFD);
1264  texres->trgba[0] += levf * (texr.trgba[0] - texres->trgba[0]);
1265  texres->trgba[1] += levf * (texr.trgba[1] - texres->trgba[1]);
1266  texres->trgba[2] += levf * (texr.trgba[2] - texres->trgba[2]);
1267  texres->trgba[3] += levf * (texr.trgba[3] - texres->trgba[3]);
1268  }
1269 
1270  if (tex->texfilter != TXF_EWA) {
1271  alpha_clip_aniso(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, extflag, texres);
1272  }
1273  }
1274  else { /* no mipmap */
1275  /* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */
1276  if (tex->texfilter == TXF_FELINE) {
1277  const float ff = sqrtf(ibuf->x), q = ibuf->y / ff;
1278  const float Ux = dxt[0] * ff, Vx = dxt[1] * q, Uy = dyt[0] * ff, Vy = dyt[1] * q;
1279  const float A = Vx * Vx + Vy * Vy;
1280  const float B = -2.0f * (Ux * Vx + Uy * Vy);
1281  const float C = Ux * Ux + Uy * Uy;
1282  const float F = A * C - B * B * 0.25f;
1283  float a, b, th, ecc, fProbes;
1284  BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
1285  a *= ff;
1286  b *= ff;
1287  a = max_ff(a, 1.0f);
1288  b = max_ff(b, 1.0f);
1289  fProbes = 2.0f * (a / b) - 1.0f;
1290  /* no limit to number of Probes here */
1291  AFD.iProbes = round_fl_to_int(fProbes);
1292  if (AFD.iProbes < fProbes) {
1293  b = 2.0f * a / (float)(AFD.iProbes + 1);
1294  }
1295  AFD.majrad = a / ff;
1296  AFD.minrad = b / ff;
1297  AFD.theta = th;
1298  AFD.dusc = 1.0f / ff;
1299  AFD.dvsc = ff / (float)ibuf->y;
1300  }
1301  filterfunc(texres, ibuf, fx, fy, &AFD);
1302  if (tex->texfilter != TXF_EWA) {
1303  alpha_clip_aniso(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, extflag, texres);
1304  }
1305  }
1306 
1307  if (tex->imaflag & TEX_CALCALPHA) {
1308  texres->trgba[3] = texres->tin = texres->trgba[3] *
1309  max_fff(texres->trgba[0], texres->trgba[1], texres->trgba[2]);
1310  }
1311  else {
1312  texres->tin = texres->trgba[3];
1313  }
1314  if (tex->flag & TEX_NEGALPHA) {
1315  texres->trgba[3] = 1.0f - texres->trgba[3];
1316  }
1317 
1318  /* de-premul, this is being pre-multiplied in shade_input_do_shade()
1319  * TXF: this currently does not (yet?) work properly, destroys edge AA in clip/checker mode,
1320  * so for now commented out also disabled in imagewraposa()
1321  * to be able to compare results with blender's default texture filtering */
1322 
1323  /* brecht: tried to fix this, see "TXF alpha" comments */
1324 
1325  /* do not de-premul for generated alpha, it is already in straight */
1326  if (texres->trgba[3] != 1.0f && texres->trgba[3] > 1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
1327  fx = 1.0f / texres->trgba[3];
1328  texres->trgba[0] *= fx;
1329  texres->trgba[1] *= fx;
1330  texres->trgba[2] *= fx;
1331  }
1332 
1333  if (ima) {
1334  BKE_image_pool_release_ibuf(ima, ibuf, pool);
1335  }
1336 
1337  BRICONTRGB;
1338 
1339  return retval;
1340 }
1341 
1343  Image *ima,
1344  ImBuf *ibuf,
1345  const float texvec[3],
1346  const float DXT[2],
1347  const float DYT[2],
1348  TexResult *texres,
1349  struct ImagePool *pool,
1350  const bool skip_load_image)
1351 {
1352  TexResult texr;
1353  float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[2], dyt[2];
1354  float maxd, pixsize;
1355  int curmap, retval, imaprepeat, imapextend;
1356 
1357  /* TXF: since dxt/dyt might be modified here and since they might be needed after imagewraposa()
1358  * call, make a local copy here so that original vecs remain untouched. */
1359  copy_v2_v2(dxt, DXT);
1360  copy_v2_v2(dyt, DYT);
1361 
1362  /* anisotropic filtering */
1363  if (tex->texfilter != TXF_BOX) {
1364  return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres, pool, skip_load_image);
1365  }
1366 
1367  texres->tin = texres->trgba[3] = texres->trgba[0] = texres->trgba[1] = texres->trgba[2] = 0.0f;
1368 
1369  retval = TEX_RGB;
1370 
1371  /* quick tests */
1372  if (ibuf == NULL && ima == NULL) {
1373  return retval;
1374  }
1375  if (ima) {
1376 
1377  /* hack for icon render */
1378  if (skip_load_image && !BKE_image_has_loaded_ibuf(ima)) {
1379  return retval;
1380  }
1381 
1382  ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
1383 
1384  ima->flag |= IMA_USED_FOR_RENDER;
1385  }
1386  if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) {
1387  if (ima) {
1388  BKE_image_pool_release_ibuf(ima, ibuf, pool);
1389  }
1390  return retval;
1391  }
1392 
1393  /* mipmap test */
1394  image_mipmap_test(tex, ibuf);
1395 
1396  if (ima) {
1397  if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) {
1398  if ((tex->imaflag & TEX_CALCALPHA) == 0) {
1399  texres->talpha = true;
1400  }
1401  }
1402  }
1403 
1404  texr.talpha = texres->talpha;
1405 
1406  if (tex->imaflag & TEX_IMAROT) {
1407  fy = texvec[0];
1408  fx = texvec[1];
1409  }
1410  else {
1411  fx = texvec[0];
1412  fy = texvec[1];
1413  }
1414 
1415  /* pixel coordinates */
1416 
1417  minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
1418  maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
1419  miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
1420  maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
1421 
1422  /* tex_sharper has been removed */
1423  minx = (maxx - minx) / 2.0f;
1424  miny = (maxy - miny) / 2.0f;
1425 
1426  if (tex->imaflag & TEX_FILTER_MIN) {
1427  /* Make sure the filtersize is minimal in pixels
1428  * (normal, ref map can have miniature pixel dx/dy). */
1429  float addval = (0.5f * tex->filtersize) / (float)MIN2(ibuf->x, ibuf->y);
1430 
1431  if (addval > minx) {
1432  minx = addval;
1433  }
1434  if (addval > miny) {
1435  miny = addval;
1436  }
1437  }
1438  else if (tex->filtersize != 1.0f) {
1439  minx *= tex->filtersize;
1440  miny *= tex->filtersize;
1441 
1442  dxt[0] *= tex->filtersize;
1443  dxt[1] *= tex->filtersize;
1444  dyt[0] *= tex->filtersize;
1445  dyt[1] *= tex->filtersize;
1446  }
1447 
1448  if (tex->imaflag & TEX_IMAROT) {
1449  SWAP(float, minx, miny);
1450  }
1451 
1452  if (minx > 0.25f) {
1453  minx = 0.25f;
1454  }
1455  else if (minx < 0.00001f) {
1456  minx = 0.00001f; /* side faces of unit-cube */
1457  }
1458  if (miny > 0.25f) {
1459  miny = 0.25f;
1460  }
1461  else if (miny < 0.00001f) {
1462  miny = 0.00001f;
1463  }
1464 
1465  /* repeat and clip */
1466  imaprepeat = (tex->extend == TEX_REPEAT);
1467  imapextend = (tex->extend == TEX_EXTEND);
1468 
1469  if (tex->extend == TEX_REPEAT) {
1470  if (tex->flag & (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) {
1471  imaprepeat = 0;
1472  imapextend = 1;
1473  }
1474  }
1475 
1476  if (tex->extend == TEX_CHECKER) {
1477  int xs, ys, xs1, ys1, xs2, ys2, boundary;
1478 
1479  xs = (int)floor(fx);
1480  ys = (int)floor(fy);
1481 
1482  /* both checkers available, no boundary exceptions, checkerdist will eat aliasing */
1483  if ((tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN)) {
1484  fx -= xs;
1485  fy -= ys;
1486  }
1487  else if ((tex->flag & TEX_CHECKER_ODD) == 0 && (tex->flag & TEX_CHECKER_EVEN) == 0) {
1488  if (ima) {
1489  BKE_image_pool_release_ibuf(ima, ibuf, pool);
1490  }
1491  return retval;
1492  }
1493  else {
1494 
1495  xs1 = (int)floor(fx - minx);
1496  ys1 = (int)floor(fy - miny);
1497  xs2 = (int)floor(fx + minx);
1498  ys2 = (int)floor(fy + miny);
1499  boundary = (xs1 != xs2) || (ys1 != ys2);
1500 
1501  if (boundary == 0) {
1502  if ((tex->flag & TEX_CHECKER_ODD) == 0) {
1503  if ((xs + ys) & 1) {
1504  /* pass */
1505  }
1506  else {
1507  if (ima) {
1508  BKE_image_pool_release_ibuf(ima, ibuf, pool);
1509  }
1510  return retval;
1511  }
1512  }
1513  if ((tex->flag & TEX_CHECKER_EVEN) == 0) {
1514  if ((xs + ys) & 1) {
1515  if (ima) {
1516  BKE_image_pool_release_ibuf(ima, ibuf, pool);
1517  }
1518  return retval;
1519  }
1520  }
1521  fx -= xs;
1522  fy -= ys;
1523  }
1524  else {
1525  if (tex->flag & TEX_CHECKER_ODD) {
1526  if ((xs1 + ys) & 1) {
1527  fx -= xs2;
1528  }
1529  else {
1530  fx -= xs1;
1531  }
1532 
1533  if ((ys1 + xs) & 1) {
1534  fy -= ys2;
1535  }
1536  else {
1537  fy -= ys1;
1538  }
1539  }
1540  if (tex->flag & TEX_CHECKER_EVEN) {
1541  if ((xs1 + ys) & 1) {
1542  fx -= xs1;
1543  }
1544  else {
1545  fx -= xs2;
1546  }
1547 
1548  if ((ys1 + xs) & 1) {
1549  fy -= ys1;
1550  }
1551  else {
1552  fy -= ys2;
1553  }
1554  }
1555  }
1556  }
1557 
1558  /* scale around center, (0.5, 0.5) */
1559  if (tex->checkerdist < 1.0f) {
1560  fx = (fx - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
1561  fy = (fy - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
1562  minx /= (1.0f - tex->checkerdist);
1563  miny /= (1.0f - tex->checkerdist);
1564  }
1565  }
1566 
1567  if (tex->extend == TEX_CLIPCUBE) {
1568  if (fx + minx < 0.0f || fy + miny < 0.0f || fx - minx > 1.0f || fy - miny > 1.0f ||
1569  texvec[2] < -1.0f || texvec[2] > 1.0f) {
1570  if (ima) {
1571  BKE_image_pool_release_ibuf(ima, ibuf, pool);
1572  }
1573  return retval;
1574  }
1575  }
1576  else if (ELEM(tex->extend, TEX_CLIP, TEX_CHECKER)) {
1577  if (fx + minx < 0.0f || fy + miny < 0.0f || fx - minx > 1.0f || fy - miny > 1.0f) {
1578  if (ima) {
1579  BKE_image_pool_release_ibuf(ima, ibuf, pool);
1580  }
1581  return retval;
1582  }
1583  }
1584  else {
1585  if (imapextend) {
1586  if (fx > 1.0f) {
1587  fx = 1.0f;
1588  }
1589  else if (fx < 0.0f) {
1590  fx = 0.0f;
1591  }
1592  }
1593  else {
1594  if (fx > 1.0f) {
1595  fx -= (int)(fx);
1596  }
1597  else if (fx < 0.0f) {
1598  fx += 1 - (int)(fx);
1599  }
1600  }
1601 
1602  if (imapextend) {
1603  if (fy > 1.0f) {
1604  fy = 1.0f;
1605  }
1606  else if (fy < 0.0f) {
1607  fy = 0.0f;
1608  }
1609  }
1610  else {
1611  if (fy > 1.0f) {
1612  fy -= (int)(fy);
1613  }
1614  else if (fy < 0.0f) {
1615  fy += 1 - (int)(fy);
1616  }
1617  }
1618  }
1619 
1620  /* Choice: */
1621  if (tex->imaflag & TEX_MIPMAP) {
1622  ImBuf *previbuf, *curibuf;
1623  float bumpscale;
1624 
1625  dx = minx;
1626  dy = miny;
1627  maxd = max_ff(dx, dy);
1628  if (maxd > 0.5f) {
1629  maxd = 0.5f;
1630  }
1631 
1632  pixsize = 1.0f / (float)MIN2(ibuf->x, ibuf->y);
1633 
1634  bumpscale = pixsize / maxd;
1635  if (bumpscale > 1.0f) {
1636  bumpscale = 1.0f;
1637  }
1638  else {
1639  bumpscale *= bumpscale;
1640  }
1641 
1642  curmap = 0;
1643  previbuf = curibuf = ibuf;
1644  while (curmap < IMB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) {
1645  if (maxd < pixsize) {
1646  break;
1647  }
1648  previbuf = curibuf;
1649  curibuf = ibuf->mipmap[curmap];
1650  pixsize = 1.0f / (float)MIN2(curibuf->x, curibuf->y);
1651  curmap++;
1652  }
1653 
1654  if (previbuf != curibuf || (tex->imaflag & TEX_INTERPOL)) {
1655  /* sample at least 1 pixel */
1656  if (minx < 0.5f / ibuf->x) {
1657  minx = 0.5f / ibuf->x;
1658  }
1659  if (miny < 0.5f / ibuf->y) {
1660  miny = 0.5f / ibuf->y;
1661  }
1662  }
1663 
1664  maxx = fx + minx;
1665  minx = fx - minx;
1666  maxy = fy + miny;
1667  miny = fy - miny;
1668 
1669  boxsample(curibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend);
1670 
1671  if (previbuf != curibuf) { /* interpolate */
1672  boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend);
1673 
1674  fx = 2.0f * (pixsize - maxd) / pixsize;
1675 
1676  if (fx >= 1.0f) {
1677  texres->trgba[3] = texr.trgba[3];
1678  texres->trgba[2] = texr.trgba[2];
1679  texres->trgba[1] = texr.trgba[1];
1680  texres->trgba[0] = texr.trgba[0];
1681  }
1682  else {
1683  fy = 1.0f - fx;
1684  texres->trgba[2] = fy * texres->trgba[2] + fx * texr.trgba[2];
1685  texres->trgba[1] = fy * texres->trgba[1] + fx * texr.trgba[1];
1686  texres->trgba[0] = fy * texres->trgba[0] + fx * texr.trgba[0];
1687  texres->trgba[3] = fy * texres->trgba[3] + fx * texr.trgba[3];
1688  }
1689  }
1690  }
1691  else {
1692  const int intpol = tex->imaflag & TEX_INTERPOL;
1693  if (intpol) {
1694  /* sample 1 pixel minimum */
1695  if (minx < 0.5f / ibuf->x) {
1696  minx = 0.5f / ibuf->x;
1697  }
1698  if (miny < 0.5f / ibuf->y) {
1699  miny = 0.5f / ibuf->y;
1700  }
1701  }
1702 
1703  boxsample(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, texres, imaprepeat, imapextend);
1704  }
1705 
1706  if (tex->imaflag & TEX_CALCALPHA) {
1707  texres->trgba[3] = texres->tin = texres->trgba[3] *
1708  max_fff(texres->trgba[0], texres->trgba[1], texres->trgba[2]);
1709  }
1710  else {
1711  texres->tin = texres->trgba[3];
1712  }
1713 
1714  if (tex->flag & TEX_NEGALPHA) {
1715  texres->trgba[3] = 1.0f - texres->trgba[3];
1716  }
1717 
1718  /* de-premul, this is being pre-multiplied in shade_input_do_shade() */
1719  /* do not de-premul for generated alpha, it is already in straight */
1720  if (texres->trgba[3] != 1.0f && texres->trgba[3] > 1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
1721  mul_v3_fl(texres->trgba, 1.0f / texres->trgba[3]);
1722  }
1723 
1724  if (ima) {
1725  BKE_image_pool_release_ibuf(ima, ibuf, pool);
1726  }
1727 
1728  BRICONTRGB;
1729 
1730  return retval;
1731 }
1732 
1734  Image *ima, float fx, float fy, float dx, float dy, float result[4], struct ImagePool *pool)
1735 {
1736  TexResult texres;
1737  ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, NULL, pool);
1738 
1739  if (UNLIKELY(ibuf == NULL)) {
1740  zero_v4(result);
1741  return;
1742  }
1743 
1744  texres.talpha = true; /* boxsample expects to be initialized */
1745  boxsample(ibuf, fx, fy, fx + dx, fy + dy, &texres, 0, 1);
1746  copy_v4_v4(result, texres.trgba);
1747 
1748  ima->flag |= IMA_USED_FOR_RENDER;
1749 
1750  BKE_image_pool_release_ibuf(ima, ibuf, pool);
1751 }
1752 
1753 void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4])
1754 {
1755  TexResult texres = {0};
1756  afdata_t AFD;
1757 
1758  AFD.dxt[0] = dx;
1759  AFD.dxt[1] = dx;
1760  AFD.dyt[0] = dy;
1761  AFD.dyt[1] = dy;
1762  // copy_v2_v2(AFD.dxt, dx);
1763  // copy_v2_v2(AFD.dyt, dy);
1764 
1765  AFD.intpol = 1;
1766  AFD.extflag = TXC_EXTD;
1767 
1768  ewa_eval(&texres, ibuf, fx, fy, &AFD);
1769 
1770  copy_v4_v4(result, texres.trgba);
1771 }
typedef float(TangentPoint)[2]
void BKE_image_pool_release_ibuf(struct Image *ima, struct ImBuf *ibuf, struct ImagePool *pool)
struct ImBuf * BKE_image_pool_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, struct ImagePool *pool)
bool BKE_image_has_loaded_ibuf(struct Image *image)
int BKE_image_get_tile_from_pos(struct Image *ima, const float uv[2], float r_uv[2], float r_ofs[2])
MINLINE float max_fff(float a, float b, float c)
MINLINE int round_fl_to_int(float a)
MINLINE float max_ff(float a, float b)
#define M_LOG2E
Definition: BLI_math_base.h:47
MINLINE float min_fff(float a, float b, float c)
#define EWA_MAXIDX
const float EWA_WTS[EWA_MAXIDX+1]
Definition: math_interp.c:503
void BLI_ewa_filter(int width, int height, bool intpol, bool use_alpha, const float uv[2], const float du[2], const float dv[2], ewa_filter_read_pixel_cb read_pixel_cb, void *userdata, float result[4])
Definition: math_interp.c:584
void BLI_ewa_imp2radangle(float A, float B, float C, float F, float *a, float *b, float *th, float *ecc)
Definition: math_interp.c:554
MINLINE void mul_v4_fl(float r[4], float f)
MINLINE void add_v4_v4(float r[4], const float a[4])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v4(float r[4])
MINLINE float len_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v4_v4fl(float r[4], const float a[4], float f)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:194
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition: BLI_rect.h:198
void BLI_thread_unlock(int type)
Definition: threads.cc:361
@ LOCK_IMAGE
Definition: BLI_threads.h:66
void BLI_thread_lock(int type)
Definition: threads.cc:356
#define CLAMPIS(a, b, c)
#define SWAP(type, a, b)
#define UNLIKELY(x)
#define ELEM(...)
#define MIN2(a, b)
@ IMA_USED_FOR_RENDER
@ IMA_ALPHA_IGNORE
@ IMA_SRC_TILED
#define TXF_AREA
#define TEX_CHECKER_EVEN
#define TEX_REPEAT_YMIR
#define TEX_EXTEND
#define TXF_EWA
#define TEX_USEALPHA
#define TEX_IMAROT
#define TEX_CHECKER
#define TEX_GAUSS_MIP
#define TEX_REPEAT
#define TEX_CALCALPHA
#define TXF_BOX
#define TXF_FELINE
#define TEX_NEGALPHA
#define TEX_RGB
#define TEX_CHECKER_ODD
#define TEX_REPEAT_XMIR
#define TEX_CLIP
#define TEX_MIPMAP
#define TEX_INTERPOL
#define TEX_CLIPCUBE
#define TEX_FILTER_MIN
_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 y1
_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 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 x2
_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 t
void IMB_remakemipmap(struct ImBuf *ibuf, int use_filter)
Definition: filter.c:537
void IMB_makemipmap(struct ImBuf *ibuf, int use_filter)
Definition: filter.c:573
Contains defines and structs used throughout the imbuf module.
@ IB_MIPMAP_INVALID
#define IMB_MIPMAP_LEVELS
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
#define C
Definition: RandGen.cpp:25
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define A
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
short source
char alpha_mode
#define logf(x)
Definition: cuda/compat.h:105
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
#define expf(x)
Definition: cuda/compat.h:106
SyclQueue void void size_t num_bytes void
uint col
int count
#define B
#define F
#define floorf(x)
Definition: metal/compat.h:224
#define sqrtf(x)
Definition: metal/compat.h:243
static unsigned a[3]
Definition: RandGen.cpp:78
T floor(const T &a)
bool isnan(double i)
Definition: numeric.h:451
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
struct ImBuf * mipmap[IMB_MIPMAP_LEVELS]
int channels
int userflags
unsigned int * rect
float * rect_float
afdata_t * AFD
ImBuf * ibuf
int talpha
Definition: RE_texture.h:89
float tin
Definition: RE_texture.h:86
float trgba[4]
Definition: RE_texture.h:87
short imaflag
float checkerdist
struct ImageUser iuser
int texfilter
short flag
short extend
float filtersize
float dvsc
float dyt[2]
float theta
float dusc
float majrad
float dxt[2]
float minrad
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
#define BRICONTRGB
static float square_rctf(rctf *rf)
@ TXC_YMIR
@ TXC_XMIR
@ TXC_REPT
@ TXC_EXTD
void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4])
int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[2], const float DYT[2], TexResult *texres, struct ImagePool *pool, const bool skip_load_image)
static float clipy_rctf(rctf *rf, float y1, float y2)
struct afdata_t afdata_t
static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[2], float dyt[2], TexResult *texres, struct ImagePool *pool, const bool skip_load_image)
static void boxsampleclip(struct ImBuf *ibuf, rctf *rf, TexResult *texres)
static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend)
int imagewrap(Tex *tex, Image *ima, const float texvec[3], TexResult *texres, struct ImagePool *pool, const bool skip_load_image)
Definition: texture_image.c:84
static int ibuf_get_color_clip_bilerp(float col[4], ImBuf *ibuf, float u, float v, int intpol, int extflag)
static float clipx_rctf(rctf *rf, float x1, float x2)
static void ewa_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
static void ibuf_get_color(float col[4], struct ImBuf *ibuf, int x, int y)
Definition: texture_image.c:50
void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4], struct ImagePool *pool)
struct ReadEWAData ReadEWAData
static void ewa_read_pixel_cb(void *userdata, int x, int y, float result[4])
static void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2)
static void area_sample(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
static void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2)
static int ibuf_get_color_clip(float col[4], ImBuf *ibuf, int x, int y, int extflag)
static void feline_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
static void alpha_clip_aniso(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, int extflag, TexResult *texres)
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:13