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