4 * ***** BEGIN GPL/BL DUAL 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. The Blender
10 * Foundation also sells licenses for use in proprietary software under
11 * the Blender License. See http://www.blender.org/BL/ for information
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): Hos, Robert Wenzlaff.
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
34 /* External modules: */
35 #include "MEM_guardedalloc.h"
36 #include "BLI_arithb.h"
37 #include "IMB_imbuf_types.h"
38 #include "IMB_imbuf.h"
39 #include "MTC_matrixops.h"
40 #include "BKE_utildefines.h"
42 #include "DNA_mesh_types.h"
43 #include "DNA_image_types.h"
44 #include "DNA_object_types.h"
45 #include "DNA_camera_types.h"
46 #include "DNA_lamp_types.h"
48 #include "BKE_global.h"
49 #include "BKE_texture.h"
52 #include "RE_callbacks.h"
53 #include "old_zbuffer_types.h"
55 #include "render_intern.h"
56 #include "zbuf.h" /* stuff like bgnaccumbuf, fillrect, ...*/
57 #include "pixelblending.h"
59 #include "renderHelp.h"
71 #include "rendercore.h"
72 #include "rendercore_int.h"
78 /* globals for this file */
79 /* moved to renderData.c? Not yet... */
86 float fmask[256], centLut[16];
87 unsigned short usegamtab=0, *mask1[9], *mask2[9], *igamtab1, *igamtab2, *gamtab;
88 char cmask[256], *centmask;
91 /* comes from texture.c (only used here !) */
92 /* extern void do_halo_tex(HaloRen *har, float xn, float yn, float *colf); */
94 void gamtabdit(unsigned short *in, char *out);
95 /* int count_mask(unsigned short ); */
96 void scanlinehalo(unsigned int *rectz, unsigned int *rectt, short ys);
97 /* void add_halo_flare(void); */
98 void edge_enhance(void);
100 /* Dither with gamma table? */
101 void gamtabdit(unsigned short *in, char *out)
102 /* unsigned short *in; */
105 static short rerr=0, gerr=0, berr=0;
112 col= gamtab[in[2]]+berr;
113 if(col>65535) col= 65535;
117 col= gamtab[in[4]]+gerr;
118 if(col>65535) col= 65535;
122 col= gamtab[in[6]]+rerr;
123 if(col>65535) col= 65535;
129 float mistfactor(float *co) /* dist en height, return alpha */
133 fac= R.zcor - R.wrld.miststa; /* R.zcor is calculated per pixel */
135 /* fac= -co[2]-R.wrld.miststa; */
138 if(fac< R.wrld.mistdist) {
140 fac= (fac/(R.wrld.mistdist));
142 if(R.wrld.mistype==0) fac*= fac;
143 else if(R.wrld.mistype==1);
150 /* height switched off mist */
151 if(R.wrld.misthi!=0.0 && fac!=0.0) {
152 /* at height misthi the mist is completely gone */
154 hi= R.viewinv[0][2]*co[0]+R.viewinv[1][2]*co[1]+R.viewinv[2][2]*co[2]+R.viewinv[3][2];
156 if(hi>R.wrld.misthi) fac= 0.0;
158 hi= (R.wrld.misthi-hi)/R.wrld.misthi;
163 return (1.0-fac)* (1-R.wrld.misi);
166 void RE_sky(float *view, char *col)
168 float lo[3], rf, gf, bf;
170 if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
171 *( (unsigned int *)col)= R.wrld.fastcol;
175 R.wrld.skytype |= WO_ZENUP;
177 if(R.wrld.skytype & WO_SKYREAL) {
179 R.inprz= view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2];
181 if(R.inprz<0.0) R.wrld.skytype-= WO_ZENUP;
182 R.inprz= fabs(R.inprz);
184 else if(R.wrld.skytype & WO_SKYPAPER) {
185 R.inprz= 0.5+ 0.5*view[1];
188 R.inprz= fabs(0.5+ view[1]);
191 if(R.wrld.skytype & WO_SKYTEX) {
193 if(R.wrld.skytype & WO_SKYREAL) {
195 MTC_Mat3MulVecfl(R.imat, lo);
197 SWAP(float, lo[1], lo[2]);
205 if(R.inprz>1.0) R.inprz= 1.0;
206 R.inprh= 1.0-R.inprz;
208 if(R.wrld.skytype & WO_SKYBLEND) {
209 rf= 255.0*(R.inprh*R.wrld.horr + R.inprz*R.wrld.zenr);
210 gf= 255.0*(R.inprh*R.wrld.horg + R.inprz*R.wrld.zeng);
211 bf= 255.0*(R.inprh*R.wrld.horb + R.inprz*R.wrld.zenb);
213 if (rf>255.0) col[0]= 255;
214 else col[0]= (char)rf;
215 if (gf>255.0) col[1]= 255;
216 else col[1]= (char)gf;
217 if (bf>255.0) col[2]= 255;
218 else col[2]= (char)bf;
221 col[0]= 255.0*R.wrld.horr;
222 col[1]= 255.0*R.wrld.horg;
223 col[2]= 255.0*R.wrld.horb;
225 col[3]= 1; /* to prevent wrong optimalisation alphaover of flares */
228 /* ------------------------------------------------------------------------- */
230 void scanlinesky(char *rect, int y)
232 /* have to type this! set to : addalphaUnder: char*, char*
233 * addalphaUnderGamma: ditto called with char *, uint* !!!
234 * unmangle this shit... */
236 float fac, u, v, view[3];
238 unsigned int col=0, *rt;
241 if(R.r.alphamode & R_ALPHAPREMUL) return;
243 if(R.r.alphamode & R_ALPHAKEY) {
247 cp[0]= 255.0*R.wrld.horr;
248 cp[1]= 255.0*R.wrld.horg;
249 cp[2]= 255.0*R.wrld.horb;
251 for(x=0; x<R.rectx; x++, rect+= 4) {
253 *( ( unsigned int *)rect)= col;
256 /* prevent 'col' to be in the image */
258 if( cp[0]==cp1[0] && cp[1]==cp1[1] && cp[2]==cp1[2] ) {
260 if(cp1[3]==255) cp1[3]= 254;
272 if(R.wrld.mode & WO_MIST) alphafunc= addalphaUnder;
273 else alphafunc= addalphaUnderGamma;
276 if(R.r.bufflag & 1) {
278 if(R.backbuf->ibuf==0) {
279 R.backbuf->ibuf= IMB_loadiffname(R.backbuf->name, IB_rect);
280 if(R.backbuf->ibuf==0) {
285 /* which scanline/ */
286 y= ((y+R.afmy+R.ystart)*R.backbuf->ibuf->y)/(R.recty);
288 if(R.flag & R_SEC_FIELD) {
289 if((R.r.mode & R_ODDFIELD)==0) {
290 if( y<R.backbuf->ibuf->y) y++;
297 rt= (R.backbuf->ibuf->rect + y*R.backbuf->ibuf->x);
299 /* at which location */
300 fac= ((float)R.backbuf->ibuf->x)/(float)(2*R.afmx);
301 ofs= (R.afmx+R.xstart)*fac;
304 dx= (int) (65536.0*fac);
309 if( rect[3] != 255) {
310 if(rect[3]==0) *((unsigned int *)rect)= *rt;
318 while( ofs > 65535 ) {
328 if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
329 for(x=0; x<R.rectx; x++, rect+= 4) {
331 if(rect[3]==0) *((unsigned int *)rect)= R.wrld.fastcol;
333 alphafunc(rect, &R.wrld.fastcol);
340 for(x=0; x<R.rectx; x++, rect+= 4) {
342 if(R.wrld.skytype & WO_SKYPAPER) {
343 view[0]= (x+(R.xstart))/(float)R.afmx;
344 view[1]= (y+(R.ystart))/(float)R.afmy;
348 view[0]= (x+(R.xstart)+1.0);
350 if(R.flag & R_SEC_FIELD) {
351 if(R.r.mode & R_ODDFIELD) view[1]= (y+R.ystart+0.5)*R.ycor;
352 else view[1]= (y+R.ystart+1.5)*R.ycor;
354 else view[1]= (y+R.ystart+1.0)*R.ycor;
358 fac= Normalise(view);
359 if(R.wrld.skytype & WO_SKYTEX) {
361 O.dyview= R.ycor/fac;
365 if(R.r.mode & R_PANORAMA) {
366 float panoco, panosi;
367 panoco = getPanovCo();
368 panosi = getPanovSi();
369 u= view[0]; v= view[2];
371 view[0]= panoco*u + panosi*v;
372 view[2]= -panosi*u + panoco*v;
375 RE_sky(view, (char *)&col);
377 if(rect[3]==0) *((unsigned int *)rect)= col;
378 else alphafunc(rect, &col);
384 /* ************************************** */
387 void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens)
389 double a, b, c, disc, nray[3], npos[3];
390 float t0, t1 = 0.0, t2= 0.0, t3, haint;
391 float p1[3], p2[3], ladist, maxz = 0.0, maxy = 0.0;
392 int snijp, doclip=1, use_yco=0;
398 VECCOPY(npos, lar->sh_invcampos); /* in initlamp calculated */
401 VECCOPY(nray, shi->view);
402 MTC_Mat3MulVecd(lar->imat, nray);
404 if(R.wrld.mode & WO_MIST) {
407 haint *= mistfactor(lar->co);
415 if(shi->co[2]==0.0) doclip= 0; /* for when halo at sky */
417 p1[0]= shi->co[0]-lar->co[0];
418 p1[1]= shi->co[1]-lar->co[1];
419 p1[2]= shi->co[2]-lar->co[2];
421 maxz= lar->imat[0][2]*p1[0]+lar->imat[1][2]*p1[1]+lar->imat[2][2]*p1[2];
423 maxy= lar->imat[0][1]*p1[0]+lar->imat[1][1]*p1[1]+lar->imat[2][1]*p1[2];
425 if( fabs(nray[2]) <0.000001 ) use_yco= 1;
428 /* scale z to make sure volume is normalized */
429 nray[2]*= lar->sh_zfac;
430 /* nray does not need normalization */
432 ladist= lar->sh_zfac*lar->dist;
435 a = nray[0] * nray[0] + nray[1] * nray[1] - nray[2]*nray[2];
436 b = nray[0] * npos[0] + nray[1] * npos[1] - nray[2]*npos[2];
437 c = npos[0] * npos[0] + npos[1] * npos[1] - npos[2]*npos[2];
440 if (fabs(a) < 0.00000001) {
442 * Only one intersection point...
453 else if (disc > 0.0) {
455 t1 = (-b + disc) / a;
456 t2 = (-b - disc) / a;
463 a= t1; t1= t2; t2= a;
466 /* z of intersection points with diabolo */
467 p1[2]= npos[2] + t1*nray[2];
468 p2[2]= npos[2] + t2*nray[2];
470 /* evaluate both points */
471 if(p1[2]<=0.0) ok1= 1;
472 if(p2[2]<=0.0 && t1!=t2) ok2= 1;
474 /* at least 1 point with negative z */
475 if(ok1==0 && ok2==0) return;
477 /* intersction point with -ladist, the bottom of the cone */
479 t3= (-ladist-npos[2])/nray[2];
481 /* de we have to replace one of the intersection points? */
483 if(p1[2]<-ladist) t1= t3;
490 if(p2[2]<-ladist) t2= t3;
497 else if(ok1==0 || ok2==0) return;
499 /* at least 1 visible interesction point */
500 if(t1<0.0 && t2<0.0) return;
507 /* sort again to be sure */
509 a= t1; t1= t2; t2= a;
512 /* calculate t0: is the maximum visible z (when halo is intersected by face) */
514 if(use_yco==0) t0= (maxz-npos[2])/nray[2];
515 else t0= (maxy-npos[1])/nray[1];
522 p1[0]= npos[0] + t1*nray[0];
523 p1[1]= npos[1] + t1*nray[1];
524 p1[2]= npos[2] + t1*nray[2];
525 p2[0]= npos[0] + t2*nray[0];
526 p2[1]= npos[1] + t2*nray[1];
527 p2[2]= npos[2] + t2*nray[2];
530 /* now we have 2 points, make three lengths with it */
532 a= sqrt(p1[0]*p1[0]+p1[1]*p1[1]+p1[2]*p1[2]);
533 b= sqrt(p2[0]*p2[0]+p2[1]*p2[1]+p2[2]*p2[2]);
542 *intens= c*( (1.0-a)+(1.0-b) );
544 /* WATCH IT: do not clip a,b en c at 1.0, this gives nasty little overflows
545 at the edges (especially with narrow halos) */
546 if(*intens<=0.0) return;
549 /* not needed because t0 has been used for p1/p2 as well */
550 /* if(doclip && t0<t2) { */
551 /* *intens *= (t0-t1)/(t2-t1); */
556 if(lar->shb && lar->shb->shadhalostep) {
557 *intens *= shadow_halo(lar, p1, p2);
563 static void renderspothalo(ShadeInput *shi, float *col)
569 for(a=0; a<R.totlamp; a++) {
571 if(lar->type==LA_SPOT && (lar->mode & LA_HALO) && lar->haint>0) {
579 spothalo(lar, shi, &i);
588 /* clip alpha, is needed for unified 'alpha threshold' (vanillaRenderPipe.c) */
589 if(col[3]>1.0) col[3]= 1.0;
592 void render_lighting_halo(HaloRen *har, float *colf)
595 float i, inp, inpr, rco[3], lv[3], lampdist, ld, t, *vn;
596 float ir, ig, ib, shadfac, soft;
600 VECCOPY(rco, har->co);
603 O.dxco[0]= har->hasize;
608 O.dyco[1]= har->hasize;
611 for(a=0; a<R.totlamp; a++) {
614 /* test for lamplayer */
615 if(lar->mode & LA_LAYER) if((lar->lay & har->lay)==0) continue;
617 /* lampdist cacluation */
618 if(lar->type==LA_SUN || lar->type==LA_HEMI) {
619 VECCOPY(lv, lar->vec);
623 lv[0]= rco[0]-lar->co[0];
624 lv[1]= rco[1]-lar->co[1];
625 lv[2]= rco[2]-lar->co[2];
626 ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
631 /* ld is re-used further on (texco's) */
633 if(lar->mode & LA_QUAD) {
636 t= lar->dist/(lar->dist+lar->ld1*ld);
638 t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld);
643 lampdist= (lar->dist/(lar->dist+ld));
646 if(lar->mode & LA_SPHERE) {
656 if(lar->mode & LA_TEXTURE) {
658 VECCOPY(shi.co, rco);
660 do_lamp_tex(lar, lv, &shi);
663 if(lar->type==LA_SPOT) {
665 if(lar->mode & LA_SQUARE) {
666 if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) {
669 /* rotate view to lampspace */
671 MTC_Mat3MulVecfl(lar->imat, lvrot);
673 x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
674 /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
676 inpr= 1.0/(sqrt(1.0+x*x));
681 inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
690 if(t<lar->spotbl && lar->spotbl!=0.0) {
694 soft= (3.0*t-2.0*t*i);
697 if(lar->mode & LA_ONLYSHADOW) {
698 /* if(ma->mode & MA_SHADOW) { */
699 /* dot product positive: front side face! */
700 inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
702 /* testshadowbuf==0.0 : 100% shadow */
703 shadfac = testshadowbuf(lar->shb, rco, inp);
705 shadfac*= inp*soft*lar->energy;
717 if(lar->mode & LA_ONLYSHADOW) continue;
721 /* dot product and reflectivity*/
723 inp= 1.0-fabs(vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]);
725 /* inp= cos(0.5*M_PI-acos(inp)); */
729 if(lar->type==LA_HEMI) {
734 /* i*= lampdist*ma->ref; */
738 if(i> -0.41) { /* heuristic valua! */
741 /* if(ma->mode & MA_SHADOW) { */
742 shadfac = testshadowbuf(lar->shb, rco, inp);
743 if(shadfac==0.0) continue;
767 void RE_shadehalo(HaloRen *har, char *col, unsigned int zz, float dist, float xn, float yn, short flarec)
770 extern float hashvectf[];
771 float t, zn, radist, ringf=0.0, linef=0.0, alpha, si, co, colf[4];
774 if(R.wrld.mode & WO_MIST) {
775 if(har->type & HA_ONLYSKY) {
776 /* stars have no mist */
782 alpha= mistfactor(har->co)*har->alfa;
785 else alpha= har->alfa;
793 /* *( (int *)col )=0; */
800 /* watch it: abused value: flarec was set to zero in pixstruct */
801 if(flarec) har->pixels+= (int)(har->rad-radist);
807 /* per ring an antialised circle */
810 for(a= har->ringc; a>0; a--, ofs+=2) {
812 rc= hashvectf + (ofs % 768);
814 fac= fabs( rc[1]*(har->rad*fabs(rc[0]) - radist) );
822 if(har->type & HA_VECT) {
823 dist= fabs( har->cos*(yn) - har->sin*(xn) )/har->rad;
824 if(dist>1.0) dist= 1.0;
826 zn= har->sin*xn - har->cos*yn;
827 yn= har->cos*xn + har->sin*yn;
831 else dist= dist/har->radsq;
833 if(har->type & HA_FLARECIRC) {
835 dist= 0.5+fabs(dist-0.5);
842 dist= sin(dist*M_PI_2);
848 else if(har->hard<20) dist*=dist;
856 /* per starpoint an antialaised line */
859 for(a= har->linec; a>0; a--, ofs+=3) {
861 rc= hashvectf + (ofs % 768);
863 fac= fabs( (xn)*rc[0]+(yn)*rc[1]);
874 if(har->starpoints) {
878 hoek*= (1.0+0.25*har->starpoints);
883 hoek= (co*xn+si*yn)*(co*yn-si*xn);
887 ster= (har->rad)/(ster);
889 if(ster<1.0) dist*= sqrt(ster);
893 /* halo intersected? */
894 if(har->zs> zz-har->zd) {
895 t= ((float)(zz-har->zs))/(float)har->zd;
896 alpha*= sqrt(sqrt(t));
911 do_halo_tex(har, xn, yn, colf);
913 /* dist== colf[3]; */
921 colf[0]= dist*har->r;
922 colf[1]= dist*har->g;
923 colf[2]= dist*har->b;
925 if(har->type & HA_XALPHA) colf[3]= dist*dist;
929 if(har->mat && har->mat->mode & MA_HALO_SHADE) {
930 /* we test for lights because of preview... */
931 if(R.totlamp) render_lighting_halo(har, colf);
935 Material *ma= har->mat;
937 colf[0]+= 255.0*linef*ma->specr;
938 colf[1]+= 255.0*linef*ma->specg;
939 colf[2]+= 255.0*linef*ma->specb;
941 if(har->type & HA_XALPHA) colf[3]+= linef*linef;
942 else colf[3]+= linef;
945 Material *ma= har->mat;
947 colf[0]+= 255.0*ringf*ma->mirr;
948 colf[1]+= 255.0*ringf*ma->mirg;
949 colf[2]+= 255.0*ringf*ma->mirb;
951 if(har->type & HA_XALPHA) colf[3]+= ringf*ringf;
952 else colf[3]+= ringf;
956 if(colt>254) col[3]= 255; else col[3]= colt;
959 if(colt>254) col[2]= 255; else col[2]= colt;
962 if(colt>254) col[1]= 255; else col[1]= colt;
965 if(colt>254) col[0]= 255; else col[0]= colt;
970 unsigned int calchalo_z(HaloRen *har, unsigned int zz)
973 if(har->type & HA_ONLYSKY) {
974 if(zz!=0x7FFFFFFF) zz= 0;
978 if(zz<0x800000) zz= (zz+0x7FFFFF);
979 else zz= (zz-0x800000);
984 void scanlinehaloPS(unsigned int *rectz, long *rectdelta, unsigned int *rectt, short ys)
988 float dist,xsq,ysq,xn,yn;
989 unsigned int a, *rz, *rt, zz;
992 short minx,maxx,x,aantal, aantalm, flarec;
995 for(a=0;a<R.tothalo;a++) {
996 if((a & 255)==0) har= R.bloha[a>>8];
999 if( RE_local_test_break() ) break;
1002 else if(ys<har->miny);
1004 minx= floor(har->xs-har->rad);
1005 maxx= ceil(har->xs+har->rad);
1008 else if(R.rectx<minx);
1011 if(maxx>=R.rectx) maxx= R.rectx-1;
1017 yn= (ys-har->ys)*R.ycor;
1019 for(x=minx; x<=maxx; x++) {
1021 flarec= har->flarec; /* har->pixels is inly allowd to count once */
1023 if( IS_A_POINTER_CODE(*rd)) {
1027 if(dist<har->radsq) {
1028 ps= (PixStr *) POINTER_FROM_CODE(*rd);
1030 accol[0]=accol[1]=accol[2]=accol[3]= 0;
1032 aantalm= count_mask(ps->mask);
1035 zz= calchalo_z(har, ps->z);
1038 RE_shadehalo(har, col, zz, dist, xn, yn, flarec);
1039 accol[0]+= aantalm*col[0];
1040 accol[1]+= aantalm*col[1];
1041 accol[2]+= aantalm*col[2];
1042 accol[3]+= aantalm*col[3];
1048 ps= (PixStr *) POINTER_FROM_CODE(*rd);
1049 aantal= R.osa-aantal;
1051 zz= calchalo_z(har, *rz);
1054 RE_shadehalo(har, col, zz, dist, xn, yn, flarec);
1055 accol[0]+= aantal*col[0];
1056 accol[1]+= aantal*col[1];
1057 accol[2]+= aantal*col[2];
1058 accol[3]+= aantal*col[3];
1062 col[0]= accol[0]/R.osa;
1063 col[1]= accol[1]/R.osa;
1064 col[2]= accol[2]/R.osa;
1065 col[3]= accol[3]/R.osa;
1067 /* if(behind > (R.osa>>1)) addalphaUnder(rt,col); */
1068 RE_addalphaAddfac((char *)rt, (char *)col, har->add);
1072 zz= calchalo_z(har, *rz);
1077 if(dist<har->radsq) {
1078 RE_shadehalo(har, col, zz, dist, xn, yn, flarec);
1079 RE_addalphaAddfac((char *)rt, (char *)col, har->add);
1094 void scanlinehalo(unsigned int *rectz, unsigned int *rectt, short ys)
1096 HaloRen *har = NULL;
1097 float dist,xsq,ysq,xn,yn;
1098 unsigned int a, *rz, *rt, zz;
1102 for(a=0; a<R.tothalo; a++) {
1103 if((a & 255)==0) har= R.bloha[a>>8];
1106 if(RE_local_test_break() ) break;
1109 else if(ys<har->miny);
1111 minx= floor(har->xs-har->rad);
1112 maxx= ceil(har->xs+har->rad);
1115 else if(R.rectx<minx);
1118 if(maxx>=R.rectx) maxx= R.rectx-1;
1123 yn= (ys-har->ys)*R.ycor;
1125 for(x=minx; x<=maxx; x++) {
1127 zz= calchalo_z(har, *rz);
1132 if(dist<har->radsq) {
1133 RE_shadehalo(har, col, zz, dist, xn, yn, har->flarec);
1134 RE_addalphaAddfac((char *)rt, (char *)col, har->add);
1149 HaloRen *har = NULL;
1150 float dist, xsq, ysq, xn, yn;
1151 unsigned int a, *rectz, *rz, *rectt, *rt, zz;
1152 int minx, maxx, miny, maxy, x, y;
1156 for(a=0;a<R.tothalo;a++) {
1157 if((a & 255)==0) har= R.bloha[a>>8];
1160 if(RE_local_test_break() ) break;
1163 else if(R.recty<har->miny);
1165 minx= floor(har->xs-har->rad);
1166 maxx= ceil(har->xs+har->rad);
1169 else if(R.rectx<minx);
1172 miny= floor(har->ys-har->rad);
1173 maxy= ceil(har->ys+har->rad);
1176 if(maxx>=R.rectx) maxx= R.rectx-1;
1178 if(maxy>R.recty) maxy= R.recty;
1180 rectt= R.rectot+ R.rectx*miny;
1181 rectz= R.rectz+ R.rectx*miny;
1183 for(y=miny;y<maxy;y++) {
1189 yn= (y - har->ys)*R.ycor;
1191 for(x=minx;x<=maxx;x++) {
1193 zz= calchalo_z(har, *rz);
1200 if(dist<har->radsq) {
1201 RE_shadehalo(har, col, zz, dist, xn, yn, har->flarec);
1203 RE_addalphaAddfac((char *)rt, (char *)col, har->add);
1214 if(RE_local_test_break() ) break;
1222 /* ---------------- shaders ----------------------- */
1224 static double Normalise_d(double *n)
1228 d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
1230 if(d>0.00000000000000001) {
1237 n[0]=n[1]=n[2]= 0.0;
1244 /* Stoke's form factor. Need doubles here for extreme small area sizes */
1245 static float area_lamp_energy(float *co, float *vn, LampRen *lar)
1248 double vec[4][3]; /* vectors of rendered co to vertices lamp */
1249 double cross[4][3]; /* cross products of this */
1250 double rad[4]; /* angles between vecs */
1252 VECSUB(vec[0], co, lar->area[0]);
1253 VECSUB(vec[1], co, lar->area[1]);
1254 VECSUB(vec[2], co, lar->area[2]);
1255 VECSUB(vec[3], co, lar->area[3]);
1257 Normalise_d(vec[0]);
1258 Normalise_d(vec[1]);
1259 Normalise_d(vec[2]);
1260 Normalise_d(vec[3]);
1263 CROSS(cross[0], vec[0], vec[1]);
1264 CROSS(cross[1], vec[1], vec[2]);
1265 CROSS(cross[2], vec[2], vec[3]);
1266 CROSS(cross[3], vec[3], vec[0]);
1268 Normalise_d(cross[0]);
1269 Normalise_d(cross[1]);
1270 Normalise_d(cross[2]);
1271 Normalise_d(cross[3]);
1274 rad[0]= vec[0][0]*vec[1][0]+ vec[0][1]*vec[1][1]+ vec[0][2]*vec[1][2];
1275 rad[1]= vec[1][0]*vec[2][0]+ vec[1][1]*vec[2][1]+ vec[1][2]*vec[2][2];
1276 rad[2]= vec[2][0]*vec[3][0]+ vec[2][1]*vec[3][1]+ vec[2][2]*vec[3][2];
1277 rad[3]= vec[3][0]*vec[0][0]+ vec[3][1]*vec[0][1]+ vec[3][2]*vec[0][2];
1279 rad[0]= acos(rad[0]);
1280 rad[1]= acos(rad[1]);
1281 rad[2]= acos(rad[2]);
1282 rad[3]= acos(rad[3]);
1285 VECMUL(cross[0], rad[0]);
1286 VECMUL(cross[1], rad[1]);
1287 VECMUL(cross[2], rad[2]);
1288 VECMUL(cross[3], rad[3]);
1290 fac= vn[0]*cross[0][0]+ vn[1]*cross[0][1]+ vn[2]*cross[0][2];
1291 fac+= vn[0]*cross[1][0]+ vn[1]*cross[1][1]+ vn[2]*cross[1][2];
1292 fac+= vn[0]*cross[2][0]+ vn[1]*cross[2][1]+ vn[2]*cross[2][2];
1293 fac+= vn[0]*cross[3][0]+ vn[1]*cross[3][1]+ vn[2]*cross[3][2];
1295 if(fac<=0.0) return 0.0;
1296 return pow(fac*lar->areasize, lar->k); // corrected for buttons size and lar->dist^2
1300 float spec(float inp, int hard)
1304 if(inp>=1.0) return 1.0;
1305 else if (inp<=0.0) return 0.0;
1309 if(b1<0.01) b1= 0.01;
1311 if((hard & 1)==0) inp= 1.0;
1312 if(hard & 2) inp*= b1;
1314 if(hard & 4) inp*= b1;
1316 if(hard & 8) inp*= b1;
1318 if(hard & 16) inp*= b1;
1322 if(b1<0.001) b1= 0.0;
1324 if(hard & 32) inp*= b1;
1326 if(hard & 64) inp*=b1;
1328 if(hard & 128) inp*=b1;
1330 if(b1<0.001) b1= 0.0;
1340 float Phong_Spec( float *n, float *l, float *v, int hard )
1350 rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2];
1352 if( rslt > 0.0 ) rslt= spec(rslt, hard);
1359 /* reduced cook torrance spec (for off-specular peak) */
1360 float CookTorr_Spec(float *n, float *l, float *v, int hard)
1362 float i, nh, nv, h[3];
1369 nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2];
1370 if(nh<0.0) return 0.0;
1371 nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2];
1381 float Blinn_Spec(float *n, float *l, float *v, float refrac, float spec_power )
1383 float i, nh, nv, nl, vh, h[3];
1384 float a, b, c, g=0.0, p, f, ang;
1386 if(refrac < 1.0) return 0.0;
1387 if(spec_power == 0.0) return 0.0;
1389 /* conversion from 'hardness' (1-255) to 'spec_power' (50 maps at 0.1) */
1390 if(spec_power<100.0)
1391 spec_power= sqrt(1.0/spec_power);
1392 else spec_power= 10.0/spec_power;
1399 nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
1401 if(nh<0.0) return 0.0;
1403 nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
1405 if(nv<=0.0) nv= 0.01;
1407 nl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
1414 vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; /* Dot product between view vector and half-way vector */
1415 if(vh<=0.0) vh= 0.01;
1421 if( a < b && a < c ) g = a;
1422 else if( b < a && b < c ) g = b;
1423 else if( c < a && c < b ) g = c;
1425 p = sqrt( (double)((refrac * refrac)+(vh*vh)-1.0) );
1426 f = (((p-vh)*(p-vh))/((p+vh)*(p+vh)))*(1+((((vh*(p+vh))-1.0)*((vh*(p+vh))-1.0))/(((vh*(p-vh))+1.0)*((vh*(p-vh))+1.0))));
1427 ang = (float)acos((double)(nh));
1429 i= f * g * exp((double)(-(ang*ang) / (2.0*spec_power*spec_power)));
1434 /* cartoon render spec */
1435 float Toon_Spec( float *n, float *l, float *v, float size, float smooth )
1446 rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2];
1450 if( ang < size ) rslt = 1.0;
1451 else if( ang >= (size + smooth) || smooth == 0.0 ) rslt = 0.0;
1452 else rslt = 1.0 - ((ang - size) / smooth);
1457 /* cartoon render diffuse */
1458 float Toon_Diff( float *n, float *l, float *v, float size, float smooth )
1462 rslt = n[0]*l[0] + n[1]*l[1] + n[2]*l[2];
1464 ang = acos( (double)(rslt) );
1466 if( ang < size ) rslt = 1.0;
1467 else if( ang >= (size + smooth) || smooth == 0.0 ) rslt = 0.0;
1468 else rslt = 1.0 - ((ang - size) / smooth);
1473 /* Oren Nayar diffuse */
1475 /* 'nl' is either dot product, or return value of area light */
1476 /* in latter case, only last multiplication uses 'nl' */
1477 float OrenNayar_Diff_i(float nl, float *n, float *l, float *v, float rough )
1479 float i, nh, nv, vh, realnl, h[3];
1480 float a, b, t, A, B;
1481 float Lit_A, View_A, Lit_B[3], View_B[3];
1488 nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
1489 if(nh<0.0) nh = 0.0;
1491 nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
1492 if(nv<=0.0) nv= 0.0;
1494 realnl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
1495 if(realnl<=0.0) return 0.0;
1496 if(nl<0.0) return 0.0; /* value from area light */
1498 vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; /* Dot product between view vector and halfway vector */
1499 if(vh<=0.0) vh= 0.0;
1501 Lit_A = acos(realnl);
1502 View_A = acos( nv );
1504 Lit_B[0] = l[0] - (realnl * n[0]);
1505 Lit_B[1] = l[1] - (realnl * n[1]);
1506 Lit_B[2] = l[2] - (realnl * n[2]);
1509 View_B[0] = v[0] - (nv * n[0]);
1510 View_B[1] = v[1] - (nv * n[1]);
1511 View_B[2] = v[2] - (nv * n[2]);
1512 Normalise( View_B );
1514 t = Lit_B[0]*View_B[0] + Lit_B[1]*View_B[1] + Lit_B[2]*View_B[2];
1517 if( Lit_A > View_A ) {
1526 A = 1 - (0.5 * ((rough * rough) / ((rough * rough) + 0.33)));
1527 B = 0.45 * ((rough * rough) / ((rough * rough) + 0.09));
1529 b*= 0.95; /* prevent tangens from shooting to inf, 'nl' can be not a dot product here. */
1530 /* overflow only happens with extreme size area light, and higher roughness */
1531 i = nl * ( A + ( B * t * sin(a) * tan(b) ) );
1536 /* Oren Nayar diffuse */
1537 float OrenNayar_Diff(float *n, float *l, float *v, float rough )
1539 float nl= n[0]*l[0] + n[1]*l[1] + n[2]*l[2];
1540 return OrenNayar_Diff_i(nl, n, l, v, rough);
1544 /* --------------------------------------------- */
1546 void calc_R_ref(ShadeInput *shi)
1550 /* shi->vn dot shi->view */
1551 i= -2*(shi->vn[0]*shi->view[0]+shi->vn[1]*shi->view[1]+shi->vn[2]*shi->view[2]);
1553 shi->ref[0]= (shi->view[0]+i*shi->vn[0]);
1554 shi->ref[1]= (shi->view[1]+i*shi->vn[1]);
1555 shi->ref[2]= (shi->view[2]+i*shi->vn[2]);
1557 if(shi->vlr->flag & R_SMOOTH) {
1558 i= -2*( (shi->vn[0]+O.dxno[0])*(shi->view[0]+O.dxview) +
1559 (shi->vn[1]+O.dxno[1])*shi->view[1]+ (shi->vn[2]+O.dxno[2])*shi->view[2] );
1561 O.dxref[0]= shi->ref[0]- ( shi->view[0]+O.dxview+i*(shi->vn[0]+O.dxno[0]));
1562 O.dxref[1]= shi->ref[1]- (shi->view[1]+ i*(shi->vn[1]+O.dxno[1]));
1563 O.dxref[2]= shi->ref[2]- (shi->view[2]+ i*(shi->vn[2]+O.dxno[2]));
1565 i= -2*( (shi->vn[0]+O.dyno[0])*shi->view[0]+
1566 (shi->vn[1]+O.dyno[1])*(shi->view[1]+O.dyview)+ (shi->vn[2]+O.dyno[2])*shi->view[2] );
1568 O.dyref[0]= shi->ref[0]- (shi->view[0]+ i*(shi->vn[0]+O.dyno[0]));
1569 O.dyref[1]= shi->ref[1]- (shi->view[1]+O.dyview+i*(shi->vn[1]+O.dyno[1]));
1570 O.dyref[2]= shi->ref[2]- (shi->view[2]+ i*(shi->vn[2]+O.dyno[2]));
1575 i= -2*( shi->vn[0]*(shi->view[0]+O.dxview) +
1576 shi->vn[1]*shi->view[1]+ shi->vn[2]*shi->view[2] );
1578 O.dxref[0]= shi->ref[0]- (shi->view[0]+O.dxview+i*shi->vn[0]);
1579 O.dxref[1]= shi->ref[1]- (shi->view[1]+ i*shi->vn[1]);
1580 O.dxref[2]= shi->ref[2]- (shi->view[2]+ i*shi->vn[2]);
1582 i= -2*( shi->vn[0]*shi->view[0]+
1583 shi->vn[1]*(shi->view[1]+O.dyview)+ shi->vn[2]*shi->view[2] );
1585 O.dyref[0]= shi->ref[0]- (shi->view[0]+ i*shi->vn[0]);
1586 O.dyref[1]= shi->ref[1]- (shi->view[1]+O.dyview+i*shi->vn[1]);
1587 O.dyref[2]= shi->ref[2]- (shi->view[2]+ i*shi->vn[2]);
1593 /* mix of 'real' fresnel and allowing control. grad defines blending gradient */
1594 float fresnel_fac(float *view, float *vn, float grad, float fac)
1598 if(fac==0.0) return 1.0;
1600 t1= (view[0]*vn[0] + view[1]*vn[1] + view[2]*vn[2]);
1601 if(t1>0.0) t2= 1.0+t1;
1604 t2= grad + (1.0-grad)*pow(t2, fac);
1606 if(t2<0.0) return 0.0;
1607 else if(t2>1.0) return 1.0;
1611 void shade_color(ShadeInput *shi, ShadeResult *shr)
1613 Material *ma= shi->matren;
1615 if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
1616 ma->r= shi->vcol[0];
1617 ma->g= shi->vcol[1];
1618 ma->b= shi->vcol[2];
1621 ma->alpha= shi->mat->alpha; // copy to render material, for fresnel and spectra
1624 if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
1625 shi->mat->r= shi->vcol[0];
1626 shi->mat->g= shi->vcol[1];
1627 shi->mat->b= shi->vcol[2];
1629 do_material_tex(shi);
1632 if(ma->mode & (MA_ZTRA|MA_RAYTRANSP)) {
1633 if(ma->fresnel_tra!=1.0)
1634 ma->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra);
1637 shr->diff[0]= ma->r;
1638 shr->diff[1]= ma->g;
1639 shr->diff[2]= ma->b;
1640 shr->alpha= ma->alpha;
1643 /* mask is used to define the amount of rays/samples */
1644 void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr, int mask)
1648 float i, inp, inpr, t, lv[3], lampdist, ld = 0;
1649 float lvrot[3], *vn, *view, shadfac[4], soft; // shadfac = rgba
1656 memset(shr, 0, sizeof(ShadeResult));
1659 if(ma->mode & MA_ONLYSHADOW) {
1662 shadfac[3]= ir= 0.0;
1663 for(a=0; a<R.totlamp; a++) {
1666 if(lar->mode & LA_LAYER) if((lar->lay & shi->vlr->lay)==0) continue;
1668 lv[0]= shi->co[0]-lar->co[0];
1669 lv[1]= shi->co[1]-lar->co[1];
1670 lv[2]= shi->co[2]-lar->co[2];
1673 /* only test within spotbundel */
1675 inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
1676 if(inpr>lar->spotsi) {
1678 inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
1680 i = testshadowbuf(lar->shb, shi->co, inp);
1682 t= inpr - lar->spotsi;
1683 if(t<lar->spotbl && lar->spotbl!=0.0) {
1697 else if(lar->mode & LA_SHAD_RAY) {
1701 if( shi->vlr->n[0]*lv[0] + shi->vlr->n[1]*lv[1] + shi->vlr->n[2]*lv[2] > -0.01) {
1702 ray_shadow(shi, lar, shad, mask);
1703 shadfac[3]+= shad[3];
1709 if(ir>0.0) shadfac[3]/= ir;
1710 shr->alpha= (shi->mat->alpha)*(1.0-shadfac[3]);
1715 if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
1716 ma->r= shi->vcol[0];
1717 ma->g= shi->vcol[1];
1718 ma->b= shi->vcol[2];
1721 ma->alpha= shi->mat->alpha; // copy to render material, for fresnel and spectra
1723 /* envmap hack, always reset */
1724 shi->refcol[0]= shi->refcol[1]= shi->refcol[2]= shi->refcol[3]= 0.0;
1727 if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
1728 shi->mat->r= shi->vcol[0];
1729 shi->mat->g= shi->vcol[1];
1730 shi->mat->b= shi->vcol[2];
1732 do_material_tex(shi);
1735 if(ma->mode & MA_SHLESS) {
1736 shr->diff[0]= ma->r;
1737 shr->diff[1]= ma->g;
1738 shr->diff[2]= ma->b;
1739 shr->alpha= ma->alpha;
1743 if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
1744 shr->diff[0]= ma->emit+shi->vcol[0];
1745 shr->diff[1]= ma->emit+shi->vcol[1];
1746 shr->diff[2]= ma->emit+shi->vcol[2];
1748 else shr->diff[0]= shr->diff[1]= shr->diff[2]= ma->emit;
1750 for(a=0; a<R.totlamp; a++) {
1753 /* test for lamp layer */
1754 if(lar->mode & LA_LAYER) if((lar->lay & shi->vlr->lay)==0) continue;
1756 /* lampdist calculation */
1757 if(lar->type==LA_SUN || lar->type==LA_HEMI) {
1758 VECCOPY(lv, lar->vec);
1762 lv[0]= shi->co[0]-lar->co[0];
1763 lv[1]= shi->co[1]-lar->co[1];
1764 lv[2]= shi->co[2]-lar->co[2];
1765 ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
1770 /* ld is re-used further on (texco's) */
1771 if(lar->type==LA_AREA) {
1775 if(lar->mode & LA_QUAD) {
1778 t= lar->dist/(lar->dist+lar->ld1*ld);
1780 t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld);
1785 lampdist= (lar->dist/(lar->dist+ld));
1788 if(lar->mode & LA_SPHERE) {
1798 if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv, shi);
1800 /* init transp shadow */
1802 if(ma->mode & MA_SHADOW_TRA) shadfac[0]= shadfac[1]= shadfac[2]= 1.0;
1804 if(lar->type==LA_SPOT) {
1806 if(lar->mode & LA_SQUARE) {
1807 if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) {
1810 /* rotate view to lampspace */
1812 MTC_Mat3MulVecfl(lar->imat, lvrot);
1814 x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
1815 /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
1817 inpr= 1.0/(sqrt(1+x*x));
1822 inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
1826 if(inpr<t) continue;
1831 if(t<lar->spotbl && lar->spotbl!=0.0) {
1835 soft= (3.0*t-2.0*t*i);
1841 if(lar->mode & LA_OSATEX) {
1842 shi->osatex= 1; /* signal for multitex() */
1844 O.dxlv[0]= lv[0] - (shi->co[0]-lar->co[0]+O.dxco[0])/ld;
1845 O.dxlv[1]= lv[1] - (shi->co[1]-lar->co[1]+O.dxco[1])/ld;
1846 O.dxlv[2]= lv[2] - (shi->co[2]-lar->co[2]+O.dxco[2])/ld;
1848 O.dylv[0]= lv[0] - (shi->co[0]-lar->co[0]+O.dyco[0])/ld;
1849 O.dylv[1]= lv[1] - (shi->co[1]-lar->co[1]+O.dyco[1])/ld;
1850 O.dylv[2]= lv[2] - (shi->co[2]-lar->co[2]+O.dyco[2])/ld;
1855 /* dot product and reflectivity*/
1857 inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
1859 if(lar->mode & LA_NO_DIFF) {
1860 i= 0.0; // skip shaders
1862 else if(lar->type==LA_HEMI) {
1867 if(lar->type==LA_AREA) {
1869 if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0)
1870 inp= area_lamp_energy(shi->co, shi->vn, lar);
1874 /* diffuse shaders (oren nayer gets inp from area light) */
1875 if(ma->diff_shader==MA_DIFF_ORENNAYAR) i= OrenNayar_Diff_i(inp, vn, lv, view, ma->roughness);
1876 else if(ma->diff_shader==MA_DIFF_TOON) i= Toon_Diff(vn, lv, view, ma->param[0], ma->param[1]);
1877 else i= inp; // Lambert
1881 i*= lampdist*ma->ref;
1884 /* shadow and spec, (lampdist==0 outside spot) */
1887 if(i>0.0 && (R.r.mode & R_SHADOW)) {
1888 if(ma->mode & MA_SHADOW) {
1891 shadfac[3] = testshadowbuf(lar->shb, shi->co, inp);
1893 else if(lar->type==LA_HEMI); // no shadow
1894 else if(lar->mode & LA_SHAD_RAY) {
1895 // this extra 0.001 prevents boundary cases (shadow on smooth sphere)
1896 if((shi->vlr->n[0]*lv[0] + shi->vlr->n[1]*lv[1] + shi->vlr->n[2]*lv[2]) > -0.001)
1897 ray_shadow(shi, lar, shadfac, mask);
1900 /* warning, here it skips the loop */
1901 if(lar->mode & LA_ONLYSHADOW) {
1903 shadfac[3]= i*lar->energy*(1.0-shadfac[3]);
1904 shr->diff[0] -= shadfac[3];
1905 shr->diff[1] -= shadfac[3];
1906 shr->diff[2] -= shadfac[3];
1911 if(shadfac[3]==0.0) continue;
1918 if(shadfac[3]>0.0 && ma->spec!=0.0 && !(lar->mode & LA_NO_SPEC)) {
1920 if(lar->type==LA_HEMI) {
1921 /* hemi uses no spec shaders (yet) */
1929 t= vn[0]*lv[0]+vn[1]*lv[1]+vn[2]*lv[2];
1931 if(lar->type==LA_HEMI) {
1935 t= shadfac[3]*ma->spec*spec(t, ma->har);
1936 shr->spec[0]+= t*(lar->r * ma->specr);
1937 shr->spec[1]+= t*(lar->g * ma->specg);
1938 shr->spec[2]+= t*(lar->b * ma->specb);
1941 /* specular shaders */
1944 if(ma->spec_shader==MA_SPEC_PHONG)
1945 specfac= Phong_Spec(vn, lv, view, ma->har);
1946 else if(ma->spec_shader==MA_SPEC_COOKTORR)
1947 specfac= CookTorr_Spec(vn, lv, view, ma->har);
1948 else if(ma->spec_shader==MA_SPEC_BLINN)
1949 specfac= Blinn_Spec(vn, lv, view, ma->refrac, (float)ma->har);
1951 specfac= Toon_Spec(vn, lv, view, ma->param[2], ma->param[3]);
1953 /* area lamp correction */
1954 if(lar->type==LA_AREA) specfac*= inp;
1956 t= shadfac[3]*ma->spec*lampdist*specfac;
1958 shr->spec[0]+= t*(lar->r * ma->specr);
1959 shr->spec[1]+= t*(lar->g * ma->specg);
1960 shr->spec[2]+= t*(lar->b * ma->specb);
1965 /* in case 'no diffuse' we still do most calculus, spec can be in shadow */
1966 if(i>0.0 && !(lar->mode & LA_NO_DIFF)) {
1967 if(ma->mode & MA_SHADOW_TRA) {
1968 shr->diff[0]+= i*shadfac[0]*lar->r;
1969 shr->diff[1]+= i*shadfac[1]*lar->g;
1970 shr->diff[2]+= i*shadfac[2]*lar->b;
1973 shr->diff[0]+= i*lar->r;
1974 shr->diff[1]+= i*lar->g;
1975 shr->diff[2]+= i*lar->b;
1980 if(ma->mode & (MA_ZTRA|MA_RAYTRANSP)) {
1981 if(ma->fresnel_tra!=1.0)
1982 ma->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra);
1984 if(ma->spectra!=0.0) {
1986 t = MAX3(shr->spec[0], shr->spec[1], shr->spec[2]);
1989 ma->alpha= (1.0-t)*ma->alpha+t;
1993 shr->alpha= ma->alpha;
1995 if(shr->spec[0]<0.0) shr->spec[0]= 0.0;
1996 if(shr->spec[1]<0.0) shr->spec[1]= 0.0;
1997 if(shr->spec[2]<0.0) shr->spec[2]= 0.0;
1999 if(shr->diff[0]<0.0) shr->diff[0]= 0.0; else shr->diff[0]*= ma->r;
2000 shr->diff[0]+= ma->ambr +ma->amb*shi->rad[0];
2002 if(shr->diff[1]<0.0) shr->diff[1]= 0.0; else shr->diff[1]*= ma->g;
2003 shr->diff[1]+= ma->ambg +ma->amb*shi->rad[1];
2005 if(shr->diff[2]<0.0) shr->diff[2]= 0.0; else shr->diff[2]*= ma->b;
2006 shr->diff[2]+= ma->ambb +ma->amb*shi->rad[2];
2008 /* refcol is for envmap only */
2009 if(shi->refcol[0]!=0.0) {
2010 shr->diff[0]= ma->mirr*shi->refcol[1] + (1.0 - ma->mirr*shi->refcol[0])*shr->diff[0];
2011 shr->diff[1]= ma->mirg*shi->refcol[2] + (1.0 - ma->mirg*shi->refcol[0])*shr->diff[1];
2012 shr->diff[2]= ma->mirb*shi->refcol[3] + (1.0 - ma->mirb*shi->refcol[0])*shr->diff[2];
2017 void shade_input_set_coords(ShadeInput *shi, float u, float v, int i1, int i2, int i3)
2019 VertRen *v1, *v2, *v3;
2020 VlakRen *vlr= shi->vlr;
2022 short texco= shi->matren->texco;
2023 int mode= shi->matren->mode;
2026 /* for rendering of quads, the following values are used to denote vertices:
2027 0 1 2 scanline tria & first half quad, and ray tria
2028 0 2 3 scanline 2nd half quad
2029 0 1 3 raytracer first half quad
2030 2 1 3 raytracer 2nd half quad
2057 /* calculate U and V, for scanline (normal u and v are -1 to 0) */
2059 if( (vlr->flag & R_SMOOTH) || (texco & NEED_UV)) {
2060 float detsh, t00, t10, t01, t11;
2062 if(vlr->snproj==0) {
2063 t00= v3->co[0]-v1->co[0]; t01= v3->co[1]-v1->co[1];
2064 t10= v3->co[0]-v2->co[0]; t11= v3->co[1]-v2->co[1];
2066 else if(vlr->snproj==1) {
2067 t00= v3->co[0]-v1->co[0]; t01= v3->co[2]-v1->co[2];
2068 t10= v3->co[0]-v2->co[0]; t11= v3->co[2]-v2->co[2];
2071 t00= v3->co[1]-v1->co[1]; t01= v3->co[2]-v1->co[2];
2072 t10= v3->co[1]-v2->co[1]; t11= v3->co[2]-v2->co[2];
2075 detsh= t00*t11-t10*t01;
2076 t00/= detsh; t01/=detsh;
2077 t10/=detsh; t11/=detsh;
2079 if(vlr->snproj==0) {
2080 u= (shi->co[0]-v3->co[0])*t11-(shi->co[1]-v3->co[1])*t10;
2081 v= (shi->co[1]-v3->co[1])*t00-(shi->co[0]-v3->co[0])*t01;
2083 O.dxuv[0]= O.dxco[0]*t11- O.dxco[1]*t10;
2084 O.dxuv[1]= O.dxco[1]*t00- O.dxco[0]*t01;
2085 O.dyuv[0]= O.dyco[0]*t11- O.dyco[1]*t10;
2086 O.dyuv[1]= O.dyco[1]*t00- O.dyco[0]*t01;
2089 else if(vlr->snproj==1) {
2090 u= (shi->co[0]-v3->co[0])*t11-(shi->co[2]-v3->co[2])*t10;
2091 v= (shi->co[2]-v3->co[2])*t00-(shi->co[0]-v3->co[0])*t01;
2093 O.dxuv[0]= O.dxco[0]*t11- O.dxco[2]*t10;
2094 O.dxuv[1]= O.dxco[2]*t00- O.dxco[0]*t01;
2095 O.dyuv[0]= O.dyco[0]*t11- O.dyco[2]*t10;
2096 O.dyuv[1]= O.dyco[2]*t00- O.dyco[0]*t01;
2100 u= (shi->co[1]-v3->co[1])*t11-(shi->co[2]-v3->co[2])*t10;
2101 v= (shi->co[2]-v3->co[2])*t00-(shi->co[1]-v3->co[1])*t01;
2103 O.dxuv[0]= O.dxco[1]*t11- O.dxco[2]*t10;
2104 O.dxuv[1]= O.dxco[2]*t00- O.dxco[1]*t01;
2105 O.dyuv[0]= O.dyco[1]*t11- O.dyco[2]*t10;
2106 O.dyuv[1]= O.dyco[2]*t00- O.dyco[1]*t01;
2114 /* calculate punos (vertexnormals) */
2115 if(vlr->flag & R_SMOOTH) {
2116 float n1[3], n2[3], n3[3];
2118 if(vlr->puno & p1) {
2119 n1[0]= -v1->n[0]; n1[1]= -v1->n[1]; n1[2]= -v1->n[2];
2121 n1[0]= v1->n[0]; n1[1]= v1->n[1]; n1[2]= v1->n[2];
2123 if(vlr->puno & p2) {
2124 n2[0]= -v2->n[0]; n2[1]= -v2->n[1]; n2[2]= -v2->n[2];
2126 n2[0]= v2->n[0]; n2[1]= v2->n[1]; n2[2]= v2->n[2];
2129 if(vlr->puno & p3) {
2130 n3[0]= -v3->n[0]; n3[1]= -v3->n[1]; n3[2]= -v3->n[2];
2132 n3[0]= v3->n[0]; n3[1]= v3->n[1]; n3[2]= v3->n[2];
2135 shi->vn[0]= l*n3[0]-u*n1[0]-v*n2[0];
2136 shi->vn[1]= l*n3[1]-u*n1[1]-v*n2[1];
2137 shi->vn[2]= l*n3[2]-u*n1[2]-v*n2[2];
2141 if(shi->osatex && (texco & (TEXCO_NORM|TEXCO_REFL)) ) {
2142 dl= O.dxuv[0]+O.dxuv[1];
2143 O.dxno[0]= dl*n3[0]-O.dxuv[0]*n1[0]-O.dxuv[1]*n2[0];
2144 O.dxno[1]= dl*n3[1]-O.dxuv[0]*n1[1]-O.dxuv[1]*n2[1];
2145 O.dxno[2]= dl*n3[2]-O.dxuv[0]*n1[2]-O.dxuv[1]*n2[2];
2146 dl= O.dyuv[0]+O.dyuv[1];
2147 O.dyno[0]= dl*n3[0]-O.dyuv[0]*n1[0]-O.dyuv[1]*n2[0];
2148 O.dyno[1]= dl*n3[1]-O.dyuv[0]*n1[1]-O.dyuv[1]*n2[1];
2149 O.dyno[2]= dl*n3[2]-O.dyuv[0]*n1[2]-O.dyuv[1]*n2[2];
2154 VECCOPY(shi->vn, vlr->n);
2157 /* texture coordinates. O.dxuv O.dyuv have been set */
2158 if(texco & NEED_UV) {
2159 if(texco & TEXCO_ORCO) {
2161 float *o1, *o2, *o3;
2167 shi->lo[0]= l*o3[0]-u*o1[0]-v*o2[0];
2168 shi->lo[1]= l*o3[1]-u*o1[1]-v*o2[1];
2169 shi->lo[2]= l*o3[2]-u*o1[2]-v*o2[2];
2172 dl= O.dxuv[0]+O.dxuv[1];
2173 O.dxlo[0]= dl*o3[0]-O.dxuv[0]*o1[0]-O.dxuv[1]*o2[0];
2174 O.dxlo[1]= dl*o3[1]-O.dxuv[0]*o1[1]-O.dxuv[1]*o2[1];
2175 O.dxlo[2]= dl*o3[2]-O.dxuv[0]*o1[2]-O.dxuv[1]*o2[2];
2176 dl= O.dyuv[0]+O.dyuv[1];
2177 O.dylo[0]= dl*o3[0]-O.dyuv[0]*o1[0]-O.dyuv[1]*o2[0];
2178 O.dylo[1]= dl*o3[1]-O.dyuv[0]*o1[1]-O.dyuv[1]*o2[1];
2179 O.dylo[2]= dl*o3[2]-O.dyuv[0]*o1[2]-O.dyuv[1]*o2[2];
2184 if(texco & TEXCO_GLOB) {
2185 VECCOPY(shi->gl, shi->co);
2186 MTC_Mat4MulVecfl(R.viewinv, shi->gl);
2188 VECCOPY(O.dxgl, O.dxco);
2189 MTC_Mat3MulVecfl(R.imat, O.dxco);
2190 VECCOPY(O.dygl, O.dyco);
2191 MTC_Mat3MulVecfl(R.imat, O.dyco);
2194 if((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL|MA_FACETEXTURE))) {
2195 int j1=i1, j2=i2, j3=i3;
2197 /* to prevent storing new tfaces or vcols, we check a split runtime */
2199 /* |\ 1| or |1 /| */
2201 /* 1---2 1---2 0 = orig face, 1 = new face */
2203 /* Update vert nums to point to correct verts of original face */
2204 if(vlr->flag & R_DIVIDE_24) {
2205 if(vlr->flag & R_FACE_SPLIT) {
2212 else if(vlr->flag & R_FACE_SPLIT) {
2216 if(mode & MA_VERTEXCOL) {
2219 char *cp1, *cp2, *cp3;
2221 cp1= (char *)(vlr->vcol+j1);
2222 cp2= (char *)(vlr->vcol+j2);
2223 cp3= (char *)(vlr->vcol+j3);
2225 shi->vcol[0]= (l*cp3[3]-u*cp1[3]-v*cp2[3])/255.0;
2226 shi->vcol[1]= (l*cp3[2]-u*cp1[2]-v*cp2[2])/255.0;
2227 shi->vcol[2]= (l*cp3[1]-u*cp1[1]-v*cp2[1])/255.0;
2237 float *uv1, *uv2, *uv3;
2239 uv1= vlr->tface->uv[j1];
2240 uv2= vlr->tface->uv[j2];
2241 uv3= vlr->tface->uv[j3];
2243 shi->uv[0]= -1.0 + 2.0*(l*uv3[0]-u*uv1[0]-v*uv2[0]);
2244 shi->uv[1]= -1.0 + 2.0*(l*uv3[1]-u*uv1[1]-v*uv2[1]);
2249 dl= O.dxuv[0]+O.dxuv[1];
2253 O.dxuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
2254 O.dxuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
2256 dl= O.dyuv[0]+O.dyuv[1];
2260 O.dyuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
2261 O.dyuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
2264 if(mode & MA_FACETEXTURE) {
2265 if((mode & MA_VERTEXCOL)==0) {
2270 if(vlr->tface) render_realtime_texture(shi);
2274 shi->uv[0]= 2.0*(u+.5);
2275 shi->uv[1]= 2.0*(v+.5);
2278 if(texco & TEXCO_NORM) {
2279 shi->orn[0]= shi->vn[0];
2280 shi->orn[1]= shi->vn[1];
2281 shi->orn[2]= shi->vn[2];
2284 if(mode & MA_RADIO) {
2285 shi->rad[0]= (l*v3->rad[0] - u*v1->rad[0] - v*v2->rad[0]);
2286 shi->rad[1]= (l*v3->rad[1] - u*v1->rad[1] - v*v2->rad[1]);
2287 shi->rad[2]= (l*v3->rad[2] - u*v1->rad[2] - v*v2->rad[2]);
2290 shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0;
2293 if(texco & TEXCO_REFL) {
2294 /* mirror reflection colour textures (and envmap) */
2300 shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0;
2304 /* x,y: window coordinate from 0 to rectx,y */
2305 /* return pointer to rendered face */
2306 void *shadepixel(float x, float y, int vlaknr, int mask, float *col)
2312 if(vlaknr< 0) { /* error */
2315 /* currently in use for dithering soft shadow */
2319 if(vlaknr==0) { /* sky */
2320 col[0]= 0.0; col[1]= 0.0; col[2]= 0.0; col[3]= 0.0;
2322 else if( (vlaknr & 0x7FFFFF) <= R.totvlak) {
2323 VertRen *v1, *v2, *v3;
2324 float alpha, fac, dvlak, deler;
2326 vlr= RE_findOrAddVlak( (vlaknr-1) & 0x7FFFFF);
2329 shi.matren= shi.mat->ren;
2331 shi.osatex= (shi.matren->texco & TEXCO_OSA);
2334 dvlak= v1->co[0]*vlr->n[0]+v1->co[1]*vlr->n[1]+v1->co[2]*vlr->n[2];
2336 /* COXYZ AND VIEW VECTOR */
2337 shi.view[0]= (x+(R.xstart)+1.0);
2339 if(R.flag & R_SEC_FIELD) {
2340 if(R.r.mode & R_ODDFIELD) shi.view[1]= (y+R.ystart+0.5)*R.ycor;
2341 else shi.view[1]= (y+R.ystart+1.5)*R.ycor;
2343 else shi.view[1]= (y+R.ystart+1.0)*R.ycor;
2345 shi.view[2]= -R.viewfac;
2347 if(R.r.mode & R_PANORAMA) {
2348 float panoco, panosi, u, v;
2349 panoco = getPanovCo();
2350 panosi = getPanovSi();
2352 u= shi.view[0]; v= shi.view[2];
2353 shi.view[0]= panoco*u + panosi*v;
2354 shi.view[2]= -panosi*u + panoco*v;
2357 deler= vlr->n[0]*shi.view[0] + vlr->n[1]*shi.view[1] + vlr->n[2]*shi.view[2];
2358 if (deler!=0.0) fac= R.zcor= dvlak/deler;
2359 else fac= R.zcor= 0.0;
2361 shi.co[0]= fac*shi.view[0];
2362 shi.co[1]= fac*shi.view[1];
2363 shi.co[2]= fac*shi.view[2];
2365 /* pixel dx/dy for render coord */
2366 if(shi.osatex || (R.r.mode & R_SHADOW) ) {
2367 float u= dvlak/(deler-vlr->n[0]);
2368 float v= dvlak/(deler- R.ycor*vlr->n[1]);
2370 O.dxco[0]= shi.co[0]- (shi.view[0]-1.0)*u;
2371 O.dxco[1]= shi.co[1]- (shi.view[1])*u;
2372 O.dxco[2]= shi.co[2]- (shi.view[2])*u;
2374 O.dyco[0]= shi.co[0]- (shi.view[0])*v;
2375 O.dyco[1]= shi.co[1]- (shi.view[1]-1.0*R.ycor)*v;
2376 O.dyco[2]= shi.co[2]- (shi.view[2])*v;
2380 fac= Normalise(shi.view);
2381 R.zcor*= fac; /* for mist */
2384 if( (shi.matren->texco & TEXCO_REFL) ) {
2386 O.dyview= -R.ycor/fac;
2390 /* calcuate normals, texture coords, vertex colors, etc */
2391 if(vlaknr & 0x800000)
2392 shade_input_set_coords(&shi, 1.0, 1.0, 0, 2, 3);
2394 shade_input_set_coords(&shi, 1.0, 1.0, 0, 1, 2);
2396 /* this only avalailable for scanline */
2397 if(shi.matren->texco & TEXCO_WINDOW) {
2398 shi.winco[0]= (x+(R.xstart))/(float)R.afmx;
2399 shi.winco[1]= (y+(R.ystart))/(float)R.afmy;
2401 /* after this the u and v AND O.dxuv and O.dyuv are incorrect */
2402 if(shi.matren->texco & TEXCO_STICKY) {
2404 extern float Zmulx, Zmuly;
2405 float *o1, *o2, *o3, hox, hoy, l, dl, u, v;
2406 float s00, s01, s10, s11, detsh;
2408 if(vlaknr & 0x800000) {
2409 v2= vlr->v3; v3= vlr->v4;
2411 v2= vlr->v2; v3= vlr->v3;
2414 s00= v3->ho[0]/v3->ho[3] - v1->ho[0]/v1->ho[3];
2415 s01= v3->ho[1]/v3->ho[3] - v1->ho[1]/v1->ho[3];
2416 s10= v3->ho[0]/v3->ho[3] - v2->ho[0]/v2->ho[3];
2417 s11= v3->ho[1]/v3->ho[3] - v2->ho[1]/v2->ho[3];
2419 detsh= s00*s11-s10*s01;
2420 s00/= detsh; s01/=detsh;
2421 s10/=detsh; s11/=detsh;
2423 /* recalc u and v again */
2426 u= (hox - v3->ho[0]/v3->ho[3])*s11 - (hoy - v3->ho[1]/v3->ho[3])*s10;
2427 v= (hoy - v3->ho[1]/v3->ho[3])*s00 - (hox - v3->ho[0]/v3->ho[3])*s01;
2434 shi.sticky[0]= l*o3[0]-u*o1[0]-v*o2[0];
2435 shi.sticky[1]= l*o3[1]-u*o1[1]-v*o2[1];
2438 O.dxuv[0]= s11/Zmulx;
2439 O.dxuv[1]= - s01/Zmulx;
2440 O.dyuv[0]= - s10/Zmuly;
2441 O.dyuv[1]= s00/Zmuly;
2443 dl= O.dxuv[0]+O.dxuv[1];
2444 O.dxsticky[0]= dl*o3[0]-O.dxuv[0]*o1[0]-O.dxuv[1]*o2[0];
2445 O.dxsticky[1]= dl*o3[1]-O.dxuv[0]*o1[1]-O.dxuv[1]*o2[1];
2446 dl= O.dyuv[0]+O.dyuv[1];
2447 O.dysticky[0]= dl*o3[0]-O.dyuv[0]*o1[0]-O.dyuv[1]*o2[0];
2448 O.dysticky[1]= dl*o3[1]-O.dyuv[0]*o1[1]-O.dyuv[1]*o2[1];
2453 /* ------ main shading loop */
2454 shade_lamp_loop(&shi, &shr, mask);
2456 if(shi.matren->translucency!=0.0) {
2459 VecMulf(shi.vn, -1.0);
2460 VecMulf(shi.vlr->n, -1.0);
2461 shade_lamp_loop(&shi, &shr_t, mask);
2462 shr.diff[0]+= shi.matren->translucency*shr_t.diff[0];
2463 shr.diff[1]+= shi.matren->translucency*shr_t.diff[1];
2464 shr.diff[2]+= shi.matren->translucency*shr_t.diff[2];
2465 VecMulf(shi.vn, -1.0);
2466 VecMulf(shi.vlr->n, -1.0);
2469 if(R.r.mode & R_RAYTRACE) {
2470 if(shi.matren->ray_mirror!=0.0 || (shi.mat->mode & MA_RAYTRANSP && shr.alpha!=1.0)) {
2471 ray_trace(&shi, &shr, mask);
2475 // doesnt look 'correct', but is better for preview, plus envmaps dont raytrace this
2476 if(shi.mat->mode & MA_RAYTRANSP) shr.alpha= 1.0;
2479 VecAddf(col, shr.diff, shr.spec);
2481 /* exposure correction */
2482 if(R.wrld.exp!=0.0 || R.wrld.range!=1.0) {
2483 if((shi.matren->mode & MA_SHLESS)==0) {
2484 col[0]= R.wrld.linfac*(1.0-exp( col[0]*R.wrld.logfac) );
2485 col[1]= R.wrld.linfac*(1.0-exp( col[1]*R.wrld.logfac) );
2486 col[2]= R.wrld.linfac*(1.0-exp( col[2]*R.wrld.logfac) );
2491 if( (R.wrld.mode & WO_MIST) && (shi.matren->mode & MA_NOMIST)==0 ){
2492 alpha= mistfactor(shi.co);
2496 if(shr.alpha!=1.0 || alpha!=1.0) {
2497 fac= alpha*(shr.alpha);
2507 if(R.flag & R_LAMPHALO) {
2508 if(vlaknr<=0) { /* calc view vector and put shi.co at far */
2510 shi.view[0]= (x+(R.xstart)+1.0);
2512 if(R.flag & R_SEC_FIELD) {
2513 if(R.r.mode & R_ODDFIELD) shi.view[1]= (y+R.ystart+0.5)*R.ycor;
2514 else shi.view[1]= (y+R.ystart+1.5)*R.ycor;
2516 else shi.view[1]= (y+R.ystart+1.0)*R.ycor;
2518 shi.view[2]= -R.viewfac;
2520 if(R.r.mode & R_PANORAMA) {
2521 float u,v, panoco, panosi;
2522 panoco = getPanovCo();
2523 panosi = getPanovSi();
2525 u= shi.view[0]; v= shi.view[2];
2526 shi.view[0]= panoco*u + panosi*v;
2527 shi.view[2]= -panosi*u + panoco*v;
2533 renderspothalo(&shi, col);
2539 void shadepixel_short(float x, float y, int vlaknr, int mask, unsigned short *shortcol)
2543 shadepixel(x, y, vlaknr, mask, colf);
2545 if(colf[0]<=0.0) shortcol[0]= 0; else if(colf[0]>=1.0) shortcol[0]= 65535;
2546 else shortcol[0]= 65535.0*colf[0];
2547 if(colf[1]<=0.0) shortcol[1]= 0; else if(colf[1]>=1.0) shortcol[1]= 65535;
2548 else shortcol[1]= 65535.0*colf[1];
2549 if(colf[2]<=0.0) shortcol[2]= 0; else if(colf[2]>=1.0) shortcol[2]= 65535;
2550 else shortcol[2]= 65535.0*colf[2];
2551 if(colf[3]<=0.0) shortcol[3]= 0; else if(colf[3]>=1.0) shortcol[3]= 65535;
2552 else shortcol[3]= 65535.0*colf[3];
2555 shortcol[0]= igamtab2[ shortcol[0] ];
2556 shortcol[1]= igamtab2[ shortcol[1] ];
2557 shortcol[2]= igamtab2[ shortcol[2] ];
2571 psm->next= (PixStrMain *)MEM_mallocN(sizeof(PixStrMain),"pixstrMain");
2575 psm->ps= (PixStr *)MEM_mallocN(4096*sizeof(PixStr),"pixstr");
2583 PixStrMain *psm,*next;
2593 if(psm!= &psmfirst) MEM_freeN(psm);
2601 void addps(long *rd, int vlak, unsigned int z, short ronde)
2603 static PixStr *prev;
2604 PixStr *ps, *last = NULL;
2607 if( IS_A_POINTER_CODE(*rd)) {
2608 ps= (PixStr *) POINTER_FROM_CODE(*rd);
2609 vlakand= (vlak & 0x7FFFFF);
2611 if( (ps->vlak0 & 0x7FFFFF) == vlakand ) return;
2614 if( (ps->vlak & 0x7FFFFF) == vlakand ) {
2615 ps->mask |= (1<<ronde);
2622 if((psmteller & 4095)==0) prev= addpsmain();
2630 prev->mask = (1<<ronde);
2636 /* make first PS (pixel struct) */
2637 if((psmteller & 4095)==0) prev= addpsmain();
2642 prev->vlak0= (int) *rd;
2645 prev->mask = (1<<ronde);
2647 *rd= POINTER_TO_CODE(prev);
2651 int count_mask(unsigned short mask)
2653 return (cmask[mask & 255]+cmask[mask>>8]);
2656 float count_maskf(unsigned short mask)
2658 return (fmask[mask & 255]+fmask[mask>>8]);
2662 void add_filt_mask(unsigned int mask, unsigned short *col, unsigned int *rb1, unsigned int *rb2, unsigned int *rb3)
2664 /* calc the value of mask */
2665 unsigned int a, maskand, maskshift;
2667 unsigned short val, r, g, b, al;
2674 maskand= (mask & 255);
2675 maskshift= (mask >>8);
2677 for(j=2; j>=0; j--) {
2681 val= *(mask1[a] +maskand) + *(mask2[a] +maskshift);
2690 val= *(mask1[a] +maskand) + *(mask2[a] +maskshift);
2699 val= *(mask1[a] +maskand) + *(mask2[a] +maskshift);
2713 void edge_enhance(void)
2715 /* use zbuffer to define edges, add it to the image */
2716 int val, y, x, col, *rz, *rz1, *rz2, *rz3;
2719 /* shift values in zbuffer 3 to the right */
2723 for(y=0; y<R.recty; y++) {
2724 for(x=0; x<R.rectx; x++, rz++) {
2729 rz1= (int *)R.rectz;
2732 rz= (int *)R.rectot+R.rectx;
2734 if(R.r.mode & R_OSA) {
2735 cp= (char *)(R.rectaccu+R.rectx);
2738 cp= (char *)(R.rectot+R.rectx);
2741 /* rz itself does not seem to be used. */
2743 for(y=0; y<R.recty-2; y++) {
2746 for(x=0; x<R.rectx-2; x++, rz++, rz1++, rz2++, rz3++, cp+=4) {
2748 col= abs(12*rz2[1]-rz1[0]-2*rz1[1]-rz1[2]-2*rz2[0]-2*rz2[2]-rz3[0]-2*rz3[1]-rz3[2])/3;
2749 /* removed the abs... now, only front/back? pixels are */
2750 /* accentuated? No, the lines seem shifted strangely. the does */
2751 /* not seem to be any overlap? strange... */
2752 /* col= -( 12*rz2[1] */
2753 /* - rz1[0] - 2*rz1[1] - rz1[2] */
2754 /* - 2*rz2[0] - 2*rz2[2] */
2755 /* - rz3[0] - 2*rz3[1] - rz3[2]) /3; */
2757 col= (R.r.edgeint*col)>>14;
2758 if(col>255) col= 255;
2761 if(R.r.mode & R_OSA) {
2765 if(val>255) cp[3]= 255; else cp[3]= val;
2769 if(val<0) cp[0]= 0; else cp[0]= val;
2771 if(val<0) cp[1]= 0; else cp[1]= val;
2773 if(val<0) cp[2]= 0; else cp[2]= val;
2786 /* ********************* MAINLOOPS ******************** */
2788 extern unsigned short *Acolrow;
2789 /* short zbuffermetdehand(); */
2790 void zbufshadeDA(void) /* Delta Accum Pixel Struct */
2792 extern float Zjitx,Zjity;
2794 float xd, yd, xs, ys;
2795 unsigned int *rz, *rp, *rt, mask, fullmask;
2796 unsigned int *rowbuf1, *rowbuf2, *rowbuf3, *rb1, *rb2, *rb3;
2799 unsigned short *colrb, *acol, shortcol[4];
2801 char *colrt, tempcol[4];
2803 R.rectdaps= MEM_callocN(sizeof(long)*R.rectx*R.recty+4,"zbufDArectd");
2804 if(R.flag & R_ZTRA) bgnaccumbuf();
2808 if(R.r.mode & R_EDGE) {
2809 R.rectaccu= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty,"zbufshadeDA");
2812 for(v=0; v<R.osa; v++) {
2819 RE_local_printrenderinfo(0.0, v);
2822 fillrect(R.rectot,R.rectx,R.recty,0);
2839 for(y=0; y<R.recty; y++) {
2840 for(x=0; x<R.rectx; x++, rp++, rd++) {