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