|
Blender
V2.59
|
00001 /* 00002 * 00003 * $Id: imagetexture.c 37899 2011-06-28 12:48:39Z campbellbarton $ 00004 * 00005 * ***** BEGIN GPL LICENSE BLOCK ***** 00006 * 00007 * This program is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU General Public License 00009 * as published by the Free Software Foundation; either version 2 00010 * of the License, or (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software Foundation, 00019 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00020 * 00021 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00022 * All rights reserved. 00023 * 00024 * Contributors: 2004/2005/2006 Blender Foundation, full recode 00025 * 00026 * ***** END GPL/BL DUAL LICENSE BLOCK ***** 00027 */ 00028 00036 #include <stdio.h> 00037 #include <string.h> 00038 #include <fcntl.h> 00039 #include <math.h> 00040 #include <float.h> 00041 #ifndef WIN32 00042 #include <unistd.h> 00043 #else 00044 #include <io.h> 00045 #endif 00046 00047 #include "MEM_guardedalloc.h" 00048 00049 #include "IMB_imbuf_types.h" 00050 #include "IMB_imbuf.h" 00051 00052 #include "DNA_image_types.h" 00053 #include "DNA_scene_types.h" 00054 #include "DNA_texture_types.h" 00055 00056 #include "BLI_math.h" 00057 #include "BLI_blenlib.h" 00058 #include "BLI_threads.h" 00059 #include "BLI_utildefines.h" 00060 00061 #include "BKE_global.h" 00062 #include "BKE_main.h" 00063 #include "BKE_image.h" 00064 #include "BKE_texture.h" 00065 #include "BKE_library.h" 00066 00067 #include "RE_render_ext.h" 00068 00069 #include "renderpipeline.h" 00070 #include "render_types.h" 00071 #include "texture.h" 00072 00073 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00074 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ 00075 /* only to be used here in this file, it's for speed */ 00076 extern struct Render R; 00077 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00078 00079 static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend); 00080 00081 /* *********** IMAGEWRAPPING ****************** */ 00082 00083 00084 /* x and y have to be checked for image size */ 00085 static void ibuf_get_color(float *col, struct ImBuf *ibuf, int x, int y) 00086 { 00087 int ofs = y * ibuf->x + x; 00088 00089 if(ibuf->rect_float) { 00090 if(ibuf->channels==4) { 00091 float *fp= ibuf->rect_float + 4*ofs; 00092 QUATCOPY(col, fp); 00093 } 00094 else if(ibuf->channels==3) { 00095 float *fp= ibuf->rect_float + 3*ofs; 00096 VECCOPY(col, fp); 00097 col[3]= 1.0f; 00098 } 00099 else { 00100 float *fp= ibuf->rect_float + ofs; 00101 col[0]= col[1]= col[2]= col[3]= *fp; 00102 } 00103 } 00104 else { 00105 char *rect = (char *)( ibuf->rect+ ofs); 00106 00107 col[0] = ((float)rect[0])*(1.0f/255.0f); 00108 col[1] = ((float)rect[1])*(1.0f/255.0f); 00109 col[2] = ((float)rect[2])*(1.0f/255.0f); 00110 col[3] = ((float)rect[3])*(1.0f/255.0f); 00111 } 00112 } 00113 00114 int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, TexResult *texres) 00115 { 00116 float fx, fy, val1, val2, val3; 00117 int x, y, retval; 00118 int xi, yi; /* original values */ 00119 00120 texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f; 00121 00122 /* we need to set retval OK, otherwise texture code generates normals itself... */ 00123 retval= texres->nor?3:1; 00124 00125 /* quick tests */ 00126 if(ibuf==NULL && ima==NULL) 00127 return retval; 00128 if(ima) { 00129 00130 /* hack for icon render */ 00131 if(ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD)) 00132 return retval; 00133 00134 ibuf= BKE_image_get_ibuf(ima, &tex->iuser); 00135 } 00136 if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) 00137 return retval; 00138 00139 /* setup mapping */ 00140 if(tex->imaflag & TEX_IMAROT) { 00141 fy= texvec[0]; 00142 fx= texvec[1]; 00143 } 00144 else { 00145 fx= texvec[0]; 00146 fy= texvec[1]; 00147 } 00148 00149 if(tex->extend == TEX_CHECKER) { 00150 int xs, ys; 00151 00152 xs= (int)floor(fx); 00153 ys= (int)floor(fy); 00154 fx-= xs; 00155 fy-= ys; 00156 00157 if( (tex->flag & TEX_CHECKER_ODD)==0) { 00158 if((xs+ys) & 1);else return retval; 00159 } 00160 if( (tex->flag & TEX_CHECKER_EVEN)==0) { 00161 if((xs+ys) & 1) return retval; 00162 } 00163 /* scale around center, (0.5, 0.5) */ 00164 if(tex->checkerdist<1.0f) { 00165 fx= (fx-0.5f)/(1.0f-tex->checkerdist) +0.5f; 00166 fy= (fy-0.5f)/(1.0f-tex->checkerdist) +0.5f; 00167 } 00168 } 00169 00170 x= xi= (int)floorf(fx*ibuf->x); 00171 y= yi= (int)floorf(fy*ibuf->y); 00172 00173 if(tex->extend == TEX_CLIPCUBE) { 00174 if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0f || texvec[2]>1.0f) { 00175 return retval; 00176 } 00177 } 00178 else if( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) { 00179 if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) { 00180 return retval; 00181 } 00182 } 00183 else { 00184 if(tex->extend==TEX_EXTEND) { 00185 if(x>=ibuf->x) x = ibuf->x-1; 00186 else if(x<0) x= 0; 00187 } 00188 else { 00189 x= x % ibuf->x; 00190 if(x<0) x+= ibuf->x; 00191 } 00192 if(tex->extend==TEX_EXTEND) { 00193 if(y>=ibuf->y) y = ibuf->y-1; 00194 else if(y<0) y= 0; 00195 } 00196 else { 00197 y= y % ibuf->y; 00198 if(y<0) y+= ibuf->y; 00199 } 00200 } 00201 00202 /* warning, no return before setting back! */ 00203 if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { 00204 ibuf->rect+= (ibuf->x*ibuf->y); 00205 } 00206 00207 /* interpolate */ 00208 if (tex->imaflag & TEX_INTERPOL) { 00209 float filterx, filtery; 00210 filterx = (0.5f * tex->filtersize) / ibuf->x; 00211 filtery = (0.5f * tex->filtersize) / ibuf->y; 00212 00213 /* important that this value is wrapped [#27782] 00214 * this applies the modifications made by the checks above, 00215 * back to the floating point values */ 00216 fx -= (float)(xi - x) / (float)ibuf->x; 00217 fy -= (float)(yi - y) / (float)ibuf->y; 00218 00219 boxsample(ibuf, fx-filterx, fy-filtery, fx+filterx, fy+filtery, texres, (tex->extend==TEX_REPEAT), (tex->extend==TEX_EXTEND)); 00220 } 00221 else { /* no filtering */ 00222 ibuf_get_color(&texres->tr, ibuf, x, y); 00223 } 00224 00225 if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { 00226 ibuf->rect-= (ibuf->x*ibuf->y); 00227 } 00228 00229 if(tex->imaflag & TEX_USEALPHA) { 00230 if(tex->imaflag & TEX_CALCALPHA); 00231 else texres->talpha= 1; 00232 } 00233 00234 if(texres->nor) { 00235 if(tex->imaflag & TEX_NORMALMAP) { 00236 // qdn: normal from color 00237 // The invert of the red channel is to make 00238 // the normal map compliant with the outside world. 00239 // It needs to be done because in Blender 00240 // the normal used in the renderer points inward. It is generated 00241 // this way in calc_vertexnormals(). Should this ever change 00242 // this negate must be removed. 00243 texres->nor[0] = -2.f*(texres->tr - 0.5f); 00244 texres->nor[1] = 2.f*(texres->tg - 0.5f); 00245 texres->nor[2] = 2.f*(texres->tb - 0.5f); 00246 } 00247 else { 00248 /* bump: take three samples */ 00249 val1= texres->tr+texres->tg+texres->tb; 00250 00251 if(x<ibuf->x-1) { 00252 float col[4]; 00253 ibuf_get_color(col, ibuf, x+1, y); 00254 val2= (col[0]+col[1]+col[2]); 00255 } 00256 else val2= val1; 00257 00258 if(y<ibuf->y-1) { 00259 float col[4]; 00260 ibuf_get_color(col, ibuf, x, y+1); 00261 val3= (col[0]+col[1]+col[2]); 00262 } 00263 else val3= val1; 00264 00265 /* do not mix up x and y here! */ 00266 texres->nor[0]= (val1-val2); 00267 texres->nor[1]= (val1-val3); 00268 } 00269 } 00270 00271 if(texres->talpha) texres->tin= texres->ta; 00272 else if(tex->imaflag & TEX_CALCALPHA) { 00273 texres->ta= texres->tin= MAX3(texres->tr, texres->tg, texres->tb); 00274 } 00275 else texres->ta= texres->tin= 1.0; 00276 00277 if(tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta; 00278 00279 /* de-premul, this is being premulled in shade_input_do_shade() */ 00280 if(texres->ta!=1.0f && texres->ta>1e-4f) { 00281 fx= 1.0f/texres->ta; 00282 texres->tr*= fx; 00283 texres->tg*= fx; 00284 texres->tb*= fx; 00285 } 00286 00287 BRICONTRGB; 00288 00289 return retval; 00290 } 00291 00292 static void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2) 00293 { 00294 rctf *rf, *newrct; 00295 short a; 00296 00297 a= *count; 00298 rf= stack; 00299 for(;a>0;a--) { 00300 if(rf->xmin<x1) { 00301 if(rf->xmax<x1) { 00302 rf->xmin+= (x2-x1); 00303 rf->xmax+= (x2-x1); 00304 } 00305 else { 00306 if(rf->xmax>x2) rf->xmax= x2; 00307 newrct= stack+ *count; 00308 (*count)++; 00309 00310 newrct->xmax= x2; 00311 newrct->xmin= rf->xmin+(x2-x1); 00312 newrct->ymin= rf->ymin; 00313 newrct->ymax= rf->ymax; 00314 00315 if(newrct->xmin==newrct->xmax) (*count)--; 00316 00317 rf->xmin= x1; 00318 } 00319 } 00320 else if(rf->xmax>x2) { 00321 if(rf->xmin>x2) { 00322 rf->xmin-= (x2-x1); 00323 rf->xmax-= (x2-x1); 00324 } 00325 else { 00326 if(rf->xmin<x1) rf->xmin= x1; 00327 newrct= stack+ *count; 00328 (*count)++; 00329 00330 newrct->xmin= x1; 00331 newrct->xmax= rf->xmax-(x2-x1); 00332 newrct->ymin= rf->ymin; 00333 newrct->ymax= rf->ymax; 00334 00335 if(newrct->xmin==newrct->xmax) (*count)--; 00336 00337 rf->xmax= x2; 00338 } 00339 } 00340 rf++; 00341 } 00342 00343 } 00344 00345 static void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2) 00346 { 00347 rctf *rf, *newrct; 00348 short a; 00349 00350 a= *count; 00351 rf= stack; 00352 for(;a>0;a--) { 00353 if(rf->ymin<y1) { 00354 if(rf->ymax<y1) { 00355 rf->ymin+= (y2-y1); 00356 rf->ymax+= (y2-y1); 00357 } 00358 else { 00359 if(rf->ymax>y2) rf->ymax= y2; 00360 newrct= stack+ *count; 00361 (*count)++; 00362 00363 newrct->ymax= y2; 00364 newrct->ymin= rf->ymin+(y2-y1); 00365 newrct->xmin= rf->xmin; 00366 newrct->xmax= rf->xmax; 00367 00368 if(newrct->ymin==newrct->ymax) (*count)--; 00369 00370 rf->ymin= y1; 00371 } 00372 } 00373 else if(rf->ymax>y2) { 00374 if(rf->ymin>y2) { 00375 rf->ymin-= (y2-y1); 00376 rf->ymax-= (y2-y1); 00377 } 00378 else { 00379 if(rf->ymin<y1) rf->ymin= y1; 00380 newrct= stack+ *count; 00381 (*count)++; 00382 00383 newrct->ymin= y1; 00384 newrct->ymax= rf->ymax-(y2-y1); 00385 newrct->xmin= rf->xmin; 00386 newrct->xmax= rf->xmax; 00387 00388 if(newrct->ymin==newrct->ymax) (*count)--; 00389 00390 rf->ymax= y2; 00391 } 00392 } 00393 rf++; 00394 } 00395 } 00396 00397 static float square_rctf(rctf *rf) 00398 { 00399 float x, y; 00400 00401 x= rf->xmax- rf->xmin; 00402 y= rf->ymax- rf->ymin; 00403 return (x*y); 00404 } 00405 00406 static float clipx_rctf(rctf *rf, float x1, float x2) 00407 { 00408 float size; 00409 00410 size= rf->xmax - rf->xmin; 00411 00412 if(rf->xmin<x1) { 00413 rf->xmin= x1; 00414 } 00415 if(rf->xmax>x2) { 00416 rf->xmax= x2; 00417 } 00418 if(rf->xmin > rf->xmax) { 00419 rf->xmin = rf->xmax; 00420 return 0.0; 00421 } 00422 else if(size!=0.0f) { 00423 return (rf->xmax - rf->xmin)/size; 00424 } 00425 return 1.0; 00426 } 00427 00428 static float clipy_rctf(rctf *rf, float y1, float y2) 00429 { 00430 float size; 00431 00432 size= rf->ymax - rf->ymin; 00433 00434 if(rf->ymin<y1) { 00435 rf->ymin= y1; 00436 } 00437 if(rf->ymax>y2) { 00438 rf->ymax= y2; 00439 } 00440 00441 if(rf->ymin > rf->ymax) { 00442 rf->ymin = rf->ymax; 00443 return 0.0; 00444 } 00445 else if(size!=0.0f) { 00446 return (rf->ymax - rf->ymin)/size; 00447 } 00448 return 1.0; 00449 00450 } 00451 00452 static void boxsampleclip(struct ImBuf *ibuf, rctf *rf, TexResult *texres) 00453 { 00454 /* sample box, is clipped already, and minx etc. have been set at ibuf size. 00455 Enlarge with antialiased edges of the pixels */ 00456 00457 float muly, mulx, div, col[4]; 00458 int x, y, startx, endx, starty, endy; 00459 00460 startx= (int)floor(rf->xmin); 00461 endx= (int)floor(rf->xmax); 00462 starty= (int)floor(rf->ymin); 00463 endy= (int)floor(rf->ymax); 00464 00465 if(startx < 0) startx= 0; 00466 if(starty < 0) starty= 0; 00467 if(endx>=ibuf->x) endx= ibuf->x-1; 00468 if(endy>=ibuf->y) endy= ibuf->y-1; 00469 00470 if(starty==endy && startx==endx) { 00471 ibuf_get_color(&texres->tr, ibuf, startx, starty); 00472 } 00473 else { 00474 div= texres->tr= texres->tg= texres->tb= texres->ta= 0.0; 00475 for(y=starty; y<=endy; y++) { 00476 00477 muly= 1.0; 00478 00479 if(starty==endy); 00480 else { 00481 if(y==starty) muly= 1.0f-(rf->ymin - y); 00482 if(y==endy) muly= (rf->ymax - y); 00483 } 00484 00485 if(startx==endx) { 00486 mulx= muly; 00487 00488 ibuf_get_color(col, ibuf, startx, y); 00489 00490 texres->ta+= mulx*col[3]; 00491 texres->tr+= mulx*col[0]; 00492 texres->tg+= mulx*col[1]; 00493 texres->tb+= mulx*col[2]; 00494 div+= mulx; 00495 } 00496 else { 00497 for(x=startx; x<=endx; x++) { 00498 mulx= muly; 00499 if(x==startx) mulx*= 1.0f-(rf->xmin - x); 00500 if(x==endx) mulx*= (rf->xmax - x); 00501 00502 ibuf_get_color(col, ibuf, x, y); 00503 00504 if(mulx==1.0f) { 00505 texres->ta+= col[3]; 00506 texres->tr+= col[0]; 00507 texres->tg+= col[1]; 00508 texres->tb+= col[2]; 00509 div+= 1.0f; 00510 } 00511 else { 00512 texres->ta+= mulx*col[3]; 00513 texres->tr+= mulx*col[0]; 00514 texres->tg+= mulx*col[1]; 00515 texres->tb+= mulx*col[2]; 00516 div+= mulx; 00517 } 00518 } 00519 } 00520 } 00521 00522 if(div!=0.0f) { 00523 div= 1.0f/div; 00524 texres->tb*= div; 00525 texres->tg*= div; 00526 texres->tr*= div; 00527 texres->ta*= div; 00528 } 00529 else { 00530 texres->tr= texres->tg= texres->tb= texres->ta= 0.0f; 00531 } 00532 } 00533 } 00534 00535 static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend) 00536 { 00537 /* Sample box, performs clip. minx etc are in range 0.0 - 1.0 . 00538 * Enlarge with antialiased edges of pixels. 00539 * If variable 'imaprepeat' has been set, the 00540 * clipped-away parts are sampled as well. 00541 */ 00542 /* note: actually minx etc isnt in the proper range... this due to filter size and offset vectors for bump */ 00543 /* note: talpha must be initialized */ 00544 /* note: even when 'imaprepeat' is set, this can only repeate once in any direction. 00545 * the point which min/max is derived from is assumed to be wrapped */ 00546 TexResult texr; 00547 rctf *rf, stack[8]; 00548 float opp, tot, alphaclip= 1.0; 00549 short count=1; 00550 00551 rf= stack; 00552 rf->xmin= minx*(ibuf->x); 00553 rf->xmax= maxx*(ibuf->x); 00554 rf->ymin= miny*(ibuf->y); 00555 rf->ymax= maxy*(ibuf->y); 00556 00557 texr.talpha= texres->talpha; /* is read by boxsample_clip */ 00558 00559 if(imapextend) { 00560 CLAMP(rf->xmin, 0.0f, ibuf->x-1); 00561 CLAMP(rf->xmax, 0.0f, ibuf->x-1); 00562 } 00563 else if(imaprepeat) 00564 clipx_rctf_swap(stack, &count, 0.0, (float)(ibuf->x)); 00565 else { 00566 alphaclip= clipx_rctf(rf, 0.0, (float)(ibuf->x)); 00567 00568 if(alphaclip<=0.0f) { 00569 texres->tr= texres->tb= texres->tg= texres->ta= 0.0; 00570 return; 00571 } 00572 } 00573 00574 if(imapextend) { 00575 CLAMP(rf->ymin, 0.0f, ibuf->y-1); 00576 CLAMP(rf->ymax, 0.0f, ibuf->y-1); 00577 } 00578 else if(imaprepeat) 00579 clipy_rctf_swap(stack, &count, 0.0, (float)(ibuf->y)); 00580 else { 00581 alphaclip*= clipy_rctf(rf, 0.0, (float)(ibuf->y)); 00582 00583 if(alphaclip<=0.0f) { 00584 texres->tr= texres->tb= texres->tg= texres->ta= 0.0; 00585 return; 00586 } 00587 } 00588 00589 if(count>1) { 00590 tot= texres->tr= texres->tb= texres->tg= texres->ta= 0.0; 00591 while(count--) { 00592 boxsampleclip(ibuf, rf, &texr); 00593 00594 opp= square_rctf(rf); 00595 tot+= opp; 00596 00597 texres->tr+= opp*texr.tr; 00598 texres->tg+= opp*texr.tg; 00599 texres->tb+= opp*texr.tb; 00600 if(texres->talpha) texres->ta+= opp*texr.ta; 00601 rf++; 00602 } 00603 if(tot!= 0.0f) { 00604 texres->tr/= tot; 00605 texres->tg/= tot; 00606 texres->tb/= tot; 00607 if(texres->talpha) texres->ta/= tot; 00608 } 00609 } 00610 else 00611 boxsampleclip(ibuf, rf, texres); 00612 00613 if(texres->talpha==0) texres->ta= 1.0; 00614 00615 if(alphaclip!=1.0f) { 00616 /* premul it all */ 00617 texres->tr*= alphaclip; 00618 texres->tg*= alphaclip; 00619 texres->tb*= alphaclip; 00620 texres->ta*= alphaclip; 00621 } 00622 } 00623 00624 //----------------------------------------------------------------------------------------------------------------- 00625 // from here, some functions only used for the new filtering 00626 00627 // anisotropic filters, data struct used instead of long line of (possibly unused) func args 00628 typedef struct afdata_t { 00629 float dxt[2], dyt[2]; 00630 int intpol, extflag; 00631 // feline only 00632 float majrad, minrad, theta; 00633 int iProbes; 00634 float dusc, dvsc; 00635 } afdata_t; 00636 00637 // this only used here to make it easier to pass extend flags as single int 00638 enum {TXC_XMIR=1, TXC_YMIR, TXC_REPT, TXC_EXTD}; 00639 00640 // similar to ibuf_get_color() but clips/wraps coords according to repeat/extend flags 00641 // returns true if out of range in clipmode 00642 static int ibuf_get_color_clip(float *col, ImBuf *ibuf, int x, int y, int extflag) 00643 { 00644 int clip = 0; 00645 switch (extflag) { 00646 case TXC_XMIR: // y rep 00647 x %= 2*ibuf->x; 00648 x += x < 0 ? 2*ibuf->x : 0; 00649 x = x >= ibuf->x ? 2*ibuf->x - x - 1 : x; 00650 y %= ibuf->y; 00651 y += y < 0 ? ibuf->y : 0; 00652 break; 00653 case TXC_YMIR: // x rep 00654 x %= ibuf->x; 00655 x += x < 0 ? ibuf->x : 0; 00656 y %= 2*ibuf->y; 00657 y += y < 0 ? 2*ibuf->y : 0; 00658 y = y >= ibuf->y ? 2*ibuf->y - y - 1 : y; 00659 break; 00660 case TXC_EXTD: 00661 x = (x < 0) ? 0 : ((x >= ibuf->x) ? (ibuf->x - 1) : x); 00662 y = (y < 0) ? 0 : ((y >= ibuf->y) ? (ibuf->y - 1) : y); 00663 break; 00664 case TXC_REPT: 00665 x %= ibuf->x; 00666 x += (x < 0) ? ibuf->x : 0; 00667 y %= ibuf->y; 00668 y += (y < 0) ? ibuf->y : 0; 00669 break; 00670 default: { // as extend, if clipped, set alpha to 0.0 00671 if (x < 0) { x = 0; } // TXF alpha: clip = 1; } 00672 if (x >= ibuf->x) { x = ibuf->x - 1; } // TXF alpha: clip = 1; } 00673 if (y < 0) { y = 0; } // TXF alpha: clip = 1; } 00674 if (y >= ibuf->y) { y = ibuf->y - 1; } // TXF alpha: clip = 1; } 00675 } 00676 } 00677 00678 if (ibuf->rect_float) { 00679 const float* fp = ibuf->rect_float + (x + y*ibuf->x)*ibuf->channels; 00680 if (ibuf->channels == 1) 00681 col[0] = col[1] = col[2] = col[3] = *fp; 00682 else { 00683 col[0] = fp[0]; 00684 col[1] = fp[1]; 00685 col[2] = fp[2]; 00686 col[3] = clip ? 0.f : (ibuf->channels == 4 ? fp[3] : 1.f); 00687 } 00688 } 00689 else { 00690 char* rect = (char*)(ibuf->rect + x + y*ibuf->x); 00691 col[0] = rect[0]*(1.f/255.f); 00692 col[1] = rect[1]*(1.f/255.f); 00693 col[2] = rect[2]*(1.f/255.f); 00694 col[3] = clip ? 0.f : rect[3]*(1.f/255.f); 00695 } 00696 return clip; 00697 } 00698 00699 // as above + bilerp 00700 static int ibuf_get_color_clip_bilerp(float *col, ImBuf *ibuf, float u, float v, int intpol, int extflag) 00701 { 00702 if (intpol) { 00703 float c00[4], c01[4], c10[4], c11[4]; 00704 const float ufl = floorf(u -= 0.5f), vfl = floorf(v -= 0.5f); 00705 const float uf = u - ufl, vf = v - vfl; 00706 const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf; 00707 const int x1 = (int)ufl, y1 = (int)vfl, x2 = x1 + 1, y2 = y1 + 1; 00708 int clip = ibuf_get_color_clip(c00, ibuf, x1, y1, extflag); 00709 clip |= ibuf_get_color_clip(c10, ibuf, x2, y1, extflag); 00710 clip |= ibuf_get_color_clip(c01, ibuf, x1, y2, extflag); 00711 clip |= ibuf_get_color_clip(c11, ibuf, x2, y2, extflag); 00712 col[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0]; 00713 col[1] = w00*c00[1] + w10*c10[1] + w01*c01[1] + w11*c11[1]; 00714 col[2] = w00*c00[2] + w10*c10[2] + w01*c01[2] + w11*c11[2]; 00715 col[3] = clip ? 0.f : w00*c00[3] + w10*c10[3] + w01*c01[3] + w11*c11[3]; 00716 return clip; 00717 } 00718 return ibuf_get_color_clip(col, ibuf, (int)u, (int)v, extflag); 00719 } 00720 00721 static void area_sample(TexResult* texr, ImBuf* ibuf, float fx, float fy, afdata_t* AFD) 00722 { 00723 int xs, ys, clip = 0; 00724 float tc[4], xsd, ysd, cw = 0.f; 00725 const float ux = ibuf->x*AFD->dxt[0], uy = ibuf->y*AFD->dxt[1]; 00726 const float vx = ibuf->x*AFD->dyt[0], vy = ibuf->y*AFD->dyt[1]; 00727 int xsam = (int)(0.5f*sqrtf(ux*ux + uy*uy) + 0.5f); 00728 int ysam = (int)(0.5f*sqrtf(vx*vx + vy*vy) + 0.5f); 00729 const int minsam = AFD->intpol ? 2 : 4; 00730 xsam = CLAMPIS(xsam, minsam, ibuf->x*2); 00731 ysam = CLAMPIS(ysam, minsam, ibuf->y*2); 00732 xsd = 1.f / xsam; 00733 ysd = 1.f / ysam; 00734 texr->tr = texr->tg = texr->tb = texr->ta = 0.f; 00735 for (ys=0; ys<ysam; ++ys) { 00736 for (xs=0; xs<xsam; ++xs) { 00737 const float su = (xs + ((ys & 1) + 0.5f)*0.5f)*xsd - 0.5f; 00738 const float sv = (ys + ((xs & 1) + 0.5f)*0.5f)*ysd - 0.5f; 00739 const float pu = fx + su*AFD->dxt[0] + sv*AFD->dyt[0]; 00740 const float pv = fy + su*AFD->dxt[1] + sv*AFD->dyt[1]; 00741 const int out = ibuf_get_color_clip_bilerp(tc, ibuf, pu*ibuf->x, pv*ibuf->y, AFD->intpol, AFD->extflag); 00742 clip |= out; 00743 cw += out ? 0.f : 1.f; 00744 texr->tr += tc[0]; 00745 texr->tg += tc[1]; 00746 texr->tb += tc[2]; 00747 texr->ta += texr->talpha ? tc[3] : 0.f; 00748 } 00749 } 00750 xsd *= ysd; 00751 texr->tr *= xsd; 00752 texr->tg *= xsd; 00753 texr->tb *= xsd; 00754 // clipping can be ignored if alpha used, texr->ta already includes filtered edge 00755 texr->ta = texr->talpha ? texr->ta*xsd : (clip ? cw*xsd : 1.f); 00756 } 00757 00758 // table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2 00759 // used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible 00760 #define EWA_MAXIDX 255 00761 static float EWA_WTS[EWA_MAXIDX + 1] = 00762 { 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f, 00763 0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f, 00764 0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f, 00765 0.794079f, 0.786653f, 0.779284f, 0.771974f, 0.76472f, 0.757523f, 0.750382f, 0.743297f, 00766 0.736267f, 0.729292f, 0.722372f, 0.715505f, 0.708693f, 0.701933f, 0.695227f, 0.688572f, 00767 0.68197f, 0.67542f, 0.66892f, 0.662471f, 0.656073f, 0.649725f, 0.643426f, 0.637176f, 00768 0.630976f, 0.624824f, 0.618719f, 0.612663f, 0.606654f, 0.600691f, 0.594776f, 0.588906f, 00769 0.583083f, 0.577305f, 0.571572f, 0.565883f, 0.56024f, 0.55464f, 0.549084f, 0.543572f, 00770 0.538102f, 0.532676f, 0.527291f, 0.521949f, 0.516649f, 0.511389f, 0.506171f, 0.500994f, 00771 0.495857f, 0.490761f, 0.485704f, 0.480687f, 0.475709f, 0.470769f, 0.465869f, 0.461006f, 00772 0.456182f, 0.451395f, 0.446646f, 0.441934f, 0.437258f, 0.432619f, 0.428017f, 0.42345f, 00773 0.418919f, 0.414424f, 0.409963f, 0.405538f, 0.401147f, 0.39679f, 0.392467f, 0.388178f, 00774 0.383923f, 0.379701f, 0.375511f, 0.371355f, 0.367231f, 0.363139f, 0.359079f, 0.355051f, 00775 0.351055f, 0.347089f, 0.343155f, 0.339251f, 0.335378f, 0.331535f, 0.327722f, 0.323939f, 00776 0.320186f, 0.316461f, 0.312766f, 0.3091f, 0.305462f, 0.301853f, 0.298272f, 0.294719f, 00777 0.291194f, 0.287696f, 0.284226f, 0.280782f, 0.277366f, 0.273976f, 0.270613f, 0.267276f, 00778 0.263965f, 0.26068f, 0.257421f, 0.254187f, 0.250979f, 0.247795f, 0.244636f, 0.241502f, 00779 0.238393f, 0.235308f, 0.232246f, 0.229209f, 0.226196f, 0.223206f, 0.220239f, 0.217296f, 00780 0.214375f, 0.211478f, 0.208603f, 0.20575f, 0.20292f, 0.200112f, 0.197326f, 0.194562f, 00781 0.191819f, 0.189097f, 0.186397f, 0.183718f, 0.18106f, 0.178423f, 0.175806f, 0.17321f, 00782 0.170634f, 0.168078f, 0.165542f, 0.163026f, 0.16053f, 0.158053f, 0.155595f, 0.153157f, 00783 0.150738f, 0.148337f, 0.145955f, 0.143592f, 0.141248f, 0.138921f, 0.136613f, 0.134323f, 00784 0.132051f, 0.129797f, 0.12756f, 0.125341f, 0.123139f, 0.120954f, 0.118786f, 0.116635f, 00785 0.114501f, 0.112384f, 0.110283f, 0.108199f, 0.106131f, 0.104079f, 0.102043f, 0.100023f, 00786 0.0980186f, 0.09603f, 0.094057f, 0.0920994f, 0.0901571f, 0.08823f, 0.0863179f, 0.0844208f, 00787 0.0825384f, 0.0806708f, 0.0788178f, 0.0769792f, 0.0751551f, 0.0733451f, 0.0715493f, 0.0697676f, 00788 0.0679997f, 0.0662457f, 0.0645054f, 0.0627786f, 0.0610654f, 0.0593655f, 0.0576789f, 0.0560055f, 00789 0.0543452f, 0.0526979f, 0.0510634f, 0.0494416f, 0.0478326f, 0.0462361f, 0.0446521f, 0.0430805f, 00790 0.0415211f, 0.039974f, 0.0384389f, 0.0369158f, 0.0354046f, 0.0339052f, 0.0324175f, 0.0309415f, 00791 0.029477f, 0.0280239f, 0.0265822f, 0.0251517f, 0.0237324f, 0.0223242f, 0.020927f, 0.0195408f, 00792 0.0181653f, 0.0168006f, 0.0154466f, 0.0141031f, 0.0127701f, 0.0114476f, 0.0101354f, 0.00883339f, 00793 0.00754159f, 0.00625989f, 0.00498819f, 0.00372644f, 0.00247454f, 0.00123242f, 0.f 00794 }; 00795 00796 // test if a float value is 'nan' 00797 // there is a C99 function for this: isnan(), but blender seems to use C90 (according to gcc warns), 00798 // and may not be supported by other compilers either 00799 #ifndef ISNAN 00800 #define ISNAN(x) ((x) != (x)) 00801 #endif 00802 //static int ISNAN(float x) { return (x != x); } 00803 00804 static void radangle2imp(float a2, float b2, float th, float* A, float* B, float* C, float* F) 00805 { 00806 float ct2 = cosf(th); 00807 const float st2 = 1.f - ct2*ct2; // <- sin(th)^2 00808 ct2 *= ct2; 00809 *A = a2*st2 + b2*ct2; 00810 *B = (b2 - a2)*sinf(2.f*th); 00811 *C = a2*ct2 + b2*st2; 00812 *F = a2*b2; 00813 } 00814 00815 // all tests here are done to make sure possible overflows are hopefully minimized 00816 static void imp2radangle(float A, float B, float C, float F, float* a, float* b, float* th, float* ecc) 00817 { 00818 if (F <= 1e-5f) { // use arbitrary major radius, zero minor, infinite eccentricity 00819 *a = sqrtf(A > C ? A : C); 00820 *b = 0.f; 00821 *ecc = 1e10f; 00822 *th = 0.5f*(atan2f(B, A - C) + (float)M_PI); 00823 } 00824 else { 00825 const float AmC = A - C, ApC = A + C, F2 = F*2.f; 00826 const float r = sqrtf(AmC*AmC + B*B); 00827 float d = ApC - r; 00828 *a = (d <= 0.f) ? sqrtf(A > C ? A : C) : sqrtf(F2 / d); 00829 d = ApC + r; 00830 if (d <= 0.f) { 00831 *b = 0.f; 00832 *ecc = 1e10f; 00833 } 00834 else { 00835 *b = sqrtf(F2 / d); 00836 *ecc = *a / *b; 00837 } 00838 // incr theta by 0.5*pi (angle of major axis) 00839 *th = 0.5f*(atan2f(B, AmC) + (float)M_PI); 00840 } 00841 } 00842 00843 static void ewa_eval(TexResult* texr, ImBuf* ibuf, float fx, float fy, afdata_t* AFD) 00844 { 00845 // scaling dxt/dyt by full resolution can cause overflow because of huge A/B/C and esp. F values, 00846 // scaling by aspect ratio alone does the opposite, so try something in between instead... 00847 const float ff2 = ibuf->x, ff = sqrtf(ff2), q = ibuf->y / ff; 00848 const float Ux = AFD->dxt[0]*ff, Vx = AFD->dxt[1]*q, Uy = AFD->dyt[0]*ff, Vy = AFD->dyt[1]*q; 00849 float A = Vx*Vx + Vy*Vy; 00850 float B = -2.f*(Ux*Vx + Uy*Vy); 00851 float C = Ux*Ux + Uy*Uy; 00852 float F = A*C - B*B*0.25f; 00853 float a, b, th, ecc, a2, b2, ue, ve, U0, V0, DDQ, U, ac1, ac2, BU, d; // TXF alpha: cw = 0.f; 00854 int u, v, u1, u2, v1, v2; // TXF alpha: clip = 0; 00855 00856 // The so-called 'high' quality ewa method simply adds a constant of 1 to both A & C, 00857 // so the ellipse always covers at least some texels. But since the filter is now always larger, 00858 // it also means that everywhere else it's also more blurry then ideally should be the case. 00859 // So instead here the ellipse radii are modified instead whenever either is too low. 00860 // Use a different radius based on interpolation switch, just enough to anti-alias when interpolation is off, 00861 // and slightly larger to make result a bit smoother than bilinear interpolation when interpolation is on 00862 // (minimum values: const float rmin = intpol ? 1.f : 0.5f;) 00863 const float rmin = (AFD->intpol ? 1.5625f : 0.765625f)/ff2; 00864 imp2radangle(A, B, C, F, &a, &b, &th, &ecc); 00865 if ((b2 = b*b) < rmin) { 00866 if ((a2 = a*a) < rmin) { 00867 B = 0.f; 00868 A = C = rmin; 00869 F = A*C; 00870 } 00871 else { 00872 b2 = rmin; 00873 radangle2imp(a2, b2, th, &A, &B, &C, &F); 00874 } 00875 } 00876 00877 ue = ff*sqrtf(C); 00878 ve = ff*sqrtf(A); 00879 d = (float)(EWA_MAXIDX + 1) / (F*ff2); 00880 A *= d; 00881 B *= d; 00882 C *= d; 00883 00884 U0 = fx*ibuf->x; 00885 V0 = fy*ibuf->y; 00886 u1 = (int)(floorf(U0 - ue)); 00887 u2 = (int)(ceilf(U0 + ue)); 00888 v1 = (int)(floorf(V0 - ve)); 00889 v2 = (int)(ceilf(V0 + ve)); 00890 U0 -= 0.5f; 00891 V0 -= 0.5f; 00892 DDQ = 2.f*A; 00893 U = u1 - U0; 00894 ac1 = A*(2.f*U + 1.f); 00895 ac2 = A*U*U; 00896 BU = B*U; 00897 00898 d = texr->tr = texr->tb = texr->tg = texr->ta = 0.f; 00899 for (v=v1; v<=v2; ++v) { 00900 const float V = v - V0; 00901 float DQ = ac1 + B*V; 00902 float Q = (C*V + BU)*V + ac2; 00903 for (u=u1; u<=u2; ++u) { 00904 if (Q < (float)(EWA_MAXIDX + 1)) { 00905 float tc[4]; 00906 const float wt = EWA_WTS[(Q < 0.f) ? 0 : (unsigned int)Q]; 00907 /*const int out =*/ ibuf_get_color_clip(tc, ibuf, u, v, AFD->extflag); 00908 // TXF alpha: clip |= out; 00909 // TXF alpha: cw += out ? 0.f : wt; 00910 texr->tr += tc[0]*wt; 00911 texr->tg += tc[1]*wt; 00912 texr->tb += tc[2]*wt; 00913 texr->ta += texr->talpha ? tc[3]*wt : 0.f; 00914 d += wt; 00915 } 00916 Q += DQ; 00917 DQ += DDQ; 00918 } 00919 } 00920 00921 // d should hopefully never be zero anymore 00922 d = 1.f/d; 00923 texr->tr *= d; 00924 texr->tg *= d; 00925 texr->tb *= d; 00926 // clipping can be ignored if alpha used, texr->ta already includes filtered edge 00927 texr->ta = texr->talpha ? texr->ta*d : 1.f; // TXF alpha (clip ? cw*d : 1.f); 00928 } 00929 00930 static void feline_eval(TexResult* texr, ImBuf* ibuf, float fx, float fy, afdata_t* AFD) 00931 { 00932 const int maxn = AFD->iProbes - 1; 00933 const float ll = ((AFD->majrad == AFD->minrad) ? 2.f*AFD->majrad : 2.f*(AFD->majrad - AFD->minrad)) / (maxn ? (float)maxn : 1.f); 00934 float du = maxn ? cosf(AFD->theta)*ll : 0.f; 00935 float dv = maxn ? sinf(AFD->theta)*ll : 0.f; 00936 //const float D = -0.5f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad); 00937 const float D = (EWA_MAXIDX + 1)*0.25f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad); 00938 float d; // TXF alpha: cw = 0.f; 00939 int n; // TXF alpha: clip = 0; 00940 // have to use same scaling for du/dv here as for Ux/Vx/Uy/Vy (*after* D calc.) 00941 du *= AFD->dusc; 00942 dv *= AFD->dvsc; 00943 d = texr->tr = texr->tb = texr->tg = texr->ta = 0.f; 00944 for (n=-maxn; n<=maxn; n+=2) { 00945 float tc[4]; 00946 const float hn = n*0.5f; 00947 const float u = fx + hn*du, v = fy + hn*dv; 00948 //const float wt = expf(n*n*D); 00949 // can use ewa table here too 00950 const float wt = EWA_WTS[(int)(n*n*D)]; 00951 /*const int out =*/ ibuf_get_color_clip_bilerp(tc, ibuf, ibuf->x*u, ibuf->y*v, AFD->intpol, AFD->extflag); 00952 // TXF alpha: clip |= out; 00953 // TXF alpha: cw += out ? 0.f : wt; 00954 texr->tr += tc[0]*wt; 00955 texr->tg += tc[1]*wt; 00956 texr->tb += tc[2]*wt; 00957 texr->ta += texr->talpha ? tc[3]*wt : 0.f; 00958 d += wt; 00959 } 00960 00961 d = 1.f/d; 00962 texr->tr *= d; 00963 texr->tg *= d; 00964 texr->tb *= d; 00965 // clipping can be ignored if alpha used, texr->ta already includes filtered edge 00966 texr->ta = texr->talpha ? texr->ta*d : 1.f; // TXF alpha: (clip ? cw*d : 1.f); 00967 } 00968 #undef EWA_MAXIDX 00969 00970 static void alpha_clip_aniso(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, int extflag, TexResult *texres) 00971 { 00972 float alphaclip; 00973 rctf rf; 00974 00975 // TXF apha: we're doing the same alphaclip here as boxsample, but i'm doubting 00976 // if this is actually correct for the all the filtering algorithms .. 00977 00978 if(!(extflag == TXC_REPT || extflag == TXC_EXTD)) { 00979 rf.xmin= minx*(ibuf->x); 00980 rf.xmax= maxx*(ibuf->x); 00981 rf.ymin= miny*(ibuf->y); 00982 rf.ymax= maxy*(ibuf->y); 00983 00984 alphaclip = clipx_rctf(&rf, 0.0, (float)(ibuf->x)); 00985 alphaclip*= clipy_rctf(&rf, 0.0, (float)(ibuf->y)); 00986 alphaclip= MAX2(alphaclip, 0.0f); 00987 00988 if(alphaclip!=1.0f) { 00989 /* premul it all */ 00990 texres->tr*= alphaclip; 00991 texres->tg*= alphaclip; 00992 texres->tb*= alphaclip; 00993 texres->ta*= alphaclip; 00994 } 00995 } 00996 } 00997 00998 static void image_mipmap_test(Tex *tex, ImBuf *ibuf) 00999 { 01000 if (tex->imaflag & TEX_MIPMAP) { 01001 if ((ibuf->flags & IB_fields) == 0) { 01002 01003 if (ibuf->mipmap[0] && (ibuf->userflags & IB_MIPMAP_INVALID)) { 01004 BLI_lock_thread(LOCK_IMAGE); 01005 if (ibuf->userflags & IB_MIPMAP_INVALID) { 01006 IMB_remakemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP); 01007 ibuf->userflags &= ~IB_MIPMAP_INVALID; 01008 } 01009 BLI_unlock_thread(LOCK_IMAGE); 01010 } 01011 if (ibuf->mipmap[0] == NULL) { 01012 BLI_lock_thread(LOCK_IMAGE); 01013 if (ibuf->mipmap[0] == NULL) 01014 IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP); 01015 BLI_unlock_thread(LOCK_IMAGE); 01016 } 01017 } 01018 } 01019 01020 } 01021 01022 static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, float *dxt, float *dyt, TexResult *texres) 01023 { 01024 TexResult texr; 01025 float fx, fy, minx, maxx, miny, maxy; 01026 float maxd, val1, val2, val3; 01027 int curmap, retval, intpol, extflag = 0; 01028 afdata_t AFD; 01029 01030 void (*filterfunc)(TexResult*, ImBuf*, float, float, afdata_t*); 01031 switch (tex->texfilter) { 01032 case TXF_EWA: 01033 filterfunc = ewa_eval; 01034 break; 01035 case TXF_FELINE: 01036 filterfunc = feline_eval; 01037 break; 01038 case TXF_AREA: 01039 default: 01040 filterfunc = area_sample; 01041 } 01042 01043 texres->tin = texres->ta = texres->tr = texres->tg = texres->tb = 0.f; 01044 01045 // we need to set retval OK, otherwise texture code generates normals itself... 01046 retval = texres->nor ? 3 : 1; 01047 01048 // quick tests 01049 if (ibuf==NULL && ima==NULL) return retval; 01050 01051 if (ima) { // hack for icon render 01052 if ((ima->ibufs.first == NULL) && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval; 01053 ibuf = BKE_image_get_ibuf(ima, &tex->iuser); 01054 } 01055 01056 if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) return retval; 01057 01058 /* mipmap test */ 01059 image_mipmap_test(tex, ibuf); 01060 01061 if ((tex->imaflag & TEX_USEALPHA) && ((tex->imaflag & TEX_CALCALPHA) == 0)) texres->talpha = 1; 01062 texr.talpha = texres->talpha; 01063 01064 if (tex->imaflag & TEX_IMAROT) { 01065 fy = texvec[0]; 01066 fx = texvec[1]; 01067 } 01068 else { 01069 fx = texvec[0]; 01070 fy = texvec[1]; 01071 } 01072 01073 if (ibuf->flags & IB_fields) { 01074 if (R.r.mode & R_FIELDS) { /* field render */ 01075 if (R.flag & R_SEC_FIELD) { /* correction for 2nd field */ 01076 /* fac1= 0.5/( (float)ibuf->y ); */ 01077 /* fy-= fac1; */ 01078 } 01079 else /* first field */ 01080 fy += 0.5f/( (float)ibuf->y ); 01081 } 01082 } 01083 01084 // pixel coordinates 01085 minx = MIN3(dxt[0], dyt[0], dxt[0] + dyt[0]); 01086 maxx = MAX3(dxt[0], dyt[0], dxt[0] + dyt[0]); 01087 miny = MIN3(dxt[1], dyt[1], dxt[1] + dyt[1]); 01088 maxy = MAX3(dxt[1], dyt[1], dxt[1] + dyt[1]); 01089 01090 // tex_sharper has been removed 01091 minx = (maxx - minx)*0.5f; 01092 miny = (maxy - miny)*0.5f; 01093 01094 if (tex->imaflag & TEX_FILTER_MIN) { 01095 // make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) 01096 const float addval = (0.5f * tex->filtersize) / (float)MIN2(ibuf->x, ibuf->y); 01097 if (addval > minx) minx = addval; 01098 if (addval > miny) miny = addval; 01099 } 01100 else if (tex->filtersize != 1.f) { 01101 minx *= tex->filtersize; 01102 miny *= tex->filtersize; 01103 dxt[0] *= tex->filtersize; 01104 dxt[1] *= tex->filtersize; 01105 dyt[0] *= tex->filtersize; 01106 dyt[1] *= tex->filtersize; 01107 } 01108 01109 if (tex->imaflag & TEX_IMAROT) { 01110 float t; 01111 SWAP(float, minx, miny); 01112 // must rotate dxt/dyt 90 deg 01113 // yet another blender problem is that swapping X/Y axes (or any tex proj switches) should do something similar, 01114 // but it doesn't, it only swaps coords, so filter area will be incorrect in those cases. 01115 t = dxt[0]; 01116 dxt[0] = dxt[1]; 01117 dxt[1] = -t; 01118 t = dyt[0]; 01119 dyt[0] = dyt[1]; 01120 dyt[1] = -t; 01121 } 01122 01123 // side faces of unit-cube 01124 minx = (minx > 0.25f) ? 0.25f : ((minx < 1e-5f) ? 1e-5f : minx); 01125 miny = (miny > 0.25f) ? 0.25f : ((miny < 1e-5f) ? 1e-5f : miny); 01126 01127 // repeat and clip 01128 01129 if (tex->extend == TEX_REPEAT) { 01130 if ((tex->flag & (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) == (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) 01131 extflag = TXC_EXTD; 01132 else if (tex->flag & TEX_REPEAT_XMIR) 01133 extflag = TXC_XMIR; 01134 else if (tex->flag & TEX_REPEAT_YMIR) 01135 extflag = TXC_YMIR; 01136 else 01137 extflag = TXC_REPT; 01138 } 01139 else if (tex->extend == TEX_EXTEND) 01140 extflag = TXC_EXTD; 01141 01142 if (tex->extend == TEX_CHECKER) { 01143 int xs = (int)floorf(fx), ys = (int)floorf(fy); 01144 // both checkers available, no boundary exceptions, checkerdist will eat aliasing 01145 if ((tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN)) { 01146 fx -= xs; 01147 fy -= ys; 01148 } 01149 else { 01150 int xs1 = (int)floorf(fx - minx); 01151 int ys1 = (int)floorf(fy - miny); 01152 int xs2 = (int)floorf(fx + minx); 01153 int ys2 = (int)floorf(fy + miny); 01154 if ((xs1 != xs2) || (ys1 != ys2)) { 01155 if (tex->flag & TEX_CHECKER_ODD) { 01156 fx -= ((xs1 + ys) & 1) ? xs2 : xs1; 01157 fy -= ((ys1 + xs) & 1) ? ys2 : ys1; 01158 } 01159 if (tex->flag & TEX_CHECKER_EVEN) { 01160 fx -= ((xs1 + ys) & 1) ? xs1 : xs2; 01161 fy -= ((ys1 + xs) & 1) ? ys1 : ys2; 01162 } 01163 } 01164 else { 01165 if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) return retval; 01166 if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) return retval; 01167 fx -= xs; 01168 fy -= ys; 01169 } 01170 } 01171 // scale around center, (0.5, 0.5) 01172 if (tex->checkerdist < 1.f) { 01173 const float omcd = 1.f / (1.f - tex->checkerdist); 01174 fx = (fx - 0.5f)*omcd + 0.5f; 01175 fy = (fy - 0.5f)*omcd + 0.5f; 01176 minx *= omcd; 01177 miny *= omcd; 01178 } 01179 } 01180 01181 if (tex->extend == TEX_CLIPCUBE) { 01182 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; 01183 } 01184 else if (tex->extend == TEX_CLIP || tex->extend == TEX_CHECKER) { 01185 if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) return retval; 01186 } 01187 else { 01188 if (tex->extend == TEX_EXTEND) { 01189 fx = (fx > 1.f) ? 1.f : ((fx < 0.f) ? 0.f : fx); 01190 fy = (fy > 1.f) ? 1.f : ((fy < 0.f) ? 0.f : fy); 01191 } 01192 else { 01193 fx -= floorf(fx); 01194 fy -= floorf(fy); 01195 } 01196 } 01197 01198 intpol = tex->imaflag & TEX_INTERPOL; 01199 01200 // warning no return! 01201 if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields)) 01202 ibuf->rect += ibuf->x*ibuf->y; 01203 01204 // struct common data 01205 copy_v2_v2(AFD.dxt, dxt); 01206 copy_v2_v2(AFD.dyt, dyt); 01207 AFD.intpol = intpol; 01208 AFD.extflag = extflag; 01209 01210 // brecht: added stupid clamping here, large dx/dy can give very large 01211 // filter sizes which take ages to render, it may be better to do this 01212 // more intelligently later in the code .. probably it's not noticeable 01213 if(AFD.dxt[0]*AFD.dxt[0] + AFD.dxt[1]*AFD.dxt[1] > 2.0f*2.0f) 01214 mul_v2_fl(AFD.dxt, 2.0f/len_v2(AFD.dxt)); 01215 if(AFD.dyt[0]*AFD.dyt[0] + AFD.dyt[1]*AFD.dyt[1] > 2.0f*2.0f) 01216 mul_v2_fl(AFD.dyt, 2.0f/len_v2(AFD.dyt)); 01217 01218 // choice: 01219 if (tex->imaflag & TEX_MIPMAP) { 01220 ImBuf *previbuf, *curibuf; 01221 float levf; 01222 int maxlev; 01223 ImBuf* mipmaps[IB_MIPMAP_LEVELS + 1]; 01224 01225 // modify ellipse minor axis if too eccentric, use for area sampling as well 01226 // scaling dxt/dyt as done in pbrt is not the same 01227 // (as in ewa_eval(), scale by sqrt(ibuf->x) to maximize precision) 01228 const float ff = sqrtf(ibuf->x), q = ibuf->y/ff; 01229 const float Ux = dxt[0]*ff, Vx = dxt[1]*q, Uy = dyt[0]*ff, Vy = dyt[1]*q; 01230 const float A = Vx*Vx + Vy*Vy; 01231 const float B = -2.f*(Ux*Vx + Uy*Vy); 01232 const float C = Ux*Ux + Uy*Uy; 01233 const float F = A*C - B*B*0.25f; 01234 float a, b, th, ecc; 01235 imp2radangle(A, B, C, F, &a, &b, &th, &ecc); 01236 if (tex->texfilter == TXF_FELINE) { 01237 float fProbes; 01238 a *= ff; 01239 b *= ff; 01240 a = MAX2(a, 1.f); 01241 b = MAX2(b, 1.f); 01242 fProbes = 2.f*(a / b) - 1.f; 01243 AFD.iProbes = (int)floorf(fProbes + 0.5f); 01244 AFD.iProbes = MIN2(AFD.iProbes, tex->afmax); 01245 if (AFD.iProbes < fProbes) 01246 b = 2.f*a / (float)(AFD.iProbes + 1); 01247 AFD.majrad = a/ff; 01248 AFD.minrad = b/ff; 01249 AFD.theta = th; 01250 AFD.dusc = 1.f/ff; 01251 AFD.dvsc = ff / (float)ibuf->y; 01252 } 01253 else { // EWA & area 01254 if (ecc > (float)tex->afmax) b = a / (float)tex->afmax; 01255 b *= ff; 01256 } 01257 maxd = MAX2(b, 1e-8f); 01258 levf = ((float)M_LOG2E)*logf(maxd); 01259 01260 curmap = 0; 01261 maxlev = 1; 01262 mipmaps[0] = ibuf; 01263 while (curmap < IB_MIPMAP_LEVELS) { 01264 mipmaps[curmap + 1] = ibuf->mipmap[curmap]; 01265 if (ibuf->mipmap[curmap]) maxlev++; 01266 curmap++; 01267 } 01268 01269 // mipmap level 01270 if (levf < 0.f) { // original image only 01271 previbuf = curibuf = mipmaps[0]; 01272 levf = 0.f; 01273 } 01274 else if (levf >= maxlev - 1) { 01275 previbuf = curibuf = mipmaps[maxlev - 1]; 01276 levf = 0.f; 01277 if (tex->texfilter == TXF_FELINE) AFD.iProbes = 1; 01278 } 01279 else { 01280 const int lev = ISNAN(levf) ? 0 : (int)levf; 01281 curibuf = mipmaps[lev]; 01282 previbuf = mipmaps[lev + 1]; 01283 levf -= floorf(levf); 01284 } 01285 01286 // filter functions take care of interpolation themselves, no need to modify dxt/dyt here 01287 01288 if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) { 01289 // color & normal 01290 filterfunc(texres, curibuf, fx, fy, &AFD); 01291 val1 = texres->tr + texres->tg + texres->tb; 01292 filterfunc(&texr, curibuf, fx + dxt[0], fy + dxt[1], &AFD); 01293 val2 = texr.tr + texr.tg + texr.tb; 01294 filterfunc(&texr, curibuf, fx + dyt[0], fy + dyt[1], &AFD); 01295 val3 = texr.tr + texr.tg + texr.tb; 01296 // don't switch x or y! 01297 texres->nor[0] = val1 - val2; 01298 texres->nor[1] = val1 - val3; 01299 if (previbuf != curibuf) { // interpolate 01300 filterfunc(&texr, previbuf, fx, fy, &AFD); 01301 // rgb 01302 texres->tr += levf*(texr.tr - texres->tr); 01303 texres->tg += levf*(texr.tg - texres->tg); 01304 texres->tb += levf*(texr.tb - texres->tb); 01305 texres->ta += levf*(texr.ta - texres->ta); 01306 // normal 01307 val1 += levf*((texr.tr + texr.tg + texr.tb) - val1); 01308 filterfunc(&texr, previbuf, fx + dxt[0], fy + dxt[1], &AFD); 01309 val2 += levf*((texr.tr + texr.tg + texr.tb) - val2); 01310 filterfunc(&texr, previbuf, fx + dyt[0], fy + dyt[1], &AFD); 01311 val3 += levf*((texr.tr + texr.tg + texr.tb) - val3); 01312 texres->nor[0] = val1 - val2; // vals have been interpolated above! 01313 texres->nor[1] = val1 - val3; 01314 } 01315 } 01316 else { // color 01317 filterfunc(texres, curibuf, fx, fy, &AFD); 01318 if (previbuf != curibuf) { // interpolate 01319 filterfunc(&texr, previbuf, fx, fy, &AFD); 01320 texres->tr += levf*(texr.tr - texres->tr); 01321 texres->tg += levf*(texr.tg - texres->tg); 01322 texres->tb += levf*(texr.tb - texres->tb); 01323 texres->ta += levf*(texr.ta - texres->ta); 01324 } 01325 01326 alpha_clip_aniso(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, extflag, texres); 01327 } 01328 } 01329 else { // no mipmap 01330 // filter functions take care of interpolation themselves, no need to modify dxt/dyt here 01331 if (tex->texfilter == TXF_FELINE) { 01332 const float ff = sqrtf(ibuf->x), q = ibuf->y/ff; 01333 const float Ux = dxt[0]*ff, Vx = dxt[1]*q, Uy = dyt[0]*ff, Vy = dyt[1]*q; 01334 const float A = Vx*Vx + Vy*Vy; 01335 const float B = -2.f*(Ux*Vx + Uy*Vy); 01336 const float C = Ux*Ux + Uy*Uy; 01337 const float F = A*C - B*B*0.25f; 01338 float a, b, th, ecc, fProbes; 01339 imp2radangle(A, B, C, F, &a, &b, &th, &ecc); 01340 a *= ff; 01341 b *= ff; 01342 a = MAX2(a, 1.f); 01343 b = MAX2(b, 1.f); 01344 fProbes = 2.f*(a / b) - 1.f; 01345 // no limit to number of Probes here 01346 AFD.iProbes = (int)floorf(fProbes + 0.5f); 01347 if (AFD.iProbes < fProbes) b = 2.f*a / (float)(AFD.iProbes + 1); 01348 AFD.majrad = a/ff; 01349 AFD.minrad = b/ff; 01350 AFD.theta = th; 01351 AFD.dusc = 1.f/ff; 01352 AFD.dvsc = ff / (float)ibuf->y; 01353 } 01354 if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) { 01355 // color & normal 01356 filterfunc(texres, ibuf, fx, fy, &AFD); 01357 val1 = texres->tr + texres->tg + texres->tb; 01358 filterfunc(&texr, ibuf, fx + dxt[0], fy + dxt[1], &AFD); 01359 val2 = texr.tr + texr.tg + texr.tb; 01360 filterfunc(&texr, ibuf, fx + dyt[0], fy + dyt[1], &AFD); 01361 val3 = texr.tr + texr.tg + texr.tb; 01362 // don't switch x or y! 01363 texres->nor[0] = val1 - val2; 01364 texres->nor[1] = val1 - val3; 01365 } 01366 else { 01367 filterfunc(texres, ibuf, fx, fy, &AFD); 01368 alpha_clip_aniso(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, extflag, texres); 01369 } 01370 } 01371 01372 if (tex->imaflag & TEX_CALCALPHA) 01373 texres->ta = texres->tin = texres->ta * MAX3(texres->tr, texres->tg, texres->tb); 01374 else 01375 texres->tin = texres->ta; 01376 if (tex->flag & TEX_NEGALPHA) texres->ta = 1.f - texres->ta; 01377 01378 if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields)) 01379 ibuf->rect -= ibuf->x*ibuf->y; 01380 01381 if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) { // normal from color 01382 // The invert of the red channel is to make 01383 // the normal map compliant with the outside world. 01384 // It needs to be done because in Blender 01385 // the normal used in the renderer points inward. It is generated 01386 // this way in calc_vertexnormals(). Should this ever change 01387 // this negate must be removed. 01388 texres->nor[0] = -2.f*(texres->tr - 0.5f); 01389 texres->nor[1] = 2.f*(texres->tg - 0.5f); 01390 texres->nor[2] = 2.f*(texres->tb - 0.5f); 01391 } 01392 01393 // de-premul, this is being premulled in shade_input_do_shade() 01394 // TXF: this currently does not (yet?) work properly, destroys edge AA in clip/checker mode, so for now commented out 01395 // also disabled in imagewraposa() to be able to compare results with blender's default texture filtering 01396 01397 // brecht: tried to fix this, see "TXF alpha" comments 01398 01399 if (texres->ta != 1.f && (texres->ta > 1e-4f)) { 01400 fx = 1.f/texres->ta; 01401 texres->tr *= fx; 01402 texres->tg *= fx; 01403 texres->tb *= fx; 01404 } 01405 01406 BRICONTRGB; 01407 01408 return retval; 01409 } 01410 01411 01412 int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, float *DXT, float *DYT, TexResult *texres) 01413 { 01414 TexResult texr; 01415 float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[3], dyt[3]; 01416 float maxd, pixsize, val1, val2, val3; 01417 int curmap, retval, imaprepeat, imapextend; 01418 01419 // TXF: since dxt/dyt might be modified here and since they might be needed after imagewraposa() call, 01420 // make a local copy here so that original vecs remain untouched 01421 VECCOPY(dxt, DXT); 01422 VECCOPY(dyt, DYT); 01423 01424 // anisotropic filtering 01425 if (tex->texfilter != TXF_BOX) 01426 return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres); 01427 01428 texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f; 01429 01430 /* we need to set retval OK, otherwise texture code generates normals itself... */ 01431 retval= texres->nor?3:1; 01432 01433 /* quick tests */ 01434 if(ibuf==NULL && ima==NULL) 01435 return retval; 01436 if(ima) { 01437 01438 /* hack for icon render */ 01439 if(ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD)) 01440 return retval; 01441 01442 ibuf= BKE_image_get_ibuf(ima, &tex->iuser); 01443 } 01444 if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) 01445 return retval; 01446 01447 /* mipmap test */ 01448 image_mipmap_test(tex, ibuf); 01449 01450 if(tex->imaflag & TEX_USEALPHA) { 01451 if(tex->imaflag & TEX_CALCALPHA); 01452 else texres->talpha= 1; 01453 } 01454 01455 texr.talpha= texres->talpha; 01456 01457 if(tex->imaflag & TEX_IMAROT) { 01458 fy= texvec[0]; 01459 fx= texvec[1]; 01460 } 01461 else { 01462 fx= texvec[0]; 01463 fy= texvec[1]; 01464 } 01465 01466 if(ibuf->flags & IB_fields) { 01467 if(R.r.mode & R_FIELDS) { /* field render */ 01468 if(R.flag & R_SEC_FIELD) { /* correction for 2nd field */ 01469 /* fac1= 0.5/( (float)ibuf->y ); */ 01470 /* fy-= fac1; */ 01471 } 01472 else { /* first field */ 01473 fy+= 0.5f/( (float)ibuf->y ); 01474 } 01475 } 01476 } 01477 01478 /* pixel coordinates */ 01479 01480 minx= MIN3(dxt[0],dyt[0],dxt[0]+dyt[0] ); 01481 maxx= MAX3(dxt[0],dyt[0],dxt[0]+dyt[0] ); 01482 miny= MIN3(dxt[1],dyt[1],dxt[1]+dyt[1] ); 01483 maxy= MAX3(dxt[1],dyt[1],dxt[1]+dyt[1] ); 01484 01485 /* tex_sharper has been removed */ 01486 minx= (maxx-minx)/2.0f; 01487 miny= (maxy-miny)/2.0f; 01488 01489 if(tex->imaflag & TEX_FILTER_MIN) { 01490 /* make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) */ 01491 float addval= (0.5f * tex->filtersize) / (float) MIN2(ibuf->x, ibuf->y); 01492 01493 if(addval > minx) 01494 minx= addval; 01495 if(addval > miny) 01496 miny= addval; 01497 } 01498 else if(tex->filtersize!=1.0f) { 01499 minx*= tex->filtersize; 01500 miny*= tex->filtersize; 01501 01502 dxt[0]*= tex->filtersize; 01503 dxt[1]*= tex->filtersize; 01504 dyt[0]*= tex->filtersize; 01505 dyt[1]*= tex->filtersize; 01506 } 01507 01508 if(tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny); 01509 01510 if(minx>0.25f) minx= 0.25f; 01511 else if(minx<0.00001f) minx= 0.00001f; /* side faces of unit-cube */ 01512 if(miny>0.25f) miny= 0.25f; 01513 else if(miny<0.00001f) miny= 0.00001f; 01514 01515 01516 /* repeat and clip */ 01517 imaprepeat= (tex->extend==TEX_REPEAT); 01518 imapextend= (tex->extend==TEX_EXTEND); 01519 01520 if(tex->extend == TEX_REPEAT) { 01521 if(tex->flag & (TEX_REPEAT_XMIR|TEX_REPEAT_YMIR)) { 01522 imaprepeat= 0; 01523 imapextend= 1; 01524 } 01525 } 01526 01527 if(tex->extend == TEX_CHECKER) { 01528 int xs, ys, xs1, ys1, xs2, ys2, boundary; 01529 01530 xs= (int)floor(fx); 01531 ys= (int)floor(fy); 01532 01533 // both checkers available, no boundary exceptions, checkerdist will eat aliasing 01534 if( (tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN) ) { 01535 fx-= xs; 01536 fy-= ys; 01537 } 01538 else { 01539 01540 xs1= (int)floor(fx-minx); 01541 ys1= (int)floor(fy-miny); 01542 xs2= (int)floor(fx+minx); 01543 ys2= (int)floor(fy+miny); 01544 boundary= (xs1!=xs2) || (ys1!=ys2); 01545 01546 if(boundary==0) { 01547 if( (tex->flag & TEX_CHECKER_ODD)==0) { 01548 if((xs+ys) & 1); 01549 else return retval; 01550 } 01551 if( (tex->flag & TEX_CHECKER_EVEN)==0) { 01552 if((xs+ys) & 1) return retval; 01553 } 01554 fx-= xs; 01555 fy-= ys; 01556 } 01557 else { 01558 if(tex->flag & TEX_CHECKER_ODD) { 01559 if((xs1+ys) & 1) fx-= xs2; 01560 else fx-= xs1; 01561 01562 if((ys1+xs) & 1) fy-= ys2; 01563 else fy-= ys1; 01564 } 01565 if(tex->flag & TEX_CHECKER_EVEN) { 01566 if((xs1+ys) & 1) fx-= xs1; 01567 else fx-= xs2; 01568 01569 if((ys1+xs) & 1) fy-= ys1; 01570 else fy-= ys2; 01571 } 01572 } 01573 } 01574 01575 /* scale around center, (0.5, 0.5) */ 01576 if(tex->checkerdist<1.0f) { 01577 fx= (fx-0.5f)/(1.0f-tex->checkerdist) +0.5f; 01578 fy= (fy-0.5f)/(1.0f-tex->checkerdist) +0.5f; 01579 minx/= (1.0f-tex->checkerdist); 01580 miny/= (1.0f-tex->checkerdist); 01581 } 01582 } 01583 01584 if(tex->extend == TEX_CLIPCUBE) { 01585 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) { 01586 return retval; 01587 } 01588 } 01589 else if(tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) { 01590 if(fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f) { 01591 return retval; 01592 } 01593 } 01594 else { 01595 if(imapextend) { 01596 if(fx>1.0f) fx = 1.0f; 01597 else if(fx<0.0f) fx= 0.0f; 01598 } 01599 else { 01600 if(fx>1.0f) fx -= (int)(fx); 01601 else if(fx<0.0f) fx+= 1-(int)(fx); 01602 } 01603 01604 if(imapextend) { 01605 if(fy>1.0f) fy = 1.0f; 01606 else if(fy<0.0f) fy= 0.0f; 01607 } 01608 else { 01609 if(fy>1.0f) fy -= (int)(fy); 01610 else if(fy<0.0f) fy+= 1-(int)(fy); 01611 } 01612 } 01613 01614 /* warning no return! */ 01615 if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { 01616 ibuf->rect+= (ibuf->x*ibuf->y); 01617 } 01618 01619 /* choice: */ 01620 if(tex->imaflag & TEX_MIPMAP) { 01621 ImBuf *previbuf, *curibuf; 01622 float bumpscale; 01623 01624 dx= minx; 01625 dy= miny; 01626 maxd= MAX2(dx, dy); 01627 if(maxd>0.5f) maxd= 0.5f; 01628 01629 pixsize = 1.0f/ (float) MIN2(ibuf->x, ibuf->y); 01630 01631 bumpscale= pixsize/maxd; 01632 if(bumpscale>1.0f) bumpscale= 1.0f; 01633 else bumpscale*=bumpscale; 01634 01635 curmap= 0; 01636 previbuf= curibuf= ibuf; 01637 while(curmap<IB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) { 01638 if(maxd < pixsize) break; 01639 previbuf= curibuf; 01640 curibuf= ibuf->mipmap[curmap]; 01641 pixsize= 1.0f / (float)MIN2(curibuf->x, curibuf->y); 01642 curmap++; 01643 } 01644 01645 if(previbuf!=curibuf || (tex->imaflag & TEX_INTERPOL)) { 01646 /* sample at least 1 pixel */ 01647 if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x; 01648 if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y; 01649 } 01650 01651 if(texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) { 01652 /* a bit extra filter */ 01653 //minx*= 1.35f; 01654 //miny*= 1.35f; 01655 01656 boxsample(curibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend); 01657 val1= texres->tr+texres->tg+texres->tb; 01658 boxsample(curibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend); 01659 val2= texr.tr + texr.tg + texr.tb; 01660 boxsample(curibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend); 01661 val3= texr.tr + texr.tg + texr.tb; 01662 01663 /* don't switch x or y! */ 01664 texres->nor[0]= (val1-val2); 01665 texres->nor[1]= (val1-val3); 01666 01667 if(previbuf!=curibuf) { /* interpolate */ 01668 01669 boxsample(previbuf, fx-minx, fy-miny, fx+minx, fy+miny, &texr, imaprepeat, imapextend); 01670 01671 /* calc rgb */ 01672 dx= 2.0f*(pixsize-maxd)/pixsize; 01673 if(dx>=1.0f) { 01674 texres->ta= texr.ta; texres->tb= texr.tb; 01675 texres->tg= texr.tg; texres->tr= texr.tr; 01676 } 01677 else { 01678 dy= 1.0f-dx; 01679 texres->tb= dy*texres->tb+ dx*texr.tb; 01680 texres->tg= dy*texres->tg+ dx*texr.tg; 01681 texres->tr= dy*texres->tr+ dx*texr.tr; 01682 texres->ta= dy*texres->ta+ dx*texr.ta; 01683 } 01684 01685 val1= dy*val1+ dx*(texr.tr + texr.tg + texr.tb); 01686 boxsample(previbuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend); 01687 val2= dy*val2+ dx*(texr.tr + texr.tg + texr.tb); 01688 boxsample(previbuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend); 01689 val3= dy*val3+ dx*(texr.tr + texr.tg + texr.tb); 01690 01691 texres->nor[0]= (val1-val2); /* vals have been interpolated above! */ 01692 texres->nor[1]= (val1-val3); 01693 01694 if(dx<1.0f) { 01695 dy= 1.0f-dx; 01696 texres->tb= dy*texres->tb+ dx*texr.tb; 01697 texres->tg= dy*texres->tg+ dx*texr.tg; 01698 texres->tr= dy*texres->tr+ dx*texr.tr; 01699 texres->ta= dy*texres->ta+ dx*texr.ta; 01700 } 01701 } 01702 texres->nor[0]*= bumpscale; 01703 texres->nor[1]*= bumpscale; 01704 } 01705 else { 01706 maxx= fx+minx; 01707 minx= fx-minx; 01708 maxy= fy+miny; 01709 miny= fy-miny; 01710 01711 boxsample(curibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend); 01712 01713 if(previbuf!=curibuf) { /* interpolate */ 01714 boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend); 01715 01716 fx= 2.0f*(pixsize-maxd)/pixsize; 01717 01718 if(fx>=1.0f) { 01719 texres->ta= texr.ta; texres->tb= texr.tb; 01720 texres->tg= texr.tg; texres->tr= texr.tr; 01721 } else { 01722 fy= 1.0f-fx; 01723 texres->tb= fy*texres->tb+ fx*texr.tb; 01724 texres->tg= fy*texres->tg+ fx*texr.tg; 01725 texres->tr= fy*texres->tr+ fx*texr.tr; 01726 texres->ta= fy*texres->ta+ fx*texr.ta; 01727 } 01728 } 01729 } 01730 } 01731 else { 01732 const int intpol = tex->imaflag & TEX_INTERPOL; 01733 if (intpol) { 01734 /* sample 1 pixel minimum */ 01735 if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x; 01736 if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y; 01737 } 01738 01739 if(texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) { 01740 boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend); 01741 val1= texres->tr+texres->tg+texres->tb; 01742 boxsample(ibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend); 01743 val2= texr.tr + texr.tg + texr.tb; 01744 boxsample(ibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend); 01745 val3= texr.tr + texr.tg + texr.tb; 01746 01747 /* don't switch x or y! */ 01748 texres->nor[0]= (val1-val2); 01749 texres->nor[1]= (val1-val3); 01750 } 01751 else 01752 boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend); 01753 } 01754 01755 if(tex->imaflag & TEX_CALCALPHA) { 01756 texres->ta= texres->tin= texres->ta*MAX3(texres->tr, texres->tg, texres->tb); 01757 } 01758 else texres->tin= texres->ta; 01759 01760 if(tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta; 01761 01762 if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { 01763 ibuf->rect-= (ibuf->x*ibuf->y); 01764 } 01765 01766 if(texres->nor && (tex->imaflag & TEX_NORMALMAP)) { 01767 // qdn: normal from color 01768 // The invert of the red channel is to make 01769 // the normal map compliant with the outside world. 01770 // It needs to be done because in Blender 01771 // the normal used in the renderer points inward. It is generated 01772 // this way in calc_vertexnormals(). Should this ever change 01773 // this negate must be removed. 01774 texres->nor[0] = -2.f*(texres->tr - 0.5f); 01775 texres->nor[1] = 2.f*(texres->tg - 0.5f); 01776 texres->nor[2] = 2.f*(texres->tb - 0.5f); 01777 } 01778 01779 /* de-premul, this is being premulled in shade_input_do_shade() */ 01780 if(texres->ta!=1.0f && texres->ta>1e-4f) { 01781 fx= 1.0f/texres->ta; 01782 texres->tr*= fx; 01783 texres->tg*= fx; 01784 texres->tb*= fx; 01785 } 01786 01787 BRICONTRGB; 01788 01789 return retval; 01790 } 01791 01792 void image_sample(Image *ima, float fx, float fy, float dx, float dy, float *result) 01793 { 01794 TexResult texres; 01795 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); 01796 01797 if(ibuf==NULL) { 01798 result[0]= result[1]= result[2]= result[3]= 0.0f; 01799 return; 01800 } 01801 01802 if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) 01803 ibuf->rect+= (ibuf->x*ibuf->y); 01804 01805 texres.talpha= 1; /* boxsample expects to be initialized */ 01806 boxsample(ibuf, fx, fy, fx+dx, fy+dy, &texres, 0, 1); 01807 result[0]= texres.tr; 01808 result[1]= texres.tg; 01809 result[2]= texres.tb; 01810 result[3]= texres.ta; 01811 01812 if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) 01813 ibuf->rect-= (ibuf->x*ibuf->y); 01814 } 01815 01816 void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result) 01817 { 01818 TexResult texres; 01819 afdata_t AFD; 01820 01821 if(ibuf==NULL) { 01822 return; 01823 } 01824 01825 AFD.dxt[0] = dx; AFD.dxt[1] = dx; 01826 AFD.dyt[0] = dy; AFD.dyt[1] = dy; 01827 //copy_v2_v2(AFD.dxt, dx); 01828 //copy_v2_v2(AFD.dyt, dy); 01829 01830 AFD.intpol = 1; 01831 AFD.extflag = TXC_EXTD; 01832 01833 memset(&texres, 0, sizeof(texres)); 01834 ewa_eval(&texres, ibuf, fx, fy, &AFD); 01835 01836 01837 result[0]= texres.tr; 01838 result[1]= texres.tg; 01839 result[2]= texres.tb; 01840 result[3]= texres.ta; 01841 }