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