Blender  V2.59
CMP_glare.c
Go to the documentation of this file.
00001 /*
00002  *
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version. 
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * The Original Code is Copyright (C) 2006 Blender Foundation.
00020  * All rights reserved.
00021  *
00022  * The Original Code is: all of this file.
00023  *
00024  * Contributor(s): Alfredo de Greef  (eeshlo)
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include "../CMP_util.h"
00035 
00036 static bNodeSocketType cmp_node_glare_in[]= {
00037         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
00038         {       -1, 0, ""       }
00039 };
00040 static bNodeSocketType cmp_node_glare_out[]= {
00041         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
00042         {       -1, 0, ""       }
00043 };
00044 
00045 
00046 // mix two images, src buffer does not have to be same size,
00047 static void mixImages(CompBuf *dst, CompBuf *src, float mix)
00048 {
00049         int x, y;
00050         fRGB c1, c2, *dcolp, *scolp;
00051         const float mf = 2.f - 2.f*fabsf(mix - 0.5f);
00052         if ((dst->x == src->x) && (dst->y == src->y)) {
00053                 for (y=0; y<dst->y; y++) {
00054                         dcolp = (fRGB*)&dst->rect[y*dst->x*dst->type];
00055                         scolp = (fRGB*)&src->rect[y*dst->x*dst->type];
00056                         for (x=0; x<dst->x; x++) {
00057                                 fRGB_copy(c1, dcolp[x]);
00058                                 fRGB_copy(c2, scolp[x]);
00059                                 c1[0] += mix*(c2[0] - c1[0]);
00060                                 c1[1] += mix*(c2[1] - c1[1]);
00061                                 c1[2] += mix*(c2[2] - c1[2]);
00062                                 if (c1[0] < 0.f) c1[0] = 0.f;
00063                                 if (c1[1] < 0.f) c1[1] = 0.f;
00064                                 if (c1[2] < 0.f) c1[2] = 0.f;
00065                                 fRGB_mult(c1, mf);
00066                                 fRGB_copy(dcolp[x], c1);
00067                         }
00068                 }
00069         }
00070         else {
00071                 float xr = src->x / (float)dst->x;
00072                 float yr = src->y / (float)dst->y;
00073                 for (y=0; y<dst->y; y++) {
00074                         dcolp = (fRGB*)&dst->rect[y*dst->x*dst->type];
00075                         for (x=0; x<dst->x; x++) {
00076                                 fRGB_copy(c1, dcolp[x]);
00077                                 qd_getPixelLerp(src, (x + 0.5f)*xr - 0.5f, (y + 0.5f)*yr - 0.5f, c2);
00078                                 c1[0] += mix*(c2[0] - c1[0]);
00079                                 c1[1] += mix*(c2[1] - c1[1]);
00080                                 c1[2] += mix*(c2[2] - c1[2]);
00081                                 if (c1[0] < 0.f) c1[0] = 0.f;
00082                                 if (c1[1] < 0.f) c1[1] = 0.f;
00083                                 if (c1[2] < 0.f) c1[2] = 0.f;
00084                                 fRGB_mult(c1, mf);
00085                                 fRGB_copy(dcolp[x], c1);
00086                         }
00087                 }
00088         }
00089 }
00090 
00091 
00092 // adds src to dst image, must be of same size
00093 static void addImage(CompBuf* dst, CompBuf* src, float scale)
00094 {
00095         if ((dst->x == src->x) && (dst->y == src->y)) {
00096                 int p = dst->x*dst->y*dst->type;
00097                 float *dcol = dst->rect, *scol = src->rect;
00098                 while (p--) *dcol++ += *scol++ * scale;
00099         }
00100 }
00101 
00102 
00103 // returns possibly downscaled copy of all pixels above threshold
00104 static CompBuf* BTP(CompBuf* src, float threshold, int scaledown)
00105 {
00106         int x, y;
00107         CompBuf* bsrc = qd_downScaledCopy(src, scaledown);
00108         float* cr = bsrc->rect;
00109         for (y=0; y<bsrc->y; ++y)
00110                 for (x=0; x<bsrc->x; ++x, cr+=4) {
00111                         if ((0.212671f*cr[0] + 0.71516f*cr[1] + 0.072169f*cr[2]) >= threshold) {
00112                                 cr[0] -= threshold, cr[1] -= threshold, cr[2] -= threshold;
00113                                 cr[0] = MAX2(cr[0], 0.f);
00114                                 cr[1] = MAX2(cr[1], 0.f);
00115                                 cr[2] = MAX2(cr[2], 0.f);
00116                         }
00117                         else cr[0] = cr[1] = cr[2] = 0.f;
00118                 }
00119         return bsrc;
00120 }
00121 
00122 //--------------------------------------------------------------------------------------------
00123 // simple 4-point star filter
00124 
00125 static void star4(NodeGlare* ndg, CompBuf* dst, CompBuf* src)
00126 {
00127         int x, y, i, xm, xp, ym, yp;
00128         float c[4] = {0,0,0,0}, tc[4] = {0,0,0,0};
00129         CompBuf *tbuf1, *tbuf2, *tsrc;
00130         const float f1 = 1.f - ndg->fade, f2 = (1.f - f1)*0.5f;
00131         //const float t3 = ndg->threshold*3.f;
00132         const float sc = (float)(1 << ndg->quality);
00133         const float isc = 1.f/sc;
00134 
00135         tsrc = BTP(src, ndg->threshold, (int)sc);
00136 
00137         tbuf1 = dupalloc_compbuf(tsrc);
00138         tbuf2 = dupalloc_compbuf(tsrc);
00139 
00140         for (i=0; i<ndg->iter; i++) {
00141                 // (x || x-1, y-1) to (x || x+1, y+1)
00142                 // F
00143                 for (y=0; y<tbuf1->y; y++) {
00144                         ym = y - i;
00145                         yp = y + i;
00146                         for (x=0; x<tbuf1->x; x++) {
00147                                 xm = x - i;
00148                                 xp = x + i;
00149                                 qd_getPixel(tbuf1, x, y, c);
00150                                 fRGB_mult(c, f1);
00151                                 qd_getPixel(tbuf1, (ndg->angle ? xm : x), ym, tc);
00152                                 fRGB_madd(c, tc, f2);
00153                                 qd_getPixel(tbuf1, (ndg->angle ? xp : x), yp, tc);
00154                                 fRGB_madd(c, tc, f2);
00155                                 qd_setPixel(tbuf1, x, y, c);
00156                         }
00157                 }
00158                 // B
00159                 for (y=tbuf1->y-1; y>=0; y--) {
00160                         ym = y - i;
00161                         yp = y + i;
00162                         for (x=tbuf1->x-1; x>=0; x--) {
00163                                 xm = x - i;
00164                                 xp = x + i;
00165                                 qd_getPixel(tbuf1, x, y, c);
00166                                 fRGB_mult(c, f1);
00167                                 qd_getPixel(tbuf1, (ndg->angle ? xm : x), ym, tc);
00168                                 fRGB_madd(c, tc, f2);
00169                                 qd_getPixel(tbuf1, (ndg->angle ? xp : x), yp, tc);
00170                                 fRGB_madd(c, tc, f2);
00171                                 qd_setPixel(tbuf1, x, y, c);
00172                         }
00173                 }
00174                 // (x-1, y || y+1) to (x+1, y || y-1)
00175                 // F
00176                 for (y=0; y<tbuf2->y; y++) {
00177                         ym = y - i;
00178                         yp = y + i;
00179                         for (x=0; x<tbuf2->x; x++) {
00180                                 xm = x - i;
00181                                 xp = x + i;
00182                                 qd_getPixel(tbuf2, x, y, c);
00183                                 fRGB_mult(c, f1);
00184                                 qd_getPixel(tbuf2, xm, (ndg->angle ? yp : y), tc);
00185                                 fRGB_madd(c, tc, f2);
00186                                 qd_getPixel(tbuf2, xp, (ndg->angle ? ym : y), tc);
00187                                 fRGB_madd(c, tc, f2);
00188                                 qd_setPixel(tbuf2, x, y, c);
00189                         }
00190                 }
00191                 // B
00192                 for (y=tbuf2->y-1; y>=0; y--) {
00193                         ym = y - i;
00194                         yp = y + i;
00195                         for (x=tbuf2->x-1; x>=0; x--) {
00196                                 xm = x - i;
00197                                 xp = x + i;
00198                                 qd_getPixel(tbuf2, x, y, c);
00199                                 fRGB_mult(c, f1);
00200                                 qd_getPixel(tbuf2, xm, (ndg->angle ? yp : y), tc);
00201                                 fRGB_madd(c, tc, f2);
00202                                 qd_getPixel(tbuf2, xp, (ndg->angle ? ym : y), tc);
00203                                 fRGB_madd(c, tc, f2);
00204                                 qd_setPixel(tbuf2, x, y, c);
00205                         }
00206                 }
00207         }
00208 
00209         for (y=0; y<tbuf1->y; ++y)
00210                 for (x=0; x<tbuf1->x; ++x) {
00211                         unsigned int p = (x + y*tbuf1->x)*tbuf1->type;
00212                         tbuf1->rect[p] += tbuf2->rect[p];
00213                         tbuf1->rect[p+1] += tbuf2->rect[p+1];
00214                         tbuf1->rect[p+2] += tbuf2->rect[p+2];
00215                 }
00216 
00217         for (y=0; y<dst->y; ++y) {
00218                 const float m = 0.5f + 0.5f*ndg->mix;
00219                 for (x=0; x<dst->x; ++x) {
00220                         unsigned int p = (x + y*dst->x)*dst->type;
00221                         qd_getPixelLerp(tbuf1, x*isc, y*isc, tc);
00222                         dst->rect[p] = src->rect[p] + m*(tc[0] - src->rect[p]);
00223                         dst->rect[p+1] = src->rect[p+1] + m*(tc[1] - src->rect[p+1]);
00224                         dst->rect[p+2] = src->rect[p+2] + m*(tc[2] - src->rect[p+2]);
00225                 }
00226         }
00227 
00228         free_compbuf(tbuf1);
00229         free_compbuf(tbuf2);
00230         free_compbuf(tsrc);
00231 }
00232 
00233 //--------------------------------------------------------------------------------------------
00234 // streak filter
00235 
00236 static void streaks(NodeGlare* ndg, CompBuf* dst, CompBuf* src)
00237 {
00238         CompBuf *bsrc, *tsrc, *tdst, *sbuf;
00239         int x, y, n;
00240         unsigned int nump=0;
00241         fRGB c1, c2, c3, c4;
00242         float a, ang = 360.f/(float)ndg->angle;
00243 
00244         bsrc = BTP(src, ndg->threshold, 1 << ndg->quality);
00245         tsrc = dupalloc_compbuf(bsrc); // sample from buffer
00246         tdst = alloc_compbuf(tsrc->x, tsrc->y, tsrc->type, 1); // sample to buffer
00247         sbuf = alloc_compbuf(tsrc->x, tsrc->y, tsrc->type, 1);  // streak sum buffer
00248 
00249         
00250         for (a=0.f; a<360.f; a+=ang) {
00251                 const float an = (a + (float)ndg->angle_ofs)*(float)M_PI/180.f;
00252                 const float vx = cos((double)an), vy = sin((double)an);
00253                 for (n=0; n<ndg->iter; ++n) {
00254                         const float p4 = pow(4.0, (double)n);
00255                         const float vxp = vx*p4, vyp = vy*p4;
00256                         const float wt = pow((double)ndg->fade, (double)p4);
00257                         const float cmo = 1.f - pow((double)ndg->colmod, (double)n+1);  // colormodulation amount relative to current pass
00258                         float* tdstcol = tdst->rect;
00259                         for (y=0; y<tsrc->y; ++y) {
00260                                 for (x=0; x<tsrc->x; ++x, tdstcol+=4) {
00261                                         // first pass no offset, always same for every pass, exact copy,
00262                                         // otherwise results in uneven brightness, only need once
00263                                         if (n==0) qd_getPixel(tsrc, x, y, c1); else c1[0]=c1[1]=c1[2]=0;
00264                                         qd_getPixelLerp(tsrc, x + vxp,     y + vyp,     c2);
00265                                         qd_getPixelLerp(tsrc, x + vxp*2.f, y + vyp*2.f, c3);
00266                                         qd_getPixelLerp(tsrc, x + vxp*3.f, y + vyp*3.f, c4);
00267                                         // modulate color to look vaguely similar to a color spectrum
00268                                         fRGB_rgbmult(c2, 1.f, cmo, cmo);
00269                                         fRGB_rgbmult(c3, cmo, cmo, 1.f);
00270                                         fRGB_rgbmult(c4, cmo, 1.f, cmo);
00271                                         tdstcol[0] = 0.5f*(tdstcol[0] + c1[0] + wt*(c2[0] + wt*(c3[0] + wt*c4[0])));
00272                                         tdstcol[1] = 0.5f*(tdstcol[1] + c1[1] + wt*(c2[1] + wt*(c3[1] + wt*c4[1])));
00273                                         tdstcol[2] = 0.5f*(tdstcol[2] + c1[2] + wt*(c2[2] + wt*(c3[2] + wt*c4[2])));
00274                                 }
00275                         }
00276                         memcpy(tsrc->rect, tdst->rect, sizeof(float)*tdst->x*tdst->y*tdst->type);
00277                 }
00278 
00279                 addImage(sbuf, tsrc, 1.f/(float)(6 - ndg->iter));
00280                 memset(tdst->rect, 0, tdst->x*tdst->y*tdst->type*sizeof(float));
00281                 memcpy(tsrc->rect, bsrc->rect, bsrc->x*bsrc->y*bsrc->type*sizeof(float));
00282                 nump++;
00283         }
00284 
00285         mixImages(dst, sbuf, 0.5f + 0.5f*ndg->mix);
00286 
00287         free_compbuf(tsrc);
00288         free_compbuf(tdst);
00289         free_compbuf(sbuf);
00290         free_compbuf(bsrc);
00291 }
00292 
00293 
00294 //--------------------------------------------------------------------------------------------
00295 // Ghosts (lensflare)
00296 
00297 static float smoothMask(float x, float y)
00298 {
00299         float t;
00300         x = 2.f*x - 1.f, y = 2.f*y - 1.f;
00301         if ((t = 1.f - sqrtf(x*x + y*y)) <= 0.f) return 0.f;
00302         return t;
00303 }
00304 
00305 static void ghosts(NodeGlare* ndg, CompBuf* dst, CompBuf* src)
00306 {
00307         // colormodulation and scale factors (cm & scalef) for 16 passes max: 64
00308         int x, y, n, p, np;
00309         fRGB c, tc, cm[64];
00310         float sc, isc, u, v, sm, s, t, ofs, scalef[64];
00311         CompBuf *tbuf1, *tbuf2, *gbuf;
00312         const float cmo = 1.f - ndg->colmod;
00313         const int qt = 1 << ndg->quality;
00314         const float s1 = 4.f/(float)qt, s2 = 2.f*s1;
00315 
00316         gbuf = BTP(src, ndg->threshold, qt);
00317         tbuf1 = dupalloc_compbuf(gbuf);
00318         IIR_gauss(tbuf1, s1, 0, 3);
00319         IIR_gauss(tbuf1, s1, 1, 3);
00320         IIR_gauss(tbuf1, s1, 2, 3);
00321         tbuf2 = dupalloc_compbuf(tbuf1);
00322         IIR_gauss(tbuf2, s2, 0, 3);
00323         IIR_gauss(tbuf2, s2, 1, 3);
00324         IIR_gauss(tbuf2, s2, 2, 3);
00325 
00326         if (ndg->iter & 1) ofs = 0.5f; else ofs = 0.f;
00327         for (x=0; x<(ndg->iter*4); x++) {
00328                 y = x & 3;
00329                 cm[x][0] = cm[x][1] = cm[x][2] = 1;
00330                 if (y==1) fRGB_rgbmult(cm[x], 1.f, cmo, cmo);
00331                 if (y==2) fRGB_rgbmult(cm[x], cmo, cmo, 1.f);
00332                 if (y==3) fRGB_rgbmult(cm[x], cmo, 1.f, cmo);
00333                 scalef[x] = 2.1f*(1.f-(x+ofs)/(float)(ndg->iter*4));
00334                 if (x & 1) scalef[x] = -0.99f/scalef[x];
00335         }
00336 
00337         sc = 2.13;
00338         isc = -0.97;
00339         for (y=0; y<gbuf->y; y++) {
00340                 v = (float)(y+0.5f) / (float)gbuf->y;
00341                 for (x=0; x<gbuf->x; x++) {
00342                         u = (float)(x+0.5f) / (float)gbuf->x;
00343                         s = (u-0.5f)*sc + 0.5f, t = (v-0.5f)*sc + 0.5f;
00344                         qd_getPixelLerp(tbuf1, s*gbuf->x, t*gbuf->y, c);
00345                         sm = smoothMask(s, t);
00346                         fRGB_mult(c, sm);
00347                         s = (u-0.5f)*isc + 0.5f, t = (v-0.5f)*isc + 0.5f;
00348                         qd_getPixelLerp(tbuf2, s*gbuf->x - 0.5f, t*gbuf->y - 0.5f, tc);
00349                         sm = smoothMask(s, t);
00350                         fRGB_madd(c, tc, sm);
00351                         qd_setPixel(gbuf, x, y, c);
00352                 }
00353         }
00354 
00355         memset(tbuf1->rect, 0, tbuf1->x*tbuf1->y*tbuf1->type*sizeof(float));
00356         for (n=1; n<ndg->iter; n++) {
00357                 for (y=0; y<gbuf->y; y++) {
00358                         v = (float)(y+0.5f) / (float)gbuf->y;
00359                         for (x=0; x<gbuf->x; x++) {
00360                                 u = (float)(x+0.5f) / (float)gbuf->x;
00361                                 tc[0] = tc[1] = tc[2] = 0.f;
00362                                 for (p=0;p<4;p++) {
00363                                         np = (n<<2) + p;
00364                                         s = (u-0.5f)*scalef[np] + 0.5f;
00365                                         t = (v-0.5f)*scalef[np] + 0.5f;
00366                                         qd_getPixelLerp(gbuf, s*gbuf->x - 0.5f, t*gbuf->y - 0.5f, c);
00367                                         fRGB_colormult(c, cm[np]);
00368                                         sm = smoothMask(s, t)*0.25f;
00369                                         fRGB_madd(tc, c, sm);
00370                                 }
00371                                 p = (x + y*tbuf1->x)*tbuf1->type;
00372                                 tbuf1->rect[p] += tc[0];
00373                                 tbuf1->rect[p+1] += tc[1];
00374                                 tbuf1->rect[p+2] += tc[2];
00375                         }
00376                 }
00377                 memcpy(gbuf->rect, tbuf1->rect, tbuf1->x*tbuf1->y*tbuf1->type*sizeof(float));
00378         }
00379 
00380         free_compbuf(tbuf1);
00381         free_compbuf(tbuf2);
00382 
00383         mixImages(dst, gbuf, 0.5f + 0.5f*ndg->mix);
00384         free_compbuf(gbuf);
00385 }
00386 
00387 //--------------------------------------------------------------------------------------------
00388 // Fog glow (convolution with kernel of exponential falloff)
00389 
00390 static void fglow(NodeGlare* ndg, CompBuf* dst, CompBuf* src)
00391 {
00392         int x, y;
00393         float scale, u, v, r, w, d;
00394         fRGB fcol;
00395         CompBuf *tsrc, *ckrn;
00396         unsigned int sz = 1 << ndg->size;
00397         const float cs_r = 1.f, cs_g = 1.f, cs_b = 1.f;
00398 
00399         // temp. src image
00400         tsrc = BTP(src, ndg->threshold, 1 << ndg->quality);
00401         // make the convolution kernel
00402         ckrn = alloc_compbuf(sz, sz, CB_RGBA, 1);
00403 
00404         scale = 0.25f*sqrtf(sz*sz);
00405 
00406         for (y=0; y<sz; ++y) {
00407                 v = 2.f*(y / (float)sz) - 1.f;
00408                 for (x=0; x<sz; ++x) {
00409                         u = 2.f*(x / (float)sz) - 1.f;
00410                         r = (u*u + v*v)*scale;
00411                         d = -sqrtf(sqrtf(sqrtf(r)))*9.f;
00412                         fcol[0] = expf(d*cs_r), fcol[1] = expf(d*cs_g), fcol[2] = expf(d*cs_b);
00413                         // linear window good enough here, visual result counts, not scientific analysis
00414                         //w = (1.f-fabs(u))*(1.f-fabs(v));
00415                         // actually, Hanning window is ok, cos^2 for some reason is slower
00416                         w = (0.5f + 0.5f*cos((double)u*M_PI))*(0.5f + 0.5f*cos((double)v*M_PI));
00417                         fRGB_mult(fcol, w);
00418                         qd_setPixel(ckrn, x, y, fcol);
00419                 }
00420         }
00421 
00422         convolve(tsrc, tsrc, ckrn);
00423         free_compbuf(ckrn);
00424         mixImages(dst, tsrc, 0.5f + 0.5f*ndg->mix);
00425         free_compbuf(tsrc);
00426 }
00427 
00428 //--------------------------------------------------------------------------------------------
00429 
00430 static void node_composit_exec_glare(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
00431 {
00432         CompBuf *new, *src, *img = in[0]->data;
00433         NodeGlare* ndg = node->storage;
00434 
00435         if ((img == NULL) || (out[0]->hasoutput == 0)) return;
00436 
00437         if (img->type != CB_RGBA) {
00438                 new = typecheck_compbuf(img, CB_RGBA);
00439                 src = typecheck_compbuf(img, CB_RGBA);
00440         } else {
00441                 new = dupalloc_compbuf(img);
00442                 src = dupalloc_compbuf(img);
00443         }
00444 
00445         {
00446                 int x, y;
00447                 for (y=0; y<new->y; ++y) {
00448                         fRGB* col = (fRGB*)&new->rect[y*new->x*new->type];
00449                         for (x=0; x<new->x; ++x) {
00450                                 col[x][0] = MAX2(col[x][0], 0.f);
00451                                 col[x][1] = MAX2(col[x][1], 0.f);
00452                                 col[x][2] = MAX2(col[x][2], 0.f);
00453                         }
00454                 }
00455         }
00456 
00457         switch (ndg->type) {
00458                 case 0:
00459                         star4(ndg, new, src);
00460                         break;
00461                 case 1:
00462                         fglow(ndg, new, src);
00463                         break;
00464                 case 3:
00465                         ghosts(ndg, new, src);
00466                         break;
00467                 case 2:
00468                 default:
00469                         streaks(ndg, new, src);
00470                         break;
00471         }
00472 
00473         free_compbuf(src);
00474         out[0]->data = new;
00475 }
00476 
00477 static void node_composit_init_glare(bNode* node)
00478 {
00479         NodeGlare *ndg = MEM_callocN(sizeof(NodeGlare), "node glare data");
00480         ndg->quality = 1;
00481         ndg->type = 2;
00482         ndg->iter = 3;
00483         ndg->colmod = 0.25;
00484         ndg->mix = 0;
00485         ndg->threshold = 1;
00486         ndg->angle = 4;
00487         ndg->angle_ofs = 0;
00488         ndg->fade = 0.9;
00489         ndg->size = 8;
00490         node->storage = ndg;
00491 }
00492 
00493 void register_node_type_cmp_glare(ListBase *lb)
00494 {
00495         static bNodeType ntype;
00496 
00497         node_type_base(&ntype, CMP_NODE_GLARE, "Glare", NODE_CLASS_OP_FILTER, NODE_OPTIONS,
00498                 cmp_node_glare_in, cmp_node_glare_out);
00499         node_type_size(&ntype, 150, 120, 200);
00500         node_type_init(&ntype, node_composit_init_glare);
00501         node_type_storage(&ntype, "NodeGlare", node_free_standard_storage, node_copy_standard_storage);
00502         node_type_exec(&ntype, node_composit_exec_glare);
00503 
00504         nodeRegisterType(lb, &ntype);
00505 }
00506