Cleanup: whitespace & break placement
[blender-staging.git] / source / blender / render / intern / source / rendercore.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributors: Hos, Robert Wenzlaff.
22  * Contributors: 2004/2005/2006 Blender Foundation, full recode
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/render/intern/source/rendercore.c
28  *  \ingroup render
29  */
30
31
32 /* system includes */
33 #include <stdio.h>
34 #include <math.h>
35 #include <float.h>
36 #include <string.h>
37 #include <assert.h>
38
39 /* External modules: */
40 #include "MEM_guardedalloc.h"
41
42 #include "BLI_math.h"
43 #include "BLI_blenlib.h"
44 #include "BLI_rand.h"
45 #include "BLI_threads.h"
46 #include "BLI_utildefines.h"
47
48 #include "DNA_image_types.h"
49 #include "DNA_lamp_types.h"
50 #include "DNA_material_types.h"
51 #include "DNA_group_types.h"
52
53 /* local include */
54 #include "renderpipeline.h"
55 #include "render_result.h"
56 #include "render_types.h"
57 #include "renderdatabase.h"
58 #include "occlusion.h"
59 #include "pixelblending.h"
60 #include "pixelshading.h"
61 #include "shadbuf.h"
62 #include "shading.h"
63 #include "sss.h"
64 #include "zbuf.h"
65
66 /* own include */
67 #include "rendercore.h"
68
69
70 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
71 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
72 /* only to be used here in this file, it's for speed */
73 extern struct Render R;
74 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
75
76 /* x and y are current pixels in rect to be rendered */
77 /* do not normalize! */
78 void calc_view_vector(float view[3], float x, float y)
79 {
80
81         view[2]= -ABS(R.clipsta);
82         
83         if (R.r.mode & R_ORTHO) {
84                 view[0]= view[1]= 0.0f;
85         }
86         else {
87                 
88                 if (R.r.mode & R_PANORAMA) {
89                         x-= R.panodxp;
90                 }
91                 
92                 /* move x and y to real viewplane coords */
93                 x = (x / (float)R.winx);
94                 view[0] = R.viewplane.xmin + x * BLI_rctf_size_x(&R.viewplane);
95                 
96                 y = (y / (float)R.winy);
97                 view[1] = R.viewplane.ymin + y * BLI_rctf_size_y(&R.viewplane);
98                 
99 //              if (R.flag & R_SEC_FIELD) {
100 //                      if (R.r.mode & R_ODDFIELD) view[1]= (y+R.ystart)*R.ycor;
101 //                      else view[1]= (y+R.ystart+1.0)*R.ycor;
102 //              }
103 //              else view[1]= (y+R.ystart+R.bluroffsy+0.5)*R.ycor;
104         
105                 if (R.r.mode & R_PANORAMA) {
106                         float u= view[0] + R.panodxv; float v= view[2];
107                         view[0]= R.panoco*u + R.panosi*v;
108                         view[2]= -R.panosi*u + R.panoco*v;
109                 }
110         }
111 }
112
113 void calc_renderco_ortho(float co[3], float x, float y, int z)
114 {
115         /* x and y 3d coordinate can be derived from pixel coord and winmat */
116         float fx= 2.0f/(R.winx*R.winmat[0][0]);
117         float fy= 2.0f/(R.winy*R.winmat[1][1]);
118         float zco;
119         
120         co[0]= (x - 0.5f*R.winx)*fx - R.winmat[3][0]/R.winmat[0][0];
121         co[1]= (y - 0.5f*R.winy)*fy - R.winmat[3][1]/R.winmat[1][1];
122         
123         zco= ((float)z)/2147483647.0f;
124         co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] );
125 }
126
127 void calc_renderco_zbuf(float co[3], const float view[3], int z)
128 {
129         float fac, zco;
130         
131         /* inverse of zbuf calc: zbuf = MAXZ*hoco_z/hoco_w */
132         zco= ((float)z)/2147483647.0f;
133         co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] );
134
135         fac= co[2]/view[2];
136         co[0]= fac*view[0];
137         co[1]= fac*view[1];
138 }
139
140 /* also used in zbuf.c and shadbuf.c */
141 int count_mask(unsigned short mask)
142 {
143         if (R.samples)
144                 return (R.samples->cmask[mask & 255]+R.samples->cmask[mask>>8]);
145         return 0;
146 }
147
148 static int calchalo_z(HaloRen *har, int zz)
149 {
150         
151         if (har->type & HA_ONLYSKY) {
152                 if (zz < 0x7FFFFFF0) zz= - 0x7FFFFF;    /* edge render messes zvalues */
153         }
154         else {
155                 zz= (zz>>8);
156         }
157         return zz;
158 }
159
160
161
162 static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, int od, float dist, float xn, float yn, PixStr *ps)
163 {
164         float col[4], accol[4], fac;
165         int amount, amountm, zz, flarec, sample, fullsample, mask=0;
166         
167         fullsample= (totsample > 1);
168         amount= 0;
169         accol[0] = accol[1] = accol[2] = accol[3]= 0.0f;
170         col[0] = col[1] = col[2] = col[3]= 0.0f;
171         flarec= har->flarec;
172         
173         while (ps) {
174                 amountm= count_mask(ps->mask);
175                 amount+= amountm;
176                 
177                 zz= calchalo_z(har, ps->z);
178                 if ((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) {
179                         if (shadeHaloFloat(har, col, zz, dist, xn, yn, flarec)) {
180                                 flarec= 0;
181
182                                 if (fullsample) {
183                                         for (sample=0; sample<totsample; sample++)
184                                                 if (ps->mask & (1 << sample)) {
185                                                         float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
186                                                         addalphaAddfacFloat(pass + od*4, col, har->add);
187                                                 }
188                                 }
189                                 else {
190                                         fac= ((float)amountm)/(float)R.osa;
191                                         accol[0]+= fac*col[0];
192                                         accol[1]+= fac*col[1];
193                                         accol[2]+= fac*col[2];
194                                         accol[3]+= fac*col[3];
195                                 }
196                         }
197                 }
198                 
199                 mask |= ps->mask;
200                 ps= ps->next;
201         }
202
203         /* now do the sky sub-pixels */
204         amount= R.osa-amount;
205         if (amount) {
206                 if (shadeHaloFloat(har, col, 0x7FFFFF, dist, xn, yn, flarec)) {
207                         if (!fullsample) {
208                                 fac= ((float)amount)/(float)R.osa;
209                                 accol[0]+= fac*col[0];
210                                 accol[1]+= fac*col[1];
211                                 accol[2]+= fac*col[2];
212                                 accol[3]+= fac*col[3];
213                         }
214                 }
215         }
216
217         if (fullsample) {
218                 for (sample=0; sample<totsample; sample++)
219                         if (!(mask & (1 << sample))) {
220                                 float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
221                                 addalphaAddfacFloat(pass + od*4, col, har->add);
222                         }
223         }
224         else {
225                 col[0]= accol[0];
226                 col[1]= accol[1];
227                 col[2]= accol[2];
228                 col[3]= accol[3];
229                 
230                 for (sample=0; sample<totsample; sample++) {
231                         float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
232                         addalphaAddfacFloat(pass + od*4, col, har->add);
233                 }
234         }
235 }
236
237 static void halo_tile(RenderPart *pa, RenderLayer *rl)
238 {
239         RenderLayer *rlpp[RE_MAX_OSA];
240         HaloRen *har;
241         rcti disprect= pa->disprect, testrect= pa->disprect;
242         float dist, xsq, ysq, xn, yn;
243         float col[4];
244         intptr_t *rd= NULL;
245         int a, *rz, zz, y, sample, totsample, od;
246         short minx, maxx, miny, maxy, x;
247         unsigned int lay= rl->lay;
248
249         /* we don't render halos in the cropped area, gives errors in flare counter */
250         if (pa->crop) {
251                 testrect.xmin+= pa->crop;
252                 testrect.xmax-= pa->crop;
253                 testrect.ymin+= pa->crop;
254                 testrect.ymax-= pa->crop;
255         }
256         
257         totsample= get_sample_layers(pa, rl, rlpp);
258
259         for (a=0; a<R.tothalo; a++) {
260                 har= R.sortedhalos[a];
261
262                 /* layer test, clip halo with y */
263                 if ((har->lay & lay) == 0) {
264                         /* pass */
265                 }
266                 else if (testrect.ymin > har->maxy) {
267                         /* pass */
268                 }
269                 else if (testrect.ymax < har->miny) {
270                         /* pass */
271                 }
272                 else {
273                         
274                         minx= floor(har->xs-har->rad);
275                         maxx= ceil(har->xs+har->rad);
276                         
277                         if (testrect.xmin > maxx) {
278                                 /* pass */
279                         }
280                         else if (testrect.xmax < minx) {
281                                 /* pass */
282                         }
283                         else {
284                                 
285                                 minx = max_ii(minx, testrect.xmin);
286                                 maxx = min_ii(maxx, testrect.xmax);
287                         
288                                 miny = max_ii(har->miny, testrect.ymin);
289                                 maxy = min_ii(har->maxy, testrect.ymax);
290                         
291                                 for (y=miny; y<maxy; y++) {
292                                         int rectofs= (y-disprect.ymin)*pa->rectx + (minx - disprect.xmin);
293                                         rz= pa->rectz + rectofs;
294                                         od= rectofs;
295                                         
296                                         if (pa->rectdaps)
297                                                 rd= pa->rectdaps + rectofs;
298                                         
299                                         yn= (y-har->ys)*R.ycor;
300                                         ysq= yn*yn;
301                                         
302                                         for (x=minx; x<maxx; x++, rz++, od++) {
303                                                 xn= x- har->xs;
304                                                 xsq= xn*xn;
305                                                 dist= xsq+ysq;
306                                                 if (dist<har->radsq) {
307                                                         if (rd && *rd) {
308                                                                 halo_pixelstruct(har, rlpp, totsample, od, dist, xn, yn, (PixStr *)*rd);
309                                                         }
310                                                         else {
311                                                                 zz= calchalo_z(har, *rz);
312                                                                 if ((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) {
313                                                                         if (shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec)) {
314                                                                                 for (sample=0; sample<totsample; sample++) {
315                                                                                         float * rect= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
316                                                                                         addalphaAddfacFloat(rect + od*4, col, har->add);
317                                                                                 }
318                                                                         }
319                                                                 }
320                                                         }
321                                                 }
322                                                 if (rd) rd++;
323                                         }
324                                 }
325                         }
326                 }
327                 if (R.test_break(R.tbh) ) break; 
328         }
329 }
330
331 static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
332 {
333         RenderLayer *rlpp[RE_MAX_OSA];
334         ShadeInput shi;
335         float *pass;
336         float fac, col[4];
337         intptr_t *rd= pa->rectdaps;
338         const int *rz= pa->rectz;
339         int x, y, sample, totsample, fullsample, od;
340         
341         totsample= get_sample_layers(pa, rl, rlpp);
342         fullsample= (totsample > 1);
343
344         shade_input_initialize(&shi, pa, rl, 0); /* this zero's ShadeInput for us */
345         
346         for (od=0, y=pa->disprect.ymin; y<pa->disprect.ymax; y++) {
347                 for (x=pa->disprect.xmin; x<pa->disprect.xmax; x++, rz++, od++) {
348                         
349                         calc_view_vector(shi.view, x, y);
350                         
351                         if (rd && *rd) {
352                                 PixStr *ps= (PixStr *)*rd;
353                                 int count, totsamp= 0, mask= 0;
354                                 
355                                 while (ps) {
356                                         if (R.r.mode & R_ORTHO)
357                                                 calc_renderco_ortho(shi.co, (float)x, (float)y, ps->z);
358                                         else
359                                                 calc_renderco_zbuf(shi.co, shi.view, ps->z);
360                                         
361                                         totsamp+= count= count_mask(ps->mask);
362                                         mask |= ps->mask;
363
364                                         col[0]= col[1]= col[2]= col[3]= 0.0f;
365                                         renderspothalo(&shi, col, 1.0f);
366
367                                         if (fullsample) {
368                                                 for (sample=0; sample<totsample; sample++) {
369                                                         if (ps->mask & (1 << sample)) {
370                                                                 pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
371                                                                 pass += od * 4;
372                                                                 pass[0]+= col[0];
373                                                                 pass[1]+= col[1];
374                                                                 pass[2]+= col[2];
375                                                                 pass[3]+= col[3];
376                                                                 if (pass[3]>1.0f) pass[3]= 1.0f;
377                                                         }
378                                                 }
379                                         }
380                                         else {
381                                                 fac= ((float)count)/(float)R.osa;
382                                                 pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
383                                                 pass += od * 4;
384                                                 pass[0]+= fac*col[0];
385                                                 pass[1]+= fac*col[1];
386                                                 pass[2]+= fac*col[2];
387                                                 pass[3]+= fac*col[3];
388                                                 if (pass[3]>1.0f) pass[3]= 1.0f;
389                                         }
390
391                                         ps= ps->next;
392                                 }
393
394                                 if (totsamp<R.osa) {
395                                         shi.co[2]= 0.0f;
396
397                                         col[0]= col[1]= col[2]= col[3]= 0.0f;
398                                         renderspothalo(&shi, col, 1.0f);
399
400                                         if (fullsample) {
401                                                 for (sample=0; sample<totsample; sample++) {
402                                                         if (!(mask & (1 << sample))) {
403
404                                                                 pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
405                                                                 pass += od * 4;
406                                                                 pass[0]+= col[0];
407                                                                 pass[1]+= col[1];
408                                                                 pass[2]+= col[2];
409                                                                 pass[3]+= col[3];
410                                                                 if (pass[3]>1.0f) pass[3]= 1.0f;
411                                                         }
412                                                 }
413                                         }
414                                         else {
415                                                 fac= ((float)R.osa-totsamp)/(float)R.osa;
416                                                 pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
417                                                 pass += od * 4;
418                                                 pass[0]+= fac*col[0];
419                                                 pass[1]+= fac*col[1];
420                                                 pass[2]+= fac*col[2];
421                                                 pass[3]+= fac*col[3];
422                                                 if (pass[3]>1.0f) pass[3]= 1.0f;
423                                         }
424                                 }
425                         }
426                         else {
427                                 if (R.r.mode & R_ORTHO)
428                                         calc_renderco_ortho(shi.co, (float)x, (float)y, *rz);
429                                 else
430                                         calc_renderco_zbuf(shi.co, shi.view, *rz);
431                                 
432                                 col[0]= col[1]= col[2]= col[3]= 0.0f;
433                                 renderspothalo(&shi, col, 1.0f);
434
435                                 for (sample=0; sample<totsample; sample++) {
436                                         pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
437                                         pass += od * 4;
438                                         pass[0]+= col[0];
439                                         pass[1]+= col[1];
440                                         pass[2]+= col[2];
441                                         pass[3]+= col[3];
442                                         if (pass[3]>1.0f) pass[3]= 1.0f;
443                                 }
444                         }
445                         
446                         if (rd) rd++;
447                 }
448                 if (y&1)
449                         if (R.test_break(R.tbh)) break; 
450         }
451 }                               
452
453
454 /* ********************* MAINLOOPS ******************** */
455
456 /* osa version */
457 static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, ShadeInput *shi, ShadeResult *shr)
458 {
459         RenderPass *rpass;
460
461         for (rpass= rl->passes.first; rpass; rpass= rpass->next) {
462                 float *fp, *col= NULL;
463                 int pixsize= 3;
464                 
465                 switch (rpass->passtype) {
466                         case SCE_PASS_COMBINED:
467                                 add_filt_fmask(curmask, shr->combined, rpass->rect + 4*offset, rectx);
468                                 break;
469                         case SCE_PASS_Z:
470                                 fp= rpass->rect + offset;
471                                 *fp= shr->z;
472                                 break;
473                         case SCE_PASS_RGBA:
474                                 col= shr->col;
475                                 pixsize= 4;
476                                 break;
477                         case SCE_PASS_EMIT:
478                                 col= shr->emit;
479                                 break;
480                         case SCE_PASS_DIFFUSE:
481                                 col= shr->diff;
482                                 break;
483                         case SCE_PASS_SPEC:
484                                 col= shr->spec;
485                                 break;
486                         case SCE_PASS_SHADOW:
487                                 col= shr->shad;
488                                 break;
489                         case SCE_PASS_AO:
490                                 col= shr->ao;
491                                 break;
492                         case SCE_PASS_ENVIRONMENT:
493                                 col= shr->env;
494                                 break;
495                         case SCE_PASS_INDIRECT:
496                                 col= shr->indirect;
497                                 break;
498                         case SCE_PASS_REFLECT:
499                                 col= shr->refl;
500                                 break;
501                         case SCE_PASS_REFRACT:
502                                 col= shr->refr;
503                                 break;
504                         case SCE_PASS_NORMAL:
505                                 col= shr->nor;
506                                 break;
507                         case SCE_PASS_UV:
508                                 /* box filter only, gauss will screwup UV too much */
509                                 if (shi->totuv) {
510                                         float mult= (float)count_mask(curmask)/(float)R.osa;
511                                         fp= rpass->rect + 3*offset;
512                                         fp[0]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[0]);
513                                         fp[1]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[1]);
514                                         fp[2]+= mult;
515                                 }
516                                 break;
517                         case SCE_PASS_INDEXOB:
518                                 /* no filter */
519                                 if (shi->vlr) {
520                                         fp= rpass->rect + offset;
521                                         if (*fp==0.0f)
522                                                 *fp= (float)shi->obr->ob->index;
523                                 }
524                                 break;
525                         case SCE_PASS_INDEXMA:
526                                         /* no filter */
527                                         if (shi->vlr) {
528                                                         fp= rpass->rect + offset;
529                                                         if (*fp==0.0f)
530                                                                         *fp= (float)shi->mat->index;
531                                         }
532                                         break;
533                         case SCE_PASS_MIST:
534                                 /*  */
535                                 col= &shr->mist;
536                                 pixsize= 1;
537                                 break;
538                         
539                         case SCE_PASS_VECTOR:
540                         {
541                                 /* add minimum speed in pixel, no filter */
542                                 fp= rpass->rect + 4*offset;
543                                 if ( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) {
544                                         fp[0]= shr->winspeed[0];
545                                         fp[1]= shr->winspeed[1];
546                                 }
547                                 if ( (ABS(shr->winspeed[2]) + ABS(shr->winspeed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) {
548                                         fp[2]= shr->winspeed[2];
549                                         fp[3]= shr->winspeed[3];
550                                 }
551
552                                 break;
553                         }
554                         case SCE_PASS_RAYHITS:
555                                 /*  */
556                                 col= shr->rayhits;
557                                 pixsize= 4;
558                                 break;
559                 }
560                 if (col) {
561                         fp= rpass->rect + pixsize*offset;
562                         add_filt_fmask_pixsize(curmask, col, fp, rectx, pixsize);
563                 }
564         }
565 }
566
567 /* non-osa version */
568 static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult *shr)
569 {
570         RenderPass *rpass;
571         float *fp;
572
573         for (rpass= rl->passes.first; rpass; rpass= rpass->next) {
574                 float *col= NULL, uvcol[3];
575                 int a, pixsize= 3;
576                 
577                 switch (rpass->passtype) {
578                         case SCE_PASS_COMBINED:
579                                 /* copy combined to use for preview */
580                                 copy_v4_v4(rpass->rect + 4*offset, shr->combined);
581                                 break;
582                         case SCE_PASS_Z:
583                                 fp= rpass->rect + offset;
584                                 *fp= shr->z;
585                                 break;
586                         case SCE_PASS_RGBA:
587                                 col= shr->col;
588                                 pixsize= 4;
589                                 break;
590                         case SCE_PASS_EMIT:
591                                 col= shr->emit;
592                                 break;
593                         case SCE_PASS_DIFFUSE:
594                                 col= shr->diff;
595                                 break;
596                         case SCE_PASS_SPEC:
597                                 col= shr->spec;
598                                 break;
599                         case SCE_PASS_SHADOW:
600                                 col= shr->shad;
601                                 break;
602                         case SCE_PASS_AO:
603                                 col= shr->ao;
604                                 break;
605                         case SCE_PASS_ENVIRONMENT:
606                                 col= shr->env;
607                                 break;
608                         case SCE_PASS_INDIRECT:
609                                 col= shr->indirect;
610                                 break;
611                         case SCE_PASS_REFLECT:
612                                 col= shr->refl;
613                                 break;
614                         case SCE_PASS_REFRACT:
615                                 col= shr->refr;
616                                 break;
617                         case SCE_PASS_NORMAL:
618                                 col= shr->nor;
619                                 break;
620                         case SCE_PASS_UV:
621                                 if (shi->totuv) {
622                                         uvcol[0]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[0];
623                                         uvcol[1]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[1];
624                                         uvcol[2]= 1.0f;
625                                         col= uvcol;
626                                 }
627                                 break;
628                         case SCE_PASS_VECTOR:
629                                 col= shr->winspeed;
630                                 pixsize= 4;
631                                 break;
632                         case SCE_PASS_INDEXOB:
633                                 if (shi->vlr) {
634                                         fp= rpass->rect + offset;
635                                         *fp= (float)shi->obr->ob->index;
636                                 }
637                                 break;
638                         case SCE_PASS_INDEXMA:
639                                 if (shi->vlr) {
640                                         fp= rpass->rect + offset;
641                                         *fp= (float)shi->mat->index;
642                                 }
643                                 break;
644                         case SCE_PASS_MIST:
645                                 fp= rpass->rect + offset;
646                                 *fp= shr->mist;
647                                 break;
648                         case SCE_PASS_RAYHITS:
649                                 col= shr->rayhits;
650                                 pixsize= 4;
651                                 break;
652                 }
653                 if (col) {
654                         fp= rpass->rect + pixsize*offset;
655                         for (a=0; a<pixsize; a++)
656                                 fp[a]= col[a];
657                 }
658         }
659 }
660
661 int get_sample_layers(RenderPart *pa, RenderLayer *rl, RenderLayer **rlpp)
662 {
663         
664         if (pa->fullresult.first) {
665                 int sample, nr= BLI_findindex(&pa->result->layers, rl);
666                 
667                 for (sample=0; sample<R.osa; sample++) {
668                         RenderResult *rr= BLI_findlink(&pa->fullresult, sample);
669                 
670                         rlpp[sample]= BLI_findlink(&rr->layers, nr);
671                 }
672                 return R.osa;
673         }
674         else {
675                 rlpp[0]= rl;
676                 return 1;
677         }
678 }
679
680
681 /* only do sky, is default in the solid layer (shade_tile) btw */
682 static void sky_tile(RenderPart *pa, RenderLayer *rl)
683 {
684         RenderLayer *rlpp[RE_MAX_OSA];
685         int x, y, od=0, totsample;
686         
687         if (R.r.alphamode!=R_ADDSKY)
688                 return;
689         
690         totsample= get_sample_layers(pa, rl, rlpp);
691         
692         for (y=pa->disprect.ymin; y<pa->disprect.ymax; y++) {
693                 for (x=pa->disprect.xmin; x<pa->disprect.xmax; x++, od+=4) {
694                         float col[4];
695                         int sample;
696                         bool done = false;
697                         
698                         for (sample= 0; sample<totsample; sample++) {
699                                 float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
700                                 pass += od;
701                                 
702                                 if (pass[3]<1.0f) {
703                                         
704                                         if (done==0) {
705                                                 shadeSkyPixel(col, x, y, pa->thread);
706                                                 done = true;
707                                         }
708                                         
709                                         if (pass[3]==0.0f) {
710                                                 copy_v4_v4(pass, col);
711                                                 pass[3] = 1.0f;
712                                         }
713                                         else {
714                                                 addAlphaUnderFloat(pass, col);
715                                                 pass[3] = 1.0f;
716                                         }
717                                 }
718                         }
719                 }
720                 
721                 if (y&1)
722                         if (R.test_break(R.tbh)) break; 
723         }
724 }
725
726 static void atm_tile(RenderPart *pa, RenderLayer *rl)
727 {
728         RenderPass *zpass;
729         GroupObject *go;
730         LampRen *lar;
731         RenderLayer *rlpp[RE_MAX_OSA];
732         int totsample;
733         int x, y, od= 0;
734         
735         totsample= get_sample_layers(pa, rl, rlpp);
736
737         /* check that z pass is enabled */
738         if (pa->rectz==NULL) return;
739         for (zpass= rl->passes.first; zpass; zpass= zpass->next)
740                 if (zpass->passtype==SCE_PASS_Z)
741                         break;
742         
743         if (zpass==NULL) return;
744
745         /* check for at least one sun lamp that its atmosphere flag is enabled */
746         for (go=R.lights.first; go; go= go->next) {
747                 lar= go->lampren;
748                 if (lar->type==LA_SUN && lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_AP))
749                         break;
750         }
751         /* do nothign and return if there is no sun lamp */
752         if (go==NULL)
753                 return;
754         
755         /* for each x,y and each sample, and each sun lamp*/
756         for (y=pa->disprect.ymin; y<pa->disprect.ymax; y++) {
757                 for (x=pa->disprect.xmin; x<pa->disprect.xmax; x++, od++) {
758                         int sample;
759                         
760                         for (sample=0; sample<totsample; sample++) {
761                                 const float *zrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_Z, R.viewname) + od;
762                                 float *rgbrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname) + 4*od;
763                                 float rgb[3] = {0};
764                                 bool done = false;
765                                 
766                                 for (go=R.lights.first; go; go= go->next) {
767                                 
768                                         
769                                         lar= go->lampren;
770                                         if (lar->type==LA_SUN &&        lar->sunsky) {
771                                                 
772                                                 /* if it's sky continue and don't apply atmosphere effect on it */
773                                                 if (*zrect >= 9.9e10f || rgbrect[3]==0.0f) {
774                                                         continue;
775                                                 }
776
777                                                 if ((lar->sunsky->effect_type & LA_SUN_EFFECT_AP)) {
778                                                         float tmp_rgb[3];
779                                                         
780                                                         /* skip if worldspace lamp vector is below horizon */
781                                                         if (go->ob->obmat[2][2] < 0.f) {
782                                                                 continue;
783                                                         }
784                                                         
785                                                         copy_v3_v3(tmp_rgb, rgbrect);
786                                                         if (rgbrect[3]!=1.0f) { /* de-premul */
787                                                                 mul_v3_fl(tmp_rgb, 1.0f/rgbrect[3]);
788                                                         }
789                                                         shadeAtmPixel(lar->sunsky, tmp_rgb, x, y, *zrect);
790                                                         if (rgbrect[3]!=1.0f) { /* premul */
791                                                                 mul_v3_fl(tmp_rgb, rgbrect[3]);
792                                                         }
793                                                         
794                                                         if (done==0) {
795                                                                 copy_v3_v3(rgb, tmp_rgb);
796                                                                 done = true;
797                                                         }
798                                                         else {
799                                                                 rgb[0] = 0.5f*rgb[0] + 0.5f*tmp_rgb[0];
800                                                                 rgb[1] = 0.5f*rgb[1] + 0.5f*tmp_rgb[1];
801                                                                 rgb[2] = 0.5f*rgb[2] + 0.5f*tmp_rgb[2];
802                                                         }
803                                                 }
804                                         }
805                                 }
806
807                                 /* if at least for one sun lamp aerial perspective was applied*/
808                                 if (done) {
809                                         copy_v3_v3(rgbrect, rgb);
810                                 }
811                         }
812                 }
813         }
814 }
815
816 static void shadeDA_tile(RenderPart *pa, RenderLayer *rl)
817 {
818         RenderResult *rr= pa->result;
819         ShadeSample ssamp;
820         intptr_t *rd, *rectdaps= pa->rectdaps;
821         int samp;
822         int x, y, seed, crop=0, offs=0, od;
823         
824         if (R.test_break(R.tbh)) return; 
825         
826         /* irregular shadowb buffer creation */
827         if (R.r.mode & R_SHADOW)
828                 ISB_create(pa, NULL);
829         
830         /* we set per pixel a fixed seed, for random AO and shadow samples */
831         seed= pa->rectx*pa->disprect.ymin;
832         
833         /* general shader info, passes */
834         shade_sample_initialize(&ssamp, pa, rl);
835
836         /* occlusion caching */
837         if (R.occlusiontree)
838                 cache_occ_samples(&R, pa, &ssamp);
839                 
840         /* filtered render, for now we assume only 1 filter size */
841         if (pa->crop) {
842                 crop= 1;
843                 rectdaps+= pa->rectx + 1;
844                 offs= pa->rectx + 1;
845         }
846         
847         /* scanline updates have to be 2 lines behind */
848         rr->renrect.ymin = 0;
849         rr->renrect.ymax = -2*crop;
850         rr->renlay= rl;
851                                 
852         for (y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) {
853                 rd= rectdaps;
854                 od= offs;
855                 
856                 for (x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, rd++, od++) {
857                         BLI_thread_srandom(pa->thread, seed++);
858                         
859                         if (*rd) {
860                                 if (shade_samples(&ssamp, (PixStr *)(*rd), x, y)) {
861                                         
862                                         /* multisample buffers or filtered mask filling? */
863                                         if (pa->fullresult.first) {
864                                                 int a;
865                                                 for (samp=0; samp<ssamp.tot; samp++) {
866                                                         int smask= ssamp.shi[samp].mask;
867                                                         for (a=0; a<R.osa; a++) {
868                                                                 int mask= 1<<a;
869                                                                 if (smask & mask)
870                                                                         add_passes(ssamp.rlpp[a], od, &ssamp.shi[samp], &ssamp.shr[samp]);
871                                                         }
872                                                 }
873                                         }
874                                         else {
875                                                 for (samp=0; samp<ssamp.tot; samp++)
876                                                         add_filt_passes(rl, ssamp.shi[samp].mask, pa->rectx, od, &ssamp.shi[samp], &ssamp.shr[samp]);
877                                         }
878                                 }
879                         }
880                 }
881                 
882                 rectdaps+= pa->rectx;
883                 offs+= pa->rectx;
884                 
885                 if (y&1) if (R.test_break(R.tbh)) break; 
886         }
887         
888         /* disable scanline updating */
889         rr->renlay= NULL;
890         
891         if (R.r.mode & R_SHADOW)
892                 ISB_free(pa);
893
894         if (R.occlusiontree)
895                 free_occ_samples(&R, pa);
896 }
897
898 /* ************* pixel struct ******** */
899
900
901 static PixStrMain *addpsmain(ListBase *lb)
902 {
903         PixStrMain *psm;
904         
905         psm= (PixStrMain *)MEM_mallocN(sizeof(PixStrMain), "pixstrMain");
906         BLI_addtail(lb, psm);
907         
908         psm->ps= (PixStr *)MEM_mallocN(4096*sizeof(PixStr), "pixstr");
909         psm->counter= 0;
910         
911         return psm;
912 }
913
914 static void freeps(ListBase *lb)
915 {
916         PixStrMain *psm, *psmnext;
917         
918         for (psm= lb->first; psm; psm= psmnext) {
919                 psmnext= psm->next;
920                 if (psm->ps)
921                         MEM_freeN(psm->ps);
922                 MEM_freeN(psm);
923         }
924         BLI_listbase_clear(lb);
925 }
926
927 static void addps(ListBase *lb, intptr_t *rd, int obi, int facenr, int z, int maskz, unsigned short mask)
928 {
929         PixStrMain *psm;
930         PixStr *ps, *last= NULL;
931         
932         if (*rd) {
933                 ps= (PixStr *)(*rd);
934                 
935                 while (ps) {
936                         if ( ps->obi == obi && ps->facenr == facenr ) {
937                                 ps->mask |= mask;
938                                 return;
939                         }
940                         last= ps;
941                         ps= ps->next;
942                 }
943         }
944         
945         /* make new PS (pixel struct) */
946         psm= lb->last;
947         
948         if (psm->counter==4095)
949                 psm= addpsmain(lb);
950         
951         ps= psm->ps + psm->counter++;
952         
953         if (last) last->next= ps;
954         else *rd= (intptr_t)ps;
955         
956         ps->next= NULL;
957         ps->obi= obi;
958         ps->facenr= facenr;
959         ps->z= z;
960         ps->maskz= maskz;
961         ps->mask = mask;
962         ps->shadfac= 0;
963 }
964
965 static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect)
966 {
967         float addcol[4];
968         int pix;
969         
970         if (arect==NULL)
971                 return;
972         
973         for (pix= pa->rectx*pa->recty; pix>0; pix--, arect++, rectf+=4) {
974                 if (*arect != 0.0f) {
975                         addcol[0]= *arect * R.r.edgeR;
976                         addcol[1]= *arect * R.r.edgeG;
977                         addcol[2]= *arect * R.r.edgeB;
978                         addcol[3]= *arect;
979                         addAlphaOverFloat(rectf, addcol);
980                 }
981         }
982 }
983
984 /* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */
985 static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl)
986 {
987         RenderLayer *rlpp[RE_MAX_OSA];
988         int y, sample, totsample;
989         
990         totsample= get_sample_layers(pa, rl, rlpp);
991
992         /* not for full sample, there we clamp after compositing */
993         if (totsample > 1)
994                 return;
995         
996         for (sample= 0; sample<totsample; sample++) {
997                 float *rectf = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
998
999                 for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) {
1000                         rectf[0] = MAX2(rectf[0], 0.0f);
1001                         rectf[1] = MAX2(rectf[1], 0.0f);
1002                         rectf[2] = MAX2(rectf[2], 0.0f);
1003                         CLAMP(rectf[3], 0.0f, 1.0f);
1004                 }
1005         }
1006 }
1007
1008 /* adds only alpha values */
1009 static void edge_enhance_tile(RenderPart *pa, float *rectf, int *rectz)
1010 {
1011         /* use zbuffer to define edges, add it to the image */
1012         int y, x, col, *rz, *rz1, *rz2, *rz3;
1013         int zval1, zval2, zval3;
1014         float *rf;
1015         
1016         /* shift values in zbuffer 4 to the right (anti overflows), for filter we need multiplying with 12 max */
1017         rz= rectz;
1018         if (rz==NULL) return;
1019         
1020         for (y=0; y<pa->recty; y++)
1021                 for (x=0; x<pa->rectx; x++, rz++) (*rz)>>= 4;
1022         
1023         rz1= rectz;
1024         rz2= rz1+pa->rectx;
1025         rz3= rz2+pa->rectx;
1026         
1027         rf= rectf+pa->rectx+1;
1028         
1029         for (y=0; y<pa->recty-2; y++) {
1030                 for (x=0; x<pa->rectx-2; x++, rz1++, rz2++, rz3++, rf++) {
1031                         
1032                         /* prevent overflow with sky z values */
1033                         zval1=   rz1[0] + 2*rz1[1] +   rz1[2];
1034                         zval2=  2*rz2[0]           + 2*rz2[2];
1035                         zval3=   rz3[0] + 2*rz3[1] +   rz3[2];
1036                         
1037                         col= ( 4*rz2[1] - (zval1 + zval2 + zval3)/3 );
1038                         if (col<0) col= -col;
1039                         
1040                         col >>= 5;
1041                         if (col > (1<<16)) col= (1<<16);
1042                         else col= (R.r.edgeint*col)>>8;
1043                         
1044                         if (col>0) {
1045                                 float fcol;
1046                                 
1047                                 if (col>255) fcol= 1.0f;
1048                                 else fcol= (float)col/255.0f;
1049                                 
1050                                 if (R.osa)
1051                                         *rf+= fcol/(float)R.osa;
1052                                 else
1053                                         *rf= fcol;
1054                         }
1055                 }
1056                 rz1+= 2;
1057                 rz2+= 2;
1058                 rz3+= 2;
1059                 rf+= 2;
1060         }
1061         
1062         /* shift back zbuf values, we might need it still */
1063         rz= rectz;
1064         for (y=0; y<pa->recty; y++)
1065                 for (x=0; x<pa->rectx; x++, rz++) (*rz)<<= 4;
1066         
1067 }
1068
1069 static void reset_sky_speed(RenderPart *pa, RenderLayer *rl)
1070 {
1071         /* for all pixels with max speed, set to zero */
1072         RenderLayer *rlpp[RE_MAX_OSA];
1073         float *fp;
1074         int a, sample, totsample;
1075         
1076         totsample= get_sample_layers(pa, rl, rlpp);
1077
1078         for (sample= 0; sample<totsample; sample++) {
1079                 fp= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_VECTOR, R.viewname);
1080                 if (fp==NULL) break;
1081
1082                 for (a= 4*pa->rectx*pa->recty - 1; a>=0; a--)
1083                         if (fp[a] == PASS_VECTOR_MAX) fp[a]= 0.0f;
1084         }
1085 }
1086
1087 static unsigned short *make_solid_mask(RenderPart *pa)
1088
1089         intptr_t *rd= pa->rectdaps;
1090         unsigned short *solidmask, *sp;
1091         int x;
1092
1093         if (rd==NULL) return NULL;
1094
1095         sp=solidmask= MEM_mallocN(sizeof(short)*pa->rectx*pa->recty, "solidmask");
1096
1097         for (x=pa->rectx*pa->recty; x>0; x--, rd++, sp++) {
1098                 if (*rd) {
1099                         PixStr *ps= (PixStr *)*rd;
1100                         
1101                         *sp= ps->mask;
1102                         for (ps= ps->next; ps; ps= ps->next)
1103                                 *sp |= ps->mask;
1104                 }
1105                 else
1106                         *sp= 0;
1107         }
1108
1109         return solidmask;
1110 }
1111
1112 static void addAlphaOverFloatMask(float *dest, float *source, unsigned short dmask, unsigned short smask)
1113 {
1114         unsigned short shared= dmask & smask;
1115         float mul= 1.0f - source[3];
1116         
1117         if (shared) {   /* overlapping masks */
1118                 
1119                 /* masks differ, we make a mixture of 'add' and 'over' */
1120                 if (shared!=dmask) {
1121                         float shared_bits= (float)count_mask(shared);           /* alpha over */
1122                         float tot_bits= (float)count_mask(smask|dmask);         /* alpha add */
1123                         
1124                         float add= (tot_bits - shared_bits)/tot_bits;           /* add level */
1125                         mul= add + (1.0f-add)*mul;
1126                 }
1127         }
1128         else if (dmask && smask) {
1129                 /* works for premul only, of course */
1130                 dest[0]+= source[0];
1131                 dest[1]+= source[1];
1132                 dest[2]+= source[2];
1133                 dest[3]+= source[3];
1134                 
1135                 return;
1136         }
1137
1138         dest[0]= (mul*dest[0]) + source[0];
1139         dest[1]= (mul*dest[1]) + source[1];
1140         dest[2]= (mul*dest[2]) + source[2];
1141         dest[3]= (mul*dest[3]) + source[3];
1142 }
1143
1144 typedef struct ZbufSolidData {
1145         RenderLayer *rl;
1146         ListBase *psmlist;
1147         float *edgerect;
1148 } ZbufSolidData;
1149
1150 static void make_pixelstructs(RenderPart *pa, ZSpan *zspan, int sample, void *data)
1151 {
1152         ZbufSolidData *sdata = (ZbufSolidData *)data;
1153         ListBase *lb= sdata->psmlist;
1154         intptr_t *rd= pa->rectdaps;
1155         const int *ro= zspan->recto;
1156         const int *rp= zspan->rectp;
1157         const int *rz= zspan->rectz;
1158         const int *rm= zspan->rectmask;
1159         int x, y;
1160         int mask= 1<<sample;
1161
1162         for (y=0; y<pa->recty; y++) {
1163                 for (x=0; x<pa->rectx; x++, rd++, rp++, ro++, rz++, rm++) {
1164                         if (*rp) {
1165                                 addps(lb, rd, *ro, *rp, *rz, (zspan->rectmask)? *rm: 0, mask);
1166                         }
1167                 }
1168         }
1169
1170         if (sdata->rl->layflag & SCE_LAY_EDGE) 
1171                 if (R.r.mode & R_EDGE) 
1172                         edge_enhance_tile(pa, sdata->edgerect, zspan->rectz);
1173 }
1174
1175 /* main call for shading Delta Accum, for OSA */
1176 /* supposed to be fully threadable! */
1177 void zbufshadeDA_tile(RenderPart *pa)
1178 {
1179         RenderResult *rr= pa->result;
1180         RenderLayer *rl;
1181         ListBase psmlist= {NULL, NULL};
1182         float *edgerect= NULL;
1183         
1184         /* allocate the necessary buffers */
1185                                 /* zbuffer inits these rects */
1186         pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto");
1187         pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
1188         pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
1189         for (rl= rr->layers.first; rl; rl= rl->next) {
1190                 float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
1191
1192                 if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK))
1193                         pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask");
1194         
1195                 /* initialize pixelstructs and edge buffer */
1196                 addpsmain(&psmlist);
1197                 pa->rectdaps= MEM_callocN(sizeof(intptr_t)*pa->rectx*pa->recty+4, "zbufDArectd");
1198                 
1199                 if (rl->layflag & SCE_LAY_EDGE) 
1200                         if (R.r.mode & R_EDGE) 
1201                                 edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge");
1202                 
1203                 /* always fill visibility */
1204                 for (pa->sample=0; pa->sample<R.osa; pa->sample+=4) {
1205                         ZbufSolidData sdata;
1206
1207                         sdata.rl= rl;
1208                         sdata.psmlist= &psmlist;
1209                         sdata.edgerect= edgerect;
1210                         zbuffer_solid(pa, rl, make_pixelstructs, &sdata);
1211                         if (R.test_break(R.tbh)) break; 
1212                 }
1213                 
1214                 /* shades solid */
1215                 if (rl->layflag & SCE_LAY_SOLID) 
1216                         shadeDA_tile(pa, rl);
1217                 
1218                 /* lamphalo after solid, before ztra, looks nicest because ztra does own halo */
1219                 if (R.flag & R_LAMPHALO)
1220                         if (rl->layflag & SCE_LAY_HALO)
1221                                 lamphalo_tile(pa, rl);
1222                 
1223                 /* halo before ztra, because ztra fills in zbuffer now */
1224                 if (R.flag & R_HALO)
1225                         if (rl->layflag & SCE_LAY_HALO)
1226                                 halo_tile(pa, rl);
1227
1228                 /* transp layer */
1229                 if (R.flag & R_ZTRA || R.totstrand) {
1230                         if (rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) {
1231                                 if (pa->fullresult.first) {
1232                                         zbuffer_transp_shade(pa, rl, rect, &psmlist);
1233                                 }
1234                                 else {
1235                                         unsigned short *ztramask, *solidmask= NULL; /* 16 bits, MAX_OSA */
1236                                         
1237                                         /* allocate, but not free here, for asynchronous display of this rect in main thread */
1238                                         rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer");
1239                                         
1240                                         /* swap for live updates, and it is used in zbuf.c!!! */
1241                                         SWAP(float *, rl->acolrect, rect);
1242                                         ztramask = zbuffer_transp_shade(pa, rl, rect, &psmlist);
1243                                         SWAP(float *, rl->acolrect, rect);
1244                                         
1245                                         /* zbuffer transp only returns ztramask if there's solid rendered */
1246                                         if (ztramask)
1247                                                 solidmask= make_solid_mask(pa);
1248
1249                                         if (ztramask && solidmask) {
1250                                                 unsigned short *sps= solidmask, *spz= ztramask;
1251                                                 unsigned short fullmask= (1<<R.osa)-1;
1252                                                 float *fcol= rect;
1253                                                 float *acol= rl->acolrect;
1254                                                 int x;
1255                                                 
1256                                                 for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4, sps++, spz++) {
1257                                                         if (*sps == fullmask)
1258                                                                 addAlphaOverFloat(fcol, acol);
1259                                                         else
1260                                                                 addAlphaOverFloatMask(fcol, acol, *sps, *spz);
1261                                                 }
1262                                         }
1263                                         else {
1264                                                 float *fcol= rect;
1265                                                 float *acol= rl->acolrect;
1266                                                 int x;
1267                                                 for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) {
1268                                                         addAlphaOverFloat(fcol, acol);
1269                                                 }
1270                                         }
1271                                         if (solidmask) MEM_freeN(solidmask);
1272                                         if (ztramask) MEM_freeN(ztramask);
1273                                 }
1274                         }
1275                 }
1276
1277                 /* sun/sky */
1278                 if (rl->layflag & SCE_LAY_SKY)
1279                         atm_tile(pa, rl);
1280                 
1281                 /* sky before edge */
1282                 if (rl->layflag & SCE_LAY_SKY)
1283                         sky_tile(pa, rl);
1284
1285                 /* extra layers */
1286                 if (rl->layflag & SCE_LAY_EDGE) 
1287                         if (R.r.mode & R_EDGE) 
1288                                 edge_enhance_add(pa, rect, edgerect);
1289                 
1290                 if (rl->passflag & SCE_PASS_VECTOR)
1291                         reset_sky_speed(pa, rl);
1292
1293                 /* clamp alpha to 0..1 range, can go outside due to filter */
1294                 clamp_alpha_rgb_range(pa, rl);
1295                 
1296                 /* free stuff within loop! */
1297                 MEM_freeN(pa->rectdaps); pa->rectdaps= NULL;
1298                 freeps(&psmlist);
1299                 
1300                 if (edgerect) MEM_freeN(edgerect);
1301                 edgerect= NULL;
1302
1303                 if (pa->rectmask) {
1304                         MEM_freeN(pa->rectmask);
1305                         pa->rectmask= NULL;
1306                 }
1307         }
1308         
1309         /* free all */
1310         MEM_freeN(pa->recto); pa->recto= NULL;
1311         MEM_freeN(pa->rectp); pa->rectp= NULL;
1312         MEM_freeN(pa->rectz); pa->rectz= NULL;
1313         
1314         /* display active layer */
1315         rr->renrect.ymin=rr->renrect.ymax = 0;
1316         rr->renlay= render_get_active_layer(&R, rr);
1317 }
1318
1319
1320 /* ------------------------------------------------------------------------ */
1321
1322 /* non OSA case, full tile render */
1323 /* supposed to be fully threadable! */
1324 void zbufshade_tile(RenderPart *pa)
1325 {
1326         ShadeSample ssamp;
1327         RenderResult *rr= pa->result;
1328         RenderLayer *rl;
1329         PixStr ps;
1330         float *edgerect= NULL;
1331         
1332         /* fake pixel struct, to comply to osa render */
1333         ps.next= NULL;
1334         ps.mask= 0xFFFF;
1335         
1336         /* zbuffer code clears/inits rects */
1337         pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto");
1338         pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
1339         pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
1340
1341         for (rl= rr->layers.first; rl; rl= rl->next) {
1342                 float *rect= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
1343                 if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK))
1344                         pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask");
1345
1346                 /* general shader info, passes */
1347                 shade_sample_initialize(&ssamp, pa, rl);
1348                 
1349                 zbuffer_solid(pa, rl, NULL, NULL);
1350                 
1351                 if (!R.test_break(R.tbh)) {     /* NOTE: this if () is not consistent */
1352                         
1353                         /* edges only for solid part, ztransp doesn't support it yet anti-aliased */
1354                         if (rl->layflag & SCE_LAY_EDGE) {
1355                                 if (R.r.mode & R_EDGE) {
1356                                         edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge");
1357                                         edge_enhance_tile(pa, edgerect, pa->rectz);
1358                                 }
1359                         }
1360                         
1361                         /* initialize scanline updates for main thread */
1362                         rr->renrect.ymin = 0;
1363                         rr->renlay= rl;
1364                         
1365                         if (rl->layflag & SCE_LAY_SOLID) {
1366                                 const float *fcol = rect;
1367                                 const int *ro= pa->recto, *rp= pa->rectp, *rz= pa->rectz;
1368                                 int x, y, offs=0, seed;
1369                                 
1370                                 /* we set per pixel a fixed seed, for random AO and shadow samples */
1371                                 seed= pa->rectx*pa->disprect.ymin;
1372                                 
1373                                 /* irregular shadowb buffer creation */
1374                                 if (R.r.mode & R_SHADOW)
1375                                         ISB_create(pa, NULL);
1376
1377                                 if (R.occlusiontree)
1378                                         cache_occ_samples(&R, pa, &ssamp);
1379                                 
1380                                 for (y=pa->disprect.ymin; y<pa->disprect.ymax; y++, rr->renrect.ymax++) {
1381                                         for (x=pa->disprect.xmin; x<pa->disprect.xmax; x++, ro++, rz++, rp++, fcol+=4, offs++) {
1382                                                 /* per pixel fixed seed */
1383                                                 BLI_thread_srandom(pa->thread, seed++);
1384                                                 
1385                                                 if (*rp) {
1386                                                         ps.obi= *ro;
1387                                                         ps.facenr= *rp;
1388                                                         ps.z= *rz;
1389                                                         if (shade_samples(&ssamp, &ps, x, y)) {
1390                                                                 /* combined and passes */
1391                                                                 add_passes(rl, offs, ssamp.shi, ssamp.shr);
1392                                                         }
1393                                                 }
1394                                         }
1395                                         if (y&1)
1396                                                 if (R.test_break(R.tbh)) break; 
1397                                 }
1398                                 
1399                                 if (R.occlusiontree)
1400                                         free_occ_samples(&R, pa);
1401                                 
1402                                 if (R.r.mode & R_SHADOW)
1403                                         ISB_free(pa);
1404                         }
1405                         
1406                         /* disable scanline updating */
1407                         rr->renlay= NULL;
1408                 }
1409                 
1410                 /* lamphalo after solid, before ztra, looks nicest because ztra does own halo */
1411                 if (R.flag & R_LAMPHALO)
1412                         if (rl->layflag & SCE_LAY_HALO)
1413                                 lamphalo_tile(pa, rl);
1414                 
1415                 /* halo before ztra, because ztra fills in zbuffer now */
1416                 if (R.flag & R_HALO)
1417                         if (rl->layflag & SCE_LAY_HALO)
1418                                 halo_tile(pa, rl);
1419                 
1420                 if (R.flag & R_ZTRA || R.totstrand) {
1421                         if (rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) {
1422                                 float *fcol, *acol;
1423                                 int x;
1424                                 
1425                                 /* allocate, but not free here, for asynchronous display of this rect in main thread */
1426                                 rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer");
1427                                 
1428                                 /* swap for live updates */
1429                                 SWAP(float *, rl->acolrect, rect);
1430                                 zbuffer_transp_shade(pa, rl, rect, NULL);
1431                                 SWAP(float *, rl->acolrect, rect);
1432                                 
1433                                 fcol= rect; acol= rl->acolrect;
1434                                 for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) {
1435                                         addAlphaOverFloat(fcol, acol);
1436                                 }
1437                         }
1438                 }
1439                 
1440                 /* sun/sky */
1441                 if (rl->layflag & SCE_LAY_SKY)
1442                         atm_tile(pa, rl);
1443                 
1444                 /* sky before edge */
1445                 if (rl->layflag & SCE_LAY_SKY)
1446                         sky_tile(pa, rl);
1447                 
1448                 if (!R.test_break(R.tbh)) {
1449                         if (rl->layflag & SCE_LAY_EDGE) 
1450                                 if (R.r.mode & R_EDGE)
1451                                         edge_enhance_add(pa, rect, edgerect);
1452                 }
1453                 
1454                 if (rl->passflag & SCE_PASS_VECTOR)
1455                         reset_sky_speed(pa, rl);
1456                 
1457                 if (edgerect) MEM_freeN(edgerect);
1458                 edgerect= NULL;
1459
1460                 if (pa->rectmask) {
1461                         MEM_freeN(pa->rectmask);
1462                         pa->rectmask= NULL;
1463                 }
1464         }
1465
1466         /* display active layer */
1467         rr->renrect.ymin=rr->renrect.ymax = 0;
1468         rr->renlay= render_get_active_layer(&R, rr);
1469         
1470         MEM_freeN(pa->recto); pa->recto= NULL;
1471         MEM_freeN(pa->rectp); pa->rectp= NULL;
1472         MEM_freeN(pa->rectz); pa->rectz= NULL;
1473 }
1474
1475 /* SSS preprocess tile render, fully threadable */
1476 typedef struct ZBufSSSHandle {
1477         RenderPart *pa;
1478         ListBase psmlist;
1479         int totps;
1480 } ZBufSSSHandle;
1481
1482 static void addps_sss(void *cb_handle, int obi, int facenr, int x, int y, int z)
1483 {
1484         ZBufSSSHandle *handle = cb_handle;
1485         RenderPart *pa= handle->pa;
1486
1487         /* extra border for filter gives double samples on part edges,
1488          * don't use those */
1489         if (x<pa->crop || x>=pa->rectx-pa->crop)
1490                 return;
1491         if (y<pa->crop || y>=pa->recty-pa->crop)
1492                 return;
1493         
1494         if (pa->rectall) {
1495                 intptr_t *rs= pa->rectall + pa->rectx*y + x;
1496
1497                 addps(&handle->psmlist, rs, obi, facenr, z, 0, 0);
1498                 handle->totps++;
1499         }
1500         if (pa->rectz) {
1501                 int *rz= pa->rectz + pa->rectx*y + x;
1502                 int *rp= pa->rectp + pa->rectx*y + x;
1503                 int *ro= pa->recto + pa->rectx*y + x;
1504
1505                 if (z < *rz) {
1506                         if (*rp == 0)
1507                                 handle->totps++;
1508                         *rz= z;
1509                         *rp= facenr;
1510                         *ro= obi;
1511                 }
1512         }
1513         if (pa->rectbackz) {
1514                 int *rz= pa->rectbackz + pa->rectx*y + x;
1515                 int *rp= pa->rectbackp + pa->rectx*y + x;
1516                 int *ro= pa->rectbacko + pa->rectx*y + x;
1517
1518                 if (z >= *rz) {
1519                         if (*rp == 0)
1520                                 handle->totps++;
1521                         *rz= z;
1522                         *rp= facenr;
1523                         *ro= obi;
1524                 }
1525         }
1526 }
1527
1528 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[3], float *area)
1529 {
1530         ShadeInput *shi= ssamp->shi;
1531         ShadeResult shr;
1532         float /* texfac,*/ /* UNUSED */ orthoarea, nor[3], alpha, sx, sy;
1533
1534         /* cache for shadow */
1535         shi->samplenr= R.shadowsamplenr[shi->thread]++;
1536         
1537         if (quad) 
1538                 shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3);
1539         else
1540                 shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
1541
1542         /* center pixel */
1543         sx = x + 0.5f;
1544         sy = y + 0.5f;
1545
1546         /* we estimate the area here using shi->dxco and shi->dyco. we need to
1547          * enabled shi->osatex these are filled. we compute two areas, one with
1548          * the normal pointed at the camera and one with the original normal, and
1549          * then clamp to avoid a too large contribution from a single pixel */
1550         shi->osatex= 1;
1551
1552         copy_v3_v3(nor, shi->facenor);
1553         calc_view_vector(shi->facenor, sx, sy);
1554         normalize_v3(shi->facenor);
1555         shade_input_set_viewco(shi, x, y, sx, sy, z);
1556         orthoarea= len_v3(shi->dxco)*len_v3(shi->dyco);
1557
1558         copy_v3_v3(shi->facenor, nor);
1559         shade_input_set_viewco(shi, x, y, sx, sy, z);
1560         *area = min_ff(len_v3(shi->dxco) * len_v3(shi->dyco), 2.0f * orthoarea);
1561
1562         shade_input_set_uv(shi);
1563         shade_input_set_normals(shi);
1564
1565         /* we don't want flipped normals, they screw up back scattering */
1566         if (shi->flippednor)
1567                 shade_input_flip_normals(shi);
1568
1569         /* not a pretty solution, but fixes common cases */
1570         if (shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) {
1571                 negate_v3(shi->vn);
1572                 negate_v3(shi->vno);
1573                 negate_v3(shi->nmapnorm);
1574         }
1575
1576         /* if nodetree, use the material that we are currently preprocessing
1577          * instead of the node material */
1578         if (shi->mat->nodetree && shi->mat->use_nodes)
1579                 shi->mat= mat;
1580
1581         /* init material vars */
1582         shade_input_init_material(shi);
1583         
1584         /* render */
1585         shade_input_set_shade_texco(shi);
1586         
1587         shade_samples_do_AO(ssamp);
1588         shade_material_loop(shi, &shr);
1589         
1590         copy_v3_v3(co, shi->co);
1591         copy_v3_v3(color, shr.combined);
1592
1593         /* texture blending */
1594         /* texfac= shi->mat->sss_texfac; */ /* UNUSED */
1595
1596         alpha= shr.combined[3];
1597         *area *= alpha;
1598 }
1599
1600 static void zbufshade_sss_free(RenderPart *pa)
1601 {
1602 #if 0
1603         MEM_freeN(pa->rectall); pa->rectall= NULL;
1604         freeps(&handle.psmlist);
1605 #else
1606         MEM_freeN(pa->rectz); pa->rectz= NULL;
1607         MEM_freeN(pa->rectp); pa->rectp= NULL;
1608         MEM_freeN(pa->recto); pa->recto= NULL;
1609         MEM_freeN(pa->rectbackz); pa->rectbackz= NULL;
1610         MEM_freeN(pa->rectbackp); pa->rectbackp= NULL;
1611         MEM_freeN(pa->rectbacko); pa->rectbacko= NULL;
1612 #endif
1613 }
1614
1615 void zbufshade_sss_tile(RenderPart *pa)
1616 {
1617         Render *re= &R;
1618         ShadeSample ssamp;
1619         ZBufSSSHandle handle;
1620         RenderResult *rr= pa->result;
1621         RenderLayer *rl;
1622         VlakRen *vlr;
1623         Material *mat= re->sss_mat;
1624         float (*co)[3], (*color)[3], *area, *fcol;
1625         int x, y, seed, quad, totpoint;
1626         const bool display = (re->r.scemode & (R_BUTS_PREVIEW | R_VIEWPORT_PREVIEW)) == 0;
1627         int *ro, *rz, *rp, *rbo, *rbz, *rbp, lay;
1628 #if 0
1629         PixStr *ps;
1630         intptr_t *rs;
1631         int z;
1632 #endif
1633
1634         /* setup pixelstr list and buffer for zbuffering */
1635         handle.pa= pa;
1636         handle.totps= 0;
1637
1638 #if 0
1639         handle.psmlist.first= handle.psmlist.last= NULL;
1640         addpsmain(&handle.psmlist);
1641
1642         pa->rectall= MEM_callocN(sizeof(intptr_t)*pa->rectx*pa->recty+4, "rectall");
1643 #else
1644         pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto");
1645         pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
1646         pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
1647         pa->rectbacko= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbacko");
1648         pa->rectbackp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackp");
1649         pa->rectbackz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackz");
1650 #endif
1651
1652         /* setup shade sample with correct passes */
1653         memset(&ssamp, 0, sizeof(ssamp));
1654         shade_sample_initialize(&ssamp, pa, rr->layers.first);
1655         ssamp.tot= 1;
1656         
1657         for (rl=rr->layers.first; rl; rl=rl->next) {
1658                 ssamp.shi[0].lay |= rl->lay;
1659                 ssamp.shi[0].layflag |= rl->layflag;
1660                 ssamp.shi[0].passflag |= rl->passflag;
1661                 ssamp.shi[0].combinedflag |= ~rl->pass_xor;
1662         }
1663
1664         rl= rr->layers.first;
1665         ssamp.shi[0].passflag |= SCE_PASS_RGBA|SCE_PASS_COMBINED;
1666         ssamp.shi[0].combinedflag &= ~(SCE_PASS_SPEC);
1667         ssamp.shi[0].mat_override= NULL;
1668         ssamp.shi[0].light_override= NULL;
1669         lay= ssamp.shi[0].lay;
1670
1671         /* create the pixelstrs to be used later */
1672         zbuffer_sss(pa, lay, &handle, addps_sss);
1673
1674         if (handle.totps==0) {
1675                 zbufshade_sss_free(pa);
1676                 return;
1677         }
1678         
1679         fcol= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
1680
1681         co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo");
1682         color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor");
1683         area= MEM_mallocN(sizeof(float)*handle.totps, "SSSArea");
1684
1685 #if 0
1686         /* create ISB (does not work currently!) */
1687         if (re->r.mode & R_SHADOW)
1688                 ISB_create(pa, NULL);
1689 #endif
1690
1691         if (display) {
1692                 /* initialize scanline updates for main thread */
1693                 rr->renrect.ymin = 0;
1694                 rr->renlay= rl;
1695         }
1696         
1697         seed= pa->rectx*pa->disprect.ymin;
1698 #if 0
1699         rs= pa->rectall;
1700 #else
1701         rz= pa->rectz;
1702         rp= pa->rectp;
1703         ro= pa->recto;
1704         rbz= pa->rectbackz;
1705         rbp= pa->rectbackp;
1706         rbo= pa->rectbacko;
1707 #endif
1708         totpoint= 0;
1709
1710         for (y=pa->disprect.ymin; y<pa->disprect.ymax; y++, rr->renrect.ymax++) {
1711                 for (x=pa->disprect.xmin; x<pa->disprect.xmax; x++, fcol+=4) {
1712                         /* per pixel fixed seed */
1713                         BLI_thread_srandom(pa->thread, seed++);
1714                         
1715 #if 0
1716                         if (rs) {
1717                                 /* for each sample in this pixel, shade it */
1718                                 for (ps = (PixStr *)(*rs); ps; ps=ps->next) {
1719                                         ObjectInstanceRen *obi= &re->objectinstance[ps->obi];
1720                                         ObjectRen *obr= obi->obr;
1721                                         vlr= RE_findOrAddVlak(obr, (ps->facenr-1) & RE_QUAD_MASK);
1722                                         quad= (ps->facenr & RE_QUAD_OFFS);
1723                                         z= ps->z;
1724
1725                                         shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, z,
1726                                                 co[totpoint], color[totpoint], &area[totpoint]);
1727
1728                                         totpoint++;
1729
1730                                         add_v3_v3(fcol, color);
1731                                         fcol[3]= 1.0f;
1732                                 }
1733
1734                                 rs++;
1735                         }
1736 #else
1737                         if (rp) {
1738                                 if (*rp != 0) {
1739                                         ObjectInstanceRen *obi= &re->objectinstance[*ro];
1740                                         ObjectRen *obr= obi->obr;
1741
1742                                         /* shade front */
1743                                         vlr= RE_findOrAddVlak(obr, (*rp-1) & RE_QUAD_MASK);
1744                                         quad= ((*rp) & RE_QUAD_OFFS);
1745
1746                                         shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, *rz,
1747                                                 co[totpoint], color[totpoint], &area[totpoint]);
1748                                         
1749                                         add_v3_v3(fcol, color[totpoint]);
1750                                         fcol[3]= 1.0f;
1751                                         totpoint++;
1752                                 }
1753
1754                                 rp++; rz++; ro++;
1755                         }
1756
1757                         if (rbp) {
1758                                 if (*rbp != 0 && !(*rbp == *(rp-1) && *rbo == *(ro-1))) {
1759                                         ObjectInstanceRen *obi= &re->objectinstance[*rbo];
1760                                         ObjectRen *obr= obi->obr;
1761
1762                                         /* shade back */
1763                                         vlr= RE_findOrAddVlak(obr, (*rbp-1) & RE_QUAD_MASK);
1764                                         quad= ((*rbp) & RE_QUAD_OFFS);
1765
1766                                         shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, *rbz,
1767                                                 co[totpoint], color[totpoint], &area[totpoint]);
1768                                         
1769                                         /* to indicate this is a back sample */
1770                                         area[totpoint]= -area[totpoint];
1771
1772                                         add_v3_v3(fcol, color[totpoint]);
1773                                         fcol[3]= 1.0f;
1774                                         totpoint++;
1775                                 }
1776
1777                                 rbz++; rbp++; rbo++;
1778                         }
1779 #endif
1780                 }
1781
1782                 if (y&1)
1783                         if (re->test_break(re->tbh)) break; 
1784         }
1785
1786         /* note: after adding we do not free these arrays, sss keeps them */
1787         if (totpoint > 0) {
1788                 sss_add_points(re, co, color, area, totpoint);
1789         }
1790         else {
1791                 MEM_freeN(co);
1792                 MEM_freeN(color);
1793                 MEM_freeN(area);
1794         }
1795         
1796 #if 0
1797         if (re->r.mode & R_SHADOW)
1798                 ISB_free(pa);
1799 #endif
1800                 
1801         if (display) {
1802                 /* display active layer */
1803                 rr->renrect.ymin=rr->renrect.ymax = 0;
1804                 rr->renlay= render_get_active_layer(&R, rr);
1805         }
1806         
1807         zbufshade_sss_free(pa);
1808 }
1809
1810 /* ------------------------------------------------------------------------ */
1811
1812 static void renderhalo_post(RenderResult *rr, float *rectf, HaloRen *har)       /* postprocess version */
1813 {
1814         float dist, xsq, ysq, xn, yn, colf[4], *rectft, *rtf;
1815         float haloxs, haloys;
1816         int minx, maxx, miny, maxy, x, y;
1817
1818         /* calculate the disprect mapped coordinate for halo. note: rectx is disprect corrected */
1819         haloxs= har->xs - R.disprect.xmin;
1820         haloys= har->ys - R.disprect.ymin;
1821         
1822         har->miny= miny= haloys - har->rad/R.ycor;
1823         har->maxy= maxy= haloys + har->rad/R.ycor;
1824         
1825         if (maxy < 0) {
1826                 /* pass */
1827         }
1828         else if (rr->recty < miny) {
1829                 /* pass */
1830         }
1831         else {
1832                 minx = floor(haloxs - har->rad);
1833                 maxx = ceil(haloxs + har->rad);
1834                         
1835                 if (maxx < 0) {
1836                         /* pass */
1837                 }
1838                 else if (rr->rectx < minx) {
1839                         /* pass */
1840                 }
1841                 else {
1842                         if (minx<0) minx= 0;
1843                         if (maxx>=rr->rectx) maxx= rr->rectx-1;
1844                         if (miny<0) miny= 0;
1845                         if (maxy>rr->recty) maxy= rr->recty;
1846         
1847                         rectft= rectf+ 4*rr->rectx*miny;
1848
1849                         for (y=miny; y<maxy; y++) {
1850         
1851                                 rtf= rectft+4*minx;
1852                                 
1853                                 yn= (y - haloys)*R.ycor;
1854                                 ysq= yn*yn;
1855                                 
1856                                 for (x=minx; x<=maxx; x++) {
1857                                         xn= x - haloxs;
1858                                         xsq= xn*xn;
1859                                         dist= xsq+ysq;
1860                                         if (dist<har->radsq) {
1861                                                 
1862                                                 if (shadeHaloFloat(har, colf, 0x7FFFFF, dist, xn, yn, har->flarec))
1863                                                         addalphaAddfacFloat(rtf, colf, har->add);
1864                                         }
1865                                         rtf+=4;
1866                                 }
1867         
1868                                 rectft+= 4*rr->rectx;
1869                                 
1870                                 if (R.test_break(R.tbh)) break; 
1871                         }
1872                 }
1873         }
1874
1875 /* ------------------------------------------------------------------------ */
1876
1877 static void renderflare(RenderResult *rr, float *rectf, HaloRen *har)
1878 {
1879         extern const float hashvectf[];
1880         HaloRen fla;
1881         Material *ma;
1882         const float *rc;
1883         float rad, alfa, visifac, vec[3];
1884         int b, type;
1885         
1886         fla= *har;
1887         fla.linec= fla.ringc= fla.flarec= 0;
1888         
1889         rad= har->rad;
1890         alfa= har->alfa;
1891         
1892         visifac= R.ycor*(har->pixels);
1893         /* all radials added / r^3 == 1.0f! */
1894         visifac /= (har->rad*har->rad*har->rad);
1895         visifac*= visifac;
1896
1897         ma= har->mat;
1898         
1899         /* first halo: just do */
1900         
1901         har->rad= rad*ma->flaresize*visifac;
1902         har->radsq= har->rad*har->rad;
1903         har->zs= fla.zs= 0;
1904         
1905         har->alfa= alfa*visifac;
1906
1907         renderhalo_post(rr, rectf, har);
1908         
1909         /* next halo's: the flares */
1910         rc= hashvectf + ma->seed2;
1911         
1912         for (b=1; b<har->flarec; b++) {
1913                 
1914                 fla.r = fabsf(rc[0]);
1915                 fla.g = fabsf(rc[1]);
1916                 fla.b = fabsf(rc[2]);
1917                 fla.alfa= ma->flareboost*fabsf(alfa*visifac*rc[3]);
1918                 fla.hard= 20.0f + fabsf(70.0f*rc[7]);
1919                 fla.tex= 0;
1920                 
1921                 type= (int)(fabsf(3.9f*rc[6]));
1922
1923                 fla.rad = ma->subsize * sqrtf(fabsf(2.0f * har->rad * rc[4]));
1924                 
1925                 if (type==3) {
1926                         fla.rad*= 3.0f;
1927                         fla.rad+= R.rectx/10;
1928                 }
1929                 
1930                 fla.radsq= fla.rad*fla.rad;
1931                 
1932                 vec[0]= 1.4f*rc[5]*(har->xs-R.winx/2);
1933                 vec[1]= 1.4f*rc[5]*(har->ys-R.winy/2);
1934                 vec[2]= 32.0f*sqrtf(vec[0]*vec[0] + vec[1]*vec[1] + 1.0f);
1935                 
1936                 fla.xs= R.winx/2 + vec[0] + (1.2f+rc[8])*R.rectx*vec[0]/vec[2];
1937                 fla.ys= R.winy/2 + vec[1] + (1.2f+rc[8])*R.rectx*vec[1]/vec[2];
1938
1939                 if (R.flag & R_SEC_FIELD) {
1940                         if (R.r.mode & R_ODDFIELD) fla.ys += 0.5f;
1941                         else fla.ys -= 0.5f;
1942                 }
1943                 if (type & 1) fla.type= HA_FLARECIRC;
1944                 else fla.type= 0;
1945                 renderhalo_post(rr, rectf, &fla);
1946
1947                 fla.alfa*= 0.5f;
1948                 if (type & 2) fla.type= HA_FLARECIRC;
1949                 else fla.type= 0;
1950                 renderhalo_post(rr, rectf, &fla);
1951                 
1952                 rc+= 7;
1953         }
1954 }
1955
1956 /* needs recode... integrate this better! */
1957 void add_halo_flare(Render *re)
1958 {
1959         RenderResult *rr= re->result;
1960         RenderLayer *rl;
1961         HaloRen *har;
1962         int a, mode;
1963         float *rect;
1964         
1965         /* for now, we get the first renderlayer in list with halos set */
1966         for (rl= rr->layers.first; rl; rl= rl->next) {
1967                 bool do_draw = false;
1968                 
1969                 if ((rl->layflag & SCE_LAY_HALO) == 0)
1970                         continue;
1971
1972                 rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname);
1973
1974                 if (rl==NULL || rect)
1975                         return;
1976                 
1977                 mode= R.r.mode;
1978                 R.r.mode &= ~R_PANORAMA;
1979                 
1980                 project_renderdata(&R, projectverto, 0, 0, 0);
1981                 
1982                 for (a=0; a<R.tothalo; a++) {
1983                         har= R.sortedhalos[a];
1984                         
1985                         if (har->flarec && (har->lay & rl->lay)) {
1986                                 do_draw = true;
1987                                 renderflare(rr, rect, har);
1988                         }
1989                 }
1990                 
1991                 if (do_draw) {
1992                         /* weak... the display callback wants an active renderlayer pointer... */
1993                         rr->renlay= rl;
1994                         re->display_update(re->duh, rr, NULL);
1995                 }
1996
1997                 R.r.mode= mode;
1998         }
1999 }
2000