Patch #8034: "soft" option for halos, which avoids ugly intersections
[plumiferos.git] / source / blender / render / intern / source / rendercore.c
bloba550b552d16c4d4446a14574dbe2910a84219531
1 /**
2 * $Id: rendercore.c 12781 2007-12-04 15:11:33Z blendix $
4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * Contributors: Hos, Robert Wenzlaff.
24 * Contributors: 2004/2005/2006 Blender Foundation, full recode
26 * ***** END GPL LICENSE BLOCK *****
29 /* system includes */
30 #include <stdio.h>
31 #include <math.h>
32 #include <string.h>
34 /* External modules: */
35 #include "MEM_guardedalloc.h"
37 #include "BLI_arithb.h"
38 #include "BLI_blenlib.h"
39 #include "BLI_jitter.h"
40 #include "BLI_rand.h"
41 #include "BLI_threads.h"
43 #include "BKE_utildefines.h"
45 #include "DNA_image_types.h"
46 #include "DNA_lamp_types.h"
47 #include "DNA_material_types.h"
48 #include "DNA_meshdata_types.h"
50 #include "BKE_global.h"
51 #include "BKE_image.h"
52 #include "BKE_main.h"
53 #include "BKE_node.h"
54 #include "BKE_texture.h"
56 #include "IMB_imbuf_types.h"
57 #include "IMB_imbuf.h"
59 /* local include */
60 #include "renderpipeline.h"
61 #include "render_types.h"
62 #include "renderdatabase.h"
63 #include "pixelblending.h"
64 #include "pixelshading.h"
65 #include "shadbuf.h"
66 #include "shading.h"
67 #include "sss.h"
68 #include "zbuf.h"
70 #include "PIL_time.h"
72 /* own include */
73 #include "rendercore.h"
76 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
77 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
78 /* only to be used here in this file, it's for speed */
79 extern struct Render R;
80 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
82 /* x and y are current pixels in rect to be rendered */
83 /* do not normalize! */
84 void calc_view_vector(float *view, float x, float y)
87 view[2]= -ABS(R.clipsta);
89 if(R.r.mode & R_ORTHO) {
90 view[0]= view[1]= 0.0f;
92 else {
94 if(R.r.mode & R_PANORAMA)
95 x-= R.panodxp;
97 /* move x and y to real viewplane coords */
98 x= (x/(float)R.winx);
99 view[0]= R.viewplane.xmin + x*(R.viewplane.xmax - R.viewplane.xmin);
101 y= (y/(float)R.winy);
102 view[1]= R.viewplane.ymin + y*(R.viewplane.ymax - R.viewplane.ymin);
104 // if(R.flag & R_SEC_FIELD) {
105 // if(R.r.mode & R_ODDFIELD) view[1]= (y+R.ystart)*R.ycor;
106 // else view[1]= (y+R.ystart+1.0)*R.ycor;
107 // }
108 // else view[1]= (y+R.ystart+R.bluroffsy+0.5)*R.ycor;
110 if(R.r.mode & R_PANORAMA) {
111 float u= view[0] + R.panodxv; float v= view[2];
112 view[0]= R.panoco*u + R.panosi*v;
113 view[2]= -R.panosi*u + R.panoco*v;
118 void calc_renderco_ortho(float *co, float x, float y, int z)
120 /* x and y 3d coordinate can be derived from pixel coord and winmat */
121 float fx= 2.0f/(R.winx*R.winmat[0][0]);
122 float fy= 2.0f/(R.winy*R.winmat[1][1]);
123 float zco;
125 co[0]= (x - 0.5f*R.winx)*fx - R.winmat[3][0]/R.winmat[0][0];
126 co[1]= (y - 0.5f*R.winy)*fy - R.winmat[3][1]/R.winmat[1][1];
128 zco= ((float)z)/2147483647.0f;
129 co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] );
132 void calc_renderco_zbuf(float *co, float *view, int z)
134 float fac, zco;
136 /* inverse of zbuf calc: zbuf = MAXZ*hoco_z/hoco_w */
137 zco= ((float)z)/2147483647.0f;
138 co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] );
140 fac= co[2]/view[2];
141 co[0]= fac*view[0];
142 co[1]= fac*view[1];
145 /* also used in zbuf.c and shadbuf.c */
146 int count_mask(unsigned short mask)
148 if(R.samples)
149 return (R.samples->cmask[mask & 255]+R.samples->cmask[mask>>8]);
150 return 0;
153 static int calchalo_z(HaloRen *har, int zz)
156 if(har->type & HA_ONLYSKY) {
157 if(zz!=0x7FFFFFFF) zz= - 0x7FFFFF;
159 else {
160 zz= (zz>>8);
162 return zz;
165 static void halo_pixelstruct(HaloRen *har, float *rb, float dist, float xn, float yn, PixStr *ps)
167 float col[4], accol[4], fac;
168 int amount, amountm, zz, flarec;
170 amount= 0;
171 accol[0]=accol[1]=accol[2]=accol[3]= 0.0f;
172 flarec= har->flarec;
174 while(ps) {
175 amountm= count_mask(ps->mask);
176 amount+= amountm;
178 zz= calchalo_z(har, ps->z);
179 if((zz> har->zs) && (har->mat->mode & MA_HALO_SOFT)) {
180 if (shadeHaloFloat(har, col, zz, dist, xn, yn, flarec)) {
181 flarec= 0;
183 fac= ((float)amountm)/(float)R.osa;
184 accol[0]+= fac*col[0];
185 accol[1]+= fac*col[1];
186 accol[2]+= fac*col[2];
187 accol[3]+= fac*col[3];
191 ps= ps->next;
193 /* now do the sky sub-pixels */
194 amount= R.osa-amount;
195 if(amount) {
196 if (shadeHaloFloat(har, col, 0x7FFFFF, dist, xn, yn, flarec)) {
197 fac= ((float)amount)/(float)R.osa;
198 accol[0]+= fac*col[0];
199 accol[1]+= fac*col[1];
200 accol[2]+= fac*col[2];
201 accol[3]+= fac*col[3];
204 col[0]= accol[0];
205 col[1]= accol[1];
206 col[2]= accol[2];
207 col[3]= accol[3];
209 addalphaAddfacFloat(rb, col, har->add);
213 static void halo_tile(RenderPart *pa, float *pass, unsigned int lay)
215 HaloRen *har = NULL;
216 rcti disprect= pa->disprect, testrect= pa->disprect;
217 float dist, xsq, ysq, xn, yn, *rb;
218 float col[4];
219 long *rd= NULL;
220 int a, *rz, zz, y;
221 short minx, maxx, miny, maxy, x;
223 /* we don't render halos in the cropped area, gives errors in flare counter */
224 if(pa->crop) {
225 testrect.xmin+= pa->crop;
226 testrect.xmax-= pa->crop;
227 testrect.ymin+= pa->crop;
228 testrect.ymax-= pa->crop;
231 for(a=0; a<R.tothalo; a++) {
232 if((a & 255)==0)
233 har= R.bloha[a>>8];
234 else har++;
236 /* layer test, clip halo with y */
237 if((har->lay & lay)==0);
238 else if(testrect.ymin > har->maxy);
239 else if(testrect.ymax < har->miny);
240 else {
242 minx= floor(har->xs-har->rad);
243 maxx= ceil(har->xs+har->rad);
245 if(testrect.xmin > maxx);
246 else if(testrect.xmax < minx);
247 else {
249 minx= MAX2(minx, testrect.xmin);
250 maxx= MIN2(maxx, testrect.xmax);
252 miny= MAX2(har->miny, testrect.ymin);
253 maxy= MIN2(har->maxy, testrect.ymax);
255 for(y=miny; y<maxy; y++) {
256 int rectofs= (y-disprect.ymin)*pa->rectx + (minx - disprect.xmin);
257 rb= pass + 4*rectofs;
258 rz= pa->rectz + rectofs;
260 if(pa->rectdaps)
261 rd= pa->rectdaps + rectofs;
263 yn= (y-har->ys)*R.ycor;
264 ysq= yn*yn;
266 for(x=minx; x<maxx; x++, rb+=4, rz++) {
267 xn= x- har->xs;
268 xsq= xn*xn;
269 dist= xsq+ysq;
270 if(dist<har->radsq) {
271 if(rd && *rd) {
272 halo_pixelstruct(har, rb, dist, xn, yn, (PixStr *)*rd);
274 else {
275 zz= calchalo_z(har, *rz);
276 if((zz> har->zs) || (har->mat->mode & MA_HALO_SOFT)) {
277 if(shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec))
278 addalphaAddfacFloat(rb, col, har->add);
282 if(rd) rd++;
287 if(R.test_break() ) break;
291 static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
293 ShadeInput shi;
294 float *pass= rl->rectf;
295 float fac;
296 long *rd= pa->rectdaps;
297 int x, y, *rz= pa->rectz;
299 shade_input_initialize(&shi, pa, rl, 0);
301 for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) {
302 for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, rz++, pass+=4) {
304 calc_view_vector(shi.view, x, y);
306 if(rd && *rd) {
307 PixStr *ps= (PixStr *)*rd;
308 int samp, totsamp= 0;
310 while(ps) {
311 if(R.r.mode & R_ORTHO)
312 calc_renderco_ortho(shi.co, (float)x, (float)y, ps->z);
313 else
314 calc_renderco_zbuf(shi.co, shi.view, ps->z);
316 totsamp+= samp= count_mask(ps->mask);
317 fac= ((float)samp)/(float)R.osa;
318 renderspothalo(&shi, pass, fac);
319 ps= ps->next;
321 if(totsamp<R.osa) {
322 fac= ((float)R.osa-totsamp)/(float)R.osa;
323 shi.co[2]= 0.0f;
324 renderspothalo(&shi, pass, fac);
327 else {
328 if(R.r.mode & R_ORTHO)
329 calc_renderco_ortho(shi.co, (float)x, (float)y, *rz);
330 else
331 calc_renderco_zbuf(shi.co, shi.view, *rz);
333 renderspothalo(&shi, pass, 1.0f);
336 if(rd) rd++;
338 if(y&1)
339 if(R.test_break()) break;
344 /* ********************* MAINLOOPS ******************** */
346 /* osa version */
347 static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, ShadeInput *shi, ShadeResult *shr)
349 RenderPass *rpass;
351 for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
352 float *fp, *col= NULL;
353 int pixsize= 3;
355 switch(rpass->passtype) {
356 case SCE_PASS_RGBA:
357 col= shr->col;
358 pixsize= 4;
359 break;
360 case SCE_PASS_DIFFUSE:
361 col= shr->diff;
362 break;
363 case SCE_PASS_SPEC:
364 col= shr->spec;
365 break;
366 case SCE_PASS_SHADOW:
367 col= shr->shad;
368 break;
369 case SCE_PASS_AO:
370 col= shr->ao;
371 break;
372 case SCE_PASS_REFLECT:
373 col= shr->refl;
374 break;
375 case SCE_PASS_REFRACT:
376 col= shr->refr;
377 break;
378 case SCE_PASS_RADIO:
379 col= shr->rad;
380 break;
381 case SCE_PASS_NORMAL:
382 col= shr->nor;
383 break;
384 case SCE_PASS_UV:
385 /* box filter only, gauss will screwup UV too much */
386 if(shi->totuv) {
387 float mult= (float)count_mask(curmask)/(float)R.osa;
388 fp= rpass->rect + 3*offset;
389 fp[0]+= mult*(0.5f + 0.5f*shi->uv[0].uv[0]);
390 fp[1]+= mult*(0.5f + 0.5f*shi->uv[0].uv[1]);
391 fp[2]+= mult;
393 break;
394 case SCE_PASS_INDEXOB:
395 /* no filter */
396 if(shi->vlr) {
397 fp= rpass->rect + offset;
398 if(*fp==0.0f)
399 *fp= (float)shi->vlr->ob->index;
401 break;
402 case SCE_PASS_INDEXMAT:
403 /* no filter */
404 if(shi->vlr) {
405 fp= rpass->rect + offset;
406 if(*fp==0.0f)
407 *fp= (float)shi->vlr->mat->index;
409 break;
410 case SCE_PASS_MIST:
411 /* */
412 col= &shr->mist;
413 pixsize= 1;
414 break;
416 case SCE_PASS_VECTOR:
418 /* add minimum speed in pixel, no filter */
419 fp= rpass->rect + 4*offset;
420 if( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) {
421 fp[0]= shr->winspeed[0];
422 fp[1]= shr->winspeed[1];
424 if( (ABS(shr->winspeed[2]) + ABS(shr->winspeed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) {
425 fp[2]= shr->winspeed[2];
426 fp[3]= shr->winspeed[3];
429 break;
431 if(col) {
432 fp= rpass->rect + pixsize*offset;
433 add_filt_fmask_pixsize(curmask, col, fp, rectx, pixsize);
438 /* non-osa version */
439 static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult *shr)
441 RenderPass *rpass;
443 for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
444 float *fp, *col= NULL, uvcol[3];
445 int a, pixsize= 3;
447 switch(rpass->passtype) {
448 case SCE_PASS_RGBA:
449 col= shr->col;
450 pixsize= 4;
451 break;
452 case SCE_PASS_DIFFUSE:
453 col= shr->diff;
454 break;
455 case SCE_PASS_SPEC:
456 col= shr->spec;
457 break;
458 case SCE_PASS_SHADOW:
459 col= shr->shad;
460 break;
461 case SCE_PASS_AO:
462 col= shr->ao;
463 break;
464 case SCE_PASS_REFLECT:
465 col= shr->refl;
466 break;
467 case SCE_PASS_REFRACT:
468 col= shr->refr;
469 break;
470 case SCE_PASS_RADIO:
471 col= shr->rad;
472 break;
473 case SCE_PASS_NORMAL:
474 col= shr->nor;
475 break;
476 case SCE_PASS_UV:
477 if(shi->totuv) {
478 uvcol[0]= 0.5f + 0.5f*shi->uv[0].uv[0];
479 uvcol[1]= 0.5f + 0.5f*shi->uv[0].uv[1];
480 uvcol[2]= 1.0f;
481 col= uvcol;
483 break;
484 case SCE_PASS_VECTOR:
485 col= shr->winspeed;
486 pixsize= 4;
487 break;
488 case SCE_PASS_INDEXOB:
489 if(shi->vlr) {
490 fp= rpass->rect + offset;
491 *fp= (float)shi->vlr->ob->index;
493 break;
494 case SCE_PASS_INDEXMAT:
495 if(shi->vlr) {
496 fp= rpass->rect + offset;
497 *fp= (float)shi->vlr->mat->index;
499 break;
500 case SCE_PASS_MIST:
501 fp= rpass->rect + offset;
502 *fp= shr->mist;
503 break;
505 if(col) {
506 fp= rpass->rect + pixsize*offset;
507 for(a=0; a<pixsize; a++)
508 fp[a]= col[a];
513 /* only do sky, is default in the solid layer (shade_tile) btw */
514 static void sky_tile(RenderPart *pa, float *pass)
516 float col[4];
517 int x, y;
519 if(R.r.alphamode!=R_ADDSKY)
520 return;
522 for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) {
523 for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, pass+=4) {
524 if(pass[3]<1.0f) {
525 if(pass[3]==0.0f)
526 shadeSkyPixel(pass, x, y);
527 else {
528 shadeSkyPixel(col, x, y);
529 addAlphaOverFloat(col, pass);
530 QUATCOPY(pass, col);
535 if(y&1)
536 if(R.test_break()) break;
540 static void shadeDA_tile(RenderPart *pa, RenderLayer *rl)
542 RenderResult *rr= pa->result;
543 ShadeSample ssamp;
544 float *fcol, *rf, *rectf= rl->rectf;
545 long *rd, *rectdaps= pa->rectdaps;
546 int samp;
547 int x, y, seed, crop=0, offs=0, od, addpassflag;
549 if(R.test_break()) return;
551 /* irregular shadowb buffer creation */
552 if(R.r.mode & R_SHADOW)
553 ISB_create(pa, NULL);
555 /* we set per pixel a fixed seed, for random AO and shadow samples */
556 seed= pa->rectx*pa->disprect.ymin;
558 /* general shader info, passes */
559 shade_sample_initialize(&ssamp, pa, rl);
560 addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
562 /* filtered render, for now we assume only 1 filter size */
563 if(pa->crop) {
564 crop= 1;
565 rectf+= 4*(pa->rectx + 1);
566 rectdaps+= pa->rectx + 1;
567 offs= pa->rectx + 1;
570 /* scanline updates have to be 2 lines behind */
571 rr->renrect.ymin= 0;
572 rr->renrect.ymax= -2*crop;
573 rr->renlay= rl;
575 for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) {
576 rf= rectf;
577 rd= rectdaps;
578 od= offs;
580 for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, rd++, rf+=4, od++) {
581 BLI_thread_srandom(pa->thread, seed++);
583 if(*rd) {
584 if(shade_samples(&ssamp, (PixStr *)(*rd), x, y)) {
585 for(samp=0; samp<ssamp.tot; samp++) {
587 fcol= ssamp.shr[samp].combined;
588 add_filt_fmask(ssamp.shi[samp].mask, fcol, rf, pa->rectx);
590 if(addpassflag)
591 add_filt_passes(rl, ssamp.shi[samp].mask, pa->rectx, od, &ssamp.shi[samp], &ssamp.shr[samp]);
597 rectf+= 4*pa->rectx;
598 rectdaps+= pa->rectx;
599 offs+= pa->rectx;
601 if(y&1) if(R.test_break()) break;
604 /* disable scanline updating */
605 rr->renlay= NULL;
607 if(R.r.mode & R_SHADOW)
608 ISB_free(pa);
611 /* ************* pixel struct ******** */
614 static PixStrMain *addpsmain(ListBase *lb)
616 PixStrMain *psm;
618 psm= (PixStrMain *)MEM_mallocN(sizeof(PixStrMain),"pixstrMain");
619 BLI_addtail(lb, psm);
621 psm->ps= (PixStr *)MEM_mallocN(4096*sizeof(PixStr),"pixstr");
622 psm->counter= 0;
624 return psm;
627 static void freeps(ListBase *lb)
629 PixStrMain *psm, *psmnext;
631 for(psm= lb->first; psm; psm= psmnext) {
632 psmnext= psm->next;
633 if(psm->ps)
634 MEM_freeN(psm->ps);
635 MEM_freeN(psm);
637 lb->first= lb->last= NULL;
640 static void addps(ListBase *lb, long *rd, int facenr, int z, unsigned short mask)
642 PixStrMain *psm;
643 PixStr *ps, *last= NULL;
645 if(*rd) {
646 ps= (PixStr *)(*rd);
648 while(ps) {
649 if( ps->facenr == facenr ) {
650 ps->mask |= mask;
651 return;
653 last= ps;
654 ps= ps->next;
658 /* make new PS (pixel struct) */
659 psm= lb->last;
661 if(psm->counter==4095)
662 psm= addpsmain(lb);
664 ps= psm->ps + psm->counter++;
666 if(last) last->next= ps;
667 else *rd= (long)ps;
669 ps->next= NULL;
670 ps->facenr= facenr;
671 ps->z= z;
672 ps->mask = mask;
673 ps->shadfac= 0;
676 static void make_pixelstructs(RenderPart *pa, ListBase *lb)
678 long *rd= pa->rectdaps;
679 int *rp= pa->rectp;
680 int *rz= pa->rectz;
681 int x, y;
682 int mask= 1<<pa->sample;
684 for(y=0; y<pa->recty; y++) {
685 for(x=0; x<pa->rectx; x++, rd++, rp++) {
686 if(*rp) {
687 addps(lb, rd, *rp, *(rz+x), mask);
690 rz+= pa->rectx;
694 static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect)
696 float addcol[4];
697 int pix;
699 if(arect==NULL)
700 return;
702 for(pix= pa->rectx*pa->recty; pix>0; pix--, arect++, rectf+=4) {
703 if(*arect != 0.0f) {
704 addcol[0]= *arect * R.r.edgeR;
705 addcol[1]= *arect * R.r.edgeG;
706 addcol[2]= *arect * R.r.edgeB;
707 addcol[3]= *arect;
708 addAlphaOverFloat(rectf, addcol);
714 static void convert_to_key_alpha(RenderPart *pa, float *rectf)
716 int y;
718 for(y= pa->rectx*pa->recty; y>0; y--, rectf+=4) {
719 if(rectf[3] >= 1.0f);
720 else if(rectf[3] > 0.0f) {
721 rectf[0] /= rectf[3];
722 rectf[1] /= rectf[3];
723 rectf[2] /= rectf[3];
728 /* adds only alpha values */
729 static void edge_enhance_tile(RenderPart *pa, float *rectf)
731 /* use zbuffer to define edges, add it to the image */
732 int y, x, col, *rz, *rz1, *rz2, *rz3;
733 int zval1, zval2, zval3;
734 float *rf;
736 /* shift values in zbuffer 4 to the right (anti overflows), for filter we need multiplying with 12 max */
737 rz= pa->rectz;
738 if(rz==NULL) return;
740 for(y=0; y<pa->recty; y++)
741 for(x=0; x<pa->rectx; x++, rz++) (*rz)>>= 4;
743 rz1= pa->rectz;
744 rz2= rz1+pa->rectx;
745 rz3= rz2+pa->rectx;
747 rf= rectf+pa->rectx+1;
749 for(y=0; y<pa->recty-2; y++) {
750 for(x=0; x<pa->rectx-2; x++, rz1++, rz2++, rz3++, rf++) {
752 /* prevent overflow with sky z values */
753 zval1= rz1[0] + 2*rz1[1] + rz1[2];
754 zval2= 2*rz2[0] + 2*rz2[2];
755 zval3= rz3[0] + 2*rz3[1] + rz3[2];
757 col= ( 4*rz2[1] - (zval1 + zval2 + zval3)/3 );
758 if(col<0) col= -col;
760 col >>= 5;
761 if(col > (1<<16)) col= (1<<16);
762 else col= (R.r.edgeint*col)>>8;
764 if(col>0) {
765 float fcol;
767 if(col>255) fcol= 1.0f;
768 else fcol= (float)col/255.0f;
770 if(R.osa)
771 *rf+= fcol/(float)R.osa;
772 else
773 *rf= fcol;
776 rz1+= 2;
777 rz2+= 2;
778 rz3+= 2;
779 rf+= 2;
782 /* shift back zbuf values, we might need it still */
783 rz= pa->rectz;
784 for(y=0; y<pa->recty; y++)
785 for(x=0; x<pa->rectx; x++, rz++) (*rz)<<= 4;
789 static void reset_sky_speed(RenderPart *pa, RenderLayer *rl)
791 /* for all pixels with max speed, set to zero */
792 float *fp;
793 int a;
795 fp= RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR);
796 if(fp==NULL) return;
798 for(a= 4*pa->rectx*pa->recty - 1; a>=0; a--)
799 if(fp[a] == PASS_VECTOR_MAX) fp[a]= 0.0f;
803 static unsigned short *make_solid_mask(RenderPart *pa)
805 long *rd= pa->rectdaps;
806 unsigned short *solidmask, *sp;
807 int x;
809 if(rd==NULL) return NULL;
811 sp=solidmask= MEM_mallocN(sizeof(short)*pa->rectx*pa->recty, "solidmask");
813 for(x=pa->rectx*pa->recty; x>0; x--, rd++, sp++) {
814 if(*rd) {
815 PixStr *ps= (PixStr *)*rd;
817 *sp= ps->mask;
818 for(ps= ps->next; ps; ps= ps->next)
819 *sp |= ps->mask;
821 else
822 *sp= 0;
825 return solidmask;
828 static void addAlphaOverFloatMask(float *dest, float *source, unsigned short dmask, unsigned short smask)
830 unsigned short shared= dmask & smask;
831 float mul= 1.0 - source[3];
833 if(shared) { /* overlapping masks */
835 /* masks differ, we make a mixture of 'add' and 'over' */
836 if(shared!=dmask) {
837 float shared_bits= (float)count_mask(shared); /* alpha over */
838 float tot_bits= (float)count_mask(smask|dmask); /* alpha add */
840 float add= (tot_bits - shared_bits)/tot_bits; /* add level */
841 mul= add + (1.0f-add)*mul;
844 else if(dmask && smask) {
845 /* works for premul only, of course */
846 dest[0]+= source[0];
847 dest[1]+= source[1];
848 dest[2]+= source[2];
849 dest[3]+= source[3];
851 return;
854 dest[0]= (mul*dest[0]) + source[0];
855 dest[1]= (mul*dest[1]) + source[1];
856 dest[2]= (mul*dest[2]) + source[2];
857 dest[3]= (mul*dest[3]) + source[3];
861 /* main call for shading Delta Accum, for OSA */
862 /* supposed to be fully threadable! */
863 void zbufshadeDA_tile(RenderPart *pa)
865 RenderResult *rr= pa->result;
866 RenderLayer *rl;
867 ListBase psmlist= {NULL, NULL};
868 float *edgerect= NULL;
870 set_part_zbuf_clipflag(pa);
872 /* allocate the necessary buffers */
873 /* zbuffer inits these rects */
874 pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
875 pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
877 for(rl= rr->layers.first; rl; rl= rl->next) {
879 /* initialize pixelstructs and edge buffer */
880 addpsmain(&psmlist);
881 pa->rectdaps= MEM_callocN(sizeof(long)*pa->rectx*pa->recty+4, "zbufDArectd");
883 if(rl->layflag & SCE_LAY_EDGE)
884 if(R.r.mode & R_EDGE)
885 edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge");
887 /* always fill visibility */
888 for(pa->sample=0; pa->sample<R.osa; pa->sample++) {
889 zbuffer_solid(pa, rl->lay, rl->layflag);
890 make_pixelstructs(pa, &psmlist);
892 if(rl->layflag & SCE_LAY_EDGE)
893 if(R.r.mode & R_EDGE)
894 edge_enhance_tile(pa, edgerect);
896 if(R.test_break()) break;
899 /* shades solid */
900 if(rl->layflag & SCE_LAY_SOLID)
901 shadeDA_tile(pa, rl);
903 /* lamphalo after solid, before ztra, looks nicest because ztra does own halo */
904 if(R.flag & R_LAMPHALO)
905 if(rl->layflag & SCE_LAY_HALO)
906 lamphalo_tile(pa, rl);
908 /* halo before ztra, because ztra fills in zbuffer now */
909 if(R.flag & R_HALO)
910 if(rl->layflag & SCE_LAY_HALO)
911 halo_tile(pa, rl->rectf, rl->lay);
913 /* transp layer */
914 if(R.flag & R_ZTRA) {
915 if(rl->layflag & SCE_LAY_ZTRA) {
916 unsigned short *ztramask, *solidmask= NULL; /* 16 bits, MAX_OSA */
918 /* allocate, but not free here, for asynchronous display of this rect in main thread */
919 rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer");
921 /* swap for live updates, and it is used in zbuf.c!!! */
922 SWAP(float *, rl->acolrect, rl->rectf);
923 ztramask= zbuffer_transp_shade(pa, rl, rl->rectf);
924 SWAP(float *, rl->acolrect, rl->rectf);
926 /* zbuffer transp only returns ztramask if there's solid rendered */
927 if(ztramask)
928 solidmask= make_solid_mask(pa);
930 if(ztramask && solidmask) {
931 unsigned short *sps= solidmask, *spz= ztramask;
932 unsigned short fullmask= (1<<R.osa)-1;
933 float *fcol= rl->rectf; float *acol= rl->acolrect;
934 int x;
936 for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4, sps++, spz++) {
937 if(*sps == fullmask)
938 addAlphaOverFloat(fcol, acol);
939 else
940 addAlphaOverFloatMask(fcol, acol, *sps, *spz);
943 else {
944 float *fcol= rl->rectf; float *acol= rl->acolrect;
945 int x;
946 for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) {
947 addAlphaOverFloat(fcol, acol);
950 if(solidmask) MEM_freeN(solidmask);
951 if(ztramask) MEM_freeN(ztramask);
954 /* sky before edge */
955 if(rl->layflag & SCE_LAY_SKY)
956 sky_tile(pa, rl->rectf);
958 /* extra layers */
959 if(rl->layflag & SCE_LAY_EDGE)
960 if(R.r.mode & R_EDGE)
961 edge_enhance_add(pa, rl->rectf, edgerect);
963 if(rl->passflag & SCE_PASS_Z)
964 convert_zbuf_to_distbuf(pa, rl);
966 if(rl->passflag & SCE_PASS_VECTOR)
967 reset_sky_speed(pa, rl);
969 /* de-premul alpha */
970 if(R.r.alphamode & R_ALPHAKEY)
971 convert_to_key_alpha(pa, rl->rectf);
973 /* free stuff within loop! */
974 MEM_freeN(pa->rectdaps); pa->rectdaps= NULL;
975 freeps(&psmlist);
977 if(edgerect) MEM_freeN(edgerect);
978 edgerect= NULL;
981 /* free all */
982 MEM_freeN(pa->rectp); pa->rectp= NULL;
983 MEM_freeN(pa->rectz); pa->rectz= NULL;
984 MEM_freeN(pa->clipflag); pa->clipflag= NULL;
986 /* display active layer */
987 rr->renrect.ymin=rr->renrect.ymax= 0;
988 rr->renlay= render_get_active_layer(&R, rr);
992 /* ------------------------------------------------------------------------ */
994 /* non OSA case, full tile render */
995 /* supposed to be fully threadable! */
996 void zbufshade_tile(RenderPart *pa)
998 ShadeSample ssamp;
999 RenderResult *rr= pa->result;
1000 RenderLayer *rl;
1001 PixStr ps;
1002 float *edgerect= NULL;
1003 int addpassflag;
1005 /* fake pixel struct, to comply to osa render */
1006 ps.next= NULL;
1007 ps.mask= 0xFFFF;
1009 set_part_zbuf_clipflag(pa);
1011 /* zbuffer code clears/inits rects */
1012 pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
1013 pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
1015 for(rl= rr->layers.first; rl; rl= rl->next) {
1017 /* general shader info, passes */
1018 shade_sample_initialize(&ssamp, pa, rl);
1019 addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
1021 zbuffer_solid(pa, rl->lay, rl->layflag);
1023 if(!R.test_break()) { /* NOTE: this if() is not consistant */
1025 /* edges only for solid part, ztransp doesn't support it yet anti-aliased */
1026 if(rl->layflag & SCE_LAY_EDGE) {
1027 if(R.r.mode & R_EDGE) {
1028 edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge");
1029 edge_enhance_tile(pa, edgerect);
1033 /* initialize scanline updates for main thread */
1034 rr->renrect.ymin= 0;
1035 rr->renlay= rl;
1037 if(rl->layflag & SCE_LAY_SOLID) {
1038 float *fcol= rl->rectf;
1039 int x, y, *rp= pa->rectp, *rz= pa->rectz, offs=0, seed;
1041 /* we set per pixel a fixed seed, for random AO and shadow samples */
1042 seed= pa->rectx*pa->disprect.ymin;
1044 /* irregular shadowb buffer creation */
1045 if(R.r.mode & R_SHADOW)
1046 ISB_create(pa, NULL);
1048 for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++, rr->renrect.ymax++) {
1049 for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, rz++, rp++, fcol+=4, offs++) {
1050 /* per pixel fixed seed */
1051 BLI_thread_srandom(pa->thread, seed++);
1053 if(*rp) {
1054 ps.facenr= *rp;
1055 ps.z= *rz;
1056 if(shade_samples(&ssamp, &ps, x, y)) {
1057 QUATCOPY(fcol, ssamp.shr[0].combined);
1059 /* passes */
1060 if(addpassflag)
1061 add_passes(rl, offs, ssamp.shi, ssamp.shr);
1065 if(y&1)
1066 if(R.test_break()) break;
1069 if(R.r.mode & R_SHADOW)
1070 ISB_free(pa);
1073 /* disable scanline updating */
1074 rr->renlay= NULL;
1077 /* lamphalo after solid, before ztra, looks nicest because ztra does own halo */
1078 if(R.flag & R_LAMPHALO)
1079 if(rl->layflag & SCE_LAY_HALO)
1080 lamphalo_tile(pa, rl);
1082 /* halo before ztra, because ztra fills in zbuffer now */
1083 if(R.flag & R_HALO)
1084 if(rl->layflag & SCE_LAY_HALO)
1085 halo_tile(pa, rl->rectf, rl->lay);
1087 if(R.flag & R_ZTRA) {
1088 if(rl->layflag & SCE_LAY_ZTRA) {
1089 float *fcol, *acol;
1090 int x;
1092 /* allocate, but not free here, for asynchronous display of this rect in main thread */
1093 rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer");
1095 /* swap for live updates */
1096 SWAP(float *, rl->acolrect, rl->rectf);
1097 zbuffer_transp_shade(pa, rl, rl->rectf);
1098 SWAP(float *, rl->acolrect, rl->rectf);
1100 fcol= rl->rectf; acol= rl->acolrect;
1101 for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) {
1102 addAlphaOverFloat(fcol, acol);
1107 /* sky before edge */
1108 if(rl->layflag & SCE_LAY_SKY)
1109 sky_tile(pa, rl->rectf);
1111 if(!R.test_break()) {
1112 if(rl->layflag & SCE_LAY_EDGE)
1113 if(R.r.mode & R_EDGE)
1114 edge_enhance_add(pa, rl->rectf, edgerect);
1117 if(rl->passflag & SCE_PASS_Z)
1118 convert_zbuf_to_distbuf(pa, rl);
1120 if(rl->passflag & SCE_PASS_VECTOR)
1121 reset_sky_speed(pa, rl);
1123 /* de-premul alpha */
1124 if(R.r.alphamode & R_ALPHAKEY)
1125 convert_to_key_alpha(pa, rl->rectf);
1127 if(edgerect) MEM_freeN(edgerect);
1128 edgerect= NULL;
1131 /* display active layer */
1132 rr->renrect.ymin=rr->renrect.ymax= 0;
1133 rr->renlay= render_get_active_layer(&R, rr);
1135 MEM_freeN(pa->rectp); pa->rectp= NULL;
1136 MEM_freeN(pa->rectz); pa->rectz= NULL;
1137 MEM_freeN(pa->clipflag); pa->clipflag= NULL;
1140 /* SSS preprocess tile render, fully threadable */
1141 typedef struct ZBufSSSHandle {
1142 RenderPart *pa;
1143 ListBase psmlist;
1144 int totps;
1145 } ZBufSSSHandle;
1147 static void addps_sss(void *cb_handle, int facenr, int x, int y, int z)
1149 ZBufSSSHandle *handle = cb_handle;
1150 RenderPart *pa= handle->pa;
1152 /* extra border for filter gives double samples on part edges,
1153 don't use those */
1154 if(x<pa->crop || x>=pa->rectx-pa->crop)
1155 return;
1156 if(y<pa->crop || y>=pa->recty-pa->crop)
1157 return;
1159 if(pa->rectall) {
1160 long *rs= pa->rectall + pa->rectx*y + x;
1162 addps(&handle->psmlist, rs, facenr, z, 0);
1163 handle->totps++;
1165 if(pa->rectz) {
1166 int *rz= pa->rectz + pa->rectx*y + x;
1167 int *rp= pa->rectp + pa->rectx*y + x;
1169 if(z < *rz) {
1170 if(*rp == 0)
1171 handle->totps++;
1172 *rz= z;
1173 *rp= facenr;
1176 if(pa->rectbackz) {
1177 int *rz= pa->rectbackz + pa->rectx*y + x;
1178 int *rp= pa->rectbackp + pa->rectx*y + x;
1180 if(z >= *rz) {
1181 if(*rp == 0)
1182 handle->totps++;
1183 *rz= z;
1184 *rp= facenr;
1189 static void shade_sample_sss(ShadeSample *ssamp, Material *mat, VlakRen *vlr, int quad, float x, float y, float z, float *co, float *color, float *area)
1191 ShadeInput *shi= ssamp->shi;
1192 ShadeResult shr;
1193 float texfac, orthoarea, nor[3];
1195 /* normal flipping must be disabled to make back scattering work, so that
1196 backside faces actually face any lighting from the back */
1197 shi->puno= 0;
1199 /* cache for shadow */
1200 shi->samplenr++;
1202 if(quad)
1203 shade_input_set_triangle_i(shi, vlr, 0, 2, 3);
1204 else
1205 shade_input_set_triangle_i(shi, vlr, 0, 1, 2);
1207 /* we don't want flipped normals, they screw up back scattering */
1208 if(vlr->noflag & R_FLIPPED_NO)
1209 VecMulf(shi->facenor, -1.0f);
1211 /* center pixel */
1212 x += 0.5f;
1213 y += 0.5f;
1215 /* we estimate the area here using shi->dxco and shi->dyco. we need to
1216 enabled shi->osatex these are filled. we compute two areas, one with
1217 the normal pointed at the camera and one with the original normal, and
1218 then clamp to avoid a too large contribution from a single pixel */
1219 shi->osatex= 1;
1221 VECCOPY(nor, shi->facenor);
1222 calc_view_vector(shi->facenor, x, y);
1223 Normalize(shi->facenor);
1224 shade_input_set_viewco(shi, x, y, z);
1225 orthoarea= VecLength(shi->dxco)*VecLength(shi->dyco);
1227 VECCOPY(shi->facenor, nor);
1228 shade_input_set_viewco(shi, x, y, z);
1229 *area= VecLength(shi->dxco)*VecLength(shi->dyco);
1230 *area= MIN2(*area, 2.0f*orthoarea);
1232 shade_input_set_uv(shi);
1233 shade_input_set_normals(shi);
1235 /* not a pretty solution, but fixes common cases */
1236 if(vlr->ob && vlr->ob->transflag & OB_NEG_SCALE) {
1237 VecMulf(shi->vn, -1.0f);
1238 VecMulf(shi->vno, -1.0f);
1241 /* if nodetree, use the material that we are currently preprocessing
1242 instead of the node material */
1243 if(shi->mat->nodetree && shi->mat->use_nodes)
1244 shi->mat= mat;
1246 /* init material vars */
1247 // note, keep this synced with render_types.h
1248 memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
1249 shi->har= shi->mat->har;
1251 /* render */
1252 shade_input_set_shade_texco(shi);
1254 shade_samples_do_AO(ssamp);
1255 shade_material_loop(shi, &shr);
1257 VECCOPY(co, shi->co);
1258 VECCOPY(color, shr.combined);
1260 /* texture blending */
1261 texfac= shi->mat->sss_texfac;
1263 if(texfac == 0.0f) {
1264 if(shr.col[0]!=0.0f) color[0] /= shr.col[0];
1265 if(shr.col[1]!=0.0f) color[1] /= shr.col[1];
1266 if(shr.col[2]!=0.0f) color[2] /= shr.col[2];
1268 else if(texfac != 1.0f) {
1269 if(shr.col[0]!=0.0f) color[0] *= pow(shr.col[0], texfac)/shr.col[0];
1270 if(shr.col[1]!=0.0f) color[1] *= pow(shr.col[1], texfac)/shr.col[1];
1271 if(shr.col[2]!=0.0f) color[2] *= pow(shr.col[2], texfac)/shr.col[2];
1275 static void zbufshade_sss_free(RenderPart *pa)
1277 MEM_freeN(pa->clipflag); pa->clipflag= NULL;
1278 #if 0
1279 MEM_freeN(pa->rectall); pa->rectall= NULL;
1280 freeps(&handle.psmlist);
1281 #else
1282 MEM_freeN(pa->rectz); pa->rectz= NULL;
1283 MEM_freeN(pa->rectp); pa->rectp= NULL;
1284 MEM_freeN(pa->rectbackz); pa->rectbackz= NULL;
1285 MEM_freeN(pa->rectbackp); pa->rectbackp= NULL;
1286 #endif
1289 void zbufshade_sss_tile(RenderPart *pa)
1291 Render *re= &R;
1292 ShadeSample ssamp;
1293 ZBufSSSHandle handle;
1294 RenderResult *rr= pa->result;
1295 RenderLayer *rl= rr->layers.first;
1296 VlakRen *vlr;
1297 Material *mat= re->sss_mat;
1298 float (*co)[3], (*color)[3], *area, *fcol= rl->rectf;
1299 int x, y, seed, quad, totpoint, display = !(re->r.scemode & R_PREVIEWBUTS);
1300 int *rz, *rp, *rbz, *rbp;
1301 #if 0
1302 PixStr *ps;
1303 long *rs;
1304 int z;
1305 #endif
1307 set_part_zbuf_clipflag(pa);
1309 /* setup pixelstr list and buffer for zbuffering */
1310 handle.pa= pa;
1311 handle.totps= 0;
1313 #if 0
1314 handle.psmlist.first= handle.psmlist.last= NULL;
1315 addpsmain(&handle.psmlist);
1317 pa->rectall= MEM_callocN(sizeof(long)*pa->rectx*pa->recty+4, "rectall");
1318 #else
1319 pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
1320 pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
1321 pa->rectbackp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackp");
1322 pa->rectbackz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackz");
1323 #endif
1325 /* create the pixelstrs to be used later */
1326 zbuffer_sss(pa, rl->lay, &handle, addps_sss);
1328 if(handle.totps==0) {
1329 zbufshade_sss_free(pa);
1330 return;
1333 co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo");
1334 color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor");
1335 area= MEM_mallocN(sizeof(float)*handle.totps, "SSSArea");
1337 #if 0
1338 /* create ISB (does not work currently!) */
1339 if(re->r.mode & R_SHADOW)
1340 ISB_create(pa, NULL);
1341 #endif
1343 /* setup shade sample with correct passes */
1344 memset(&ssamp, 0, sizeof(ssamp));
1345 shade_sample_initialize(&ssamp, pa, rl);
1346 ssamp.shi[0].passflag= SCE_PASS_DIFFUSE|SCE_PASS_AO|SCE_PASS_RADIO;
1347 ssamp.shi[0].passflag |= SCE_PASS_RGBA;
1348 ssamp.shi[0].combinedflag= ~(SCE_PASS_SPEC);
1349 ssamp.tot= 1;
1351 if(display) {
1352 /* initialize scanline updates for main thread */
1353 rr->renrect.ymin= 0;
1354 rr->renlay= rl;
1357 seed= pa->rectx*pa->disprect.ymin;
1358 #if 0
1359 rs= pa->rectall;
1360 #else
1361 rz= pa->rectz;
1362 rp= pa->rectp;
1363 rbz= pa->rectbackz;
1364 rbp= pa->rectbackp;
1365 #endif
1366 totpoint= 0;
1368 for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++, rr->renrect.ymax++) {
1369 for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, fcol+=4) {
1370 /* per pixel fixed seed */
1371 BLI_thread_srandom(pa->thread, seed++);
1373 #if 0
1374 if(rs) {
1375 /* for each sample in this pixel, shade it */
1376 for(ps=(PixStr*)*rs; ps; ps=ps->next) {
1377 vlr= RE_findOrAddVlak(re, (ps->facenr-1) & RE_QUAD_MASK);
1378 quad= (ps->facenr & RE_QUAD_OFFS);
1379 z= ps->z;
1381 shade_sample_sss(&ssamp, mat, vlr, quad, x, y, z,
1382 co[totpoint], color[totpoint], &area[totpoint]);
1384 totpoint++;
1386 VECADD(fcol, fcol, color);
1387 fcol[3]= 1.0f;
1390 rs++;
1392 #else
1393 if(rp) {
1394 if(*rp != 0) {
1395 /* shade front */
1396 vlr= RE_findOrAddVlak(re, (*rp-1) & RE_QUAD_MASK);
1397 quad= ((*rp) & RE_QUAD_OFFS);
1399 shade_sample_sss(&ssamp, mat, vlr, quad, x, y, *rz,
1400 co[totpoint], color[totpoint], &area[totpoint]);
1402 VECADD(fcol, fcol, color[totpoint]);
1403 fcol[3]= 1.0f;
1404 totpoint++;
1407 rp++; rz++;
1410 if(rbp) {
1411 if(*rbp != 0 && *rbp != *(rp-1)) {
1412 /* shade back */
1413 vlr= RE_findOrAddVlak(re, (*rbp-1) & RE_QUAD_MASK);
1414 quad= ((*rbp) & RE_QUAD_OFFS);
1416 shade_sample_sss(&ssamp, mat, vlr, quad, x, y, *rbz,
1417 co[totpoint], color[totpoint], &area[totpoint]);
1419 /* to indicate this is a back sample */
1420 area[totpoint]= -area[totpoint];
1422 VECADD(fcol, fcol, color[totpoint]);
1423 fcol[3]= 1.0f;
1424 totpoint++;
1427 rbz++; rbp++;
1429 #endif
1432 if(y&1)
1433 if(re->test_break()) break;
1436 /* note: after adding we do not free these arrays, sss keeps them */
1437 if(totpoint > 0) {
1438 sss_add_points(re, co, color, area, totpoint);
1440 else {
1441 MEM_freeN(co);
1442 MEM_freeN(color);
1443 MEM_freeN(area);
1446 #if 0
1447 if(re->r.mode & R_SHADOW)
1448 ISB_free(pa);
1449 #endif
1451 if(display) {
1452 /* display active layer */
1453 rr->renrect.ymin=rr->renrect.ymax= 0;
1454 rr->renlay= render_get_active_layer(&R, rr);
1457 zbufshade_sss_free(pa);
1460 /* ------------------------------------------------------------------------ */
1462 static void renderhalo_post(RenderResult *rr, float *rectf, HaloRen *har) /* postprocess version */
1464 float dist, xsq, ysq, xn, yn, colf[4], *rectft, *rtf;
1465 float haloxs, haloys;
1466 int minx, maxx, miny, maxy, x, y;
1468 /* calculate the disprect mapped coordinate for halo. note: rectx is disprect corrected */
1469 haloxs= har->xs - R.disprect.xmin;
1470 haloys= har->ys - R.disprect.ymin;
1472 har->miny= miny= haloys - har->rad/R.ycor;
1473 har->maxy= maxy= haloys + har->rad/R.ycor;
1475 if(maxy<0);
1476 else if(rr->recty<miny);
1477 else {
1478 minx= floor(haloxs-har->rad);
1479 maxx= ceil(haloxs+har->rad);
1481 if(maxx<0);
1482 else if(rr->rectx<minx);
1483 else {
1485 if(minx<0) minx= 0;
1486 if(maxx>=rr->rectx) maxx= rr->rectx-1;
1487 if(miny<0) miny= 0;
1488 if(maxy>rr->recty) maxy= rr->recty;
1490 rectft= rectf+ 4*rr->rectx*miny;
1492 for(y=miny; y<maxy; y++) {
1494 rtf= rectft+4*minx;
1496 yn= (y - haloys)*R.ycor;
1497 ysq= yn*yn;
1499 for(x=minx; x<=maxx; x++) {
1500 xn= x - haloxs;
1501 xsq= xn*xn;
1502 dist= xsq+ysq;
1503 if(dist<har->radsq) {
1505 if(shadeHaloFloat(har, colf, 0x7FFFFF, dist, xn, yn, har->flarec))
1506 addalphaAddfacFloat(rtf, colf, har->add);
1508 rtf+=4;
1511 rectft+= 4*rr->rectx;
1513 if(R.test_break()) break;
1518 /* ------------------------------------------------------------------------ */
1520 static void renderflare(RenderResult *rr, float *rectf, HaloRen *har)
1522 extern float hashvectf[];
1523 HaloRen fla;
1524 Material *ma;
1525 float *rc, rad, alfa, visifac, vec[3];
1526 int b, type;
1528 fla= *har;
1529 fla.linec= fla.ringc= fla.flarec= 0;
1531 rad= har->rad;
1532 alfa= har->alfa;
1534 visifac= R.ycor*(har->pixels);
1535 /* all radials added / r^3 == 1.0f! */
1536 visifac /= (har->rad*har->rad*har->rad);
1537 visifac*= visifac;
1539 ma= har->mat;
1541 /* first halo: just do */
1543 har->rad= rad*ma->flaresize*visifac;
1544 har->radsq= har->rad*har->rad;
1545 har->zs= fla.zs= 0;
1547 har->alfa= alfa*visifac;
1549 renderhalo_post(rr, rectf, har);
1551 /* next halo's: the flares */
1552 rc= hashvectf + ma->seed2;
1554 for(b=1; b<har->flarec; b++) {
1556 fla.r= fabs(rc[0]);
1557 fla.g= fabs(rc[1]);
1558 fla.b= fabs(rc[2]);
1559 fla.alfa= ma->flareboost*fabs(alfa*visifac*rc[3]);
1560 fla.hard= 20.0f + fabs(70*rc[7]);
1561 fla.tex= 0;
1563 type= (int)(fabs(3.9*rc[6]));
1565 fla.rad= ma->subsize*sqrt(fabs(2.0f*har->rad*rc[4]));
1567 if(type==3) {
1568 fla.rad*= 3.0f;
1569 fla.rad+= R.rectx/10;
1572 fla.radsq= fla.rad*fla.rad;
1574 vec[0]= 1.4*rc[5]*(har->xs-R.winx/2);
1575 vec[1]= 1.4*rc[5]*(har->ys-R.winy/2);
1576 vec[2]= 32.0f*sqrt(vec[0]*vec[0] + vec[1]*vec[1] + 1.0f);
1578 fla.xs= R.winx/2 + vec[0] + (1.2+rc[8])*R.rectx*vec[0]/vec[2];
1579 fla.ys= R.winy/2 + vec[1] + (1.2+rc[8])*R.rectx*vec[1]/vec[2];
1581 if(R.flag & R_SEC_FIELD) {
1582 if(R.r.mode & R_ODDFIELD) fla.ys += 0.5;
1583 else fla.ys -= 0.5;
1585 if(type & 1) fla.type= HA_FLARECIRC;
1586 else fla.type= 0;
1587 renderhalo_post(rr, rectf, &fla);
1589 fla.alfa*= 0.5;
1590 if(type & 2) fla.type= HA_FLARECIRC;
1591 else fla.type= 0;
1592 renderhalo_post(rr, rectf, &fla);
1594 rc+= 7;
1598 /* needs recode... integrate this better! */
1599 void add_halo_flare(Render *re)
1601 RenderResult *rr= re->result;
1602 RenderLayer *rl;
1603 HaloRen *har = NULL;
1604 int a, mode, do_draw=0;
1606 /* for now, we get the first renderlayer in list with halos set */
1607 for(rl= rr->layers.first; rl; rl= rl->next)
1608 if(rl->layflag & SCE_LAY_HALO)
1609 break;
1611 if(rl==NULL || rl->rectf==NULL)
1612 return;
1614 mode= R.r.mode;
1615 R.r.mode &= ~R_PANORAMA;
1617 project_renderdata(&R, projectverto, 0, 0);
1619 for(a=0; a<R.tothalo; a++) {
1620 if((a & 255)==0) har= R.bloha[a>>8];
1621 else har++;
1623 if(har->flarec) {
1624 do_draw= 1;
1625 renderflare(rr, rl->rectf, har);
1629 if(do_draw) {
1630 /* weak... the display callback wants an active renderlayer pointer... */
1631 rr->renlay= rl;
1632 re->display_draw(rr, NULL);
1635 R.r.mode= mode;
1638 /* ************************* used for shaded view ************************ */
1640 /* if *re, then initialize, otherwise execute */
1641 void RE_shade_external(Render *re, ShadeInput *shi, ShadeResult *shr)
1643 static VlakRen vlr;
1645 /* init */
1646 if(re) {
1647 R= *re;
1649 /* fake render face */
1650 memset(&vlr, 0, sizeof(VlakRen));
1651 vlr.lay= -1;
1653 return;
1655 shi->vlr= &vlr;
1657 if(shi->mat->nodetree && shi->mat->use_nodes)
1658 ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
1659 else {
1660 /* copy all relevant material vars, note, keep this synced with render_types.h */
1661 memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
1662 shi->har= shi->mat->har;
1664 shade_material_loop(shi, shr);
1668 /* ************************* bake ************************ */
1670 #define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val))
1672 typedef struct BakeShade {
1673 ShadeSample ssamp;
1674 VlakRen *vlr;
1676 ZSpan *zspan;
1677 Image *ima;
1678 ImBuf *ibuf;
1680 int rectx, recty, quad, type, vdone, ready;
1682 unsigned int *rect;
1683 float *rect_float;
1684 } BakeShade;
1686 static void do_bake_shade(void *handle, int x, int y, float u, float v)
1688 BakeShade *bs= handle;
1689 ShadeSample *ssamp= &bs->ssamp;
1690 ShadeInput *shi= ssamp->shi;
1691 ShadeResult shr;
1692 VlakRen *vlr= bs->vlr;
1693 float l, *v1, *v2, *v3;
1695 /* fast threadsafe break test */
1696 if(R.test_break())
1697 return;
1699 /* setup render coordinates */
1700 if(bs->quad) {
1701 v1= vlr->v1->co;
1702 v2= vlr->v3->co;
1703 v3= vlr->v4->co;
1705 else {
1706 v1= vlr->v1->co;
1707 v2= vlr->v2->co;
1708 v3= vlr->v3->co;
1711 /* renderco */
1712 l= 1.0f-u-v;
1714 shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0];
1715 shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1];
1716 shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2];
1718 /* set up view vector */
1719 VECCOPY(shi->view, shi->co);
1720 Normalize(shi->view);
1722 /* no face normal flip */
1723 shi->puno= 0;
1725 /* cache for shadow */
1726 shi->samplenr++;
1728 if(bs->quad)
1729 shade_input_set_triangle_i(shi, vlr, 0, 2, 3);
1730 else
1731 shade_input_set_triangle_i(shi, vlr, 0, 1, 2);
1733 shi->u= -u;
1734 shi->v= -v;
1735 shi->xs= x;
1736 shi->ys= y;
1738 shade_input_set_normals(shi);
1740 /* init material vars */
1741 memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); // note, keep this synced with render_types.h
1742 shi->har= shi->mat->har;
1744 if(bs->type==RE_BAKE_AO) {
1745 ambient_occlusion(shi);
1746 ambient_occlusion_to_diffuse(shi, shr.combined);
1748 else {
1750 shade_input_set_shade_texco(shi);
1752 shade_samples_do_AO(ssamp);
1754 if(shi->mat->nodetree && shi->mat->use_nodes) {
1755 ntreeShaderExecTree(shi->mat->nodetree, shi, &shr);
1756 shi->mat= vlr->mat; /* shi->mat is being set in nodetree */
1758 else
1759 shade_material_loop(shi, &shr);
1761 if(bs->type==RE_BAKE_NORMALS) {
1762 shr.combined[0]= shi->vn[0]/2.0f + 0.5f;
1763 shr.combined[1]= 0.5f - shi->vn[1]/2.0f;
1764 shr.combined[2]= shi->vn[2]/2.0f + 0.5f;
1766 else if(bs->type==RE_BAKE_TEXTURE) {
1767 shr.combined[0]= shi->r;
1768 shr.combined[1]= shi->g;
1769 shr.combined[2]= shi->b;
1773 if(bs->rect) {
1774 char *col= (char *)(bs->rect + bs->rectx*y + x);
1775 col[0]= FTOCHAR(shr.combined[0]);
1776 col[1]= FTOCHAR(shr.combined[1]);
1777 col[2]= FTOCHAR(shr.combined[2]);
1778 col[3]= 255;
1780 else {
1781 float *col= bs->rect_float + 4*(bs->rectx*y + x);
1782 VECCOPY(col, shr.combined);
1783 col[3]= 1.0f;
1787 static int get_next_bake_face(BakeShade *bs)
1789 VlakRen *vlr;
1790 MTFace *tface;
1791 static int v= 0, vdone= 0;
1793 if(bs==NULL) {
1794 vlr= NULL;
1795 v= vdone= 0;
1796 return 0;
1799 BLI_lock_thread(LOCK_CUSTOM1);
1801 for(; v<R.totvlak; v++) {
1802 vlr= RE_findOrAddVlak(&R, v);
1804 if(vlr->ob->flag & SELECT) {
1805 tface= RE_vlakren_get_tface(&R, vlr, 0, NULL, 0);
1807 if(tface && tface->tpage) {
1808 Image *ima= tface->tpage;
1809 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
1810 float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f};
1812 if(ibuf==NULL)
1813 continue;
1815 if(ibuf->rect==NULL && ibuf->rect_float==NULL)
1816 continue;
1818 if(ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4))
1819 continue;
1821 /* find the image for the first time? */
1822 if(ima->id.flag & LIB_DOIT) {
1823 ima->id.flag &= ~LIB_DOIT;
1825 /* we either fill in float or char, this ensures things go fine */
1826 if(ibuf->rect_float)
1827 imb_freerectImBuf(ibuf);
1828 /* clear image */
1829 if(R.r.bake_flag & R_BAKE_CLEAR)
1830 IMB_rectfill(ibuf, vec);
1832 /* might be read by UI to set active image for display */
1833 R.bakebuf= ima;
1836 bs->vlr= vlr;
1838 bs->vdone++; /* only for error message if nothing was rendered */
1839 v++;
1841 BLI_unlock_thread(LOCK_CUSTOM1);
1842 return 1;
1847 BLI_unlock_thread(LOCK_CUSTOM1);
1848 return 0;
1851 /* already have tested for tface and ima and zspan */
1852 static void shade_tface(BakeShade *bs)
1854 VlakRen *vlr= bs->vlr;
1855 MTFace *tface= RE_vlakren_get_tface(&R, vlr, 0, NULL, 0);
1856 Image *ima= tface->tpage;
1857 float vec[4][2];
1858 int a, i1, i2, i3;
1860 /* check valid zspan */
1861 if(ima!=bs->ima) {
1862 bs->ima= ima;
1863 bs->ibuf= BKE_image_get_ibuf(ima, NULL);
1864 /* note, these calls only free/fill contents of zspan struct, not zspan itself */
1865 zbuf_free_span(bs->zspan);
1866 zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y);
1869 bs->rectx= bs->ibuf->x;
1870 bs->recty= bs->ibuf->y;
1871 bs->rect= bs->ibuf->rect;
1872 bs->rect_float= bs->ibuf->rect_float;
1873 bs->quad= 0;
1875 /* get pixel level vertex coordinates */
1876 for(a=0; a<4; a++) {
1877 vec[a][0]= tface->uv[a][0]*(float)bs->rectx - 0.5f;
1878 vec[a][1]= tface->uv[a][1]*(float)bs->recty - 0.5f;
1881 /* UV indices have to be corrected for possible quad->tria splits */
1882 i1= 0; i2= 1; i3= 2;
1883 vlr_set_uv_indices(vlr, &i1, &i2, &i3);
1884 zspan_scanconvert(bs->zspan, bs, vec[i1], vec[i2], vec[i3], do_bake_shade);
1886 if(vlr->v4) {
1887 bs->quad= 1;
1888 zspan_scanconvert(bs->zspan, bs, vec[0], vec[2], vec[3], do_bake_shade);
1892 static void *do_bake_thread(void *bs_v)
1894 BakeShade *bs= bs_v;
1896 while(get_next_bake_face(bs)) {
1897 shade_tface(bs);
1899 /* fast threadsafe break test */
1900 if(R.test_break())
1901 break;
1903 bs->ready= 1;
1905 return NULL;
1908 /* using object selection tags, the faces with UV maps get baked */
1909 /* render should have been setup */
1910 /* returns 0 if nothing was handled */
1911 int RE_bake_shade_all_selected(Render *re, int type)
1913 BakeShade handles[BLENDER_MAX_THREADS];
1914 ListBase threads;
1915 Image *ima;
1916 int a, vdone=0;
1918 /* initialize static vars */
1919 get_next_bake_face(NULL);
1921 /* baker uses this flag to detect if image was initialized */
1922 for(ima= G.main->image.first; ima; ima= ima->id.next)
1923 ima->id.flag |= LIB_DOIT;
1925 /* initialize render global */
1926 R= *re;
1927 R.bakebuf= NULL;
1929 BLI_init_threads(&threads, do_bake_thread, re->r.threads);
1931 /* get the threads running */
1932 for(a=0; a<re->r.threads; a++) {
1933 /* set defaults in handles */
1934 memset(&handles[a], 0, sizeof(BakeShade));
1936 handles[a].ssamp.shi[0].lay= re->scene->lay;
1937 handles[a].ssamp.shi[0].passflag= SCE_PASS_COMBINED;
1938 handles[a].ssamp.shi[0].combinedflag= ~(SCE_PASS_SPEC);
1939 handles[a].ssamp.shi[0].thread= a;
1940 handles[a].ssamp.tot= 1;
1942 handles[a].type= type;
1943 handles[a].zspan= MEM_callocN(sizeof(ZSpan), "zspan for bake");
1945 BLI_insert_thread(&threads, &handles[a]);
1948 /* wait for everything to be done */
1949 a= 0;
1950 while(a!=re->r.threads) {
1952 PIL_sleep_ms(50);
1954 for(a=0; a<re->r.threads; a++)
1955 if(handles[a].ready==0)
1956 break;
1959 /* filter images */
1960 for(ima= G.main->image.first; ima; ima= ima->id.next) {
1961 if((ima->id.flag & LIB_DOIT)==0) {
1962 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
1963 for(a=0; a<re->r.bake_filter; a++)
1964 IMB_filter_extend(ibuf);
1965 ibuf->userflags |= IB_BITMAPDIRTY;
1969 /* calculate return value */
1970 for(a=0; a<re->r.threads; a++) {
1971 vdone+= handles[a].vdone;
1973 zbuf_free_span(handles[a].zspan);
1974 MEM_freeN(handles[a].zspan);
1977 BLI_end_threads(&threads);
1978 return vdone;
1981 struct Image *RE_bake_shade_get_image(void)
1983 return R.bakebuf;