Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2006 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include "node_composite_util.h" 00034 00035 /* ************ qdn: Defocus node ****************** */ 00036 static bNodeSocketTemplate cmp_node_defocus_in[]= { 00037 { SOCK_RGBA, 1, "Image", 1.0f, 1.0f, 1.0f, 1.0f}, 00038 { SOCK_FLOAT, 1, "Z", 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, 00039 { -1, 0, "" } 00040 }; 00041 static bNodeSocketTemplate cmp_node_defocus_out[]= { 00042 { SOCK_RGBA, 0, "Image"}, 00043 { -1, 0, "" } 00044 }; 00045 00046 00047 // line coefs for point sampling & scancon. data. 00048 typedef struct BokehCoeffs { 00049 float x0, y0, dx, dy; 00050 float ls_x, ls_y; 00051 float min_x, min_y, max_x, max_y; 00052 } BokehCoeffs; 00053 00054 // returns array of BokehCoeffs 00055 // returns length of array in 'len_bkh', 00056 // radius squared of inscribed disk in 'inradsq', needed in getWeight() test, 00057 // BKH[8] is the data returned for the bokeh shape & bkh_b[4] is it's 2d bound 00058 static void makeBokeh(char bktype, char ro, int* len_bkh, float* inradsq, BokehCoeffs BKH[8], float bkh_b[4]) 00059 { 00060 float x0, x1, y0, y1, dx, dy, iDxy; 00061 /* ro now is in radians. */ 00062 float w = MAX2(1e-6f, ro); // never reported stangely enough, but a zero offset causes missing center line... 00063 float wi = DEG2RADF(360.f/bktype); 00064 int i, ov, nv; 00065 00066 // bktype must be at least 3 & <= 8 00067 bktype = (bktype<3) ? 3 : ((bktype>8) ? 8 : bktype); 00068 *len_bkh = bktype; 00069 *inradsq = -1.f; 00070 00071 for (i=0; i<(*len_bkh); i++) { 00072 x0 = cos(w); 00073 y0 = sin(w); 00074 w += wi; 00075 x1 = cos(w); 00076 y1 = sin(w); 00077 if ((*inradsq)<0.f) { 00078 // radius squared of inscribed disk 00079 float idx=(x0+x1)*0.5f, idy=(y0+y1)*0.5f; 00080 *inradsq = idx*idx + idy*idy; 00081 } 00082 BKH[i].x0 = x0; 00083 BKH[i].y0 = y0; 00084 dx = x1-x0, dy = y1-y0; 00085 iDxy = 1.f / sqrtf(dx*dx + dy*dy); 00086 dx *= iDxy; 00087 dy *= iDxy; 00088 BKH[i].dx = dx; 00089 BKH[i].dy = dy; 00090 } 00091 00092 // precalc scanconversion data 00093 // bokeh bound, not transformed, for scanconvert 00094 bkh_b[0] = bkh_b[2] = 1e10f; // xmin/ymin 00095 bkh_b[1] = bkh_b[3] = -1e10f; // xmax/ymax 00096 ov = (*len_bkh) - 1; 00097 for (nv=0; nv<(*len_bkh); nv++) { 00098 bkh_b[0] = MIN2(bkh_b[0], BKH[nv].x0); // xmin 00099 bkh_b[1] = MAX2(bkh_b[1], BKH[nv].x0); // xmax 00100 bkh_b[2] = MIN2(bkh_b[2], BKH[nv].y0); // ymin 00101 bkh_b[3] = MAX2(bkh_b[3], BKH[nv].y0); // ymax 00102 BKH[nv].min_x = MIN2(BKH[ov].x0, BKH[nv].x0); 00103 BKH[nv].max_x = MAX2(BKH[ov].x0, BKH[nv].x0); 00104 BKH[nv].min_y = MIN2(BKH[ov].y0, BKH[nv].y0); 00105 BKH[nv].max_y = MAX2(BKH[ov].y0, BKH[nv].y0); 00106 dy = BKH[nv].y0 - BKH[ov].y0; 00107 BKH[nv].ls_x = (BKH[nv].x0 - BKH[ov].x0) / ((dy==0.f) ? 1.f : dy); 00108 BKH[nv].ls_y = (BKH[nv].ls_x==0.f) ? 1.f : (1.f/BKH[nv].ls_x); 00109 ov = nv; 00110 } 00111 } 00112 00113 // test if u/v inside shape & returns weight value 00114 static float getWeight(BokehCoeffs* BKH, int len_bkh, float u, float v, float rad, float inradsq) 00115 { 00116 BokehCoeffs* bc = BKH; 00117 float cdist, irad = (rad==0.f) ? 1.f : (1.f/rad); 00118 u *= irad; 00119 v *= irad; 00120 00121 // early out test1: if point outside outer unit disk, it cannot be inside shape 00122 cdist = u*u + v*v; 00123 if (cdist>1.f) return 0.f; 00124 00125 // early out test2: if point inside or on inner disk, point must be inside shape 00126 if (cdist<=inradsq) return 1.f; 00127 00128 while (len_bkh--) { 00129 if ((bc->dy*(u - bc->x0) - bc->dx*(v - bc->y0)) > 0.f) return 0.f; 00130 bc++; 00131 } 00132 return 1.f; 00133 } 00134 00135 // QMC.seq. for sampling, A.Keller, EMS 00136 static float RI_vdC(unsigned int bits, unsigned int r) 00137 { 00138 bits = ( bits << 16) | ( bits >> 16); 00139 bits = ((bits & 0x00ff00ff) << 8) | ((bits & 0xff00ff00) >> 8); 00140 bits = ((bits & 0x0f0f0f0f) << 4) | ((bits & 0xf0f0f0f0) >> 4); 00141 bits = ((bits & 0x33333333) << 2) | ((bits & 0xcccccccc) >> 2); 00142 bits = ((bits & 0x55555555) << 1) | ((bits & 0xaaaaaaaa) >> 1); 00143 bits ^= r; 00144 return (float)((double)bits / 4294967296.0); 00145 } 00146 00147 // single channel IIR gaussian filtering 00148 // much faster than anything else, constant time independent of width 00149 // should extend to multichannel and make this a node, could be useful 00150 // note: this is an almost exact copy of 'IIR_gauss' 00151 static void IIR_gauss_single(CompBuf* buf, float sigma) 00152 { 00153 double q, q2, sc, cf[4], tsM[9], tsu[3], tsv[3]; 00154 float *X, *Y, *W; 00155 int i, x, y, sz; 00156 00157 // single channel only for now 00158 if (buf->type != CB_VAL) return; 00159 00160 // <0.5 not valid, though can have a possibly useful sort of sharpening effect 00161 if (sigma < 0.5f) return; 00162 00163 // see "Recursive Gabor Filtering" by Young/VanVliet 00164 // all factors here in double.prec. Required, because for single.prec it seems to blow up if sigma > ~200 00165 if (sigma >= 3.556f) 00166 q = 0.9804f*(sigma - 3.556f) + 2.5091f; 00167 else // sigma >= 0.5 00168 q = (0.0561f*sigma + 0.5784f)*sigma - 0.2568f; 00169 q2 = q*q; 00170 sc = (1.1668 + q)*(3.203729649 + (2.21566 + q)*q); 00171 // no gabor filtering here, so no complex multiplies, just the regular coefs. 00172 // all negated here, so as not to have to recalc Triggs/Sdika matrix 00173 cf[1] = q*(5.788961737 + (6.76492 + 3.0*q)*q)/ sc; 00174 cf[2] = -q2*(3.38246 + 3.0*q)/sc; 00175 // 0 & 3 unchanged 00176 cf[3] = q2*q/sc; 00177 cf[0] = 1.0 - cf[1] - cf[2] - cf[3]; 00178 00179 // Triggs/Sdika border corrections, 00180 // it seems to work, not entirely sure if it is actually totally correct, 00181 // Besides J.M.Geusebroek's anigauss.c (see http://www.science.uva.nl/~mark), 00182 // found one other implementation by Cristoph Lampert, 00183 // but neither seem to be quite the same, result seems to be ok sofar anyway. 00184 // Extra scale factor here to not have to do it in filter, 00185 // though maybe this had something to with the precision errors 00186 sc = cf[0]/((1.0 + cf[1] - cf[2] + cf[3])*(1.0 - cf[1] - cf[2] - cf[3])*(1.0 + cf[2] + (cf[1] - cf[3])*cf[3])); 00187 tsM[0] = sc*(-cf[3]*cf[1] + 1.0 - cf[3]*cf[3] - cf[2]); 00188 tsM[1] = sc*((cf[3] + cf[1])*(cf[2] + cf[3]*cf[1])); 00189 tsM[2] = sc*(cf[3]*(cf[1] + cf[3]*cf[2])); 00190 tsM[3] = sc*(cf[1] + cf[3]*cf[2]); 00191 tsM[4] = sc*(-(cf[2] - 1.0)*(cf[2] + cf[3]*cf[1])); 00192 tsM[5] = sc*(-(cf[3]*cf[1] + cf[3]*cf[3] + cf[2] - 1.0)*cf[3]); 00193 tsM[6] = sc*(cf[3]*cf[1] + cf[2] + cf[1]*cf[1] - cf[2]*cf[2]); 00194 tsM[7] = sc*(cf[1]*cf[2] + cf[3]*cf[2]*cf[2] - cf[1]*cf[3]*cf[3] - cf[3]*cf[3]*cf[3] - cf[3]*cf[2] + cf[3]); 00195 tsM[8] = sc*(cf[3]*(cf[1] + cf[3]*cf[2])); 00196 00197 #define YVV(L)\ 00198 {\ 00199 W[0] = cf[0]*X[0] + cf[1]*X[0] + cf[2]*X[0] + cf[3]*X[0];\ 00200 W[1] = cf[0]*X[1] + cf[1]*W[0] + cf[2]*X[0] + cf[3]*X[0];\ 00201 W[2] = cf[0]*X[2] + cf[1]*W[1] + cf[2]*W[0] + cf[3]*X[0];\ 00202 for (i=3; i<L; i++)\ 00203 W[i] = cf[0]*X[i] + cf[1]*W[i-1] + cf[2]*W[i-2] + cf[3]*W[i-3];\ 00204 tsu[0] = W[L-1] - X[L-1];\ 00205 tsu[1] = W[L-2] - X[L-1];\ 00206 tsu[2] = W[L-3] - X[L-1];\ 00207 tsv[0] = tsM[0]*tsu[0] + tsM[1]*tsu[1] + tsM[2]*tsu[2] + X[L-1];\ 00208 tsv[1] = tsM[3]*tsu[0] + tsM[4]*tsu[1] + tsM[5]*tsu[2] + X[L-1];\ 00209 tsv[2] = tsM[6]*tsu[0] + tsM[7]*tsu[1] + tsM[8]*tsu[2] + X[L-1];\ 00210 Y[L-1] = cf[0]*W[L-1] + cf[1]*tsv[0] + cf[2]*tsv[1] + cf[3]*tsv[2];\ 00211 Y[L-2] = cf[0]*W[L-2] + cf[1]*Y[L-1] + cf[2]*tsv[0] + cf[3]*tsv[1];\ 00212 Y[L-3] = cf[0]*W[L-3] + cf[1]*Y[L-2] + cf[2]*Y[L-1] + cf[3]*tsv[0];\ 00213 for (i=L-4; i>=0; i--)\ 00214 Y[i] = cf[0]*W[i] + cf[1]*Y[i+1] + cf[2]*Y[i+2] + cf[3]*Y[i+3];\ 00215 } 00216 00217 // intermediate buffers 00218 sz = MAX2(buf->x, buf->y); 00219 Y = MEM_callocN(sz*sizeof(float), "IIR_gauss Y buf"); 00220 W = MEM_callocN(sz*sizeof(float), "IIR_gauss W buf"); 00221 // H 00222 for (y=0; y<buf->y; y++) { 00223 X = &buf->rect[y*buf->x]; 00224 YVV(buf->x); 00225 memcpy(X, Y, sizeof(float)*buf->x); 00226 } 00227 // V 00228 X = MEM_callocN(buf->y*sizeof(float), "IIR_gauss X buf"); 00229 for (x=0; x<buf->x; x++) { 00230 for (y=0; y<buf->y; y++) 00231 X[y] = buf->rect[x + y*buf->x]; 00232 YVV(buf->y); 00233 for (y=0; y<buf->y; y++) 00234 buf->rect[x + y*buf->x] = Y[y]; 00235 } 00236 MEM_freeN(X); 00237 00238 MEM_freeN(W); 00239 MEM_freeN(Y); 00240 #undef YVV 00241 } 00242 00243 static void defocus_blur(bNode *node, CompBuf *new, CompBuf *img, CompBuf *zbuf, float inpval, int no_zbuf) 00244 { 00245 NodeDefocus *nqd = node->storage; 00246 CompBuf *wts; // weights buffer 00247 CompBuf *crad; // CoC radius buffer 00248 BokehCoeffs BKH[8]; // bokeh shape data, here never > 8 pts. 00249 float bkh_b[4] = {0}; // shape 2D bound 00250 float cam_fdist=1, cam_invfdist=1, cam_lens=35; 00251 float dof_sp, maxfgc, bk_hn_theta=0, inradsq=0; 00252 int y, len_bkh=0, ydone=0; 00253 float aspect, aperture; 00254 int minsz; 00255 //float bcrad, nmaxc, scf; 00256 00257 // get some required params from the current scene camera 00258 // (ton) this is wrong, needs fixed 00259 Scene *scene= (Scene*)node->id; 00260 Object* camob = (scene)? scene->camera: NULL; 00261 if (camob && camob->type==OB_CAMERA) { 00262 Camera* cam = (Camera*)camob->data; 00263 cam_lens = cam->lens; 00264 cam_fdist = object_camera_dof_distance(camob); 00265 if (cam_fdist==0.0f) cam_fdist = 1e10f; /* if the dof is 0.0 then set it be be far away */ 00266 cam_invfdist = 1.f/cam_fdist; 00267 } 00268 00269 // guess work here.. best match with raytraced result 00270 minsz = MIN2(img->x, img->y); 00271 dof_sp = (float)minsz / (16.f / cam_lens); // <- == aspect * MIN2(img->x, img->y) / tan(0.5f * fov); 00272 00273 // aperture 00274 aspect = (img->x > img->y) ? (img->y / (float)img->x) : (img->x / (float)img->y); 00275 aperture = 0.5f*(cam_lens / (aspect*32.f)) / nqd->fstop; 00276 00277 // if not disk, make bokeh coefficients and other needed data 00278 if (nqd->bktype!=0) { 00279 makeBokeh(nqd->bktype, nqd->rotation, &len_bkh, &inradsq, BKH, bkh_b); 00280 bk_hn_theta = 0.5 * nqd->bktype * sin(2.0 * M_PI / nqd->bktype); // weight factor 00281 } 00282 00283 // accumulated weights 00284 wts = alloc_compbuf(img->x, img->y, CB_VAL, 1); 00285 // CoC radius buffer 00286 crad = alloc_compbuf(img->x, img->y, CB_VAL, 1); 00287 00288 // if 'no_zbuf' flag set (which is always set if input is not an image), 00289 // values are instead interpreted directly as blur radius values 00290 if (no_zbuf) { 00291 // to prevent *reaaallly* big radius values and impossible calculation times, 00292 // limit the maximum to half the image width or height, whichever is smaller 00293 float maxr = 0.5f*(float)MIN2(img->x, img->y); 00294 unsigned int p; 00295 00296 for (p=0; p<(unsigned int)(img->x*img->y); p++) { 00297 crad->rect[p] = zbuf ? (zbuf->rect[p]*nqd->scale) : inpval; 00298 // bug #5921, limit minimum 00299 crad->rect[p] = MAX2(1e-5f, crad->rect[p]); 00300 crad->rect[p] = MIN2(crad->rect[p], maxr); 00301 // if maxblur!=0, limit maximum 00302 if (nqd->maxblur != 0.f) crad->rect[p] = MIN2(crad->rect[p], nqd->maxblur); 00303 } 00304 } 00305 else { 00306 float wt; 00307 00308 // actual zbuffer. 00309 // separate foreground from background CoC's 00310 // then blur background and blend in again with foreground, 00311 // improves the 'blurred foreground overlapping in-focus midground' sharp boundary problem. 00312 // wts buffer here used for blendmask 00313 maxfgc = 0.f; // maximum foreground CoC radius 00314 for (y=0; y<img->y; y++) { 00315 unsigned int p = y * img->x; 00316 int x; 00317 for (x=0; x<img->x; x++) { 00318 unsigned int px = p + x; 00319 float iZ = (zbuf->rect[px]==0.f) ? 0.f : (1.f/zbuf->rect[px]); 00320 crad->rect[px] = 0.5f*(aperture*(dof_sp*(cam_invfdist - iZ) - 1.f)); 00321 if (crad->rect[px] <= 0.f) { 00322 wts->rect[px] = 1.f; 00323 crad->rect[px] = -crad->rect[px]; 00324 if (crad->rect[px] > maxfgc) maxfgc = crad->rect[px]; 00325 } 00326 else crad->rect[px] = wts->rect[px] = 0; 00327 } 00328 } 00329 00330 // fast blur... 00331 // bug #6656 part 1, probably when previous node_composite.c was split into separate files, it was not properly updated 00332 // to include recent cvs commits (well, at least not defocus node), so this part was missing... 00333 wt = aperture*128.f; 00334 IIR_gauss_single(crad, wt); 00335 IIR_gauss_single(wts, wt); 00336 00337 // bug #6656 part 2a, although foreground blur is not based anymore on closest object, 00338 // the rescaling op below was still based on that anyway, and unlike the comment in below code, 00339 // the difference is therefore not always that small at all... 00340 // so for now commented out, not sure if this is going to cause other future problems, lets just wait and see... 00341 /* 00342 // find new maximum to scale it back to original 00343 // (could skip this, not strictly necessary, in general, difference is quite small, but just in case...) 00344 nmaxc = 0; 00345 for (p=0; p<(img->x*img->y); p++) 00346 if (crad->rect[p] > nmaxc) nmaxc = crad->rect[p]; 00347 // rescale factor 00348 scf = (nmaxc==0.f) ? 1.f: (maxfgc / nmaxc); 00349 */ 00350 00351 // and blend... 00352 for (y=0; y<img->y; y++) { 00353 unsigned int p = y*img->x; 00354 int x; 00355 00356 for (x=0; x<img->x; x++) { 00357 unsigned px = p + x; 00358 if (zbuf->rect[px]!=0.f) { 00359 float iZ = (zbuf->rect[px]==0.f) ? 0.f : (1.f/zbuf->rect[px]); 00360 00361 // bug #6656 part 2b, do not rescale 00362 /* 00363 bcrad = 0.5f*fabs(aperture*(dof_sp*(cam_invfdist - iZ) - 1.f)); 00364 // scale crad back to original maximum and blend 00365 crad->rect[px] = bcrad + wts->rect[px]*(scf*crad->rect[px] - bcrad); 00366 */ 00367 crad->rect[px] = 0.5f*fabsf(aperture*(dof_sp*(cam_invfdist - iZ) - 1.f)); 00368 00369 // 'bug' #6615, limit minimum radius to 1 pixel, not really a solution, but somewhat mitigates the problem 00370 crad->rect[px] = MAX2(crad->rect[px], 0.5f); 00371 // if maxblur!=0, limit maximum 00372 if (nqd->maxblur != 0.f) crad->rect[px] = MIN2(crad->rect[px], nqd->maxblur); 00373 } 00374 else crad->rect[px] = 0.f; 00375 // clear weights for next part 00376 wts->rect[px] = 0.f; 00377 } 00378 // esc set by main calling process 00379 if(node->exec & NODE_BREAK) 00380 break; 00381 } 00382 } 00383 00384 //------------------------------------------------------------------ 00385 // main loop 00386 #ifndef __APPLE__ /* can crash on Mac, see bug #22856, disabled for now */ 00387 #ifdef __INTEL_COMPILER /* icc doesn't like the compound statement -- internal error: 0_1506 */ 00388 #pragma omp parallel for private(y) if(!nqd->preview) schedule(guided) 00389 #else 00390 #pragma omp parallel for private(y) if(!nqd->preview && img->y*img->x > 16384) schedule(guided) 00391 #endif 00392 #endif 00393 for (y=0; y<img->y; y++) { 00394 unsigned int p, p4, zp, cp, cp4; 00395 float *ctcol, u, v, ct_crad, cR2=0; 00396 int x, sx, sy; 00397 00398 // some sort of visual feedback would be nice, or at least this text in the renderwin header 00399 // but for now just print some info in the console every 8 scanlines. 00400 #pragma omp critical 00401 { 00402 if (((ydone & 7)==0) || (ydone==(img->y-1))) { 00403 if(G.background==0) { 00404 printf("\rdefocus: Processing Line %d of %d ... ", ydone+1, img->y); 00405 fflush(stdout); 00406 } 00407 } 00408 00409 ydone++; 00410 } 00411 00412 // esc set by main calling process. don't break because openmp doesn't 00413 // allow it, just continue and do nothing 00414 if(node->exec & NODE_BREAK) 00415 continue; 00416 00417 zp = y * img->x; 00418 for (x=0; x<img->x; x++) { 00419 cp = zp + x; 00420 cp4 = cp * img->type; 00421 00422 // Circle of Confusion radius for current pixel 00423 cR2 = ct_crad = crad->rect[cp]; 00424 // skip if zero (border render) 00425 if (ct_crad==0.f) { 00426 // related to bug #5921, forgot output image when skipping 0 radius values 00427 new->rect[cp4] = img->rect[cp4]; 00428 if (new->type != CB_VAL) { 00429 new->rect[cp4+1] = img->rect[cp4+1]; 00430 new->rect[cp4+2] = img->rect[cp4+2]; 00431 new->rect[cp4+3] = img->rect[cp4+3]; 00432 } 00433 continue; 00434 } 00435 cR2 *= cR2; 00436 00437 // pixel color 00438 ctcol = &img->rect[cp4]; 00439 00440 if (!nqd->preview) { 00441 int xs, xe, ys, ye; 00442 float lwt, wtcol[4] = {0}, aacol[4] = {0}; 00443 float wt; 00444 00445 // shape weight 00446 if (nqd->bktype==0) // disk 00447 wt = 1.f/((float)M_PI*cR2); 00448 else 00449 wt = 1.f/(cR2*bk_hn_theta); 00450 00451 // weighted color 00452 wtcol[0] = wt*ctcol[0]; 00453 if (new->type != CB_VAL) { 00454 wtcol[1] = wt*ctcol[1]; 00455 wtcol[2] = wt*ctcol[2]; 00456 wtcol[3] = wt*ctcol[3]; 00457 } 00458 00459 // macro for background blur overlap test 00460 // unfortunately, since this is done per pixel, 00461 // it has a very significant negative impact on processing time... 00462 // (eg. aa disk blur without test: 112 sec, vs with test: 176 sec...) 00463 // iff center blur radius > threshold 00464 // and if overlap pixel in focus, do nothing, else add color/weigbt 00465 // (threshold constant is dependant on amount of blur) 00466 #define TESTBG1(c, w) {\ 00467 if (ct_crad > nqd->bthresh) {\ 00468 if (crad->rect[p] > nqd->bthresh) {\ 00469 new->rect[p] += c[0];\ 00470 wts->rect[p] += w;\ 00471 }\ 00472 }\ 00473 else {\ 00474 new->rect[p] += c[0];\ 00475 wts->rect[p] += w;\ 00476 }\ 00477 } 00478 #define TESTBG4(c, w) {\ 00479 if (ct_crad > nqd->bthresh) {\ 00480 if (crad->rect[p] > nqd->bthresh) {\ 00481 new->rect[p4] += c[0];\ 00482 new->rect[p4+1] += c[1];\ 00483 new->rect[p4+2] += c[2];\ 00484 new->rect[p4+3] += c[3];\ 00485 wts->rect[p] += w;\ 00486 }\ 00487 }\ 00488 else {\ 00489 new->rect[p4] += c[0];\ 00490 new->rect[p4+1] += c[1];\ 00491 new->rect[p4+2] += c[2];\ 00492 new->rect[p4+3] += c[3];\ 00493 wts->rect[p] += w;\ 00494 }\ 00495 } 00496 if (nqd->bktype == 0) { 00497 // Disk 00498 int _x, i, j, di; 00499 float Dj, T; 00500 // AA pixel 00501 #define AAPIX(a, b) {\ 00502 int _ny = b;\ 00503 if ((_ny >= 0) && (_ny < new->y)) {\ 00504 int _nx = a;\ 00505 if ((_nx >=0) && (_nx < new->x)) {\ 00506 p = _ny*new->x + _nx;\ 00507 if (new->type==CB_VAL) {\ 00508 TESTBG1(aacol, lwt);\ 00509 }\ 00510 else {\ 00511 p4 = p * new->type;\ 00512 TESTBG4(aacol, lwt);\ 00513 }\ 00514 }\ 00515 }\ 00516 } 00517 // circle scanline 00518 #define CSCAN(a, b) {\ 00519 int _ny = y + b;\ 00520 if ((_ny >= 0) && (_ny < new->y)) {\ 00521 xs = x - a + 1;\ 00522 if (xs < 0) xs = 0;\ 00523 xe = x + a;\ 00524 if (xe > new->x) xe = new->x;\ 00525 p = _ny*new->x + xs;\ 00526 if (new->type==CB_VAL) {\ 00527 for (_x=xs; _x<xe; _x++, p++) TESTBG1(wtcol, wt);\ 00528 }\ 00529 else {\ 00530 p4 = p * new->type;\ 00531 for (_x=xs; _x<xe; _x++, p++, p4+=new->type) TESTBG4(wtcol, wt);\ 00532 }\ 00533 }\ 00534 } 00535 00536 i = ceil(ct_crad); 00537 j = 0; 00538 T = 0; 00539 while (i > j) { 00540 Dj = sqrt(cR2 - j*j); 00541 Dj -= floorf(Dj); 00542 di = 0; 00543 if (Dj > T) { i--; di = 1; } 00544 T = Dj; 00545 aacol[0] = wtcol[0]*Dj; 00546 if (new->type != CB_VAL) { 00547 aacol[1] = wtcol[1]*Dj; 00548 aacol[2] = wtcol[2]*Dj; 00549 aacol[3] = wtcol[3]*Dj; 00550 } 00551 lwt = wt*Dj; 00552 if (i!=j) { 00553 // outer pixels 00554 AAPIX(x+j, y+i) 00555 AAPIX(x+j, y-i) 00556 if (j) { 00557 AAPIX(x-j, y+i) // BL 00558 AAPIX(x-j, y-i) // TL 00559 } 00560 if (di) { // only when i changed, interior of outer section 00561 CSCAN(j, i) // bottom 00562 CSCAN(j, -i) // top 00563 } 00564 } 00565 // lower mid section 00566 AAPIX(x+i, y+j) 00567 if (i) AAPIX(x-i, y+j) 00568 CSCAN(i, j) 00569 // upper mid section 00570 if (j) { 00571 AAPIX(x+i, y-j) 00572 if (i) AAPIX(x-i, y-j) 00573 CSCAN(i, -j) 00574 } 00575 j++; 00576 } 00577 #undef CSCAN 00578 #undef AAPIX 00579 } 00580 else { 00581 // n-agonal 00582 int ov, nv; 00583 float mind, maxd, lwt; 00584 ys = MAX2((int)floor(bkh_b[2]*ct_crad + y), 0); 00585 ye = MIN2((int)ceil(bkh_b[3]*ct_crad + y), new->y - 1); 00586 for (sy=ys; sy<=ye; sy++) { 00587 float fxs = 1e10f, fxe = -1e10f; 00588 float yf = (sy - y)/ct_crad; 00589 int found = 0; 00590 ov = len_bkh - 1; 00591 mind = maxd = 0; 00592 for (nv=0; nv<len_bkh; nv++) { 00593 if ((BKH[nv].max_y >= yf) && (BKH[nv].min_y <= yf)) { 00594 float tx = BKH[ov].x0 + BKH[nv].ls_x*(yf - BKH[ov].y0); 00595 if (tx < fxs) { fxs = tx; mind = BKH[nv].ls_x; } 00596 if (tx > fxe) { fxe = tx; maxd = BKH[nv].ls_x; } 00597 if (++found == 2) break; 00598 } 00599 ov = nv; 00600 } 00601 if (found) { 00602 fxs = fxs*ct_crad + x; 00603 fxe = fxe*ct_crad + x; 00604 xs = (int)floor(fxs), xe = (int)ceil(fxe); 00605 // AA hack for first and last x pixel, near vertical edges only 00606 if (fabsf(mind) <= 1.f) { 00607 if ((xs >= 0) && (xs < new->x)) { 00608 lwt = 1.f-(fxs - xs); 00609 aacol[0] = wtcol[0]*lwt; 00610 p = xs + sy*new->x; 00611 if (new->type==CB_VAL) { 00612 lwt *= wt; 00613 TESTBG1(aacol, lwt); 00614 } 00615 else { 00616 p4 = p * new->type; 00617 aacol[1] = wtcol[1]*lwt; 00618 aacol[2] = wtcol[2]*lwt; 00619 aacol[3] = wtcol[3]*lwt; 00620 lwt *= wt; 00621 TESTBG4(aacol, lwt); 00622 } 00623 } 00624 } 00625 if (fabsf(maxd) <= 1.f) { 00626 if ((xe >= 0) && (xe < new->x)) { 00627 lwt = 1.f-(xe - fxe); 00628 aacol[0] = wtcol[0]*lwt; 00629 p = xe + sy*new->x; 00630 if (new->type==CB_VAL) { 00631 lwt *= wt; 00632 TESTBG1(aacol, lwt); 00633 } 00634 else { 00635 p4 = p * new->type; 00636 aacol[1] = wtcol[1]*lwt; 00637 aacol[2] = wtcol[2]*lwt; 00638 aacol[3] = wtcol[3]*lwt; 00639 lwt *= wt; 00640 TESTBG4(aacol, lwt); 00641 } 00642 } 00643 } 00644 xs = MAX2(xs+1, 0); 00645 xe = MIN2(xe, new->x); 00646 // remaining interior scanline 00647 p = sy*new->x + xs; 00648 if (new->type==CB_VAL) { 00649 for (sx=xs; sx<xe; sx++, p++) TESTBG1(wtcol, wt); 00650 } 00651 else { 00652 p4 = p * new->type; 00653 for (sx=xs; sx<xe; sx++, p++, p4+=new->type) TESTBG4(wtcol, wt); 00654 } 00655 } 00656 } 00657 00658 // now traverse in opposite direction, y scanlines, 00659 // but this time only draw the near horizontal edges, 00660 // applying same AA hack as above 00661 xs = MAX2((int)floor(bkh_b[0]*ct_crad + x), 0); 00662 xe = MIN2((int)ceil(bkh_b[1]*ct_crad + x), img->x - 1); 00663 for (sx=xs; sx<=xe; sx++) { 00664 float xf = (sx - x)/ct_crad; 00665 float fys = 1e10f, fye = -1e10f; 00666 int found = 0; 00667 ov = len_bkh - 1; 00668 mind = maxd = 0; 00669 for (nv=0; nv<len_bkh; nv++) { 00670 if ((BKH[nv].max_x >= xf) && (BKH[nv].min_x <= xf)) { 00671 float ty = BKH[ov].y0 + BKH[nv].ls_y*(xf - BKH[ov].x0); 00672 if (ty < fys) { fys = ty; mind = BKH[nv].ls_y; } 00673 if (ty > fye) { fye = ty; maxd = BKH[nv].ls_y; } 00674 if (++found == 2) break; 00675 } 00676 ov = nv; 00677 } 00678 if (found) { 00679 fys = fys*ct_crad + y; 00680 fye = fye*ct_crad + y; 00681 // near horizontal edges only, line slope <= 1 00682 if (fabsf(mind) <= 1.f) { 00683 int iys = (int)floor(fys); 00684 if ((iys >= 0) && (iys < new->y)) { 00685 lwt = 1.f - (fys - iys); 00686 aacol[0] = wtcol[0]*lwt; 00687 p = sx + iys*new->x; 00688 if (new->type==CB_VAL) { 00689 lwt *= wt; 00690 TESTBG1(aacol, lwt); 00691 } 00692 else { 00693 p4 = p * new->type; 00694 aacol[1] = wtcol[1]*lwt; 00695 aacol[2] = wtcol[2]*lwt; 00696 aacol[3] = wtcol[3]*lwt; 00697 lwt *= wt; 00698 TESTBG4(aacol, lwt); 00699 } 00700 } 00701 } 00702 if (fabsf(maxd) <= 1.f) { 00703 int iye = ceil(fye); 00704 if ((iye >= 0) && (iye < new->y)) { 00705 lwt = 1.f - (iye - fye); 00706 aacol[0] = wtcol[0]*lwt; 00707 p = sx + iye*new->x; 00708 if (new->type==CB_VAL) { 00709 lwt *= wt; 00710 TESTBG1(aacol, lwt); 00711 } 00712 else { 00713 p4 = p * new->type; 00714 aacol[1] = wtcol[1]*lwt; 00715 aacol[2] = wtcol[2]*lwt; 00716 aacol[3] = wtcol[3]*lwt; 00717 lwt *= wt; 00718 TESTBG4(aacol, lwt); 00719 } 00720 } 00721 } 00722 } 00723 } 00724 00725 } 00726 #undef TESTBG4 00727 #undef TESTBG1 00728 00729 } 00730 else { 00731 // sampled, simple rejection sampling here, good enough 00732 unsigned int maxsam, s, ui = BLI_rand()*BLI_rand(); 00733 float wcor, cpr = BLI_frand(), lwt; 00734 if (no_zbuf) 00735 maxsam = nqd->samples; // no zbuffer input, use sample value directly 00736 else { 00737 // depth adaptive sampling hack, the more out of focus, the more samples taken, 16 minimum. 00738 maxsam = (int)(0.5f + nqd->samples*(1.f-(float)exp(-fabs(zbuf->rect[cp] - cam_fdist)))); 00739 if (maxsam < 16) maxsam = 16; 00740 } 00741 wcor = 1.f/(float)maxsam; 00742 for (s=0; s<maxsam; ++s) { 00743 u = ct_crad*(2.f*RI_vdC(s, ui) - 1.f); 00744 v = ct_crad*(2.f*(s + cpr)/(float)maxsam - 1.f); 00745 sx = (int)(x + u + 0.5f), sy = (int)(y + v + 0.5f); 00746 if ((sx<0) || (sx >= new->x) || (sy<0) || (sy >= new->y)) continue; 00747 p = sx + sy*new->x; 00748 p4 = p * new->type; 00749 if (nqd->bktype==0) // Disk 00750 lwt = ((u*u + v*v)<=cR2) ? wcor : 0.f; 00751 else // AA not needed here 00752 lwt = wcor * getWeight(BKH, len_bkh, u, v, ct_crad, inradsq); 00753 // prevent background bleeding onto in-focus pixels, user-option 00754 if (ct_crad > nqd->bthresh) { // if center blur > threshold 00755 if (crad->rect[p] > nqd->bthresh) { // if overlap pixel in focus, do nothing, else add color/weigbt 00756 new->rect[p4] += ctcol[0] * lwt; 00757 if (new->type != CB_VAL) { 00758 new->rect[p4+1] += ctcol[1] * lwt; 00759 new->rect[p4+2] += ctcol[2] * lwt; 00760 new->rect[p4+3] += ctcol[3] * lwt; 00761 } 00762 wts->rect[p] += lwt; 00763 } 00764 } 00765 else { 00766 new->rect[p4] += ctcol[0] * lwt; 00767 if (new->type != CB_VAL) { 00768 new->rect[p4+1] += ctcol[1] * lwt; 00769 new->rect[p4+2] += ctcol[2] * lwt; 00770 new->rect[p4+3] += ctcol[3] * lwt; 00771 } 00772 wts->rect[p] += lwt; 00773 } 00774 } 00775 } 00776 00777 } 00778 } 00779 00780 // finally, normalize 00781 for (y=0; y<new->y; y++) { 00782 unsigned int p = y * new->x; 00783 unsigned int p4 = p * new->type; 00784 int x; 00785 00786 for (x=0; x<new->x; x++) { 00787 float dv = (wts->rect[p]==0.f) ? 1.f : (1.f/wts->rect[p]); 00788 new->rect[p4] *= dv; 00789 if (new->type!=CB_VAL) { 00790 new->rect[p4+1] *= dv; 00791 new->rect[p4+2] *= dv; 00792 new->rect[p4+3] *= dv; 00793 } 00794 p++; 00795 p4 += new->type; 00796 } 00797 } 00798 00799 free_compbuf(crad); 00800 free_compbuf(wts); 00801 00802 printf("Done\n"); 00803 } 00804 00805 00806 static void node_composit_exec_defocus(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) 00807 { 00808 CompBuf *new, *old, *zbuf_use = NULL, *img = in[0]->data, *zbuf = in[1]->data; 00809 NodeDefocus *nqd = node->storage; 00810 int no_zbuf = nqd->no_zbuf; 00811 00812 if ((img==NULL) || (out[0]->hasoutput==0)) return; 00813 00814 // if image not valid type or fstop==infinite (128), nothing to do, pass in to out 00815 if (((img->type!=CB_RGBA) && (img->type!=CB_VAL)) || ((no_zbuf==0) && (nqd->fstop==128.f))) { 00816 out[0]->data = pass_on_compbuf(img); 00817 return; 00818 } 00819 00820 if (zbuf!=NULL) { 00821 // Zbuf input, check to make sure, single channel, same size 00822 // doesn't have to be actual zbuffer, but must be value type 00823 if ((zbuf->x != img->x) || (zbuf->y != img->y)) { 00824 // could do a scale here instead... 00825 printf("Z input must be same size as image !\n"); 00826 return; 00827 } 00828 zbuf_use = typecheck_compbuf(zbuf, CB_VAL); 00829 } 00830 else no_zbuf = 1; // no zbuffer input 00831 00832 // ok, process 00833 old = img; 00834 if (nqd->gamco) { 00835 // gamma correct, blender func is simplified, fixed value & RGBA only, 00836 // should make user param. also depremul and premul afterwards, gamma 00837 // correction can't work with premul alpha 00838 old = dupalloc_compbuf(img); 00839 premul_compbuf(old, 1); 00840 gamma_correct_compbuf(old, 0); 00841 premul_compbuf(old, 0); 00842 } 00843 00844 new = alloc_compbuf(old->x, old->y, old->type, 1); 00845 defocus_blur(node, new, old, zbuf_use, in[1]->vec[0]*nqd->scale, no_zbuf); 00846 00847 if (nqd->gamco) { 00848 premul_compbuf(new, 1); 00849 gamma_correct_compbuf(new, 1); 00850 premul_compbuf(new, 0); 00851 free_compbuf(old); 00852 } 00853 if(node->exec & NODE_BREAK) { 00854 free_compbuf(new); 00855 new= NULL; 00856 } 00857 out[0]->data = new; 00858 if (zbuf_use && (zbuf_use != zbuf)) free_compbuf(zbuf_use); 00859 } 00860 00861 static void node_composit_init_defocus(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) 00862 { 00863 /* qdn: defocus node */ 00864 NodeDefocus *nbd = MEM_callocN(sizeof(NodeDefocus), "node defocus data"); 00865 nbd->bktype = 0; 00866 nbd->rotation = 0.0f; 00867 nbd->preview = 1; 00868 nbd->gamco = 0; 00869 nbd->samples = 16; 00870 nbd->fstop = 128.f; 00871 nbd->maxblur = 0; 00872 nbd->bthresh = 1.f; 00873 nbd->scale = 1.f; 00874 nbd->no_zbuf = 1; 00875 node->storage = nbd; 00876 } 00877 00878 void register_node_type_cmp_defocus(bNodeTreeType *ttype) 00879 { 00880 static bNodeType ntype; 00881 00882 node_type_base(ttype, &ntype, CMP_NODE_DEFOCUS, "Defocus", NODE_CLASS_OP_FILTER, NODE_OPTIONS); 00883 node_type_socket_templates(&ntype, cmp_node_defocus_in, cmp_node_defocus_out); 00884 node_type_size(&ntype, 150, 120, 200); 00885 node_type_init(&ntype, node_composit_init_defocus); 00886 node_type_storage(&ntype, "NodeDefocus", node_free_standard_storage, node_copy_standard_storage); 00887 node_type_exec(&ntype, node_composit_exec_defocus); 00888 00889 nodeRegisterType(ttype, &ntype); 00890 }