Blender V2.61 - r43446

rendercore.c

Go to the documentation of this file.
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) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * Contributors: Hos, Robert Wenzlaff.
00022  * Contributors: 2004/2005/2006 Blender Foundation, full recode
00023  *
00024  * ***** END GPL LICENSE BLOCK *****
00025  */
00026 
00032 /* system includes */
00033 #include <stdio.h>
00034 #include <math.h>
00035 #include <float.h>
00036 #include <string.h>
00037 #include <assert.h>
00038 
00039 /* External modules: */
00040 #include "MEM_guardedalloc.h"
00041 
00042 #include "BLI_math.h"
00043 #include "BLI_blenlib.h"
00044 #include "BLI_jitter.h"
00045 #include "BLI_rand.h"
00046 #include "BLI_threads.h"
00047 #include "BLI_utildefines.h"
00048 
00049 
00050 
00051 #include "DNA_image_types.h"
00052 #include "DNA_lamp_types.h"
00053 #include "DNA_material_types.h"
00054 #include "DNA_meshdata_types.h"
00055 #include "DNA_group_types.h"
00056 
00057 #include "BKE_global.h"
00058 #include "BKE_image.h"
00059 #include "BKE_main.h"
00060 #include "BKE_node.h"
00061 #include "BKE_texture.h"
00062 
00063 #include "IMB_imbuf_types.h"
00064 #include "IMB_imbuf.h"
00065 
00066 /* local include */
00067 #include "rayintersection.h"
00068 #include "rayobject.h"
00069 #include "renderpipeline.h"
00070 #include "render_result.h"
00071 #include "render_types.h"
00072 #include "renderdatabase.h"
00073 #include "occlusion.h"
00074 #include "pixelblending.h"
00075 #include "pixelshading.h"
00076 #include "shadbuf.h"
00077 #include "shading.h"
00078 #include "sss.h"
00079 #include "zbuf.h"
00080 
00081 #include "PIL_time.h"
00082 
00083 /* own include */
00084 #include "rendercore.h"
00085 
00086 
00087 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00088 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
00089 /* only to be used here in this file, it's for speed */
00090 extern struct Render R;
00091 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00092 
00093 /* x and y are current pixels in rect to be rendered */
00094 /* do not normalize! */
00095 void calc_view_vector(float *view, float x, float y)
00096 {
00097 
00098     view[2]= -ABS(R.clipsta);
00099     
00100     if(R.r.mode & R_ORTHO) {
00101         view[0]= view[1]= 0.0f;
00102     }
00103     else {
00104         
00105         if(R.r.mode & R_PANORAMA) {
00106             x-= R.panodxp;
00107         }
00108         
00109         /* move x and y to real viewplane coords */
00110         x= (x/(float)R.winx);
00111         view[0]= R.viewplane.xmin + x*(R.viewplane.xmax - R.viewplane.xmin);
00112         
00113         y= (y/(float)R.winy);
00114         view[1]= R.viewplane.ymin + y*(R.viewplane.ymax - R.viewplane.ymin);
00115         
00116 //      if(R.flag & R_SEC_FIELD) {
00117 //          if(R.r.mode & R_ODDFIELD) view[1]= (y+R.ystart)*R.ycor;
00118 //          else view[1]= (y+R.ystart+1.0)*R.ycor;
00119 //      }
00120 //      else view[1]= (y+R.ystart+R.bluroffsy+0.5)*R.ycor;
00121     
00122         if(R.r.mode & R_PANORAMA) {
00123             float u= view[0] + R.panodxv; float v= view[2];
00124             view[0]= R.panoco*u + R.panosi*v;
00125             view[2]= -R.panosi*u + R.panoco*v;
00126         }
00127     }
00128 }
00129 
00130 void calc_renderco_ortho(float co[3], float x, float y, int z)
00131 {
00132     /* x and y 3d coordinate can be derived from pixel coord and winmat */
00133     float fx= 2.0f/(R.winx*R.winmat[0][0]);
00134     float fy= 2.0f/(R.winy*R.winmat[1][1]);
00135     float zco;
00136     
00137     co[0]= (x - 0.5f*R.winx)*fx - R.winmat[3][0]/R.winmat[0][0];
00138     co[1]= (y - 0.5f*R.winy)*fy - R.winmat[3][1]/R.winmat[1][1];
00139     
00140     zco= ((float)z)/2147483647.0f;
00141     co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] );
00142 }
00143 
00144 void calc_renderco_zbuf(float co[3], const float view[3], int z)
00145 {
00146     float fac, zco;
00147     
00148     /* inverse of zbuf calc: zbuf = MAXZ*hoco_z/hoco_w */
00149     zco= ((float)z)/2147483647.0f;
00150     co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] );
00151 
00152     fac= co[2]/view[2];
00153     co[0]= fac*view[0];
00154     co[1]= fac*view[1];
00155 }
00156 
00157 /* also used in zbuf.c and shadbuf.c */
00158 int count_mask(unsigned short mask)
00159 {
00160     if(R.samples)
00161         return (R.samples->cmask[mask & 255]+R.samples->cmask[mask>>8]);
00162     return 0;
00163 }
00164 
00165 static int calchalo_z(HaloRen *har, int zz)
00166 {
00167     
00168     if(har->type & HA_ONLYSKY) {
00169         if(zz < 0x7FFFFFF0) zz= - 0x7FFFFF; /* edge render messes zvalues */
00170     }
00171     else {
00172         zz= (zz>>8);
00173     }
00174     return zz;
00175 }
00176 
00177 
00178 
00179 static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, int od, float dist, float xn, float yn, PixStr *ps)
00180 {
00181     float col[4], accol[4], fac;
00182     int amount, amountm, zz, flarec, sample, fullsample, mask=0;
00183     
00184     fullsample= (totsample > 1);
00185     amount= 0;
00186     accol[0]=accol[1]=accol[2]=accol[3]= 0.0f;
00187     flarec= har->flarec;
00188     
00189     while(ps) {
00190         amountm= count_mask(ps->mask);
00191         amount+= amountm;
00192         
00193         zz= calchalo_z(har, ps->z);
00194         if((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) {
00195             if(shadeHaloFloat(har, col, zz, dist, xn, yn, flarec)) {
00196                 flarec= 0;
00197 
00198                 if(fullsample) {
00199                     for(sample=0; sample<totsample; sample++)
00200                         if(ps->mask & (1 << sample))
00201                             addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add);
00202                 }
00203                 else {
00204                     fac= ((float)amountm)/(float)R.osa;
00205                     accol[0]+= fac*col[0];
00206                     accol[1]+= fac*col[1];
00207                     accol[2]+= fac*col[2];
00208                     accol[3]+= fac*col[3];
00209                 }
00210             }
00211         }
00212         
00213         mask |= ps->mask;
00214         ps= ps->next;
00215     }
00216 
00217     /* now do the sky sub-pixels */
00218     amount= R.osa-amount;
00219     if(amount) {
00220         if(shadeHaloFloat(har, col, 0x7FFFFF, dist, xn, yn, flarec)) {
00221             if(!fullsample) {
00222                 fac= ((float)amount)/(float)R.osa;
00223                 accol[0]+= fac*col[0];
00224                 accol[1]+= fac*col[1];
00225                 accol[2]+= fac*col[2];
00226                 accol[3]+= fac*col[3];
00227             }
00228         }
00229     }
00230 
00231     if(fullsample) {
00232         for(sample=0; sample<totsample; sample++)
00233             if(!(mask & (1 << sample)))
00234                 addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add);
00235     }
00236     else {
00237         col[0]= accol[0];
00238         col[1]= accol[1];
00239         col[2]= accol[2];
00240         col[3]= accol[3];
00241         
00242         for(sample=0; sample<totsample; sample++)
00243             addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add);
00244     }
00245 }
00246 
00247 static void halo_tile(RenderPart *pa, RenderLayer *rl)
00248 {
00249     RenderLayer *rlpp[RE_MAX_OSA];
00250     HaloRen *har;
00251     rcti disprect= pa->disprect, testrect= pa->disprect;
00252     float dist, xsq, ysq, xn, yn;
00253     float col[4];
00254     intptr_t *rd= NULL;
00255     int a, *rz, zz, y, sample, totsample, od;
00256     short minx, maxx, miny, maxy, x;
00257     unsigned int lay= rl->lay;
00258 
00259     /* we don't render halos in the cropped area, gives errors in flare counter */
00260     if(pa->crop) {
00261         testrect.xmin+= pa->crop;
00262         testrect.xmax-= pa->crop;
00263         testrect.ymin+= pa->crop;
00264         testrect.ymax-= pa->crop;
00265     }
00266     
00267     totsample= get_sample_layers(pa, rl, rlpp);
00268 
00269     for(a=0; a<R.tothalo; a++) {
00270         har= R.sortedhalos[a];
00271 
00272         /* layer test, clip halo with y */
00273         if((har->lay & lay)==0);
00274         else if(testrect.ymin > har->maxy);
00275         else if(testrect.ymax < har->miny);
00276         else {
00277             
00278             minx= floor(har->xs-har->rad);
00279             maxx= ceil(har->xs+har->rad);
00280             
00281             if(testrect.xmin > maxx);
00282             else if(testrect.xmax < minx);
00283             else {
00284                 
00285                 minx= MAX2(minx, testrect.xmin);
00286                 maxx= MIN2(maxx, testrect.xmax);
00287             
00288                 miny= MAX2(har->miny, testrect.ymin);
00289                 maxy= MIN2(har->maxy, testrect.ymax);
00290             
00291                 for(y=miny; y<maxy; y++) {
00292                     int rectofs= (y-disprect.ymin)*pa->rectx + (minx - disprect.xmin);
00293                     rz= pa->rectz + rectofs;
00294                     od= rectofs;
00295                     
00296                     if(pa->rectdaps)
00297                         rd= pa->rectdaps + rectofs;
00298                     
00299                     yn= (y-har->ys)*R.ycor;
00300                     ysq= yn*yn;
00301                     
00302                     for(x=minx; x<maxx; x++, rz++, od++) {
00303                         xn= x- har->xs;
00304                         xsq= xn*xn;
00305                         dist= xsq+ysq;
00306                         if(dist<har->radsq) {
00307                             if(rd && *rd) {
00308                                 halo_pixelstruct(har, rlpp, totsample, od, dist, xn, yn, (PixStr *)*rd);
00309                             }
00310                             else {
00311                                 zz= calchalo_z(har, *rz);
00312                                 if((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) {
00313                                     if(shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec)) {
00314                                         for(sample=0; sample<totsample; sample++)
00315                                             addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add);
00316                                     }
00317                                 }
00318                             }
00319                         }
00320                         if(rd) rd++;
00321                     }
00322                 }
00323             }
00324         }
00325         if(R.test_break(R.tbh) ) break; 
00326     }
00327 }
00328 
00329 static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
00330 {
00331     RenderLayer *rlpp[RE_MAX_OSA];
00332     ShadeInput shi;
00333     float *pass;
00334     float fac, col[4];
00335     intptr_t *rd= pa->rectdaps;
00336     int *rz= pa->rectz;
00337     int x, y, sample, totsample, fullsample, od;
00338     
00339     totsample= get_sample_layers(pa, rl, rlpp);
00340     fullsample= (totsample > 1);
00341 
00342     shade_input_initialize(&shi, pa, rl, 0); /* this zero's ShadeInput for us */
00343     
00344     for(od=0, y=pa->disprect.ymin; y<pa->disprect.ymax; y++) {
00345         for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, rz++, od++) {
00346             
00347             calc_view_vector(shi.view, x, y);
00348             
00349             if(rd && *rd) {
00350                 PixStr *ps= (PixStr *)*rd;
00351                 int count, totsamp= 0, mask= 0;
00352                 
00353                 while(ps) {
00354                     if(R.r.mode & R_ORTHO)
00355                         calc_renderco_ortho(shi.co, (float)x, (float)y, ps->z);
00356                     else
00357                         calc_renderco_zbuf(shi.co, shi.view, ps->z);
00358                     
00359                     totsamp+= count= count_mask(ps->mask);
00360                     mask |= ps->mask;
00361 
00362                     col[0]= col[1]= col[2]= col[3]= 0.0f;
00363                     renderspothalo(&shi, col, 1.0f);
00364 
00365                     if(fullsample) {
00366                         for(sample=0; sample<totsample; sample++) {
00367                             if(ps->mask & (1 << sample)) {
00368                                 pass= rlpp[sample]->rectf + od*4;
00369                                 pass[0]+= col[0];
00370                                 pass[1]+= col[1];
00371                                 pass[2]+= col[2];
00372                                 pass[3]+= col[3];
00373                                 if(pass[3]>1.0f) pass[3]= 1.0f;
00374                             }
00375                         }
00376                     }
00377                     else {
00378                         fac= ((float)count)/(float)R.osa;
00379                         pass= rl->rectf + od*4;
00380                         pass[0]+= fac*col[0];
00381                         pass[1]+= fac*col[1];
00382                         pass[2]+= fac*col[2];
00383                         pass[3]+= fac*col[3];
00384                         if(pass[3]>1.0f) pass[3]= 1.0f;
00385                     }
00386 
00387                     ps= ps->next;
00388                 }
00389 
00390                 if(totsamp<R.osa) {
00391                     shi.co[2]= 0.0f;
00392 
00393                     col[0]= col[1]= col[2]= col[3]= 0.0f;
00394                     renderspothalo(&shi, col, 1.0f);
00395 
00396                     if(fullsample) {
00397                         for(sample=0; sample<totsample; sample++) {
00398                             if(!(mask & (1 << sample))) {
00399                                 pass= rlpp[sample]->rectf + od*4;
00400                                 pass[0]+= col[0];
00401                                 pass[1]+= col[1];
00402                                 pass[2]+= col[2];
00403                                 pass[3]+= col[3];
00404                                 if(pass[3]>1.0f) pass[3]= 1.0f;
00405                             }
00406                         }
00407                     }
00408                     else {
00409                         fac= ((float)R.osa-totsamp)/(float)R.osa;
00410                         pass= rl->rectf + od*4;
00411                         pass[0]+= fac*col[0];
00412                         pass[1]+= fac*col[1];
00413                         pass[2]+= fac*col[2];
00414                         pass[3]+= fac*col[3];
00415                         if(pass[3]>1.0f) pass[3]= 1.0f;
00416                     }
00417                 }
00418             }
00419             else {
00420                 if(R.r.mode & R_ORTHO)
00421                     calc_renderco_ortho(shi.co, (float)x, (float)y, *rz);
00422                 else
00423                     calc_renderco_zbuf(shi.co, shi.view, *rz);
00424                 
00425                 col[0]= col[1]= col[2]= col[3]= 0.0f;
00426                 renderspothalo(&shi, col, 1.0f);
00427 
00428                 for(sample=0; sample<totsample; sample++) {
00429                     pass= rlpp[sample]->rectf + od*4;
00430                     pass[0]+= col[0];
00431                     pass[1]+= col[1];
00432                     pass[2]+= col[2];
00433                     pass[3]+= col[3];
00434                     if(pass[3]>1.0f) pass[3]= 1.0f;
00435                 }
00436             }
00437             
00438             if(rd) rd++;
00439         }
00440         if(y&1)
00441             if(R.test_break(R.tbh)) break; 
00442     }
00443 }               
00444 
00445 
00446 /* ********************* MAINLOOPS ******************** */
00447 
00448 /* osa version */
00449 static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, ShadeInput *shi, ShadeResult *shr)
00450 {
00451     RenderPass *rpass;
00452 
00453     /* combined rgb */
00454     add_filt_fmask(curmask, shr->combined, rl->rectf + 4*offset, rectx);
00455     
00456     for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
00457         float *fp, *col= NULL;
00458         int pixsize= 3;
00459         
00460         switch(rpass->passtype) {
00461             case SCE_PASS_Z:
00462                 fp= rpass->rect + offset;
00463                 *fp= shr->z;
00464                 break;
00465             case SCE_PASS_RGBA:
00466                 col= shr->col;
00467                 pixsize= 4;
00468                 break;
00469             case SCE_PASS_EMIT:
00470                 col= shr->emit;
00471                 break;
00472             case SCE_PASS_DIFFUSE:
00473                 col= shr->diff;
00474                 break;
00475             case SCE_PASS_SPEC:
00476                 col= shr->spec;
00477                 break;
00478             case SCE_PASS_SHADOW:
00479                 col= shr->shad;
00480                 break;
00481             case SCE_PASS_AO:
00482                 col= shr->ao;
00483                 break;
00484             case SCE_PASS_ENVIRONMENT:
00485                 col= shr->env;
00486                 break;
00487             case SCE_PASS_INDIRECT:
00488                 col= shr->indirect;
00489                 break;
00490             case SCE_PASS_REFLECT:
00491                 col= shr->refl;
00492                 break;
00493             case SCE_PASS_REFRACT:
00494                 col= shr->refr;
00495                 break;
00496             case SCE_PASS_NORMAL:
00497                 col= shr->nor;
00498                 break;
00499             case SCE_PASS_UV:
00500                 /* box filter only, gauss will screwup UV too much */
00501                 if(shi->totuv) {
00502                     float mult= (float)count_mask(curmask)/(float)R.osa;
00503                     fp= rpass->rect + 3*offset;
00504                     fp[0]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[0]);
00505                     fp[1]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[1]);
00506                     fp[2]+= mult;
00507                 }
00508                 break;
00509             case SCE_PASS_INDEXOB:
00510                 /* no filter */
00511                 if(shi->vlr) {
00512                     fp= rpass->rect + offset;
00513                     if(*fp==0.0f)
00514                         *fp= (float)shi->obr->ob->index;
00515                 }
00516                 break;
00517             case SCE_PASS_INDEXMA:
00518                     /* no filter */
00519                     if(shi->vlr) {
00520                             fp= rpass->rect + offset;
00521                             if(*fp==0.0f)
00522                                     *fp= (float)shi->mat->index;
00523                     }
00524                     break;
00525             case SCE_PASS_MIST:
00526                 /*  */
00527                 col= &shr->mist;
00528                 pixsize= 1;
00529                 break;
00530             
00531             case SCE_PASS_VECTOR:
00532             {
00533                 /* add minimum speed in pixel, no filter */
00534                 fp= rpass->rect + 4*offset;
00535                 if( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) {
00536                     fp[0]= shr->winspeed[0];
00537                     fp[1]= shr->winspeed[1];
00538                 }
00539                 if( (ABS(shr->winspeed[2]) + ABS(shr->winspeed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) {
00540                     fp[2]= shr->winspeed[2];
00541                     fp[3]= shr->winspeed[3];
00542                 }
00543             }
00544                 break;
00545 
00546             case SCE_PASS_RAYHITS:
00547                 /*  */
00548                 col= shr->rayhits;
00549                 pixsize= 4;
00550                 break;
00551         }
00552         if(col) {
00553             fp= rpass->rect + pixsize*offset;
00554             add_filt_fmask_pixsize(curmask, col, fp, rectx, pixsize);
00555         }
00556     }
00557 }
00558 
00559 /* non-osa version */
00560 static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult *shr)
00561 {
00562     RenderPass *rpass;
00563     float *fp;
00564     
00565     fp= rl->rectf + 4*offset;
00566     copy_v4_v4(fp, shr->combined);
00567     
00568     for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
00569         float *col= NULL, uvcol[3];
00570         int a, pixsize= 3;
00571         
00572         switch(rpass->passtype) {
00573             case SCE_PASS_Z:
00574                 fp= rpass->rect + offset;
00575                 *fp= shr->z;
00576                 break;
00577             case SCE_PASS_RGBA:
00578                 col= shr->col;
00579                 pixsize= 4;
00580                 break;
00581             case SCE_PASS_EMIT:
00582                 col= shr->emit;
00583                 break;
00584             case SCE_PASS_DIFFUSE:
00585                 col= shr->diff;
00586                 break;
00587             case SCE_PASS_SPEC:
00588                 col= shr->spec;
00589                 break;
00590             case SCE_PASS_SHADOW:
00591                 col= shr->shad;
00592                 break;
00593             case SCE_PASS_AO:
00594                 col= shr->ao;
00595                 break;
00596             case SCE_PASS_ENVIRONMENT:
00597                 col= shr->env;
00598                 break;
00599             case SCE_PASS_INDIRECT:
00600                 col= shr->indirect;
00601                 break;
00602             case SCE_PASS_REFLECT:
00603                 col= shr->refl;
00604                 break;
00605             case SCE_PASS_REFRACT:
00606                 col= shr->refr;
00607                 break;
00608             case SCE_PASS_NORMAL:
00609                 col= shr->nor;
00610                 break;
00611             case SCE_PASS_UV:
00612                 if(shi->totuv) {
00613                     uvcol[0]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[0];
00614                     uvcol[1]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[1];
00615                     uvcol[2]= 1.0f;
00616                     col= uvcol;
00617                 }
00618                 break;
00619             case SCE_PASS_VECTOR:
00620                 col= shr->winspeed;
00621                 pixsize= 4;
00622                 break;
00623             case SCE_PASS_INDEXOB:
00624                 if(shi->vlr) {
00625                     fp= rpass->rect + offset;
00626                     *fp= (float)shi->obr->ob->index;
00627                 }
00628                 break;
00629             case SCE_PASS_INDEXMA:
00630                 if(shi->vlr) {
00631                     fp= rpass->rect + offset;
00632                     *fp= (float)shi->mat->index;
00633                 }
00634                 break;
00635             case SCE_PASS_MIST:
00636                 fp= rpass->rect + offset;
00637                 *fp= shr->mist;
00638                 break;
00639             case SCE_PASS_RAYHITS:
00640                 col= shr->rayhits;
00641                 pixsize= 4;
00642                 break;
00643         }
00644         if(col) {
00645             fp= rpass->rect + pixsize*offset;
00646             for(a=0; a<pixsize; a++)
00647                 fp[a]= col[a];
00648         }
00649     }
00650 }
00651 
00652 int get_sample_layers(RenderPart *pa, RenderLayer *rl, RenderLayer **rlpp)
00653 {
00654     
00655     if(pa->fullresult.first) {
00656         int sample, nr= BLI_findindex(&pa->result->layers, rl);
00657         
00658         for(sample=0; sample<R.osa; sample++) {
00659             RenderResult *rr= BLI_findlink(&pa->fullresult, sample);
00660         
00661             rlpp[sample]= BLI_findlink(&rr->layers, nr);
00662         }       
00663         return R.osa;
00664     }
00665     else {
00666         rlpp[0]= rl;
00667         return 1;
00668     }
00669 }
00670 
00671 
00672 /* only do sky, is default in the solid layer (shade_tile) btw */
00673 static void sky_tile(RenderPart *pa, RenderLayer *rl)
00674 {
00675     RenderLayer *rlpp[RE_MAX_OSA];
00676     int x, y, od=0, totsample;
00677     
00678     if(R.r.alphamode!=R_ADDSKY)
00679         return;
00680     
00681     totsample= get_sample_layers(pa, rl, rlpp);
00682     
00683     for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) {
00684         for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, od+=4) {
00685             float col[4];
00686             int sample, done= 0;
00687             
00688             for(sample= 0; sample<totsample; sample++) {
00689                 float *pass= rlpp[sample]->rectf + od;
00690                 
00691                 if(pass[3]<1.0f) {
00692                     
00693                     if(done==0) {
00694                         shadeSkyPixel(col, x, y, pa->thread);
00695                         done= 1;
00696                     }
00697                     
00698                     if(pass[3]==0.0f) {
00699                         copy_v4_v4(pass, col);
00700                     }
00701                     else {
00702                         addAlphaUnderFloat(pass, col);
00703                     }
00704                 }
00705             }           
00706         }
00707         
00708         if(y&1)
00709             if(R.test_break(R.tbh)) break; 
00710     }
00711 }
00712 
00713 static void atm_tile(RenderPart *pa, RenderLayer *rl)
00714 {
00715     RenderPass *zpass;
00716     GroupObject *go;
00717     LampRen *lar;
00718     RenderLayer *rlpp[RE_MAX_OSA];
00719     int totsample;
00720     int x, y, od= 0;
00721     
00722     totsample= get_sample_layers(pa, rl, rlpp);
00723 
00724     /* check that z pass is enabled */
00725     if(pa->rectz==NULL) return;
00726     for(zpass= rl->passes.first; zpass; zpass= zpass->next)
00727         if(zpass->passtype==SCE_PASS_Z)
00728             break;
00729     
00730     if(zpass==NULL) return;
00731 
00732     /* check for at least one sun lamp that its atmosphere flag is enabled */
00733     for(go=R.lights.first; go; go= go->next) {
00734         lar= go->lampren;
00735         if(lar->type==LA_SUN && lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_AP))
00736             break;
00737     }
00738     /* do nothign and return if there is no sun lamp */
00739     if(go==NULL)
00740         return;
00741     
00742     /* for each x,y and each sample, and each sun lamp*/
00743     for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) {
00744         for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, od++) {
00745             int sample;
00746             
00747             for(sample=0; sample<totsample; sample++) {
00748                 float *zrect= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_Z) + od;
00749                 float *rgbrect = rlpp[sample]->rectf + 4*od;
00750                 float rgb[3] = {0};
00751                 int done= 0;
00752                 
00753                 for(go=R.lights.first; go; go= go->next) {
00754                 
00755                     
00756                     lar= go->lampren;
00757                     if(lar->type==LA_SUN && lar->sunsky) {
00758                         
00759                         /* if it's sky continue and don't apply atmosphere effect on it */
00760                         if(*zrect >= 9.9e10f || rgbrect[3]==0.0f) {
00761                             continue;
00762                         }
00763                                                 
00764                         if((lar->sunsky->effect_type & LA_SUN_EFFECT_AP)) { 
00765                             float tmp_rgb[3];
00766                             
00767                             /* skip if worldspace lamp vector is below horizon */
00768                             if(go->ob->obmat[2][2] < 0.f) {
00769                                 continue;
00770                             }
00771                             
00772                             copy_v3_v3(tmp_rgb, rgbrect);
00773                             if(rgbrect[3]!=1.0f) {  /* de-premul */
00774                                 mul_v3_fl(tmp_rgb, 1.0f/rgbrect[3]);
00775                             }
00776                             shadeAtmPixel(lar->sunsky, tmp_rgb, x, y, *zrect);
00777                             if(rgbrect[3]!=1.0f) {  /* premul */
00778                                 mul_v3_fl(tmp_rgb, rgbrect[3]);
00779                             }
00780                             
00781                             if(done==0) {
00782                                 copy_v3_v3(rgb, tmp_rgb);
00783                                 done = 1;                       
00784                             }
00785                             else{
00786                                 rgb[0] = 0.5f*rgb[0] + 0.5f*tmp_rgb[0];
00787                                 rgb[1] = 0.5f*rgb[1] + 0.5f*tmp_rgb[1];
00788                                 rgb[2] = 0.5f*rgb[2] + 0.5f*tmp_rgb[2];
00789                             }
00790                         }
00791                     }
00792                 }
00793 
00794                 /* if at least for one sun lamp aerial perspective was applied*/
00795                 if(done) {
00796                     copy_v3_v3(rgbrect, rgb);
00797                 }
00798             }
00799         }
00800     }
00801 }
00802 
00803 static void shadeDA_tile(RenderPart *pa, RenderLayer *rl)
00804 {
00805     RenderResult *rr= pa->result;
00806     ShadeSample ssamp;
00807     intptr_t *rd, *rectdaps= pa->rectdaps;
00808     int samp;
00809     int x, y, seed, crop=0, offs=0, od;
00810     
00811     if(R.test_break(R.tbh)) return; 
00812     
00813     /* irregular shadowb buffer creation */
00814     if(R.r.mode & R_SHADOW)
00815         ISB_create(pa, NULL);
00816     
00817     /* we set per pixel a fixed seed, for random AO and shadow samples */
00818     seed= pa->rectx*pa->disprect.ymin;
00819     
00820     /* general shader info, passes */
00821     shade_sample_initialize(&ssamp, pa, rl);
00822 
00823     /* occlusion caching */
00824     if(R.occlusiontree)
00825         cache_occ_samples(&R, pa, &ssamp);
00826         
00827     /* filtered render, for now we assume only 1 filter size */
00828     if(pa->crop) {
00829         crop= 1;
00830         rectdaps+= pa->rectx + 1;
00831         offs= pa->rectx + 1;
00832     }
00833     
00834     /* scanline updates have to be 2 lines behind */
00835     rr->renrect.ymin= 0;
00836     rr->renrect.ymax= -2*crop;
00837     rr->renlay= rl;
00838                 
00839     for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) {
00840         rd= rectdaps;
00841         od= offs;
00842         
00843         for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, rd++, od++) {
00844             BLI_thread_srandom(pa->thread, seed++);
00845             
00846             if(*rd) {
00847                 if(shade_samples(&ssamp, (PixStr *)(*rd), x, y)) {
00848                     
00849                     /* multisample buffers or filtered mask filling? */
00850                     if(pa->fullresult.first) {
00851                         int a;
00852                         for(samp=0; samp<ssamp.tot; samp++) {
00853                             int smask= ssamp.shi[samp].mask;
00854                             for(a=0; a<R.osa; a++) {
00855                                 int mask= 1<<a;
00856                                 if(smask & mask)
00857                                     add_passes(ssamp.rlpp[a], od, &ssamp.shi[samp], &ssamp.shr[samp]);
00858                             }
00859                         }
00860                     }
00861                     else {
00862                         for(samp=0; samp<ssamp.tot; samp++)
00863                             add_filt_passes(rl, ssamp.shi[samp].mask, pa->rectx, od, &ssamp.shi[samp], &ssamp.shr[samp]);
00864                     }
00865                 }
00866             }
00867         }
00868         
00869         rectdaps+= pa->rectx;
00870         offs+= pa->rectx;
00871         
00872         if(y&1) if(R.test_break(R.tbh)) break; 
00873     }
00874     
00875     /* disable scanline updating */
00876     rr->renlay= NULL;
00877     
00878     if(R.r.mode & R_SHADOW)
00879         ISB_free(pa);
00880 
00881     if(R.occlusiontree)
00882         free_occ_samples(&R, pa);
00883 }
00884 
00885 /* ************* pixel struct ******** */
00886 
00887 
00888 static PixStrMain *addpsmain(ListBase *lb)
00889 {
00890     PixStrMain *psm;
00891     
00892     psm= (PixStrMain *)MEM_mallocN(sizeof(PixStrMain),"pixstrMain");
00893     BLI_addtail(lb, psm);
00894     
00895     psm->ps= (PixStr *)MEM_mallocN(4096*sizeof(PixStr),"pixstr");
00896     psm->counter= 0;
00897     
00898     return psm;
00899 }
00900 
00901 static void freeps(ListBase *lb)
00902 {
00903     PixStrMain *psm, *psmnext;
00904     
00905     for(psm= lb->first; psm; psm= psmnext) {
00906         psmnext= psm->next;
00907         if(psm->ps)
00908             MEM_freeN(psm->ps);
00909         MEM_freeN(psm);
00910     }
00911     lb->first= lb->last= NULL;
00912 }
00913 
00914 static void addps(ListBase *lb, intptr_t *rd, int obi, int facenr, int z, int maskz, unsigned short mask)
00915 {
00916     PixStrMain *psm;
00917     PixStr *ps, *last= NULL;
00918     
00919     if(*rd) {   
00920         ps= (PixStr *)(*rd);
00921         
00922         while(ps) {
00923             if( ps->obi == obi && ps->facenr == facenr ) {
00924                 ps->mask |= mask;
00925                 return;
00926             }
00927             last= ps;
00928             ps= ps->next;
00929         }
00930     }
00931     
00932     /* make new PS (pixel struct) */
00933     psm= lb->last;
00934     
00935     if(psm->counter==4095)
00936         psm= addpsmain(lb);
00937     
00938     ps= psm->ps + psm->counter++;
00939     
00940     if(last) last->next= ps;
00941     else *rd= (intptr_t)ps;
00942     
00943     ps->next= NULL;
00944     ps->obi= obi;
00945     ps->facenr= facenr;
00946     ps->z= z;
00947     ps->maskz= maskz;
00948     ps->mask = mask;
00949     ps->shadfac= 0;
00950 }
00951 
00952 static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect)
00953 {
00954     float addcol[4];
00955     int pix;
00956     
00957     if(arect==NULL)
00958         return;
00959     
00960     for(pix= pa->rectx*pa->recty; pix>0; pix--, arect++, rectf+=4) {
00961         if(*arect != 0.0f) {
00962             addcol[0]= *arect * R.r.edgeR;
00963             addcol[1]= *arect * R.r.edgeG;
00964             addcol[2]= *arect * R.r.edgeB;
00965             addcol[3]= *arect;
00966             addAlphaOverFloat(rectf, addcol);
00967         }
00968     }
00969 }
00970 
00971 static void convert_to_key_alpha(RenderPart *pa, RenderLayer *rl)
00972 {
00973     RenderLayer *rlpp[RE_MAX_OSA];
00974     int y, sample, totsample;
00975     
00976     totsample= get_sample_layers(pa, rl, rlpp);
00977     
00978     for(sample= 0; sample<totsample; sample++) {
00979         float *rectf= rlpp[sample]->rectf;
00980         
00981         for(y= pa->rectx*pa->recty; y>0; y--, rectf+=4) {
00982             if(rectf[3] >= 1.0f);
00983             else if(rectf[3] > 0.0f) {
00984                 rectf[0] /= rectf[3];
00985                 rectf[1] /= rectf[3];
00986                 rectf[2] /= rectf[3];
00987             }
00988         }
00989     }
00990 }
00991 
00992 /* adds only alpha values */
00993 static void edge_enhance_tile(RenderPart *pa, float *rectf, int *rectz)
00994 {
00995     /* use zbuffer to define edges, add it to the image */
00996     int y, x, col, *rz, *rz1, *rz2, *rz3;
00997     int zval1, zval2, zval3;
00998     float *rf;
00999     
01000     /* shift values in zbuffer 4 to the right (anti overflows), for filter we need multiplying with 12 max */
01001     rz= rectz;
01002     if(rz==NULL) return;
01003     
01004     for(y=0; y<pa->recty; y++)
01005         for(x=0; x<pa->rectx; x++, rz++) (*rz)>>= 4;
01006     
01007     rz1= rectz;
01008     rz2= rz1+pa->rectx;
01009     rz3= rz2+pa->rectx;
01010     
01011     rf= rectf+pa->rectx+1;
01012     
01013     for(y=0; y<pa->recty-2; y++) {
01014         for(x=0; x<pa->rectx-2; x++, rz1++, rz2++, rz3++, rf++) {
01015             
01016             /* prevent overflow with sky z values */
01017             zval1=   rz1[0] + 2*rz1[1] +   rz1[2];
01018             zval2=  2*rz2[0]           + 2*rz2[2];
01019             zval3=   rz3[0] + 2*rz3[1] +   rz3[2];
01020             
01021             col= ( 4*rz2[1] - (zval1 + zval2 + zval3)/3 );
01022             if(col<0) col= -col;
01023             
01024             col >>= 5;
01025             if(col > (1<<16)) col= (1<<16);
01026             else col= (R.r.edgeint*col)>>8;
01027             
01028             if(col>0) {
01029                 float fcol;
01030                 
01031                 if(col>255) fcol= 1.0f;
01032                 else fcol= (float)col/255.0f;
01033                 
01034                 if(R.osa)
01035                     *rf+= fcol/(float)R.osa;
01036                 else
01037                     *rf= fcol;
01038             }
01039         }
01040         rz1+= 2;
01041         rz2+= 2;
01042         rz3+= 2;
01043         rf+= 2;
01044     }
01045     
01046     /* shift back zbuf values, we might need it still */
01047     rz= rectz;
01048     for(y=0; y<pa->recty; y++)
01049         for(x=0; x<pa->rectx; x++, rz++) (*rz)<<= 4;
01050     
01051 }
01052 
01053 static void reset_sky_speed(RenderPart *pa, RenderLayer *rl)
01054 {
01055     /* for all pixels with max speed, set to zero */
01056     RenderLayer *rlpp[RE_MAX_OSA];
01057     float *fp;
01058     int a, sample, totsample;
01059     
01060     totsample= get_sample_layers(pa, rl, rlpp);
01061 
01062     for(sample= 0; sample<totsample; sample++) {
01063         fp= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_VECTOR);
01064         if(fp==NULL) break;
01065 
01066         for(a= 4*pa->rectx*pa->recty - 1; a>=0; a--)
01067             if(fp[a] == PASS_VECTOR_MAX) fp[a]= 0.0f;
01068     }
01069 }
01070 
01071 static unsigned short *make_solid_mask(RenderPart *pa)
01072 { 
01073     intptr_t *rd= pa->rectdaps;
01074     unsigned short *solidmask, *sp;
01075     int x;
01076 
01077     if(rd==NULL) return NULL;
01078 
01079     sp=solidmask= MEM_mallocN(sizeof(short)*pa->rectx*pa->recty, "solidmask");
01080 
01081     for(x=pa->rectx*pa->recty; x>0; x--, rd++, sp++) {
01082         if(*rd) {
01083             PixStr *ps= (PixStr *)*rd;
01084             
01085             *sp= ps->mask;
01086             for(ps= ps->next; ps; ps= ps->next)
01087                 *sp |= ps->mask;
01088         }
01089         else
01090             *sp= 0;
01091     }
01092 
01093     return solidmask;
01094 }
01095 
01096 static void addAlphaOverFloatMask(float *dest, float *source, unsigned short dmask, unsigned short smask)
01097 {
01098     unsigned short shared= dmask & smask;
01099     float mul= 1.0f - source[3];
01100     
01101     if(shared) {    /* overlapping masks */
01102         
01103         /* masks differ, we make a mixture of 'add' and 'over' */
01104         if(shared!=dmask) {
01105             float shared_bits= (float)count_mask(shared);       /* alpha over */
01106             float tot_bits= (float)count_mask(smask|dmask);     /* alpha add */
01107             
01108             float add= (tot_bits - shared_bits)/tot_bits;       /* add level */
01109             mul= add + (1.0f-add)*mul;
01110         }
01111     }
01112     else if(dmask && smask) {
01113         /* works for premul only, of course */
01114         dest[0]+= source[0];
01115         dest[1]+= source[1];
01116         dest[2]+= source[2];
01117         dest[3]+= source[3];
01118         
01119         return;
01120      }
01121 
01122     dest[0]= (mul*dest[0]) + source[0];
01123     dest[1]= (mul*dest[1]) + source[1];
01124     dest[2]= (mul*dest[2]) + source[2];
01125     dest[3]= (mul*dest[3]) + source[3];
01126 }
01127 
01128 typedef struct ZbufSolidData {
01129     RenderLayer *rl;
01130     ListBase *psmlist;
01131     float *edgerect;
01132 } ZbufSolidData;
01133 
01134 static void make_pixelstructs(RenderPart *pa, ZSpan *zspan, int sample, void *data)
01135 {
01136     ZbufSolidData *sdata= (ZbufSolidData*)data;
01137     ListBase *lb= sdata->psmlist;
01138     intptr_t *rd= pa->rectdaps;
01139     int *ro= zspan->recto;
01140     int *rp= zspan->rectp;
01141     int *rz= zspan->rectz;
01142     int *rm= zspan->rectmask;
01143     int x, y;
01144     int mask= 1<<sample;
01145 
01146     for(y=0; y<pa->recty; y++) {
01147         for(x=0; x<pa->rectx; x++, rd++, rp++, ro++, rz++, rm++) {
01148             if(*rp) {
01149                 addps(lb, rd, *ro, *rp, *rz, (zspan->rectmask)? *rm: 0, mask);
01150             }
01151         }
01152     }
01153 
01154     if(sdata->rl->layflag & SCE_LAY_EDGE) 
01155         if(R.r.mode & R_EDGE) 
01156             edge_enhance_tile(pa, sdata->edgerect, zspan->rectz);
01157 }
01158 
01159 /* main call for shading Delta Accum, for OSA */
01160 /* supposed to be fully threadable! */
01161 void zbufshadeDA_tile(RenderPart *pa)
01162 {
01163     RenderResult *rr= pa->result;
01164     RenderLayer *rl;
01165     ListBase psmlist= {NULL, NULL};
01166     float *edgerect= NULL;
01167     
01168     /* allocate the necessary buffers */
01169                 /* zbuffer inits these rects */
01170     pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto");
01171     pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
01172     pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
01173     for(rl= rr->layers.first; rl; rl= rl->next) {
01174         if((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK))
01175             pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask");
01176     
01177         /* initialize pixelstructs and edge buffer */
01178         addpsmain(&psmlist);
01179         pa->rectdaps= MEM_callocN(sizeof(intptr_t)*pa->rectx*pa->recty+4, "zbufDArectd");
01180         
01181         if(rl->layflag & SCE_LAY_EDGE) 
01182             if(R.r.mode & R_EDGE) 
01183                 edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge");
01184         
01185         /* always fill visibility */
01186         for(pa->sample=0; pa->sample<R.osa; pa->sample+=4) {
01187             ZbufSolidData sdata;
01188 
01189             sdata.rl= rl;
01190             sdata.psmlist= &psmlist;
01191             sdata.edgerect= edgerect;
01192             zbuffer_solid(pa, rl, make_pixelstructs, &sdata);
01193             if(R.test_break(R.tbh)) break; 
01194         }
01195         
01196         /* shades solid */
01197         if(rl->layflag & SCE_LAY_SOLID) 
01198             shadeDA_tile(pa, rl);
01199         
01200         /* lamphalo after solid, before ztra, looks nicest because ztra does own halo */
01201         if(R.flag & R_LAMPHALO)
01202             if(rl->layflag & SCE_LAY_HALO)
01203                 lamphalo_tile(pa, rl);
01204         
01205         /* halo before ztra, because ztra fills in zbuffer now */
01206         if(R.flag & R_HALO)
01207             if(rl->layflag & SCE_LAY_HALO)
01208                 halo_tile(pa, rl);
01209 
01210         /* transp layer */
01211         if(R.flag & R_ZTRA || R.totstrand) {
01212             if(rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) {
01213                 if(pa->fullresult.first) {
01214                     zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist);
01215                 }
01216                 else {
01217                     unsigned short *ztramask, *solidmask= NULL; /* 16 bits, MAX_OSA */
01218                     
01219                     /* allocate, but not free here, for asynchronous display of this rect in main thread */
01220                     rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer");
01221                     
01222                     /* swap for live updates, and it is used in zbuf.c!!! */
01223                     SWAP(float *, rl->acolrect, rl->rectf);
01224                     ztramask= zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist);
01225                     SWAP(float *, rl->acolrect, rl->rectf);
01226                     
01227                     /* zbuffer transp only returns ztramask if there's solid rendered */
01228                     if(ztramask)
01229                         solidmask= make_solid_mask(pa);
01230 
01231                     if(ztramask && solidmask) {
01232                         unsigned short *sps= solidmask, *spz= ztramask;
01233                         unsigned short fullmask= (1<<R.osa)-1;
01234                         float *fcol= rl->rectf; float *acol= rl->acolrect;
01235                         int x;
01236                         
01237                         for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4, sps++, spz++) {
01238                             if(*sps == fullmask)
01239                                 addAlphaOverFloat(fcol, acol);
01240                             else
01241                                 addAlphaOverFloatMask(fcol, acol, *sps, *spz);
01242                         }
01243                     }
01244                     else {
01245                         float *fcol= rl->rectf; float *acol= rl->acolrect;
01246                         int x;
01247                         for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) {
01248                             addAlphaOverFloat(fcol, acol);
01249                         }
01250                     }
01251                     if(solidmask) MEM_freeN(solidmask);
01252                     if(ztramask) MEM_freeN(ztramask);
01253                 }
01254             }
01255         }
01256 
01257         /* sun/sky */
01258         if(rl->layflag & SCE_LAY_SKY)
01259             atm_tile(pa, rl);
01260         
01261         /* sky before edge */
01262         if(rl->layflag & SCE_LAY_SKY)
01263             sky_tile(pa, rl);
01264 
01265         /* extra layers */
01266         if(rl->layflag & SCE_LAY_EDGE) 
01267             if(R.r.mode & R_EDGE) 
01268                 edge_enhance_add(pa, rl->rectf, edgerect);
01269         
01270         if(rl->passflag & SCE_PASS_VECTOR)
01271             reset_sky_speed(pa, rl);
01272         
01273         /* de-premul alpha */
01274         if(R.r.alphamode & R_ALPHAKEY)
01275             convert_to_key_alpha(pa, rl);
01276         
01277         /* free stuff within loop! */
01278         MEM_freeN(pa->rectdaps); pa->rectdaps= NULL;
01279         freeps(&psmlist);
01280         
01281         if(edgerect) MEM_freeN(edgerect);
01282         edgerect= NULL;
01283 
01284         if(pa->rectmask) {
01285             MEM_freeN(pa->rectmask);
01286             pa->rectmask= NULL;
01287         }
01288     }
01289     
01290     /* free all */
01291     MEM_freeN(pa->recto); pa->recto= NULL;
01292     MEM_freeN(pa->rectp); pa->rectp= NULL;
01293     MEM_freeN(pa->rectz); pa->rectz= NULL;
01294     
01295     /* display active layer */
01296     rr->renrect.ymin=rr->renrect.ymax= 0;
01297     rr->renlay= render_get_active_layer(&R, rr);
01298 }
01299 
01300 
01301 /* ------------------------------------------------------------------------ */
01302 
01303 /* non OSA case, full tile render */
01304 /* supposed to be fully threadable! */
01305 void zbufshade_tile(RenderPart *pa)
01306 {
01307     ShadeSample ssamp;
01308     RenderResult *rr= pa->result;
01309     RenderLayer *rl;
01310     PixStr ps;
01311     float *edgerect= NULL;
01312     
01313     /* fake pixel struct, to comply to osa render */
01314     ps.next= NULL;
01315     ps.mask= 0xFFFF;
01316     
01317     /* zbuffer code clears/inits rects */
01318     pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto");
01319     pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
01320     pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
01321 
01322     for(rl= rr->layers.first; rl; rl= rl->next) {
01323         if((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK))
01324             pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask");
01325 
01326         /* general shader info, passes */
01327         shade_sample_initialize(&ssamp, pa, rl);
01328         
01329         zbuffer_solid(pa, rl, NULL, NULL);
01330         
01331         if(!R.test_break(R.tbh)) {  /* NOTE: this if() is not consistent */
01332             
01333             /* edges only for solid part, ztransp doesn't support it yet anti-aliased */
01334             if(rl->layflag & SCE_LAY_EDGE) {
01335                 if(R.r.mode & R_EDGE) {
01336                     edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge");
01337                     edge_enhance_tile(pa, edgerect, pa->rectz);
01338                 }
01339             }
01340             
01341             /* initialize scanline updates for main thread */
01342             rr->renrect.ymin= 0;
01343             rr->renlay= rl;
01344             
01345             if(rl->layflag & SCE_LAY_SOLID) {
01346                 float *fcol= rl->rectf;
01347                 int *ro= pa->recto, *rp= pa->rectp, *rz= pa->rectz;
01348                 int x, y, offs=0, seed;
01349                 
01350                 /* we set per pixel a fixed seed, for random AO and shadow samples */
01351                 seed= pa->rectx*pa->disprect.ymin;
01352                 
01353                 /* irregular shadowb buffer creation */
01354                 if(R.r.mode & R_SHADOW)
01355                     ISB_create(pa, NULL);
01356 
01357                 if(R.occlusiontree)
01358                     cache_occ_samples(&R, pa, &ssamp);
01359                 
01360                 for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++, rr->renrect.ymax++) {
01361                     for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, ro++, rz++, rp++, fcol+=4, offs++) {
01362                         /* per pixel fixed seed */
01363                         BLI_thread_srandom(pa->thread, seed++);
01364                         
01365                         if(*rp) {
01366                             ps.obi= *ro;
01367                             ps.facenr= *rp;
01368                             ps.z= *rz;
01369                             if(shade_samples(&ssamp, &ps, x, y)) {
01370                                 /* combined and passes */
01371                                 add_passes(rl, offs, ssamp.shi, ssamp.shr);
01372                             }
01373                         }
01374                     }
01375                     if(y&1)
01376                         if(R.test_break(R.tbh)) break; 
01377                 }
01378                 
01379                 if(R.occlusiontree)
01380                     free_occ_samples(&R, pa);
01381                 
01382                 if(R.r.mode & R_SHADOW)
01383                     ISB_free(pa);
01384             }
01385             
01386             /* disable scanline updating */
01387             rr->renlay= NULL;
01388         }
01389         
01390         /* lamphalo after solid, before ztra, looks nicest because ztra does own halo */
01391         if(R.flag & R_LAMPHALO)
01392             if(rl->layflag & SCE_LAY_HALO)
01393                 lamphalo_tile(pa, rl);
01394         
01395         /* halo before ztra, because ztra fills in zbuffer now */
01396         if(R.flag & R_HALO)
01397             if(rl->layflag & SCE_LAY_HALO)
01398                 halo_tile(pa, rl);
01399         
01400         if(R.flag & R_ZTRA || R.totstrand) {
01401             if(rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) {
01402                 float *fcol, *acol;
01403                 int x;
01404                 
01405                 /* allocate, but not free here, for asynchronous display of this rect in main thread */
01406                 rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer");
01407                 
01408                 /* swap for live updates */
01409                 SWAP(float *, rl->acolrect, rl->rectf);
01410                 zbuffer_transp_shade(pa, rl, rl->rectf, NULL);
01411                 SWAP(float *, rl->acolrect, rl->rectf);
01412                 
01413                 fcol= rl->rectf; acol= rl->acolrect;
01414                 for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) {
01415                     addAlphaOverFloat(fcol, acol);
01416                 }
01417             }
01418         }
01419         
01420         /* sun/sky */
01421         if(rl->layflag & SCE_LAY_SKY)
01422             atm_tile(pa, rl);
01423         
01424         /* sky before edge */
01425         if(rl->layflag & SCE_LAY_SKY)
01426             sky_tile(pa, rl);
01427         
01428         if(!R.test_break(R.tbh)) {
01429             if(rl->layflag & SCE_LAY_EDGE) 
01430                 if(R.r.mode & R_EDGE)
01431                     edge_enhance_add(pa, rl->rectf, edgerect);
01432         }
01433         
01434         if(rl->passflag & SCE_PASS_VECTOR)
01435             reset_sky_speed(pa, rl);
01436         
01437         /* de-premul alpha */
01438         if(R.r.alphamode & R_ALPHAKEY)
01439             convert_to_key_alpha(pa, rl);
01440         
01441         if(edgerect) MEM_freeN(edgerect);
01442         edgerect= NULL;
01443 
01444         if(pa->rectmask) {
01445             MEM_freeN(pa->rectmask);
01446             pa->rectmask= NULL;
01447         }
01448     }
01449 
01450     /* display active layer */
01451     rr->renrect.ymin=rr->renrect.ymax= 0;
01452     rr->renlay= render_get_active_layer(&R, rr);
01453     
01454     MEM_freeN(pa->recto); pa->recto= NULL;
01455     MEM_freeN(pa->rectp); pa->rectp= NULL;
01456     MEM_freeN(pa->rectz); pa->rectz= NULL;
01457 }
01458 
01459 /* SSS preprocess tile render, fully threadable */
01460 typedef struct ZBufSSSHandle {
01461     RenderPart *pa;
01462     ListBase psmlist;
01463     int totps;
01464 } ZBufSSSHandle;
01465 
01466 static void addps_sss(void *cb_handle, int obi, int facenr, int x, int y, int z)
01467 {
01468     ZBufSSSHandle *handle = cb_handle;
01469     RenderPart *pa= handle->pa;
01470 
01471     /* extra border for filter gives double samples on part edges,
01472        don't use those */
01473     if(x<pa->crop || x>=pa->rectx-pa->crop)
01474         return;
01475     if(y<pa->crop || y>=pa->recty-pa->crop)
01476         return;
01477     
01478     if(pa->rectall) {
01479         intptr_t *rs= pa->rectall + pa->rectx*y + x;
01480 
01481         addps(&handle->psmlist, rs, obi, facenr, z, 0, 0);
01482         handle->totps++;
01483     }
01484     if(pa->rectz) {
01485         int *rz= pa->rectz + pa->rectx*y + x;
01486         int *rp= pa->rectp + pa->rectx*y + x;
01487         int *ro= pa->recto + pa->rectx*y + x;
01488 
01489         if(z < *rz) {
01490             if(*rp == 0)
01491                 handle->totps++;
01492             *rz= z;
01493             *rp= facenr;
01494             *ro= obi;
01495         }
01496     }
01497     if(pa->rectbackz) {
01498         int *rz= pa->rectbackz + pa->rectx*y + x;
01499         int *rp= pa->rectbackp + pa->rectx*y + x;
01500         int *ro= pa->rectbacko + pa->rectx*y + x;
01501 
01502         if(z >= *rz) {
01503             if(*rp == 0)
01504                 handle->totps++;
01505             *rz= z;
01506             *rp= facenr;
01507             *ro= obi;
01508         }
01509     }
01510 }
01511 
01512 static void shade_sample_sss(ShadeSample *ssamp, Material *mat, ObjectInstanceRen *obi, VlakRen *vlr, int quad, float x, float y, float z, float *co, float *color, float *area)
01513 {
01514     ShadeInput *shi= ssamp->shi;
01515     ShadeResult shr;
01516     float /* texfac,*/ /* UNUSED */ orthoarea, nor[3], alpha, sx, sy;
01517 
01518     /* cache for shadow */
01519     shi->samplenr= R.shadowsamplenr[shi->thread]++;
01520     
01521     if(quad) 
01522         shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3);
01523     else
01524         shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
01525 
01526     /* center pixel */
01527     sx = x + 0.5f;
01528     sy = y + 0.5f;
01529 
01530     /* we estimate the area here using shi->dxco and shi->dyco. we need to
01531        enabled shi->osatex these are filled. we compute two areas, one with
01532        the normal pointed at the camera and one with the original normal, and
01533        then clamp to avoid a too large contribution from a single pixel */
01534     shi->osatex= 1;
01535 
01536     copy_v3_v3(nor, shi->facenor);
01537     calc_view_vector(shi->facenor, sx, sy);
01538     normalize_v3(shi->facenor);
01539     shade_input_set_viewco(shi, x, y, sx, sy, z);
01540     orthoarea= len_v3(shi->dxco)*len_v3(shi->dyco);
01541 
01542     copy_v3_v3(shi->facenor, nor);
01543     shade_input_set_viewco(shi, x, y, sx, sy, z);
01544     *area= len_v3(shi->dxco)*len_v3(shi->dyco);
01545     *area= MIN2(*area, 2.0f*orthoarea);
01546 
01547     shade_input_set_uv(shi);
01548     shade_input_set_normals(shi);
01549 
01550     /* we don't want flipped normals, they screw up back scattering */
01551     if(shi->flippednor)
01552         shade_input_flip_normals(shi);
01553 
01554     /* not a pretty solution, but fixes common cases */
01555     if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) {
01556         negate_v3(shi->vn);
01557         negate_v3(shi->vno);
01558         negate_v3(shi->nmapnorm);
01559     }
01560 
01561     /* if nodetree, use the material that we are currently preprocessing
01562        instead of the node material */
01563     if(shi->mat->nodetree && shi->mat->use_nodes)
01564         shi->mat= mat;
01565 
01566     /* init material vars */
01567     shade_input_init_material(shi);
01568     
01569     /* render */
01570     shade_input_set_shade_texco(shi);
01571     
01572     shade_samples_do_AO(ssamp);
01573     shade_material_loop(shi, &shr);
01574     
01575     copy_v3_v3(co, shi->co);
01576     copy_v3_v3(color, shr.combined);
01577 
01578     /* texture blending */
01579     /* texfac= shi->mat->sss_texfac; */ /* UNUSED */
01580 
01581     alpha= shr.combined[3];
01582     *area *= alpha;
01583 }
01584 
01585 static void zbufshade_sss_free(RenderPart *pa)
01586 {
01587 #if 0
01588     MEM_freeN(pa->rectall); pa->rectall= NULL;
01589     freeps(&handle.psmlist);
01590 #else
01591     MEM_freeN(pa->rectz); pa->rectz= NULL;
01592     MEM_freeN(pa->rectp); pa->rectp= NULL;
01593     MEM_freeN(pa->recto); pa->recto= NULL;
01594     MEM_freeN(pa->rectbackz); pa->rectbackz= NULL;
01595     MEM_freeN(pa->rectbackp); pa->rectbackp= NULL;
01596     MEM_freeN(pa->rectbacko); pa->rectbacko= NULL;
01597 #endif
01598 }
01599 
01600 void zbufshade_sss_tile(RenderPart *pa)
01601 {
01602     Render *re= &R;
01603     ShadeSample ssamp;
01604     ZBufSSSHandle handle;
01605     RenderResult *rr= pa->result;
01606     RenderLayer *rl;
01607     VlakRen *vlr;
01608     Material *mat= re->sss_mat;
01609     float (*co)[3], (*color)[3], *area, *fcol;
01610     int x, y, seed, quad, totpoint, display = !(re->r.scemode & R_PREVIEWBUTS);
01611     int *ro, *rz, *rp, *rbo, *rbz, *rbp, lay;
01612 #if 0
01613     PixStr *ps;
01614     intptr_t *rs;
01615     int z;
01616 #endif
01617 
01618     /* setup pixelstr list and buffer for zbuffering */
01619     handle.pa= pa;
01620     handle.totps= 0;
01621 
01622 #if 0
01623     handle.psmlist.first= handle.psmlist.last= NULL;
01624     addpsmain(&handle.psmlist);
01625 
01626     pa->rectall= MEM_callocN(sizeof(intptr_t)*pa->rectx*pa->recty+4, "rectall");
01627 #else
01628     pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto");
01629     pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
01630     pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
01631     pa->rectbacko= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbacko");
01632     pa->rectbackp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackp");
01633     pa->rectbackz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackz");
01634 #endif
01635 
01636     /* setup shade sample with correct passes */
01637     memset(&ssamp, 0, sizeof(ssamp));
01638     shade_sample_initialize(&ssamp, pa, rr->layers.first);
01639     ssamp.tot= 1;
01640     
01641     for(rl=rr->layers.first; rl; rl=rl->next) {
01642         ssamp.shi[0].lay |= rl->lay;
01643         ssamp.shi[0].layflag |= rl->layflag;
01644         ssamp.shi[0].passflag |= rl->passflag;
01645         ssamp.shi[0].combinedflag |= ~rl->pass_xor;
01646     }
01647 
01648     rl= rr->layers.first;
01649     ssamp.shi[0].passflag |= SCE_PASS_RGBA|SCE_PASS_COMBINED;
01650     ssamp.shi[0].combinedflag &= ~(SCE_PASS_SPEC);
01651     ssamp.shi[0].mat_override= NULL;
01652     ssamp.shi[0].light_override= NULL;
01653     lay= ssamp.shi[0].lay;
01654 
01655     /* create the pixelstrs to be used later */
01656     zbuffer_sss(pa, lay, &handle, addps_sss);
01657 
01658     if(handle.totps==0) {
01659         zbufshade_sss_free(pa);
01660         return;
01661     }
01662     
01663     fcol= rl->rectf;
01664 
01665     co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo");
01666     color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor");
01667     area= MEM_mallocN(sizeof(float)*handle.totps, "SSSArea");
01668 
01669 #if 0
01670     /* create ISB (does not work currently!) */
01671     if(re->r.mode & R_SHADOW)
01672         ISB_create(pa, NULL);
01673 #endif
01674 
01675     if(display) {
01676         /* initialize scanline updates for main thread */
01677         rr->renrect.ymin= 0;
01678         rr->renlay= rl;
01679     }
01680     
01681     seed= pa->rectx*pa->disprect.ymin;
01682 #if 0
01683     rs= pa->rectall;
01684 #else
01685     rz= pa->rectz;
01686     rp= pa->rectp;
01687     ro= pa->recto;
01688     rbz= pa->rectbackz;
01689     rbp= pa->rectbackp;
01690     rbo= pa->rectbacko;
01691 #endif
01692     totpoint= 0;
01693 
01694     for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++, rr->renrect.ymax++) {
01695         for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, fcol+=4) {
01696             /* per pixel fixed seed */
01697             BLI_thread_srandom(pa->thread, seed++);
01698             
01699 #if 0
01700             if(rs) {
01701                 /* for each sample in this pixel, shade it */
01702                 for(ps=(PixStr*)*rs; ps; ps=ps->next) {
01703                     ObjectInstanceRen *obi= &re->objectinstance[ps->obi];
01704                     ObjectRen *obr= obi->obr;
01705                     vlr= RE_findOrAddVlak(obr, (ps->facenr-1) & RE_QUAD_MASK);
01706                     quad= (ps->facenr & RE_QUAD_OFFS);
01707                     z= ps->z;
01708 
01709                     shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, z,
01710                         co[totpoint], color[totpoint], &area[totpoint]);
01711 
01712                     totpoint++;
01713 
01714                     add_v3_v3(fcol, color);
01715                     fcol[3]= 1.0f;
01716                 }
01717 
01718                 rs++;
01719             }
01720 #else
01721             if(rp) {
01722                 if(*rp != 0) {
01723                     ObjectInstanceRen *obi= &re->objectinstance[*ro];
01724                     ObjectRen *obr= obi->obr;
01725 
01726                     /* shade front */
01727                     vlr= RE_findOrAddVlak(obr, (*rp-1) & RE_QUAD_MASK);
01728                     quad= ((*rp) & RE_QUAD_OFFS);
01729 
01730                     shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, *rz,
01731                         co[totpoint], color[totpoint], &area[totpoint]);
01732                     
01733                     add_v3_v3(fcol, color[totpoint]);
01734                     fcol[3]= 1.0f;
01735                     totpoint++;
01736                 }
01737 
01738                 rp++; rz++; ro++;
01739             }
01740 
01741             if(rbp) {
01742                 if(*rbp != 0 && !(*rbp == *(rp-1) && *rbo == *(ro-1))) {
01743                     ObjectInstanceRen *obi= &re->objectinstance[*rbo];
01744                     ObjectRen *obr= obi->obr;
01745 
01746                     /* shade back */
01747                     vlr= RE_findOrAddVlak(obr, (*rbp-1) & RE_QUAD_MASK);
01748                     quad= ((*rbp) & RE_QUAD_OFFS);
01749 
01750                     shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, *rbz,
01751                         co[totpoint], color[totpoint], &area[totpoint]);
01752                     
01753                     /* to indicate this is a back sample */
01754                     area[totpoint]= -area[totpoint];
01755 
01756                     add_v3_v3(fcol, color[totpoint]);
01757                     fcol[3]= 1.0f;
01758                     totpoint++;
01759                 }
01760 
01761                 rbz++; rbp++; rbo++;
01762             }
01763 #endif
01764         }
01765 
01766         if(y&1)
01767             if(re->test_break(re->tbh)) break; 
01768     }
01769 
01770     /* note: after adding we do not free these arrays, sss keeps them */
01771     if(totpoint > 0) {
01772         sss_add_points(re, co, color, area, totpoint);
01773     }
01774     else {
01775         MEM_freeN(co);
01776         MEM_freeN(color);
01777         MEM_freeN(area);
01778     }
01779     
01780 #if 0
01781     if(re->r.mode & R_SHADOW)
01782         ISB_free(pa);
01783 #endif
01784         
01785     if(display) {
01786         /* display active layer */
01787         rr->renrect.ymin=rr->renrect.ymax= 0;
01788         rr->renlay= render_get_active_layer(&R, rr);
01789     }
01790     
01791     zbufshade_sss_free(pa);
01792 }
01793 
01794 /* ------------------------------------------------------------------------ */
01795 
01796 static void renderhalo_post(RenderResult *rr, float *rectf, HaloRen *har)   /* postprocess version */
01797 {
01798     float dist, xsq, ysq, xn, yn, colf[4], *rectft, *rtf;
01799     float haloxs, haloys;
01800     int minx, maxx, miny, maxy, x, y;
01801 
01802     /* calculate the disprect mapped coordinate for halo. note: rectx is disprect corrected */
01803     haloxs= har->xs - R.disprect.xmin;
01804     haloys= har->ys - R.disprect.ymin;
01805     
01806     har->miny= miny= haloys - har->rad/R.ycor;
01807     har->maxy= maxy= haloys + har->rad/R.ycor;
01808     
01809     if(maxy<0);
01810     else if(rr->recty<miny);
01811     else {
01812         minx= floor(haloxs-har->rad);
01813         maxx= ceil(haloxs+har->rad);
01814             
01815         if(maxx<0);
01816         else if(rr->rectx<minx);
01817         else {
01818         
01819             if(minx<0) minx= 0;
01820             if(maxx>=rr->rectx) maxx= rr->rectx-1;
01821             if(miny<0) miny= 0;
01822             if(maxy>rr->recty) maxy= rr->recty;
01823     
01824             rectft= rectf+ 4*rr->rectx*miny;
01825 
01826             for(y=miny; y<maxy; y++) {
01827     
01828                 rtf= rectft+4*minx;
01829                 
01830                 yn= (y - haloys)*R.ycor;
01831                 ysq= yn*yn;
01832                 
01833                 for(x=minx; x<=maxx; x++) {
01834                     xn= x - haloxs;
01835                     xsq= xn*xn;
01836                     dist= xsq+ysq;
01837                     if(dist<har->radsq) {
01838                         
01839                         if(shadeHaloFloat(har, colf, 0x7FFFFF, dist, xn, yn, har->flarec))
01840                             addalphaAddfacFloat(rtf, colf, har->add);
01841                     }
01842                     rtf+=4;
01843                 }
01844     
01845                 rectft+= 4*rr->rectx;
01846                 
01847                 if(R.test_break(R.tbh)) break; 
01848             }
01849         }
01850     }
01851 } 
01852 /* ------------------------------------------------------------------------ */
01853 
01854 static void renderflare(RenderResult *rr, float *rectf, HaloRen *har)
01855 {
01856     extern float hashvectf[];
01857     HaloRen fla;
01858     Material *ma;
01859     float *rc, rad, alfa, visifac, vec[3];
01860     int b, type;
01861     
01862     fla= *har;
01863     fla.linec= fla.ringc= fla.flarec= 0;
01864     
01865     rad= har->rad;
01866     alfa= har->alfa;
01867     
01868     visifac= R.ycor*(har->pixels);
01869     /* all radials added / r^3  == 1.0f! */
01870     visifac /= (har->rad*har->rad*har->rad);
01871     visifac*= visifac;
01872 
01873     ma= har->mat;
01874     
01875     /* first halo: just do */
01876     
01877     har->rad= rad*ma->flaresize*visifac;
01878     har->radsq= har->rad*har->rad;
01879     har->zs= fla.zs= 0;
01880     
01881     har->alfa= alfa*visifac;
01882 
01883     renderhalo_post(rr, rectf, har);
01884     
01885     /* next halo's: the flares */
01886     rc= hashvectf + ma->seed2;
01887     
01888     for(b=1; b<har->flarec; b++) {
01889         
01890         fla.r= fabs(rc[0]);
01891         fla.g= fabs(rc[1]);
01892         fla.b= fabs(rc[2]);
01893         fla.alfa= ma->flareboost*fabsf(alfa*visifac*rc[3]);
01894         fla.hard= 20.0f + fabsf(70.0f*rc[7]);
01895         fla.tex= 0;
01896         
01897         type= (int)(fabs(3.9f*rc[6]));
01898 
01899         fla.rad= ma->subsize*sqrtf(fabs(2.0f*har->rad*rc[4]));
01900         
01901         if(type==3) {
01902             fla.rad*= 3.0f;
01903             fla.rad+= R.rectx/10;
01904         }
01905         
01906         fla.radsq= fla.rad*fla.rad;
01907         
01908         vec[0]= 1.4f*rc[5]*(har->xs-R.winx/2);
01909         vec[1]= 1.4f*rc[5]*(har->ys-R.winy/2);
01910         vec[2]= 32.0f*sqrtf(vec[0]*vec[0] + vec[1]*vec[1] + 1.0f);
01911         
01912         fla.xs= R.winx/2 + vec[0] + (1.2f+rc[8])*R.rectx*vec[0]/vec[2];
01913         fla.ys= R.winy/2 + vec[1] + (1.2f+rc[8])*R.rectx*vec[1]/vec[2];
01914 
01915         if(R.flag & R_SEC_FIELD) {
01916             if(R.r.mode & R_ODDFIELD) fla.ys += 0.5f;
01917             else fla.ys -= 0.5f;
01918         }
01919         if(type & 1) fla.type= HA_FLARECIRC;
01920         else fla.type= 0;
01921         renderhalo_post(rr, rectf, &fla);
01922 
01923         fla.alfa*= 0.5f;
01924         if(type & 2) fla.type= HA_FLARECIRC;
01925         else fla.type= 0;
01926         renderhalo_post(rr, rectf, &fla);
01927         
01928         rc+= 7;
01929     }
01930 }
01931 
01932 /* needs recode... integrate this better! */
01933 void add_halo_flare(Render *re)
01934 {
01935     RenderResult *rr= re->result;
01936     RenderLayer *rl;
01937     HaloRen *har;
01938     int a, mode, do_draw=0;
01939     
01940     /* for now, we get the first renderlayer in list with halos set */
01941     for(rl= rr->layers.first; rl; rl= rl->next)
01942         if(rl->layflag & SCE_LAY_HALO)
01943             break;
01944 
01945     if(rl==NULL || rl->rectf==NULL)
01946         return;
01947     
01948     mode= R.r.mode;
01949     R.r.mode &= ~R_PANORAMA;
01950     
01951     project_renderdata(&R, projectverto, 0, 0, 0);
01952     
01953     for(a=0; a<R.tothalo; a++) {
01954         har= R.sortedhalos[a];
01955         
01956         if(har->flarec) {
01957             do_draw= 1;
01958             renderflare(rr, rl->rectf, har);
01959         }
01960     }
01961 
01962     if(do_draw) {
01963         /* weak... the display callback wants an active renderlayer pointer... */
01964         rr->renlay= rl;
01965         re->display_draw(re->ddh, rr, NULL);
01966     }
01967     
01968     R.r.mode= mode; 
01969 }
01970 
01971 /* ************************* bake ************************ */
01972 
01973 
01974 typedef struct BakeShade {
01975     ShadeSample ssamp;
01976     ObjectInstanceRen *obi;
01977     VlakRen *vlr;
01978     
01979     ZSpan *zspan;
01980     Image *ima;
01981     ImBuf *ibuf;
01982     
01983     int rectx, recty, quad, type, vdone, ready;
01984 
01985     float dir[3];
01986     Object *actob;
01987     
01988     unsigned int *rect;
01989     float *rect_float;
01990     
01991     int usemask;
01992     char *rect_mask; /* bake pixel mask */
01993 
01994     float dxco[3], dyco[3];
01995 
01996     short *do_update;
01997 } BakeShade;
01998 
01999 static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int UNUSED(isect), int x, int y, float u, float v)
02000 {
02001     if(quad) 
02002         shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3);
02003     else
02004         shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
02005         
02006     /* cache for shadow */
02007     shi->samplenr= R.shadowsamplenr[shi->thread]++;
02008 
02009     shi->mask= 0xFFFF; /* all samples */
02010     
02011     shi->u= -u;
02012     shi->v= -v;
02013     shi->xs= x;
02014     shi->ys= y;
02015     
02016     shade_input_set_uv(shi);
02017     shade_input_set_normals(shi);
02018 
02019     /* no normal flip */
02020     if(shi->flippednor)
02021         shade_input_flip_normals(shi);
02022 
02023     /* set up view vector to look right at the surface (note that the normal
02024      * is negated in the renderer so it does not need to be done here) */
02025     shi->view[0]= shi->vn[0];
02026     shi->view[1]= shi->vn[1];
02027     shi->view[2]= shi->vn[2];
02028 }
02029 
02030 static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(quad), int x, int y, float UNUSED(u), float UNUSED(v), float *tvn, float *ttang)
02031 {
02032     BakeShade *bs= handle;
02033     ShadeSample *ssamp= &bs->ssamp;
02034     ShadeResult shr;
02035     VlakRen *vlr= shi->vlr;
02036     
02037     shade_input_init_material(shi);
02038     
02039     if(bs->type==RE_BAKE_AO) {
02040         ambient_occlusion(shi);
02041 
02042         if(R.r.bake_flag & R_BAKE_NORMALIZE) {
02043             copy_v3_v3(shr.combined, shi->ao);
02044         }
02045         else {
02046             zero_v3(shr.combined);
02047             environment_lighting_apply(shi, &shr);
02048         }
02049     }
02050     else {
02051         if (bs->type==RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */
02052             shi->r = shi->g = shi->b = 1.0f;
02053     
02054         shade_input_set_shade_texco(shi);
02055         
02056         /* only do AO for a full bake (and obviously AO bakes)
02057             AO for light bakes is a leftover and might not be needed */
02058         if( ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT))
02059             shade_samples_do_AO(ssamp);
02060         
02061         if(shi->mat->nodetree && shi->mat->use_nodes) {
02062             ntreeShaderExecTree(shi->mat->nodetree, shi, &shr);
02063             shi->mat= vlr->mat;     /* shi->mat is being set in nodetree */
02064         }
02065         else
02066             shade_material_loop(shi, &shr);
02067         
02068         if(bs->type==RE_BAKE_NORMALS) {
02069             float nor[3];
02070 
02071             copy_v3_v3(nor, shi->vn);
02072 
02073             if(R.r.bake_normal_space == R_BAKE_SPACE_CAMERA);
02074             else if(R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) {
02075                 float mat[3][3], imat[3][3];
02076 
02077                 /* bitangent */
02078                 if(tvn && ttang) {
02079                     copy_v3_v3(mat[0], ttang);
02080                     cross_v3_v3v3(mat[1], tvn, ttang);
02081                     mul_v3_fl(mat[1], ttang[3]);
02082                     copy_v3_v3(mat[2], tvn);
02083                 }
02084                 else {
02085                     copy_v3_v3(mat[0], shi->nmaptang);
02086                     cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang);
02087                     mul_v3_fl(mat[1], shi->nmaptang[3]);
02088                     copy_v3_v3(mat[2], shi->nmapnorm);
02089                 }
02090 
02091                 invert_m3_m3(imat, mat);
02092                 mul_m3_v3(imat, nor);
02093             }
02094             else if(R.r.bake_normal_space == R_BAKE_SPACE_OBJECT)
02095                 mul_mat3_m4_v3(ob->imat_ren, nor); /* ob->imat_ren includes viewinv! */
02096             else if(R.r.bake_normal_space == R_BAKE_SPACE_WORLD)
02097                 mul_mat3_m4_v3(R.viewinv, nor);
02098 
02099             normalize_v3(nor); /* in case object has scaling */
02100 
02101             // The invert of the red channel is to make
02102             // the normal map compliant with the outside world.
02103             // It needs to be done because in Blender
02104             // the normal used in the renderer points inward. It is generated
02105             // this way in calc_vertexnormals(). Should this ever change
02106             // this negate must be removed.
02107             shr.combined[0]= (-nor[0])/2.0f + 0.5f;
02108             shr.combined[1]= nor[1]/2.0f + 0.5f;
02109             shr.combined[2]= nor[2]/2.0f + 0.5f;
02110         }
02111         else if(bs->type==RE_BAKE_TEXTURE) {
02112             shr.combined[0]= shi->r;
02113             shr.combined[1]= shi->g;
02114             shr.combined[2]= shi->b;
02115             shr.alpha = shi->alpha;
02116         }
02117         else if(bs->type==RE_BAKE_SHADOW) {
02118             copy_v3_v3(shr.combined, shr.shad);
02119             shr.alpha = shi->alpha;
02120         }
02121         else if(bs->type==RE_BAKE_SPEC_COLOR) {
02122             shr.combined[0]= shi->specr;
02123             shr.combined[1]= shi->specg;
02124             shr.combined[2]= shi->specb;
02125             shr.alpha = 1.0f;
02126         }
02127         else if(bs->type==RE_BAKE_SPEC_INTENSITY) {
02128             shr.combined[0]=
02129             shr.combined[1]=
02130             shr.combined[2]= shi->spec;
02131             shr.alpha = 1.0f;
02132         }
02133         else if(bs->type==RE_BAKE_MIRROR_COLOR) {
02134             shr.combined[0]= shi->mirr;
02135             shr.combined[1]= shi->mirg;
02136             shr.combined[2]= shi->mirb;
02137             shr.alpha = 1.0f;
02138         }
02139         else if(bs->type==RE_BAKE_MIRROR_INTENSITY) {
02140             shr.combined[0]=
02141             shr.combined[1]=
02142             shr.combined[2]= shi->ray_mirror;
02143             shr.alpha = 1.0f;
02144         }
02145         else if(bs->type==RE_BAKE_ALPHA) {
02146             shr.combined[0]=
02147             shr.combined[1]=
02148             shr.combined[2]= shi->alpha;
02149             shr.alpha = 1.0f;
02150         }
02151         else if(bs->type==RE_BAKE_EMIT) {
02152             shr.combined[0]=
02153             shr.combined[1]=
02154             shr.combined[2]= shi->emit;
02155             shr.alpha = 1.0f;
02156         }
02157     }
02158     
02159     if(bs->rect_float) {
02160         float *col= bs->rect_float + 4*(bs->rectx*y + x);
02161         copy_v3_v3(col, shr.combined);
02162         if (bs->type==RE_BAKE_ALL || bs->type==RE_BAKE_TEXTURE) {
02163             col[3]= shr.alpha;
02164         } else {
02165             col[3]= 1.0;
02166         }
02167     }
02168     else {
02169         char *col= (char *)(bs->rect + bs->rectx*y + x);
02170 
02171         if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE) && (R.r.color_mgt_flag & R_COLOR_MANAGEMENT)) {
02172             float srgb[3];
02173             srgb[0]= linearrgb_to_srgb(shr.combined[0]);
02174             srgb[1]= linearrgb_to_srgb(shr.combined[1]);
02175             srgb[2]= linearrgb_to_srgb(shr.combined[2]);
02176             
02177             col[0]= FTOCHAR(srgb[0]);
02178             col[1]= FTOCHAR(srgb[1]);
02179             col[2]= FTOCHAR(srgb[2]);
02180         } else {
02181             col[0]= FTOCHAR(shr.combined[0]);
02182             col[1]= FTOCHAR(shr.combined[1]);
02183             col[2]= FTOCHAR(shr.combined[2]);
02184         }
02185         
02186         if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
02187             col[3]= FTOCHAR(shr.alpha);
02188         } else {
02189             col[3]= 255;
02190         }
02191     }
02192     
02193     if (bs->rect_mask) {
02194         bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED;
02195     }
02196 }
02197 
02198 static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist, int x, int y)
02199 {
02200     BakeShade *bs= handle;
02201     float disp;
02202     
02203     if(R.r.bake_flag & R_BAKE_NORMALIZE && R.r.bake_maxdist) {
02204         disp = (dist+R.r.bake_maxdist) / (R.r.bake_maxdist*2); /* alter the range from [-bake_maxdist, bake_maxdist] to [0, 1]*/
02205     } else {
02206         disp = 0.5f + dist; /* alter the range from [-0.5,0.5] to [0,1]*/
02207     }
02208     
02209     if(bs->rect_float) {
02210         float *col= bs->rect_float + 4*(bs->rectx*y + x);
02211         col[0] = col[1] = col[2] = disp;
02212         col[3]= 1.0f;
02213     } else {    
02214         char *col= (char *)(bs->rect + bs->rectx*y + x);
02215         col[0]= FTOCHAR(disp);
02216         col[1]= FTOCHAR(disp);
02217         col[2]= FTOCHAR(disp);
02218         col[3]= 255;
02219     }
02220     if (bs->rect_mask) {
02221         bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED;
02222     }
02223 }
02224 
02225 static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, float *dir, float sign, float *hitco, float *dist)
02226 {
02227     float maxdist;
02228     int hit;
02229 
02230     /* might be useful to make a user setting for maxsize*/
02231     if(R.r.bake_maxdist > 0.0f)
02232         maxdist= R.r.bake_maxdist;
02233     else
02234         maxdist= RE_RAYTRACE_MAXDIST + R.r.bake_biasdist;
02235 
02236     /* 'dir' is always normalized */
02237     madd_v3_v3v3fl(isect->start, start, dir, -R.r.bake_biasdist);
02238 
02239     mul_v3_v3fl(isect->dir, dir, sign);
02240 
02241     isect->dist = maxdist;
02242 
02243     hit = RE_rayobject_raycast(raytree, isect);
02244     if(hit) {
02245         madd_v3_v3v3fl(hitco, isect->start, isect->dir, isect->dist);
02246 
02247         *dist= isect->dist;
02248     }
02249 
02250     return hit;
02251 }
02252 
02253 static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3)
02254 {
02255     VlakRen *vlr= bs->vlr;
02256     float A, d1, d2, d3, *v1, *v2, *v3;
02257 
02258     if(bs->quad) {
02259         v1= vlr->v1->co;
02260         v2= vlr->v3->co;
02261         v3= vlr->v4->co;
02262     }
02263     else {
02264         v1= vlr->v1->co;
02265         v2= vlr->v2->co;
02266         v3= vlr->v3->co;
02267     }
02268 
02269     /* formula derived from barycentric coordinates:
02270      * (uvArea1*v1 + uvArea2*v2 + uvArea3*v3)/uvArea
02271      * then taking u and v partial derivatives to get dxco and dyco */
02272     A= (uv2[0] - uv1[0])*(uv3[1] - uv1[1]) - (uv3[0] - uv1[0])*(uv2[1] - uv1[1]);
02273 
02274     if(fabsf(A) > FLT_EPSILON) {
02275         A= 0.5f/A;
02276 
02277         d1= uv2[1] - uv3[1];
02278         d2= uv3[1] - uv1[1];
02279         d3= uv1[1] - uv2[1];
02280         bs->dxco[0]= (v1[0]*d1 + v2[0]*d2 + v3[0]*d3)*A;
02281         bs->dxco[1]= (v1[1]*d1 + v2[1]*d2 + v3[1]*d3)*A;
02282         bs->dxco[2]= (v1[2]*d1 + v2[2]*d2 + v3[2]*d3)*A;
02283 
02284         d1= uv3[0] - uv2[0];
02285         d2= uv1[0] - uv3[0];
02286         d3= uv2[0] - uv1[0];
02287         bs->dyco[0]= (v1[0]*d1 + v2[0]*d2 + v3[0]*d3)*A;
02288         bs->dyco[1]= (v1[1]*d1 + v2[1]*d2 + v3[1]*d3)*A;
02289         bs->dyco[2]= (v1[2]*d1 + v2[2]*d2 + v3[2]*d3)*A;
02290     }
02291     else {
02292         bs->dxco[0]= bs->dxco[1]= bs->dxco[2]= 0.0f;
02293         bs->dyco[0]= bs->dyco[1]= bs->dyco[2]= 0.0f;
02294     }
02295 
02296     if(bs->obi->flag & R_TRANSFORMED) {
02297         mul_m3_v3(bs->obi->nmat, bs->dxco);
02298         mul_m3_v3(bs->obi->nmat, bs->dyco);
02299     }
02300 }
02301 
02302 static void do_bake_shade(void *handle, int x, int y, float u, float v)
02303 {
02304     BakeShade *bs= handle;
02305     VlakRen *vlr= bs->vlr;
02306     ObjectInstanceRen *obi= bs->obi;
02307     Object *ob= obi->obr->ob;
02308     float l, *v1, *v2, *v3, tvn[3], ttang[4];
02309     int quad;
02310     ShadeSample *ssamp= &bs->ssamp;
02311     ShadeInput *shi= ssamp->shi;
02312     
02313     /* fast threadsafe break test */
02314     if(R.test_break(R.tbh))
02315         return;
02316     
02317     /* setup render coordinates */
02318     if(bs->quad) {
02319         v1= vlr->v1->co;
02320         v2= vlr->v3->co;
02321         v3= vlr->v4->co;
02322     }
02323     else {
02324         v1= vlr->v1->co;
02325         v2= vlr->v2->co;
02326         v3= vlr->v3->co;
02327     }
02328     
02329     /* renderco */
02330     l= 1.0f-u-v;
02331     
02332     shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0];
02333     shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1];
02334     shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2];
02335     
02336     if(obi->flag & R_TRANSFORMED)
02337         mul_m4_v3(obi->mat, shi->co);
02338     
02339     copy_v3_v3(shi->dxco, bs->dxco);
02340     copy_v3_v3(shi->dyco, bs->dyco);
02341 
02342     quad= bs->quad;
02343     bake_set_shade_input(obi, vlr, shi, quad, 0, x, y, u, v);
02344 
02345     if(bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT) {
02346         shade_input_set_shade_texco(shi);
02347         copy_v3_v3(tvn, shi->nmapnorm);
02348         copy_v4_v4(ttang, shi->nmaptang);
02349     }
02350 
02351     /* if we are doing selected to active baking, find point on other face */
02352     if(bs->actob) {
02353         Isect isec, minisec;
02354         float co[3], minco[3], dist, mindist=0.0f;
02355         int hit, sign, dir=1;
02356         
02357         /* intersect with ray going forward and backward*/
02358         hit= 0;
02359         memset(&minisec, 0, sizeof(minisec));
02360         minco[0]= minco[1]= minco[2]= 0.0f;
02361         
02362         copy_v3_v3(bs->dir, shi->vn);
02363         
02364         for(sign=-1; sign<=1; sign+=2) {
02365             memset(&isec, 0, sizeof(isec));
02366             isec.mode= RE_RAY_MIRROR;
02367 
02368             isec.orig.ob   = obi;
02369             isec.orig.face = vlr;
02370             isec.userdata= bs->actob;
02371             isec.check = RE_CHECK_VLR_BAKE;
02372             isec.skip = RE_SKIP_VLR_NEIGHBOUR;
02373             
02374             if(bake_intersect_tree(R.raytree, &isec, shi->co, shi->vn, sign, co, &dist)) {
02375                 if(!hit || len_squared_v3v3(shi->co, co) < len_squared_v3v3(shi->co, minco)) {
02376                     minisec= isec;
02377                     mindist= dist;
02378                     copy_v3_v3(minco, co);
02379                     hit= 1;
02380                     dir = sign;
02381                 }
02382             }
02383         }
02384 
02385         if (bs->type==RE_BAKE_DISPLACEMENT) {
02386             if(hit)
02387                 bake_displacement(handle, shi, (dir==-1)? mindist:-mindist, x, y);
02388             else
02389                 bake_displacement(handle, shi, 0.0f, x, y);
02390             return;
02391         }
02392 
02393         /* if hit, we shade from the new point, otherwise from point one starting face */
02394         if(hit) {
02395             obi= (ObjectInstanceRen*)minisec.hit.ob;
02396             vlr= (VlakRen*)minisec.hit.face;
02397             quad= (minisec.isect == 2);
02398             copy_v3_v3(shi->co, minco);
02399             
02400             u= -minisec.u;
02401             v= -minisec.v;
02402             bake_set_shade_input(obi, vlr, shi, quad, 1, x, y, u, v);
02403         }
02404     }
02405 
02406     if(bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT)
02407         bake_shade(handle, ob, shi, quad, x, y, u, v, tvn, ttang);
02408     else
02409         bake_shade(handle, ob, shi, quad, x, y, u, v, 0, 0);
02410 }
02411 
02412 static int get_next_bake_face(BakeShade *bs)
02413 {
02414     ObjectRen *obr;
02415     VlakRen *vlr;
02416     MTFace *tface;
02417     static int v= 0, vdone= 0;
02418     static ObjectInstanceRen *obi= NULL;
02419     
02420     if(bs==NULL) {
02421         vlr= NULL;
02422         v= vdone= 0;
02423         obi= R.instancetable.first;
02424         return 0;
02425     }
02426     
02427     BLI_lock_thread(LOCK_CUSTOM1);  
02428 
02429     for(; obi; obi=obi->next, v=0) {
02430         obr= obi->obr;
02431 
02432         for(; v<obr->totvlak; v++) {
02433             vlr= RE_findOrAddVlak(obr, v);
02434 
02435             if((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) {
02436                 tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
02437 
02438                 if(tface && tface->tpage) {
02439                     Image *ima= tface->tpage;
02440                     ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
02441                     const float vec_alpha[4]= {0.0f, 0.0f, 0.0f, 0.0f};
02442                     const float vec_solid[4]= {0.0f, 0.0f, 0.0f, 1.0f};
02443                     
02444                     if(ibuf==NULL)
02445                         continue;
02446                     
02447                     if(ibuf->rect==NULL && ibuf->rect_float==NULL)
02448                         continue;
02449                     
02450                     if(ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4))
02451                         continue;
02452                     
02453                     /* find the image for the first time? */
02454                     if(ima->id.flag & LIB_DOIT) {
02455                         ima->id.flag &= ~LIB_DOIT;
02456                         
02457                         /* we either fill in float or char, this ensures things go fine */
02458                         if(ibuf->rect_float)
02459                             imb_freerectImBuf(ibuf);
02460                         /* clear image */
02461                         if(R.r.bake_flag & R_BAKE_CLEAR)
02462                             IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
02463                     
02464                         /* might be read by UI to set active image for display */
02465                         R.bakebuf= ima;
02466                     }               
02467                     
02468                     bs->obi= obi;
02469                     bs->vlr= vlr;
02470                     
02471                     bs->vdone++;    /* only for error message if nothing was rendered */
02472                     v++;
02473                     
02474                     BLI_unlock_thread(LOCK_CUSTOM1);
02475                     return 1;
02476                 }
02477             }
02478         }
02479     }
02480     
02481     BLI_unlock_thread(LOCK_CUSTOM1);
02482     return 0;
02483 }
02484 
02485 /* already have tested for tface and ima and zspan */
02486 static void shade_tface(BakeShade *bs)
02487 {
02488     VlakRen *vlr= bs->vlr;
02489     ObjectInstanceRen *obi= bs->obi;
02490     ObjectRen *obr= obi->obr;
02491     MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
02492     Image *ima= tface->tpage;
02493     float vec[4][2];
02494     int a, i1, i2, i3;
02495     
02496     /* check valid zspan */
02497     if(ima!=bs->ima) {
02498         bs->ima= ima;
02499         bs->ibuf= BKE_image_get_ibuf(ima, NULL);
02500         /* note, these calls only free/fill contents of zspan struct, not zspan itself */
02501         zbuf_free_span(bs->zspan);
02502         zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop);
02503     }               
02504     
02505     bs->rectx= bs->ibuf->x;
02506     bs->recty= bs->ibuf->y;
02507     bs->rect= bs->ibuf->rect;
02508     bs->rect_float= bs->ibuf->rect_float;
02509     bs->quad= 0;
02510     
02511     if (bs->usemask) {
02512         if (bs->ibuf->userdata==NULL) {
02513             BLI_lock_thread(LOCK_CUSTOM1);
02514             if (bs->ibuf->userdata==NULL) /* since the thread was locked, its possible another thread alloced the value */
02515                 bs->ibuf->userdata = (void *)MEM_callocN(sizeof(char)*bs->rectx*bs->recty, "BakeMask");
02516             bs->rect_mask= (char *)bs->ibuf->userdata;
02517             BLI_unlock_thread(LOCK_CUSTOM1);
02518         } else {
02519             bs->rect_mask= (char *)bs->ibuf->userdata;
02520         }
02521     }
02522     
02523     /* get pixel level vertex coordinates */
02524     for(a=0; a<4; a++) {
02525         /* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests
02526          * where a pixel gets in between 2 faces or the middle of a quad,
02527          * camera aligned quads also have this problem but they are less common.
02528          * Add a small offset to the UVs, fixes bug #18685 - Campbell */
02529         vec[a][0]= tface->uv[a][0]*(float)bs->rectx - (0.5f + 0.001f);
02530         vec[a][1]= tface->uv[a][1]*(float)bs->recty - (0.5f + 0.002f);
02531     }
02532     
02533     /* UV indices have to be corrected for possible quad->tria splits */
02534     i1= 0; i2= 1; i3= 2;
02535     vlr_set_uv_indices(vlr, &i1, &i2, &i3);
02536     bake_set_vlr_dxyco(bs, vec[i1], vec[i2], vec[i3]);
02537     zspan_scanconvert(bs->zspan, bs, vec[i1], vec[i2], vec[i3], do_bake_shade);
02538     
02539     if(vlr->v4) {
02540         bs->quad= 1;
02541         bake_set_vlr_dxyco(bs, vec[0], vec[2], vec[3]);
02542         zspan_scanconvert(bs->zspan, bs, vec[0], vec[2], vec[3], do_bake_shade);
02543     }
02544 }
02545 
02546 static void *do_bake_thread(void *bs_v)
02547 {
02548     BakeShade *bs= bs_v;
02549     
02550     while(get_next_bake_face(bs)) {
02551         shade_tface(bs);
02552         
02553         /* fast threadsafe break test */
02554         if(R.test_break(R.tbh))
02555             break;
02556 
02557         /* access is not threadsafe but since its just true/false probably ok
02558          * only used for interactive baking */
02559         if(bs->do_update)
02560             *bs->do_update= TRUE;
02561     }
02562     bs->ready= 1;
02563     
02564     return NULL;
02565 }
02566 
02567 void RE_bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter)
02568 {
02569     /* must check before filtering */
02570     const short is_new_alpha= (ibuf->planes != R_IMF_PLANES_RGBA) && BKE_alphatest_ibuf(ibuf);
02571 
02572     /* Margin */
02573     if(filter) {
02574         IMB_filter_extend(ibuf, mask, filter);
02575     }
02576 
02577     /* if the bake results in new alpha then change the image setting */
02578     if(is_new_alpha) {
02579         ibuf->planes= R_IMF_PLANES_RGBA;
02580     }
02581     else {
02582         if(filter && ibuf->planes != R_IMF_PLANES_RGBA) {
02583             /* clear alpha added by filtering */
02584             IMB_rectfill_alpha(ibuf, 1.0f);
02585         }
02586     }
02587 }
02588 
02589 /* using object selection tags, the faces with UV maps get baked */
02590 /* render should have been setup */
02591 /* returns 0 if nothing was handled */
02592 int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_update, float *progress)
02593 {
02594     BakeShade *handles;
02595     ListBase threads;
02596     Image *ima;
02597     int a, vdone=0, usemask=0;
02598     
02599     /* initialize render global */
02600     R= *re;
02601     R.bakebuf= NULL;
02602     
02603     /* initialize static vars */
02604     get_next_bake_face(NULL);
02605     
02606     /* do we need a mask? */
02607     if (re->r.bake_filter)
02608         usemask = 1;
02609     
02610     /* baker uses this flag to detect if image was initialized */
02611     for(ima= G.main->image.first; ima; ima= ima->id.next) {
02612         ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
02613         ima->id.flag |= LIB_DOIT;
02614         if(ibuf) {
02615             ibuf->userdata = NULL; /* use for masking if needed */
02616             if(ibuf->rect_float)
02617                 ibuf->profile = IB_PROFILE_LINEAR_RGB;
02618         }
02619     }
02620     
02621     BLI_init_threads(&threads, do_bake_thread, re->r.threads);
02622 
02623     handles= MEM_callocN(sizeof(BakeShade)*re->r.threads, "BakeShade");
02624 
02625     /* get the threads running */
02626     for(a=0; a<re->r.threads; a++) {
02627         /* set defaults in handles */
02628         handles[a].ssamp.shi[0].lay= re->lay;
02629         
02630         if (type==RE_BAKE_SHADOW) {
02631             handles[a].ssamp.shi[0].passflag= SCE_PASS_SHADOW;
02632         } else {
02633             handles[a].ssamp.shi[0].passflag= SCE_PASS_COMBINED;
02634         }
02635         handles[a].ssamp.shi[0].combinedflag= ~(SCE_PASS_SPEC);
02636         handles[a].ssamp.shi[0].thread= a;
02637         handles[a].ssamp.tot= 1;
02638         
02639         handles[a].type= type;
02640         handles[a].actob= actob;
02641         handles[a].zspan= MEM_callocN(sizeof(ZSpan), "zspan for bake");
02642         
02643         handles[a].usemask = usemask;
02644 
02645         handles[a].do_update = do_update; /* use to tell the view to update */
02646         
02647         BLI_insert_thread(&threads, &handles[a]);
02648     }
02649     
02650     /* wait for everything to be done */
02651     a= 0;
02652     while(a!=re->r.threads) {
02653         PIL_sleep_ms(50);
02654 
02655         /* calculate progress */
02656         for(vdone=0, a=0; a<re->r.threads; a++)
02657             vdone+= handles[a].vdone;
02658         if (progress)
02659             *progress = (float)(vdone / (float)re->totvlak);
02660         
02661         for(a=0; a<re->r.threads; a++) {
02662             if(handles[a].ready==0)
02663                 break;
02664         }
02665     }
02666     
02667     /* filter and refresh images */
02668     for(ima= G.main->image.first; ima; ima= ima->id.next) {
02669         if((ima->id.flag & LIB_DOIT)==0) {
02670             ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
02671 
02672             if(!ibuf)
02673                 continue;
02674 
02675             RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, re->r.bake_filter);
02676 
02677             ibuf->userflags |= IB_BITMAPDIRTY;
02678             if (ibuf->rect_float) IMB_rect_from_float(ibuf);
02679         }
02680     }
02681     
02682     /* calculate return value */
02683     for(a=0; a<re->r.threads; a++) {
02684         zbuf_free_span(handles[a].zspan);
02685         MEM_freeN(handles[a].zspan);
02686     }
02687 
02688     MEM_freeN(handles);
02689     
02690     BLI_end_threads(&threads);
02691 
02692     return vdone;
02693 }
02694 
02695 struct Image *RE_bake_shade_get_image(void)
02696 {
02697     return R.bakebuf;
02698 }
02699