4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * Contributors: 2004/2005/2006 Blender Foundation, full recode
25 * ***** END GPL/BL DUAL LICENSE BLOCK *****
28 /** \file blender/render/intern/source/imagetexture.c
46 #include "MEM_guardedalloc.h"
48 #include "IMB_imbuf_types.h"
49 #include "IMB_imbuf.h"
51 #include "DNA_image_types.h"
52 #include "DNA_scene_types.h"
53 #include "DNA_texture_types.h"
56 #include "BLI_blenlib.h"
57 #include "BLI_threads.h"
58 #include "BLI_utildefines.h"
60 #include "BKE_global.h"
62 #include "BKE_image.h"
63 #include "BKE_texture.h"
64 #include "BKE_library.h"
66 #include "RE_render_ext.h"
68 #include "renderpipeline.h"
69 #include "render_types.h"
72 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
73 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
74 /* only to be used here in this file, it's for speed */
75 extern struct Render R;
76 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
78 static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend);
80 /* *********** IMAGEWRAPPING ****************** */
83 /* x and y have to be checked for image size */
84 static void ibuf_get_color(float *col, struct ImBuf *ibuf, int x, int y)
86 int ofs = y * ibuf->x + x;
88 if (ibuf->rect_float) {
89 if (ibuf->channels==4) {
90 float *fp= ibuf->rect_float + 4*ofs;
93 else if (ibuf->channels==3) {
94 float *fp= ibuf->rect_float + 3*ofs;
99 float *fp= ibuf->rect_float + ofs;
100 col[0]= col[1]= col[2]= col[3]= *fp;
104 char *rect = (char *)( ibuf->rect+ ofs);
106 col[0] = ((float)rect[0])*(1.0f/255.0f);
107 col[1] = ((float)rect[1])*(1.0f/255.0f);
108 col[2] = ((float)rect[2])*(1.0f/255.0f);
109 col[3] = ((float)rect[3])*(1.0f/255.0f);
113 int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres)
115 float fx, fy, val1, val2, val3;
117 int xi, yi; /* original values */
119 texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
121 /* we need to set retval OK, otherwise texture code generates normals itself... */
122 retval= texres->nor?3:1;
125 if (ibuf==NULL && ima==NULL)
129 /* hack for icon render */
130 if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
133 ibuf= BKE_image_get_ibuf(ima, &tex->iuser);
135 ima->flag|= IMA_USED_FOR_RENDER;
137 if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
141 if (tex->imaflag & TEX_IMAROT) {
150 if (tex->extend == TEX_CHECKER) {
158 if ( (tex->flag & TEX_CHECKER_ODD)==0) {
159 if ((xs+ys) & 1);else return retval;
161 if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
162 if ((xs+ys) & 1) return retval;
164 /* scale around center, (0.5, 0.5) */
165 if (tex->checkerdist<1.0f) {
166 fx= (fx-0.5f)/(1.0f-tex->checkerdist) +0.5f;
167 fy= (fy-0.5f)/(1.0f-tex->checkerdist) +0.5f;
171 x= xi= (int)floorf(fx*ibuf->x);
172 y= yi= (int)floorf(fy*ibuf->y);
174 if (tex->extend == TEX_CLIPCUBE) {
175 if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0f || texvec[2]>1.0f) {
179 else if ( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
180 if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) {
185 if (tex->extend==TEX_EXTEND) {
186 if (x>=ibuf->x) x = ibuf->x-1;
191 if (x<0) x+= ibuf->x;
193 if (tex->extend==TEX_EXTEND) {
194 if (y>=ibuf->y) y = ibuf->y-1;
199 if (y<0) y+= ibuf->y;
203 /* warning, no return before setting back! */
204 if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
205 ibuf->rect+= (ibuf->x*ibuf->y);
208 /* keep this before interpolation [#29761] */
209 if (tex->imaflag & TEX_USEALPHA) {
210 if ((tex->imaflag & TEX_CALCALPHA) == 0) {
211 texres->talpha = TRUE;
216 if (tex->imaflag & TEX_INTERPOL) {
217 float filterx, filtery;
218 filterx = (0.5f * tex->filtersize) / ibuf->x;
219 filtery = (0.5f * tex->filtersize) / ibuf->y;
221 /* important that this value is wrapped [#27782]
222 * this applies the modifications made by the checks above,
223 * back to the floating point values */
224 fx -= (float)(xi - x) / (float)ibuf->x;
225 fy -= (float)(yi - y) / (float)ibuf->y;
227 boxsample(ibuf, fx-filterx, fy-filtery, fx+filterx, fy+filtery, texres, (tex->extend==TEX_REPEAT), (tex->extend==TEX_EXTEND));
229 else { /* no filtering */
230 ibuf_get_color(&texres->tr, ibuf, x, y);
233 if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
234 ibuf->rect-= (ibuf->x*ibuf->y);
238 if (tex->imaflag & TEX_NORMALMAP) {
239 // qdn: normal from color
240 // The invert of the red channel is to make
241 // the normal map compliant with the outside world.
242 // It needs to be done because in Blender
243 // the normal used in the renderer points inward. It is generated
244 // this way in calc_vertexnormals(). Should this ever change
245 // this negate must be removed.
246 texres->nor[0] = -2.f*(texres->tr - 0.5f);
247 texres->nor[1] = 2.f*(texres->tg - 0.5f);
248 texres->nor[2] = 2.f*(texres->tb - 0.5f);
251 /* bump: take three samples */
252 val1= texres->tr+texres->tg+texres->tb;
256 ibuf_get_color(col, ibuf, x+1, y);
257 val2= (col[0]+col[1]+col[2]);
263 ibuf_get_color(col, ibuf, x, y+1);
264 val3= (col[0]+col[1]+col[2]);
268 /* do not mix up x and y here! */
269 texres->nor[0]= (val1-val2);
270 texres->nor[1]= (val1-val3);
274 if (texres->talpha) texres->tin= texres->ta;
275 else if (tex->imaflag & TEX_CALCALPHA) {
276 texres->ta= texres->tin= MAX3(texres->tr, texres->tg, texres->tb);
278 else texres->ta= texres->tin= 1.0;
280 if (tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
282 /* de-premul, this is being premulled in shade_input_do_shade() */
283 if (texres->ta!=1.0f && texres->ta>1e-4f) {
295 static void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2)
309 if (rf->xmax>x2) rf->xmax = x2;
310 newrct= stack+ *count;
314 newrct->xmin = rf->xmin+(x2-x1);
315 newrct->ymin = rf->ymin;
316 newrct->ymax = rf->ymax;
318 if (newrct->xmin ==newrct->xmax) (*count)--;
323 else if (rf->xmax>x2) {
329 if (rf->xmin<x1) rf->xmin = x1;
330 newrct= stack+ *count;
334 newrct->xmax = rf->xmax-(x2-x1);
335 newrct->ymin = rf->ymin;
336 newrct->ymax = rf->ymax;
338 if (newrct->xmin ==newrct->xmax) (*count)--;
348 static void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2)
362 if (rf->ymax>y2) rf->ymax = y2;
363 newrct= stack+ *count;
367 newrct->ymin = rf->ymin+(y2-y1);
368 newrct->xmin = rf->xmin;
369 newrct->xmax = rf->xmax;
371 if (newrct->ymin==newrct->ymax) (*count)--;
376 else if (rf->ymax>y2) {
382 if (rf->ymin<y1) rf->ymin = y1;
383 newrct= stack+ *count;
387 newrct->ymax = rf->ymax-(y2-y1);
388 newrct->xmin = rf->xmin;
389 newrct->xmax = rf->xmax;
391 if (newrct->ymin==newrct->ymax) (*count)--;
400 static float square_rctf(rctf *rf)
404 x= rf->xmax- rf->xmin;
405 y= rf->ymax- rf->ymin;
409 static float clipx_rctf(rctf *rf, float x1, float x2)
413 size= rf->xmax - rf->xmin;
421 if (rf->xmin > rf->xmax) {
425 else if (size!=0.0f) {
426 return (rf->xmax - rf->xmin)/size;
431 static float clipy_rctf(rctf *rf, float y1, float y2)
435 size= rf->ymax - rf->ymin;
444 if (rf->ymin > rf->ymax) {
448 else if (size!=0.0f) {
449 return (rf->ymax - rf->ymin)/size;
455 static void boxsampleclip(struct ImBuf *ibuf, rctf *rf, TexResult *texres)
457 /* sample box, is clipped already, and minx etc. have been set at ibuf size.
458 * Enlarge with antialiased edges of the pixels */
460 float muly, mulx, div, col[4];
461 int x, y, startx, endx, starty, endy;
463 startx= (int)floor(rf->xmin);
464 endx= (int)floor(rf->xmax);
465 starty= (int)floor(rf->ymin);
466 endy= (int)floor(rf->ymax);
468 if (startx < 0) startx= 0;
469 if (starty < 0) starty= 0;
470 if (endx>=ibuf->x) endx= ibuf->x-1;
471 if (endy>=ibuf->y) endy= ibuf->y-1;
473 if (starty==endy && startx==endx) {
474 ibuf_get_color(&texres->tr, ibuf, startx, starty);
477 div= texres->tr= texres->tg= texres->tb= texres->ta= 0.0;
478 for (y=starty; y<=endy; y++) {
484 if (y==starty) muly= 1.0f-(rf->ymin - y);
485 if (y==endy) muly= (rf->ymax - y);
491 ibuf_get_color(col, ibuf, startx, y);
493 texres->ta+= mulx*col[3];
494 texres->tr+= mulx*col[0];
495 texres->tg+= mulx*col[1];
496 texres->tb+= mulx*col[2];
500 for (x=startx; x<=endx; x++) {
502 if (x==startx) mulx*= 1.0f-(rf->xmin - x);
503 if (x==endx) mulx*= (rf->xmax - x);
505 ibuf_get_color(col, ibuf, x, y);
515 texres->ta+= mulx*col[3];
516 texres->tr+= mulx*col[0];
517 texres->tg+= mulx*col[1];
518 texres->tb+= mulx*col[2];
533 texres->tr= texres->tg= texres->tb= texres->ta= 0.0f;
538 static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend)
540 /* Sample box, performs clip. minx etc are in range 0.0 - 1.0 .
541 * Enlarge with antialiased edges of pixels.
542 * If variable 'imaprepeat' has been set, the
543 * clipped-away parts are sampled as well.
545 /* note: actually minx etc isn't in the proper range... this due to filter size and offset vectors for bump */
546 /* note: talpha must be initialized */
547 /* note: even when 'imaprepeat' is set, this can only repeate once in any direction.
548 * the point which min/max is derived from is assumed to be wrapped */
551 float opp, tot, alphaclip= 1.0;
555 rf->xmin = minx*(ibuf->x);
556 rf->xmax = maxx*(ibuf->x);
557 rf->ymin = miny*(ibuf->y);
558 rf->ymax = maxy*(ibuf->y);
560 texr.talpha= texres->talpha; /* is read by boxsample_clip */
563 CLAMP(rf->xmin, 0.0f, ibuf->x-1);
564 CLAMP(rf->xmax, 0.0f, ibuf->x-1);
567 clipx_rctf_swap(stack, &count, 0.0, (float)(ibuf->x));
569 alphaclip= clipx_rctf(rf, 0.0, (float)(ibuf->x));
571 if (alphaclip<=0.0f) {
572 texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
578 CLAMP(rf->ymin, 0.0f, ibuf->y-1);
579 CLAMP(rf->ymax, 0.0f, ibuf->y-1);
582 clipy_rctf_swap(stack, &count, 0.0, (float)(ibuf->y));
584 alphaclip*= clipy_rctf(rf, 0.0, (float)(ibuf->y));
586 if (alphaclip<=0.0f) {
587 texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
593 tot= texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
595 boxsampleclip(ibuf, rf, &texr);
597 opp= square_rctf(rf);
600 texres->tr+= opp*texr.tr;
601 texres->tg+= opp*texr.tg;
602 texres->tb+= opp*texr.tb;
603 if (texres->talpha) texres->ta+= opp*texr.ta;
610 if (texres->talpha) texres->ta/= tot;
614 boxsampleclip(ibuf, rf, texres);
616 if (texres->talpha==0) texres->ta= 1.0;
618 if (alphaclip!=1.0f) {
620 texres->tr*= alphaclip;
621 texres->tg*= alphaclip;
622 texres->tb*= alphaclip;
623 texres->ta*= alphaclip;
627 //-----------------------------------------------------------------------------------------------------------------
628 // from here, some functions only used for the new filtering
630 // anisotropic filters, data struct used instead of long line of (possibly unused) func args
631 typedef struct afdata_t {
632 float dxt[2], dyt[2];
635 float majrad, minrad, theta;
640 // this only used here to make it easier to pass extend flags as single int
641 enum {TXC_XMIR=1, TXC_YMIR, TXC_REPT, TXC_EXTD};
643 // similar to ibuf_get_color() but clips/wraps coords according to repeat/extend flags
644 // returns true if out of range in clipmode
645 static int ibuf_get_color_clip(float *col, ImBuf *ibuf, int x, int y, int extflag)
649 case TXC_XMIR: // y rep
651 x += x < 0 ? 2*ibuf->x : 0;
652 x = x >= ibuf->x ? 2*ibuf->x - x - 1 : x;
654 y += y < 0 ? ibuf->y : 0;
656 case TXC_YMIR: // x rep
658 x += x < 0 ? ibuf->x : 0;
660 y += y < 0 ? 2*ibuf->y : 0;
661 y = y >= ibuf->y ? 2*ibuf->y - y - 1 : y;
664 x = (x < 0) ? 0 : ((x >= ibuf->x) ? (ibuf->x - 1) : x);
665 y = (y < 0) ? 0 : ((y >= ibuf->y) ? (ibuf->y - 1) : y);
669 x += (x < 0) ? ibuf->x : 0;
671 y += (y < 0) ? ibuf->y : 0;
673 default: { // as extend, if clipped, set alpha to 0.0
674 if (x < 0) { x = 0; } // TXF alpha: clip = 1; }
675 if (x >= ibuf->x) { x = ibuf->x - 1; } // TXF alpha: clip = 1; }
676 if (y < 0) { y = 0; } // TXF alpha: clip = 1; }
677 if (y >= ibuf->y) { y = ibuf->y - 1; } // TXF alpha: clip = 1; }
681 if (ibuf->rect_float) {
682 const float* fp = ibuf->rect_float + (x + y*ibuf->x)*ibuf->channels;
683 if (ibuf->channels == 1)
684 col[0] = col[1] = col[2] = col[3] = *fp;
689 col[3] = clip ? 0.f : (ibuf->channels == 4 ? fp[3] : 1.f);
693 char* rect = (char*)(ibuf->rect + x + y*ibuf->x);
694 col[0] = rect[0]*(1.f/255.f);
695 col[1] = rect[1]*(1.f/255.f);
696 col[2] = rect[2]*(1.f/255.f);
697 col[3] = clip ? 0.f : rect[3]*(1.f/255.f);
703 static int ibuf_get_color_clip_bilerp(float *col, ImBuf *ibuf, float u, float v, int intpol, int extflag)
706 float c00[4], c01[4], c10[4], c11[4];
707 const float ufl = floorf(u -= 0.5f), vfl = floorf(v -= 0.5f);
708 const float uf = u - ufl, vf = v - vfl;
709 const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf;
710 const int x1 = (int)ufl, y1 = (int)vfl, x2 = x1 + 1, y2 = y1 + 1;
711 int clip = ibuf_get_color_clip(c00, ibuf, x1, y1, extflag);
712 clip |= ibuf_get_color_clip(c10, ibuf, x2, y1, extflag);
713 clip |= ibuf_get_color_clip(c01, ibuf, x1, y2, extflag);
714 clip |= ibuf_get_color_clip(c11, ibuf, x2, y2, extflag);
715 col[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0];
716 col[1] = w00*c00[1] + w10*c10[1] + w01*c01[1] + w11*c11[1];
717 col[2] = w00*c00[2] + w10*c10[2] + w01*c01[2] + w11*c11[2];
718 col[3] = clip ? 0.f : w00*c00[3] + w10*c10[3] + w01*c01[3] + w11*c11[3];
721 return ibuf_get_color_clip(col, ibuf, (int)u, (int)v, extflag);
724 static void area_sample(TexResult* texr, ImBuf* ibuf, float fx, float fy, afdata_t* AFD)
726 int xs, ys, clip = 0;
727 float tc[4], xsd, ysd, cw = 0.f;
728 const float ux = ibuf->x*AFD->dxt[0], uy = ibuf->y*AFD->dxt[1];
729 const float vx = ibuf->x*AFD->dyt[0], vy = ibuf->y*AFD->dyt[1];
730 int xsam = (int)(0.5f*sqrtf(ux*ux + uy*uy) + 0.5f);
731 int ysam = (int)(0.5f*sqrtf(vx*vx + vy*vy) + 0.5f);
732 const int minsam = AFD->intpol ? 2 : 4;
733 xsam = CLAMPIS(xsam, minsam, ibuf->x*2);
734 ysam = CLAMPIS(ysam, minsam, ibuf->y*2);
737 texr->tr = texr->tg = texr->tb = texr->ta = 0.f;
738 for (ys=0; ys<ysam; ++ys) {
739 for (xs=0; xs<xsam; ++xs) {
740 const float su = (xs + ((ys & 1) + 0.5f)*0.5f)*xsd - 0.5f;
741 const float sv = (ys + ((xs & 1) + 0.5f)*0.5f)*ysd - 0.5f;
742 const float pu = fx + su*AFD->dxt[0] + sv*AFD->dyt[0];
743 const float pv = fy + su*AFD->dxt[1] + sv*AFD->dyt[1];
744 const int out = ibuf_get_color_clip_bilerp(tc, ibuf, pu*ibuf->x, pv*ibuf->y, AFD->intpol, AFD->extflag);
746 cw += out ? 0.f : 1.f;
750 texr->ta += texr->talpha ? tc[3] : 0.f;
757 // clipping can be ignored if alpha used, texr->ta already includes filtered edge
758 texr->ta = texr->talpha ? texr->ta*xsd : (clip ? cw*xsd : 1.f);
761 // table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2
762 // used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible
763 #define EWA_MAXIDX 255
764 static float EWA_WTS[EWA_MAXIDX + 1] =
765 { 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f,
766 0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f,
767 0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f,
768 0.794079f, 0.786653f, 0.779284f, 0.771974f, 0.76472f, 0.757523f, 0.750382f, 0.743297f,
769 0.736267f, 0.729292f, 0.722372f, 0.715505f, 0.708693f, 0.701933f, 0.695227f, 0.688572f,
770 0.68197f, 0.67542f, 0.66892f, 0.662471f, 0.656073f, 0.649725f, 0.643426f, 0.637176f,
771 0.630976f, 0.624824f, 0.618719f, 0.612663f, 0.606654f, 0.600691f, 0.594776f, 0.588906f,
772 0.583083f, 0.577305f, 0.571572f, 0.565883f, 0.56024f, 0.55464f, 0.549084f, 0.543572f,
773 0.538102f, 0.532676f, 0.527291f, 0.521949f, 0.516649f, 0.511389f, 0.506171f, 0.500994f,
774 0.495857f, 0.490761f, 0.485704f, 0.480687f, 0.475709f, 0.470769f, 0.465869f, 0.461006f,
775 0.456182f, 0.451395f, 0.446646f, 0.441934f, 0.437258f, 0.432619f, 0.428017f, 0.42345f,
776 0.418919f, 0.414424f, 0.409963f, 0.405538f, 0.401147f, 0.39679f, 0.392467f, 0.388178f,
777 0.383923f, 0.379701f, 0.375511f, 0.371355f, 0.367231f, 0.363139f, 0.359079f, 0.355051f,
778 0.351055f, 0.347089f, 0.343155f, 0.339251f, 0.335378f, 0.331535f, 0.327722f, 0.323939f,
779 0.320186f, 0.316461f, 0.312766f, 0.3091f, 0.305462f, 0.301853f, 0.298272f, 0.294719f,
780 0.291194f, 0.287696f, 0.284226f, 0.280782f, 0.277366f, 0.273976f, 0.270613f, 0.267276f,
781 0.263965f, 0.26068f, 0.257421f, 0.254187f, 0.250979f, 0.247795f, 0.244636f, 0.241502f,
782 0.238393f, 0.235308f, 0.232246f, 0.229209f, 0.226196f, 0.223206f, 0.220239f, 0.217296f,
783 0.214375f, 0.211478f, 0.208603f, 0.20575f, 0.20292f, 0.200112f, 0.197326f, 0.194562f,
784 0.191819f, 0.189097f, 0.186397f, 0.183718f, 0.18106f, 0.178423f, 0.175806f, 0.17321f,
785 0.170634f, 0.168078f, 0.165542f, 0.163026f, 0.16053f, 0.158053f, 0.155595f, 0.153157f,
786 0.150738f, 0.148337f, 0.145955f, 0.143592f, 0.141248f, 0.138921f, 0.136613f, 0.134323f,
787 0.132051f, 0.129797f, 0.12756f, 0.125341f, 0.123139f, 0.120954f, 0.118786f, 0.116635f,
788 0.114501f, 0.112384f, 0.110283f, 0.108199f, 0.106131f, 0.104079f, 0.102043f, 0.100023f,
789 0.0980186f, 0.09603f, 0.094057f, 0.0920994f, 0.0901571f, 0.08823f, 0.0863179f, 0.0844208f,
790 0.0825384f, 0.0806708f, 0.0788178f, 0.0769792f, 0.0751551f, 0.0733451f, 0.0715493f, 0.0697676f,
791 0.0679997f, 0.0662457f, 0.0645054f, 0.0627786f, 0.0610654f, 0.0593655f, 0.0576789f, 0.0560055f,
792 0.0543452f, 0.0526979f, 0.0510634f, 0.0494416f, 0.0478326f, 0.0462361f, 0.0446521f, 0.0430805f,
793 0.0415211f, 0.039974f, 0.0384389f, 0.0369158f, 0.0354046f, 0.0339052f, 0.0324175f, 0.0309415f,
794 0.029477f, 0.0280239f, 0.0265822f, 0.0251517f, 0.0237324f, 0.0223242f, 0.020927f, 0.0195408f,
795 0.0181653f, 0.0168006f, 0.0154466f, 0.0141031f, 0.0127701f, 0.0114476f, 0.0101354f, 0.00883339f,
796 0.00754159f, 0.00625989f, 0.00498819f, 0.00372644f, 0.00247454f, 0.00123242f, 0.f
799 // test if a float value is 'nan'
800 // there is a C99 function for this: isnan(), but blender seems to use C90 (according to gcc warns),
801 // and may not be supported by other compilers either
803 #define ISNAN(x) ((x) != (x))
805 //static int ISNAN(float x) { return (x != x); }
807 static void radangle2imp(float a2, float b2, float th, float* A, float* B, float* C, float* F)
809 float ct2 = cosf(th);
810 const float st2 = 1.f - ct2*ct2; // <- sin(th)^2
812 *A = a2*st2 + b2*ct2;
813 *B = (b2 - a2)*sinf(2.f*th);
814 *C = a2*ct2 + b2*st2;
818 // all tests here are done to make sure possible overflows are hopefully minimized
819 static void imp2radangle(float A, float B, float C, float F, float* a, float* b, float* th, float* ecc)
821 if (F <= 1e-5f) { // use arbitrary major radius, zero minor, infinite eccentricity
822 *a = sqrtf(A > C ? A : C);
825 *th = 0.5f*(atan2f(B, A - C) + (float)M_PI);
828 const float AmC = A - C, ApC = A + C, F2 = F*2.f;
829 const float r = sqrtf(AmC*AmC + B*B);
831 *a = (d <= 0.f) ? sqrtf(A > C ? A : C) : sqrtf(F2 / d);
841 // incr theta by 0.5*pi (angle of major axis)
842 *th = 0.5f*(atan2f(B, AmC) + (float)M_PI);
846 static void ewa_eval(TexResult* texr, ImBuf* ibuf, float fx, float fy, afdata_t* AFD)
848 // scaling dxt/dyt by full resolution can cause overflow because of huge A/B/C and esp. F values,
849 // scaling by aspect ratio alone does the opposite, so try something in between instead...
850 const float ff2 = ibuf->x, ff = sqrtf(ff2), q = ibuf->y / ff;
851 const float Ux = AFD->dxt[0]*ff, Vx = AFD->dxt[1]*q, Uy = AFD->dyt[0]*ff, Vy = AFD->dyt[1]*q;
852 float A = Vx*Vx + Vy*Vy;
853 float B = -2.f*(Ux*Vx + Uy*Vy);
854 float C = Ux*Ux + Uy*Uy;
855 float F = A*C - B*B*0.25f;
856 float a, b, th, ecc, a2, b2, ue, ve, U0, V0, DDQ, U, ac1, ac2, BU, d; // TXF alpha: cw = 0.f;
857 int u, v, u1, u2, v1, v2; // TXF alpha: clip = 0;
859 // The so-called 'high' quality ewa method simply adds a constant of 1 to both A & C,
860 // so the ellipse always covers at least some texels. But since the filter is now always larger,
861 // it also means that everywhere else it's also more blurry then ideally should be the case.
862 // So instead here the ellipse radii are modified instead whenever either is too low.
863 // Use a different radius based on interpolation switch, just enough to anti-alias when interpolation is off,
864 // and slightly larger to make result a bit smoother than bilinear interpolation when interpolation is on
865 // (minimum values: const float rmin = intpol ? 1.f : 0.5f;)
866 const float rmin = (AFD->intpol ? 1.5625f : 0.765625f)/ff2;
867 imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
868 if ((b2 = b*b) < rmin) {
869 if ((a2 = a*a) < rmin) {
876 radangle2imp(a2, b2, th, &A, &B, &C, &F);
882 d = (float)(EWA_MAXIDX + 1) / (F*ff2);
889 u1 = (int)(floorf(U0 - ue));
890 u2 = (int)(ceilf(U0 + ue));
891 v1 = (int)(floorf(V0 - ve));
892 v2 = (int)(ceilf(V0 + ve));
897 ac1 = A*(2.f*U + 1.f);
901 d = texr->tr = texr->tb = texr->tg = texr->ta = 0.f;
902 for (v=v1; v<=v2; ++v) {
903 const float V = v - V0;
904 float DQ = ac1 + B*V;
905 float Q = (C*V + BU)*V + ac2;
906 for (u=u1; u<=u2; ++u) {
907 if (Q < (float)(EWA_MAXIDX + 1)) {
909 const float wt = EWA_WTS[(Q < 0.f) ? 0 : (unsigned int)Q];
910 /*const int out =*/ ibuf_get_color_clip(tc, ibuf, u, v, AFD->extflag);
911 // TXF alpha: clip |= out;
912 // TXF alpha: cw += out ? 0.f : wt;
913 texr->tr += tc[0]*wt;
914 texr->tg += tc[1]*wt;
915 texr->tb += tc[2]*wt;
916 texr->ta += texr->talpha ? tc[3]*wt : 0.f;
924 // d should hopefully never be zero anymore
929 // clipping can be ignored if alpha used, texr->ta already includes filtered edge
930 texr->ta = texr->talpha ? texr->ta*d : 1.f; // TXF alpha (clip ? cw*d : 1.f);
933 static void feline_eval(TexResult* texr, ImBuf* ibuf, float fx, float fy, afdata_t* AFD)
935 const int maxn = AFD->iProbes - 1;
936 const float ll = ((AFD->majrad == AFD->minrad) ? 2.f*AFD->majrad : 2.f*(AFD->majrad - AFD->minrad)) / (maxn ? (float)maxn : 1.f);
937 float du = maxn ? cosf(AFD->theta)*ll : 0.f;
938 float dv = maxn ? sinf(AFD->theta)*ll : 0.f;
939 //const float D = -0.5f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad);
940 const float D = (EWA_MAXIDX + 1)*0.25f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad);
941 float d; // TXF alpha: cw = 0.f;
942 int n; // TXF alpha: clip = 0;
943 // have to use same scaling for du/dv here as for Ux/Vx/Uy/Vy (*after* D calc.)
946 d = texr->tr = texr->tb = texr->tg = texr->ta = 0.f;
947 for (n=-maxn; n<=maxn; n+=2) {
949 const float hn = n*0.5f;
950 const float u = fx + hn*du, v = fy + hn*dv;
951 //const float wt = expf(n*n*D);
952 // can use ewa table here too
953 const float wt = EWA_WTS[(int)(n*n*D)];
954 /*const int out =*/ ibuf_get_color_clip_bilerp(tc, ibuf, ibuf->x*u, ibuf->y*v, AFD->intpol, AFD->extflag);
955 // TXF alpha: clip |= out;
956 // TXF alpha: cw += out ? 0.f : wt;
957 texr->tr += tc[0]*wt;
958 texr->tg += tc[1]*wt;
959 texr->tb += tc[2]*wt;
960 texr->ta += texr->talpha ? tc[3]*wt : 0.f;
968 // clipping can be ignored if alpha used, texr->ta already includes filtered edge
969 texr->ta = texr->talpha ? texr->ta*d : 1.f; // TXF alpha: (clip ? cw*d : 1.f);
973 static void alpha_clip_aniso(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, int extflag, TexResult *texres)
978 // TXF apha: we're doing the same alphaclip here as boxsample, but i'm doubting
979 // if this is actually correct for the all the filtering algorithms ..
981 if (!(extflag == TXC_REPT || extflag == TXC_EXTD)) {
982 rf.xmin = minx*(ibuf->x);
983 rf.xmax = maxx*(ibuf->x);
984 rf.ymin = miny*(ibuf->y);
985 rf.ymax = maxy*(ibuf->y);
987 alphaclip = clipx_rctf(&rf, 0.0, (float)(ibuf->x));
988 alphaclip*= clipy_rctf(&rf, 0.0, (float)(ibuf->y));
989 alphaclip= MAX2(alphaclip, 0.0f);
991 if (alphaclip!=1.0f) {
993 texres->tr*= alphaclip;
994 texres->tg*= alphaclip;
995 texres->tb*= alphaclip;
996 texres->ta*= alphaclip;
1001 static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
1003 if (tex->imaflag & TEX_MIPMAP) {
1004 if ((ibuf->flags & IB_fields) == 0) {
1006 if (ibuf->mipmap[0] && (ibuf->userflags & IB_MIPMAP_INVALID)) {
1007 BLI_lock_thread(LOCK_IMAGE);
1008 if (ibuf->userflags & IB_MIPMAP_INVALID) {
1009 IMB_remakemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
1010 ibuf->userflags &= ~IB_MIPMAP_INVALID;
1012 BLI_unlock_thread(LOCK_IMAGE);
1014 if (ibuf->mipmap[0] == NULL) {
1015 BLI_lock_thread(LOCK_IMAGE);
1016 if (ibuf->mipmap[0] == NULL)
1017 IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
1018 BLI_unlock_thread(LOCK_IMAGE);
1025 static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[3], float dyt[3], TexResult *texres)
1028 float fx, fy, minx, maxx, miny, maxy;
1029 float maxd, val1, val2, val3;
1030 int curmap, retval, intpol, extflag = 0;
1033 void (*filterfunc)(TexResult*, ImBuf*, float, float, afdata_t*);
1034 switch (tex->texfilter) {
1036 filterfunc = ewa_eval;
1039 filterfunc = feline_eval;
1043 filterfunc = area_sample;
1046 texres->tin = texres->ta = texres->tr = texres->tg = texres->tb = 0.f;
1048 // we need to set retval OK, otherwise texture code generates normals itself...
1049 retval = texres->nor ? 3 : 1;
1052 if (ibuf==NULL && ima==NULL) return retval;
1054 if (ima) { // hack for icon render
1055 if ((ima->ibufs.first == NULL) && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval;
1056 ibuf = BKE_image_get_ibuf(ima, &tex->iuser);
1059 if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) return retval;
1062 image_mipmap_test(tex, ibuf);
1064 if ((tex->imaflag & TEX_USEALPHA) && ((tex->imaflag & TEX_CALCALPHA) == 0)) texres->talpha = 1;
1065 texr.talpha = texres->talpha;
1067 if (tex->imaflag & TEX_IMAROT) {
1076 if (ibuf->flags & IB_fields) {
1077 if (R.r.mode & R_FIELDS) { /* field render */
1078 if (R.flag & R_SEC_FIELD) { /* correction for 2nd field */
1079 /* fac1= 0.5/( (float)ibuf->y ); */
1082 else /* first field */
1083 fy += 0.5f/( (float)ibuf->y );
1087 // pixel coordinates
1088 minx = MIN3(dxt[0], dyt[0], dxt[0] + dyt[0]);
1089 maxx = MAX3(dxt[0], dyt[0], dxt[0] + dyt[0]);
1090 miny = MIN3(dxt[1], dyt[1], dxt[1] + dyt[1]);
1091 maxy = MAX3(dxt[1], dyt[1], dxt[1] + dyt[1]);
1093 // tex_sharper has been removed
1094 minx = (maxx - minx)*0.5f;
1095 miny = (maxy - miny)*0.5f;
1097 if (tex->imaflag & TEX_FILTER_MIN) {
1098 // make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy)
1099 const float addval = (0.5f * tex->filtersize) / (float)MIN2(ibuf->x, ibuf->y);
1100 if (addval > minx) minx = addval;
1101 if (addval > miny) miny = addval;
1103 else if (tex->filtersize != 1.f) {
1104 minx *= tex->filtersize;
1105 miny *= tex->filtersize;
1106 dxt[0] *= tex->filtersize;
1107 dxt[1] *= tex->filtersize;
1108 dyt[0] *= tex->filtersize;
1109 dyt[1] *= tex->filtersize;
1112 if (tex->imaflag & TEX_IMAROT) {
1114 SWAP(float, minx, miny);
1115 // must rotate dxt/dyt 90 deg
1116 // yet another blender problem is that swapping X/Y axes (or any tex proj switches) should do something similar,
1117 // but it doesn't, it only swaps coords, so filter area will be incorrect in those cases.
1126 // side faces of unit-cube
1127 minx = (minx > 0.25f) ? 0.25f : ((minx < 1e-5f) ? 1e-5f : minx);
1128 miny = (miny > 0.25f) ? 0.25f : ((miny < 1e-5f) ? 1e-5f : miny);
1132 if (tex->extend == TEX_REPEAT) {
1133 if ((tex->flag & (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) == (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR))
1135 else if (tex->flag & TEX_REPEAT_XMIR)
1137 else if (tex->flag & TEX_REPEAT_YMIR)
1142 else if (tex->extend == TEX_EXTEND)
1145 if (tex->extend == TEX_CHECKER) {
1146 int xs = (int)floorf(fx), ys = (int)floorf(fy);
1147 // both checkers available, no boundary exceptions, checkerdist will eat aliasing
1148 if ((tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN)) {
1153 int xs1 = (int)floorf(fx - minx);
1154 int ys1 = (int)floorf(fy - miny);
1155 int xs2 = (int)floorf(fx + minx);
1156 int ys2 = (int)floorf(fy + miny);
1157 if ((xs1 != xs2) || (ys1 != ys2)) {
1158 if (tex->flag & TEX_CHECKER_ODD) {
1159 fx -= ((xs1 + ys) & 1) ? xs2 : xs1;
1160 fy -= ((ys1 + xs) & 1) ? ys2 : ys1;
1162 if (tex->flag & TEX_CHECKER_EVEN) {
1163 fx -= ((xs1 + ys) & 1) ? xs1 : xs2;
1164 fy -= ((ys1 + xs) & 1) ? ys1 : ys2;
1168 if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) return retval;
1169 if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) return retval;
1174 // scale around center, (0.5, 0.5)
1175 if (tex->checkerdist < 1.f) {
1176 const float omcd = 1.f / (1.f - tex->checkerdist);
1177 fx = (fx - 0.5f)*omcd + 0.5f;
1178 fy = (fy - 0.5f)*omcd + 0.5f;
1184 if (tex->extend == TEX_CLIPCUBE) {
1185 if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f || texvec[2] < -1.f || texvec[2] > 1.f) return retval;
1187 else if (tex->extend == TEX_CLIP || tex->extend == TEX_CHECKER) {
1188 if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) return retval;
1191 if (tex->extend == TEX_EXTEND) {
1192 fx = (fx > 1.f) ? 1.f : ((fx < 0.f) ? 0.f : fx);
1193 fy = (fy > 1.f) ? 1.f : ((fy < 0.f) ? 0.f : fy);
1201 intpol = tex->imaflag & TEX_INTERPOL;
1203 // warning no return!
1204 if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields))
1205 ibuf->rect += ibuf->x*ibuf->y;
1207 // struct common data
1208 copy_v2_v2(AFD.dxt, dxt);
1209 copy_v2_v2(AFD.dyt, dyt);
1210 AFD.intpol = intpol;
1211 AFD.extflag = extflag;
1213 // brecht: added stupid clamping here, large dx/dy can give very large
1214 // filter sizes which take ages to render, it may be better to do this
1215 // more intelligently later in the code .. probably it's not noticeable
1216 if (AFD.dxt[0]*AFD.dxt[0] + AFD.dxt[1]*AFD.dxt[1] > 2.0f*2.0f)
1217 mul_v2_fl(AFD.dxt, 2.0f/len_v2(AFD.dxt));
1218 if (AFD.dyt[0]*AFD.dyt[0] + AFD.dyt[1]*AFD.dyt[1] > 2.0f*2.0f)
1219 mul_v2_fl(AFD.dyt, 2.0f/len_v2(AFD.dyt));
1222 if (tex->imaflag & TEX_MIPMAP) {
1223 ImBuf *previbuf, *curibuf;
1226 ImBuf* mipmaps[IB_MIPMAP_LEVELS + 1];
1228 // modify ellipse minor axis if too eccentric, use for area sampling as well
1229 // scaling dxt/dyt as done in pbrt is not the same
1230 // (as in ewa_eval(), scale by sqrt(ibuf->x) to maximize precision)
1231 const float ff = sqrtf(ibuf->x), q = ibuf->y/ff;
1232 const float Ux = dxt[0]*ff, Vx = dxt[1]*q, Uy = dyt[0]*ff, Vy = dyt[1]*q;
1233 const float A = Vx*Vx + Vy*Vy;
1234 const float B = -2.f*(Ux*Vx + Uy*Vy);
1235 const float C = Ux*Ux + Uy*Uy;
1236 const float F = A*C - B*B*0.25f;
1237 float a, b, th, ecc;
1238 imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
1239 if (tex->texfilter == TXF_FELINE) {
1245 fProbes = 2.f*(a / b) - 1.f;
1246 AFD.iProbes = (int)floorf(fProbes + 0.5f);
1247 AFD.iProbes = MIN2(AFD.iProbes, tex->afmax);
1248 if (AFD.iProbes < fProbes)
1249 b = 2.f*a / (float)(AFD.iProbes + 1);
1254 AFD.dvsc = ff / (float)ibuf->y;
1256 else { // EWA & area
1257 if (ecc > (float)tex->afmax) b = a / (float)tex->afmax;
1260 maxd = MAX2(b, 1e-8f);
1261 levf = ((float)M_LOG2E)*logf(maxd);
1266 while (curmap < IB_MIPMAP_LEVELS) {
1267 mipmaps[curmap + 1] = ibuf->mipmap[curmap];
1268 if (ibuf->mipmap[curmap]) maxlev++;
1273 if (levf < 0.f) { // original image only
1274 previbuf = curibuf = mipmaps[0];
1277 else if (levf >= maxlev - 1) {
1278 previbuf = curibuf = mipmaps[maxlev - 1];
1280 if (tex->texfilter == TXF_FELINE) AFD.iProbes = 1;
1283 const int lev = ISNAN(levf) ? 0 : (int)levf;
1284 curibuf = mipmaps[lev];
1285 previbuf = mipmaps[lev + 1];
1286 levf -= floorf(levf);
1289 // filter functions take care of interpolation themselves, no need to modify dxt/dyt here
1291 if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
1293 filterfunc(texres, curibuf, fx, fy, &AFD);
1294 val1 = texres->tr + texres->tg + texres->tb;
1295 filterfunc(&texr, curibuf, fx + dxt[0], fy + dxt[1], &AFD);
1296 val2 = texr.tr + texr.tg + texr.tb;
1297 filterfunc(&texr, curibuf, fx + dyt[0], fy + dyt[1], &AFD);
1298 val3 = texr.tr + texr.tg + texr.tb;
1299 // don't switch x or y!
1300 texres->nor[0] = val1 - val2;
1301 texres->nor[1] = val1 - val3;
1302 if (previbuf != curibuf) { // interpolate
1303 filterfunc(&texr, previbuf, fx, fy, &AFD);
1305 texres->tr += levf*(texr.tr - texres->tr);
1306 texres->tg += levf*(texr.tg - texres->tg);
1307 texres->tb += levf*(texr.tb - texres->tb);
1308 texres->ta += levf*(texr.ta - texres->ta);
1310 val1 += levf*((texr.tr + texr.tg + texr.tb) - val1);
1311 filterfunc(&texr, previbuf, fx + dxt[0], fy + dxt[1], &AFD);
1312 val2 += levf*((texr.tr + texr.tg + texr.tb) - val2);
1313 filterfunc(&texr, previbuf, fx + dyt[0], fy + dyt[1], &AFD);
1314 val3 += levf*((texr.tr + texr.tg + texr.tb) - val3);
1315 texres->nor[0] = val1 - val2; // vals have been interpolated above!
1316 texres->nor[1] = val1 - val3;
1320 filterfunc(texres, curibuf, fx, fy, &AFD);
1321 if (previbuf != curibuf) { // interpolate
1322 filterfunc(&texr, previbuf, fx, fy, &AFD);
1323 texres->tr += levf*(texr.tr - texres->tr);
1324 texres->tg += levf*(texr.tg - texres->tg);
1325 texres->tb += levf*(texr.tb - texres->tb);
1326 texres->ta += levf*(texr.ta - texres->ta);
1329 alpha_clip_aniso(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, extflag, texres);
1333 // filter functions take care of interpolation themselves, no need to modify dxt/dyt here
1334 if (tex->texfilter == TXF_FELINE) {
1335 const float ff = sqrtf(ibuf->x), q = ibuf->y/ff;
1336 const float Ux = dxt[0]*ff, Vx = dxt[1]*q, Uy = dyt[0]*ff, Vy = dyt[1]*q;
1337 const float A = Vx*Vx + Vy*Vy;
1338 const float B = -2.f*(Ux*Vx + Uy*Vy);
1339 const float C = Ux*Ux + Uy*Uy;
1340 const float F = A*C - B*B*0.25f;
1341 float a, b, th, ecc, fProbes;
1342 imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
1347 fProbes = 2.f*(a / b) - 1.f;
1348 // no limit to number of Probes here
1349 AFD.iProbes = (int)floorf(fProbes + 0.5f);
1350 if (AFD.iProbes < fProbes) b = 2.f*a / (float)(AFD.iProbes + 1);
1355 AFD.dvsc = ff / (float)ibuf->y;
1357 if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
1359 filterfunc(texres, ibuf, fx, fy, &AFD);
1360 val1 = texres->tr + texres->tg + texres->tb;
1361 filterfunc(&texr, ibuf, fx + dxt[0], fy + dxt[1], &AFD);
1362 val2 = texr.tr + texr.tg + texr.tb;
1363 filterfunc(&texr, ibuf, fx + dyt[0], fy + dyt[1], &AFD);
1364 val3 = texr.tr + texr.tg + texr.tb;
1365 // don't switch x or y!
1366 texres->nor[0] = val1 - val2;
1367 texres->nor[1] = val1 - val3;
1370 filterfunc(texres, ibuf, fx, fy, &AFD);
1371 alpha_clip_aniso(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, extflag, texres);
1375 if (tex->imaflag & TEX_CALCALPHA)
1376 texres->ta = texres->tin = texres->ta * MAX3(texres->tr, texres->tg, texres->tb);
1378 texres->tin = texres->ta;
1379 if (tex->flag & TEX_NEGALPHA) texres->ta = 1.f - texres->ta;
1381 if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields))
1382 ibuf->rect -= ibuf->x*ibuf->y;
1384 if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) { // normal from color
1385 // The invert of the red channel is to make
1386 // the normal map compliant with the outside world.
1387 // It needs to be done because in Blender
1388 // the normal used in the renderer points inward. It is generated
1389 // this way in calc_vertexnormals(). Should this ever change
1390 // this negate must be removed.
1391 texres->nor[0] = -2.f*(texres->tr - 0.5f);
1392 texres->nor[1] = 2.f*(texres->tg - 0.5f);
1393 texres->nor[2] = 2.f*(texres->tb - 0.5f);
1396 // de-premul, this is being premulled in shade_input_do_shade()
1397 // TXF: this currently does not (yet?) work properly, destroys edge AA in clip/checker mode, so for now commented out
1398 // also disabled in imagewraposa() to be able to compare results with blender's default texture filtering
1400 // brecht: tried to fix this, see "TXF alpha" comments
1402 if (texres->ta != 1.f && (texres->ta > 1e-4f)) {
1403 fx = 1.f/texres->ta;
1415 int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[3], const float DYT[3], TexResult *texres)
1418 float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[3], dyt[3];
1419 float maxd, pixsize, val1, val2, val3;
1420 int curmap, retval, imaprepeat, imapextend;
1422 // TXF: since dxt/dyt might be modified here and since they might be needed after imagewraposa() call,
1423 // make a local copy here so that original vecs remain untouched
1424 copy_v3_v3(dxt, DXT);
1425 copy_v3_v3(dyt, DYT);
1427 // anisotropic filtering
1428 if (tex->texfilter != TXF_BOX)
1429 return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres);
1431 texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
1433 /* we need to set retval OK, otherwise texture code generates normals itself... */
1434 retval= texres->nor?3:1;
1437 if (ibuf==NULL && ima==NULL)
1441 /* hack for icon render */
1442 if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
1445 ibuf= BKE_image_get_ibuf(ima, &tex->iuser);
1447 ima->flag|= IMA_USED_FOR_RENDER;
1449 if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
1453 image_mipmap_test(tex, ibuf);
1455 if (tex->imaflag & TEX_USEALPHA) {
1456 if (tex->imaflag & TEX_CALCALPHA);
1457 else texres->talpha= 1;
1460 texr.talpha= texres->talpha;
1462 if (tex->imaflag & TEX_IMAROT) {
1471 if (ibuf->flags & IB_fields) {
1472 if (R.r.mode & R_FIELDS) { /* field render */
1473 if (R.flag & R_SEC_FIELD) { /* correction for 2nd field */
1474 /* fac1= 0.5/( (float)ibuf->y ); */
1477 else { /* first field */
1478 fy+= 0.5f/( (float)ibuf->y );
1483 /* pixel coordinates */
1485 minx= MIN3(dxt[0],dyt[0],dxt[0]+dyt[0] );
1486 maxx= MAX3(dxt[0],dyt[0],dxt[0]+dyt[0] );
1487 miny= MIN3(dxt[1],dyt[1],dxt[1]+dyt[1] );
1488 maxy= MAX3(dxt[1],dyt[1],dxt[1]+dyt[1] );
1490 /* tex_sharper has been removed */
1491 minx= (maxx-minx)/2.0f;
1492 miny= (maxy-miny)/2.0f;
1494 if (tex->imaflag & TEX_FILTER_MIN) {
1495 /* make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) */
1496 float addval= (0.5f * tex->filtersize) / (float) MIN2(ibuf->x, ibuf->y);
1503 else if (tex->filtersize!=1.0f) {
1504 minx*= tex->filtersize;
1505 miny*= tex->filtersize;
1507 dxt[0]*= tex->filtersize;
1508 dxt[1]*= tex->filtersize;
1509 dyt[0]*= tex->filtersize;
1510 dyt[1]*= tex->filtersize;
1513 if (tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny);
1515 if (minx>0.25f) minx= 0.25f;
1516 else if (minx<0.00001f) minx= 0.00001f; /* side faces of unit-cube */
1517 if (miny>0.25f) miny= 0.25f;
1518 else if (miny<0.00001f) miny= 0.00001f;
1521 /* repeat and clip */
1522 imaprepeat= (tex->extend==TEX_REPEAT);
1523 imapextend= (tex->extend==TEX_EXTEND);
1525 if (tex->extend == TEX_REPEAT) {
1526 if (tex->flag & (TEX_REPEAT_XMIR|TEX_REPEAT_YMIR)) {
1532 if (tex->extend == TEX_CHECKER) {
1533 int xs, ys, xs1, ys1, xs2, ys2, boundary;
1538 // both checkers available, no boundary exceptions, checkerdist will eat aliasing
1539 if ( (tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN) ) {
1545 xs1= (int)floor(fx-minx);
1546 ys1= (int)floor(fy-miny);
1547 xs2= (int)floor(fx+minx);
1548 ys2= (int)floor(fy+miny);
1549 boundary= (xs1!=xs2) || (ys1!=ys2);
1552 if ( (tex->flag & TEX_CHECKER_ODD)==0) {
1556 if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
1557 if ((xs+ys) & 1) return retval;
1563 if (tex->flag & TEX_CHECKER_ODD) {
1564 if ((xs1+ys) & 1) fx-= xs2;
1567 if ((ys1+xs) & 1) fy-= ys2;
1570 if (tex->flag & TEX_CHECKER_EVEN) {
1571 if ((xs1+ys) & 1) fx-= xs1;
1574 if ((ys1+xs) & 1) fy-= ys1;
1580 /* scale around center, (0.5, 0.5) */
1581 if (tex->checkerdist<1.0f) {
1582 fx= (fx-0.5f)/(1.0f-tex->checkerdist) +0.5f;
1583 fy= (fy-0.5f)/(1.0f-tex->checkerdist) +0.5f;
1584 minx/= (1.0f-tex->checkerdist);
1585 miny/= (1.0f-tex->checkerdist);
1589 if (tex->extend == TEX_CLIPCUBE) {
1590 if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f || texvec[2]<-1.0f || texvec[2]>1.0f) {
1594 else if (tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
1595 if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f) {
1601 if (fx>1.0f) fx = 1.0f;
1602 else if (fx<0.0f) fx= 0.0f;
1605 if (fx>1.0f) fx -= (int)(fx);
1606 else if (fx<0.0f) fx+= 1-(int)(fx);
1610 if (fy>1.0f) fy = 1.0f;
1611 else if (fy<0.0f) fy= 0.0f;
1614 if (fy>1.0f) fy -= (int)(fy);
1615 else if (fy<0.0f) fy+= 1-(int)(fy);
1619 /* warning no return! */
1620 if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
1621 ibuf->rect+= (ibuf->x*ibuf->y);
1625 if (tex->imaflag & TEX_MIPMAP) {
1626 ImBuf *previbuf, *curibuf;
1632 if (maxd>0.5f) maxd= 0.5f;
1634 pixsize = 1.0f/ (float) MIN2(ibuf->x, ibuf->y);
1636 bumpscale= pixsize/maxd;
1637 if (bumpscale>1.0f) bumpscale= 1.0f;
1638 else bumpscale*=bumpscale;
1641 previbuf= curibuf= ibuf;
1642 while (curmap<IB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) {
1643 if (maxd < pixsize) break;
1645 curibuf= ibuf->mipmap[curmap];
1646 pixsize= 1.0f / (float)MIN2(curibuf->x, curibuf->y);
1650 if (previbuf!=curibuf || (tex->imaflag & TEX_INTERPOL)) {
1651 /* sample at least 1 pixel */
1652 if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x;
1653 if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y;
1656 if (texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
1657 /* a bit extra filter */
1661 boxsample(curibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
1662 val1= texres->tr+texres->tg+texres->tb;
1663 boxsample(curibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
1664 val2= texr.tr + texr.tg + texr.tb;
1665 boxsample(curibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
1666 val3= texr.tr + texr.tg + texr.tb;
1668 /* don't switch x or y! */
1669 texres->nor[0]= (val1-val2);
1670 texres->nor[1]= (val1-val3);
1672 if (previbuf!=curibuf) { /* interpolate */
1674 boxsample(previbuf, fx-minx, fy-miny, fx+minx, fy+miny, &texr, imaprepeat, imapextend);
1677 dx= 2.0f*(pixsize-maxd)/pixsize;
1679 texres->ta= texr.ta; texres->tb= texr.tb;
1680 texres->tg= texr.tg; texres->tr= texr.tr;
1684 texres->tb= dy*texres->tb+ dx*texr.tb;
1685 texres->tg= dy*texres->tg+ dx*texr.tg;
1686 texres->tr= dy*texres->tr+ dx*texr.tr;
1687 texres->ta= dy*texres->ta+ dx*texr.ta;
1690 val1= dy*val1+ dx*(texr.tr + texr.tg + texr.tb);
1691 boxsample(previbuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
1692 val2= dy*val2+ dx*(texr.tr + texr.tg + texr.tb);
1693 boxsample(previbuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
1694 val3= dy*val3+ dx*(texr.tr + texr.tg + texr.tb);
1696 texres->nor[0]= (val1-val2); /* vals have been interpolated above! */
1697 texres->nor[1]= (val1-val3);
1701 texres->tb= dy*texres->tb+ dx*texr.tb;
1702 texres->tg= dy*texres->tg+ dx*texr.tg;
1703 texres->tr= dy*texres->tr+ dx*texr.tr;
1704 texres->ta= dy*texres->ta+ dx*texr.ta;
1707 texres->nor[0]*= bumpscale;
1708 texres->nor[1]*= bumpscale;
1716 boxsample(curibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend);
1718 if (previbuf!=curibuf) { /* interpolate */
1719 boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend);
1721 fx= 2.0f*(pixsize-maxd)/pixsize;
1724 texres->ta= texr.ta; texres->tb= texr.tb;
1725 texres->tg= texr.tg; texres->tr= texr.tr;
1729 texres->tb= fy*texres->tb+ fx*texr.tb;
1730 texres->tg= fy*texres->tg+ fx*texr.tg;
1731 texres->tr= fy*texres->tr+ fx*texr.tr;
1732 texres->ta= fy*texres->ta+ fx*texr.ta;
1738 const int intpol = tex->imaflag & TEX_INTERPOL;
1740 /* sample 1 pixel minimum */
1741 if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x;
1742 if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y;
1745 if (texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
1746 boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
1747 val1= texres->tr+texres->tg+texres->tb;
1748 boxsample(ibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
1749 val2= texr.tr + texr.tg + texr.tb;
1750 boxsample(ibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
1751 val3= texr.tr + texr.tg + texr.tb;
1753 /* don't switch x or y! */
1754 texres->nor[0]= (val1-val2);
1755 texres->nor[1]= (val1-val3);
1758 boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
1761 if (tex->imaflag & TEX_CALCALPHA) {
1762 texres->ta= texres->tin= texres->ta*MAX3(texres->tr, texres->tg, texres->tb);
1764 else texres->tin= texres->ta;
1766 if (tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
1768 if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
1769 ibuf->rect-= (ibuf->x*ibuf->y);
1772 if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) {
1773 // qdn: normal from color
1774 // The invert of the red channel is to make
1775 // the normal map compliant with the outside world.
1776 // It needs to be done because in Blender
1777 // the normal used in the renderer points inward. It is generated
1778 // this way in calc_vertexnormals(). Should this ever change
1779 // this negate must be removed.
1780 texres->nor[0] = -2.f*(texres->tr - 0.5f);
1781 texres->nor[1] = 2.f*(texres->tg - 0.5f);
1782 texres->nor[2] = 2.f*(texres->tb - 0.5f);
1785 /* de-premul, this is being premulled in shade_input_do_shade() */
1786 if (texres->ta!=1.0f && texres->ta>1e-4f) {
1787 fx= 1.0f/texres->ta;
1798 void image_sample(Image *ima, float fx, float fy, float dx, float dy, float *result)
1801 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
1804 result[0]= result[1]= result[2]= result[3]= 0.0f;
1808 if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) )
1809 ibuf->rect+= (ibuf->x*ibuf->y);
1811 texres.talpha= 1; /* boxsample expects to be initialized */
1812 boxsample(ibuf, fx, fy, fx+dx, fy+dy, &texres, 0, 1);
1813 result[0]= texres.tr;
1814 result[1]= texres.tg;
1815 result[2]= texres.tb;
1816 result[3]= texres.ta;
1818 if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) )
1819 ibuf->rect-= (ibuf->x*ibuf->y);
1821 ima->flag|= IMA_USED_FOR_RENDER;
1824 void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result)
1833 AFD.dxt[0] = dx; AFD.dxt[1] = dx;
1834 AFD.dyt[0] = dy; AFD.dyt[1] = dy;
1835 //copy_v2_v2(AFD.dxt, dx);
1836 //copy_v2_v2(AFD.dyt, dy);
1839 AFD.extflag = TXC_EXTD;
1841 memset(&texres, 0, sizeof(texres));
1842 ewa_eval(&texres, ibuf, fx, fy, &AFD);
1845 result[0]= texres.tr;
1846 result[1]= texres.tg;
1847 result[2]= texres.tb;
1848 result[3]= texres.ta;