a561e39fb6fe41b32e27e05ca121b761d5d0185a
[blender.git] / source / blender / render / intern / source / rendercore.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
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
12  * about this.
13  *
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.
18  *
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.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): Hos, Robert Wenzlaff.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33
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
41 #include "BKE_utildefines.h"
42
43 #include "DNA_mesh_types.h"
44 #include "DNA_meshdata_types.h"
45 #include "DNA_image_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_camera_types.h"
48 #include "DNA_lamp_types.h"
49 #include "DNA_texture_types.h"
50
51 #include "BKE_global.h"
52 #include "BKE_texture.h"
53
54 #include "BLI_rand.h"
55
56 /* local include */
57 #include "RE_callbacks.h"
58 #include "render.h"
59 #include "zbuf.h"               /* stuff like bgnaccumbuf, fillrect, ...*/
60 #include "pixelblending.h"
61 #include "pixelshading.h"
62 #include "vanillaRenderPipe.h"  /* transfercolour... */
63 #include "gammaCorrectionTables.h"
64 #include "shadbuf.h"
65 #include "renderHelp.h"
66
67 #include "jitter.h"
68 #include "texture.h"
69
70 /* system includes */
71 #include <math.h>
72 #include <string.h>
73 #include <stdlib.h>
74
75
76 /* own include */
77 #include "rendercore.h"
78
79 #ifdef HAVE_CONFIG_H
80 #include <config.h>
81 #endif
82
83 #include "SDL_thread.h"
84
85
86 /* global for this file. struct render will be more dynamic later, to allow multiple renderers */
87 RE_Render R;
88
89 float mistfactor(float *co)     /* dist en height, return alpha */
90 {
91         float fac, hi;
92         
93         fac= R.zcor - R.wrld.miststa;   /* R.zcor is calculated per pixel */
94
95         /* fac= -co[2]-R.wrld.miststa; */
96
97         if(fac>0.0) {
98                 if(fac< R.wrld.mistdist) {
99                         
100                         fac= (fac/(R.wrld.mistdist));
101                         
102                         if(R.wrld.mistype==0) fac*= fac;
103                         else if(R.wrld.mistype==1);
104                         else fac= sqrt(fac);
105                 }
106                 else fac= 1.0;
107         }
108         else fac= 0.0;
109         
110         /* height switched off mist */
111         if(R.wrld.misthi!=0.0 && fac!=0.0) {
112                 /* at height misthi the mist is completely gone */
113
114                 hi= R.viewinv[0][2]*co[0]+R.viewinv[1][2]*co[1]+R.viewinv[2][2]*co[2]+R.viewinv[3][2];
115                 
116                 if(hi>R.wrld.misthi) fac= 0.0;
117                 else if(hi>0.0) {
118                         hi= (R.wrld.misthi-hi)/R.wrld.misthi;
119                         fac*= hi*hi;
120                 }
121         }
122
123         return (1.0-fac)* (1-R.wrld.misi);      
124 }
125
126 /* external for preview only */
127 void RE_sky_char(float *view, char *col)
128 {
129         float f, colf[3];
130         float dither_value;
131
132         dither_value = ( (BLI_frand()-0.5)*R.r.dither_intensity)/256.0; 
133         
134         shadeSkyPixelFloat(colf, view, NULL);
135         
136         f= 255.0*(colf[0]+dither_value);
137         if(f<=0.0) col[0]= 0; else if(f>255.0) col[0]= 255;
138         else col[0]= (char)f;
139         f= 255.0*(colf[1]+dither_value);
140         if(f<=0.0) col[1]= 0; else if(f>255.0) col[1]= 255;
141         else col[1]= (char)f;
142         f= 255.0*(colf[2]+dither_value);
143         if(f<=0.0) col[2]= 0; else if(f>255.0) col[2]= 255;
144         else col[2]= (char)f;
145         col[3]= 1;      /* to prevent wrong optimalisation alphaover of flares */
146 }
147
148
149 /* ************************************** */
150
151
152 static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens)
153 {
154         double a, b, c, disc, nray[3], npos[3];
155         float t0, t1 = 0.0, t2= 0.0, t3, haint;
156         float p1[3], p2[3], ladist, maxz = 0.0, maxy = 0.0;
157         int snijp, doclip=1, use_yco=0;
158         int ok1=0, ok2=0;
159         
160         *intens= 0.0;
161         haint= lar->haint;
162         
163         VECCOPY(npos, lar->sh_invcampos);       /* in initlamp calculated */
164         
165         /* rotate view */
166         VECCOPY(nray, shi->view);
167         MTC_Mat3MulVecd(lar->imat, nray);
168         
169         if(R.wrld.mode & WO_MIST) {
170                 /* patchy... */
171                 R.zcor= -lar->co[2];
172                 haint *= mistfactor(lar->co);
173                 if(haint==0.0) {
174                         return;
175                 }
176         }
177
178
179         /* rotate maxz */
180         if(shi->co[2]==0.0) doclip= 0;  /* for when halo at sky */
181         else {
182                 p1[0]= shi->co[0]-lar->co[0];
183                 p1[1]= shi->co[1]-lar->co[1];
184                 p1[2]= shi->co[2]-lar->co[2];
185         
186                 maxz= lar->imat[0][2]*p1[0]+lar->imat[1][2]*p1[1]+lar->imat[2][2]*p1[2];
187                 maxz*= lar->sh_zfac;
188                 maxy= lar->imat[0][1]*p1[0]+lar->imat[1][1]*p1[1]+lar->imat[2][1]*p1[2];
189
190                 if( fabs(nray[2]) <0.000001 ) use_yco= 1;
191         }
192         
193         /* scale z to make sure volume is normalized */ 
194         nray[2]*= lar->sh_zfac;
195         /* nray does not need normalization */
196         
197         ladist= lar->sh_zfac*lar->dist;
198         
199         /* solve */
200         a = nray[0] * nray[0] + nray[1] * nray[1] - nray[2]*nray[2];
201         b = nray[0] * npos[0] + nray[1] * npos[1] - nray[2]*npos[2];
202         c = npos[0] * npos[0] + npos[1] * npos[1] - npos[2]*npos[2];
203
204         snijp= 0;
205         if (fabs(a) < 0.00000001) {
206                 /*
207                  * Only one intersection point...
208                  */
209                 return;
210         }
211         else {
212                 disc = b*b - a*c;
213                 
214                 if(disc==0.0) {
215                         t1=t2= (-b)/ a;
216                         snijp= 2;
217                 }
218                 else if (disc > 0.0) {
219                         disc = sqrt(disc);
220                         t1 = (-b + disc) / a;
221                         t2 = (-b - disc) / a;
222                         snijp= 2;
223                 }
224         }
225         if(snijp==2) {
226                 /* sort */
227                 if(t1>t2) {
228                         a= t1; t1= t2; t2= a;
229                 }
230
231                 /* z of intersection points with diabolo */
232                 p1[2]= npos[2] + t1*nray[2];
233                 p2[2]= npos[2] + t2*nray[2];
234
235                 /* evaluate both points */
236                 if(p1[2]<=0.0) ok1= 1;
237                 if(p2[2]<=0.0 && t1!=t2) ok2= 1;
238                 
239                 /* at least 1 point with negative z */
240                 if(ok1==0 && ok2==0) return;
241                 
242                 /* intersction point with -ladist, the bottom of the cone */
243                 if(use_yco==0) {
244                         t3= (-ladist-npos[2])/nray[2];
245                                 
246                         /* de we have to replace one of the intersection points? */
247                         if(ok1) {
248                                 if(p1[2]<-ladist) t1= t3;
249                         }
250                         else {
251                                 ok1= 1;
252                                 t1= t3;
253                         }
254                         if(ok2) {
255                                 if(p2[2]<-ladist) t2= t3;
256                         }
257                         else {
258                                 ok2= 1;
259                                 t2= t3;
260                         }
261                 }
262                 else if(ok1==0 || ok2==0) return;
263                 
264                 /* at least 1 visible interesction point */
265                 if(t1<0.0 && t2<0.0) return;
266                 
267                 if(t1<0.0) t1= 0.0;
268                 if(t2<0.0) t2= 0.0;
269                 
270                 if(t1==t2) return;
271                 
272                 /* sort again to be sure */
273                 if(t1>t2) {
274                         a= t1; t1= t2; t2= a;
275                 }
276                 
277                 /* calculate t0: is the maximum visible z (when halo is intersected by face) */ 
278                 if(doclip) {
279                         if(use_yco==0) t0= (maxz-npos[2])/nray[2];
280                         else t0= (maxy-npos[1])/nray[1];
281
282                         if(t0<t1) return;
283                         if(t0<t2) t2= t0;
284                 }
285
286                 /* calc points */
287                 p1[0]= npos[0] + t1*nray[0];
288                 p1[1]= npos[1] + t1*nray[1];
289                 p1[2]= npos[2] + t1*nray[2];
290                 p2[0]= npos[0] + t2*nray[0];
291                 p2[1]= npos[1] + t2*nray[1];
292                 p2[2]= npos[2] + t2*nray[2];
293                 
294                         
295                 /* now we have 2 points, make three lengths with it */
296                 
297                 a= sqrt(p1[0]*p1[0]+p1[1]*p1[1]+p1[2]*p1[2]);
298                 b= sqrt(p2[0]*p2[0]+p2[1]*p2[1]+p2[2]*p2[2]);
299                 c= VecLenf(p1, p2);
300                 
301                 a/= ladist;
302                 a= sqrt(a);
303                 b/= ladist; 
304                 b= sqrt(b);
305                 c/= ladist;
306                 
307                 *intens= c*( (1.0-a)+(1.0-b) );
308
309                 /* WATCH IT: do not clip a,b en c at 1.0, this gives nasty little overflows
310                         at the edges (especially with narrow halos) */
311                 if(*intens<=0.0) return;
312
313                 /* soft area */
314                 /* not needed because t0 has been used for p1/p2 as well */
315                 /* if(doclip && t0<t2) { */
316                 /*      *intens *= (t0-t1)/(t2-t1); */
317                 /* } */
318                 
319                 *intens *= haint;
320                 
321                 if(lar->shb && lar->shb->shadhalostep) {
322                         *intens *= shadow_halo(lar, p1, p2);
323                 }
324                 
325         }
326 }
327
328 static void renderspothalo(ShadeInput *shi, float *col)
329 {
330         LampRen *lar;
331         float i;
332         int a;
333         
334         for(a=0; a<R.totlamp; a++) {
335                 lar= R.la[a];
336                 if(lar->type==LA_SPOT && (lar->mode & LA_HALO) && lar->haint>0) {
337         
338                         spothalo(lar, shi, &i);
339                         if(i>0.0) {
340                                 col[3]+= i;
341                                 col[0]+= i*lar->r;
342                                 col[1]+= i*lar->g;
343                                 col[2]+= i*lar->b;                      
344                         }
345                 }
346         }
347         /* clip alpha, is needed for unified 'alpha threshold' (vanillaRenderPipe.c) */
348         if(col[3]>1.0) col[3]= 1.0;
349 }
350
351
352 static unsigned int calchalo_z(HaloRen *har, unsigned int zz)
353 {
354
355         if(har->type & HA_ONLYSKY) {
356                 if(zz!=0x7FFFFFFF) zz= 0;
357         }
358         else {
359                 zz= (zz>>8);
360                 if(zz<0x800000) zz= (zz+0x7FFFFF);
361                 else zz= (zz-0x800000);
362         }
363         return zz;
364 }
365
366 static void scanlinehaloPS(unsigned int *rectz, long *rectdelta, float *rowbuf, short ys)
367 {
368         HaloRen *har = NULL;
369         PixStr *ps;
370         float dist, xsq, ysq, xn, yn;
371         float *rb;
372         float col[4], accol[4];
373         unsigned int a, *rz, zz;
374         long *rd;
375         short minx, maxx, x, aantal, aantalm, flarec;
376
377         for(a=0; a<R.tothalo; a++) {
378                 if((a & 255)==0) {
379                         har= R.bloha[a>>8];
380                         if( RE_local_test_break() ) break;  
381                 }
382                 else har++;
383
384                 if(ys>har->maxy);
385                 else if(ys<har->miny);
386                 else {
387                         minx= floor(har->xs-har->rad);
388                         maxx= ceil(har->xs+har->rad);
389                         
390                         if(maxx<0);
391                         else if(R.rectx<minx);
392                         else {
393                                 if(minx<0) minx= 0;
394                                 if(maxx>=R.rectx) maxx= R.rectx-1;
395
396                                 rb= rowbuf + 4*minx;
397                                 rd= rectdelta + minx;
398                                 rz= rectz + minx;
399
400                                 yn= (ys-har->ys)*R.ycor;
401                                 ysq= yn*yn;
402                                 for(x=minx; x<=maxx; x++) {
403                                         
404                                         flarec= har->flarec;    /* har->pixels is inly allowd to count once */
405
406                                         if( IS_A_POINTER_CODE(*rd)) {
407                                                 xn= x-har->xs;
408                                                 xsq= xn*xn;
409                                                 dist= xsq+ysq;
410                                                 if(dist<har->radsq) {
411                                                         
412                                                         ps= (PixStr *) POINTER_FROM_CODE(*rd);
413                                                         aantal= 0;
414                                                         accol[0]=accol[1]=accol[2]=accol[3]= 0.0;
415                                                         
416                                                         while(ps) {
417                                                                 aantalm= count_mask(ps->mask);
418                                                                 aantal+= aantalm;
419
420                                                                 zz= calchalo_z(har, ps->z);
421                                                                 if(zz> har->zs) {
422                                                                         float fac;
423                                                                         
424                                                                         shadeHaloFloat(har, col, zz, dist, xn, yn, flarec);
425                                                                         fac= ((float)aantalm)/(float)R.osa;
426                                                                         accol[0]+= fac*col[0];
427                                                                         accol[1]+= fac*col[1];
428                                                                         accol[2]+= fac*col[2];
429                                                                         accol[3]+= fac*col[3];
430                                                                         flarec= 0;
431                                                                 }
432
433                                                                 ps= ps->next;
434                                                         }
435                                                         ps= (PixStr *) POINTER_FROM_CODE(*rd);
436                                                         aantal= R.osa-aantal;
437                                                         
438                                                         zz= calchalo_z(har, *rz);
439                                                         if(zz> har->zs) {
440                                                                 float fac;
441
442                                                                 shadeHaloFloat(har, col, zz, dist, xn, yn, flarec);
443                                                                 fac= ((float)aantal)/(float)R.osa;
444                                                                 accol[0]+= fac*col[0];
445                                                                 accol[1]+= fac*col[1];
446                                                                 accol[2]+= fac*col[2];
447                                                                 accol[3]+= fac*col[3];
448                                                         }
449
450                                                         col[0]= accol[0];
451                                                         col[1]= accol[1];
452                                                         col[2]= accol[2];
453                                                         col[3]= accol[3];
454
455                                                         /* if(behind > (R.osa>>1)) addalphaUnder(rt,col); */
456                                                         if(do_gamma) {
457                                                                 col[0]= gammaCorrect(col[0]);
458                                                                 col[1]= gammaCorrect(col[1]);
459                                                                 col[2]= gammaCorrect(col[2]);
460                                                         }
461                                                         addalphaAddfacFloat(rb, col, har->add);
462                                                 }
463                                         }
464                                         else {
465                                                 zz= calchalo_z(har, *rz);
466                                                 if(zz> har->zs) {
467                                                         xn= x- har->xs;
468                                                         xsq= xn*xn;
469                                                         dist= xsq+ysq;
470                                                         if(dist<har->radsq) {
471                                                                 shadeHaloFloat(har, col, zz, dist, xn, yn, flarec);
472                                                                 if(do_gamma) {
473                                                                         col[0]= gammaCorrect(col[0]);
474                                                                         col[1]= gammaCorrect(col[1]);
475                                                                         col[2]= gammaCorrect(col[2]);
476                                                                 }
477                                                                 addalphaAddfacFloat(rb, col, har->add);
478                                                         }
479                                                 }
480                                         }
481                                         rb+=4;
482                                         rz++;
483                                         rd++;
484                                 }
485                         }
486                 }
487         }
488 }
489
490 static void scanlinehalo(unsigned int *rectz, float *rowbuf, short ys)
491 {
492         HaloRen *har = NULL;
493         float dist, xsq, ysq, xn, yn, *rb;
494         float col[4];
495         unsigned int a, *rz, zz;
496         short minx, maxx, x;
497
498         for(a=0; a<R.tothalo; a++) {
499                 if((a & 255)==0) har= R.bloha[a>>8];
500                 else har++;
501
502                 if(RE_local_test_break() ) break; 
503
504                 if(ys>har->maxy);
505                 else if(ys<har->miny);
506                 else {
507                         minx= floor(har->xs-har->rad);
508                         maxx= ceil(har->xs+har->rad);
509                         
510                         if(maxx<0);
511                         else if(R.rectx<minx);
512                         else {
513                                 if(minx<0) minx= 0;
514                                 if(maxx>=R.rectx) maxx= R.rectx-1;
515
516                                 rb= rowbuf + 4*minx;
517                                 rz= rectz + minx;
518
519                                 yn= (ys-har->ys)*R.ycor;
520                                 ysq= yn*yn;
521                                 for(x=minx; x<=maxx; x++) {
522                                 
523                                         zz= calchalo_z(har, *rz);
524                                         if(zz> har->zs) {
525                                                 xn= x- har->xs;
526                                                 xsq= xn*xn;
527                                                 dist= xsq+ysq;
528                                                 if(dist<har->radsq) {
529                                                         shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec);
530                                                         addalphaAddfacFloat(rb, col, har->add);
531                                                 }
532                                         }
533
534                                         rb+=4;
535                                         rz++;
536                                 }
537                         }
538                 }
539         }
540 }
541
542 /* ---------------- shaders ----------------------- */
543
544 static double Normalise_d(double *n)
545 {
546         double d;
547         
548         d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
549
550         if(d>0.00000000000000001) {
551                 d= sqrt(d);
552
553                 n[0]/=d; 
554                 n[1]/=d; 
555                 n[2]/=d;
556         } else {
557                 n[0]=n[1]=n[2]= 0.0;
558                 d= 0.0;
559         }
560         return d;
561 }
562
563
564 /* Stoke's form factor. Need doubles here for extreme small area sizes */
565 static float area_lamp_energy(float *co, float *vn, LampRen *lar)
566 {
567         double fac;
568         double vec[4][3];       /* vectors of rendered co to vertices lamp */
569         double cross[4][3];     /* cross products of this */
570         double rad[4];          /* angles between vecs */
571
572         VECSUB(vec[0], co, lar->area[0]);
573         VECSUB(vec[1], co, lar->area[1]);
574         VECSUB(vec[2], co, lar->area[2]);
575         VECSUB(vec[3], co, lar->area[3]);
576         
577         Normalise_d(vec[0]);
578         Normalise_d(vec[1]);
579         Normalise_d(vec[2]);
580         Normalise_d(vec[3]);
581
582         /* cross product */
583         CROSS(cross[0], vec[0], vec[1]);
584         CROSS(cross[1], vec[1], vec[2]);
585         CROSS(cross[2], vec[2], vec[3]);
586         CROSS(cross[3], vec[3], vec[0]);
587
588         Normalise_d(cross[0]);
589         Normalise_d(cross[1]);
590         Normalise_d(cross[2]);
591         Normalise_d(cross[3]);
592
593         /* angles */
594         rad[0]= vec[0][0]*vec[1][0]+ vec[0][1]*vec[1][1]+ vec[0][2]*vec[1][2];
595         rad[1]= vec[1][0]*vec[2][0]+ vec[1][1]*vec[2][1]+ vec[1][2]*vec[2][2];
596         rad[2]= vec[2][0]*vec[3][0]+ vec[2][1]*vec[3][1]+ vec[2][2]*vec[3][2];
597         rad[3]= vec[3][0]*vec[0][0]+ vec[3][1]*vec[0][1]+ vec[3][2]*vec[0][2];
598
599         rad[0]= acos(rad[0]);
600         rad[1]= acos(rad[1]);
601         rad[2]= acos(rad[2]);
602         rad[3]= acos(rad[3]);
603
604         /* Stoke formula */
605         VECMUL(cross[0], rad[0]);
606         VECMUL(cross[1], rad[1]);
607         VECMUL(cross[2], rad[2]);
608         VECMUL(cross[3], rad[3]);
609
610         fac=  vn[0]*cross[0][0]+ vn[1]*cross[0][1]+ vn[2]*cross[0][2];
611         fac+= vn[0]*cross[1][0]+ vn[1]*cross[1][1]+ vn[2]*cross[1][2];
612         fac+= vn[0]*cross[2][0]+ vn[1]*cross[2][1]+ vn[2]*cross[2][2];
613         fac+= vn[0]*cross[3][0]+ vn[1]*cross[3][1]+ vn[2]*cross[3][2];
614
615         if(fac<=0.0) return 0.0;
616         return pow(fac*lar->areasize, lar->k);  // corrected for buttons size and lar->dist^2
617 }
618
619
620 float spec(float inp, int hard) 
621 {
622         float b1;
623         
624         if(inp>=1.0) return 1.0;
625         else if (inp<=0.0) return 0.0;
626         
627         b1= inp*inp;
628         /* avoid FPE */
629         if(b1<0.01) b1= 0.01;   
630         
631         if((hard & 1)==0)  inp= 1.0;
632         if(hard & 2)  inp*= b1;
633         b1*= b1;
634         if(hard & 4)  inp*= b1;
635         b1*= b1;
636         if(hard & 8)  inp*= b1;
637         b1*= b1;
638         if(hard & 16) inp*= b1;
639         b1*= b1;
640
641         /* avoid FPE */
642         if(b1<0.001) b1= 0.0;   
643
644         if(hard & 32) inp*= b1;
645         b1*= b1;
646         if(hard & 64) inp*=b1;
647         b1*= b1;
648         if(hard & 128) inp*=b1;
649
650         if(b1<0.001) b1= 0.0;   
651
652         if(hard & 256) {
653                 b1*= b1;
654                 inp*=b1;
655         }
656
657         return inp;
658 }
659
660 float Phong_Spec( float *n, float *l, float *v, int hard )
661 {
662         float h[3];
663         float rslt;
664
665         h[0] = l[0] + v[0];
666         h[1] = l[1] + v[1];
667         h[2] = l[2] + v[2];
668         Normalise(h);
669
670         rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2];
671
672         if( rslt > 0.0 ) rslt= spec(rslt, hard);
673         else rslt = 0.0;
674
675         return rslt;
676 }
677
678
679 /* reduced cook torrance spec (for off-specular peak) */
680 float CookTorr_Spec(float *n, float *l, float *v, int hard)
681 {
682         float i, nh, nv, h[3];
683
684         h[0]= v[0]+l[0];
685         h[1]= v[1]+l[1];
686         h[2]= v[2]+l[2];
687         Normalise(h);
688
689         nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2];
690         if(nh<0.0) return 0.0;
691         nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2];
692         if(nv<0.0) nv= 0.0;
693
694         i= spec(nh, hard);
695
696         i= i/(0.1+nv);
697         return i;
698 }
699
700 /* Blinn spec */
701 float Blinn_Spec(float *n, float *l, float *v, float refrac, float spec_power )
702 {
703         float i, nh, nv, nl, vh, h[3];
704         float a, b, c, g=0.0, p, f, ang;
705
706         if(refrac < 1.0) return 0.0;
707         if(spec_power == 0.0) return 0.0;
708         
709         /* conversion from 'hardness' (1-255) to 'spec_power' (50 maps at 0.1) */
710         if(spec_power<100.0)
711                 spec_power= sqrt(1.0/spec_power);
712         else spec_power= 10.0/spec_power;
713         
714         h[0]= v[0]+l[0];
715         h[1]= v[1]+l[1];
716         h[2]= v[2]+l[2];
717         Normalise(h);
718
719         nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
720
721         if(nh<0.0) return 0.0;
722
723         nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
724
725         if(nv<=0.0) nv= 0.01;
726
727         nl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
728
729         if(nl<=0.0) {
730                 nl= 0.0;
731                 return 0.0;
732         }
733
734         vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; /* Dot product between view vector and half-way vector */
735         if(vh<=0.0) vh= 0.01;
736
737         a = 1.0;
738         b = (2.0*nh*nv)/vh;
739         c = (2.0*nh*nl)/vh;
740
741         if( a < b && a < c ) g = a;
742         else if( b < a && b < c ) g = b;
743         else if( c < a && c < b ) g = c;
744
745         p = sqrt( (double)((refrac * refrac)+(vh*vh)-1.0) );
746         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))));
747         ang = (float)acos((double)(nh));
748
749         i= f * g * exp((double)(-(ang*ang) / (2.0*spec_power*spec_power)));
750
751         return i;
752 }
753
754 /* cartoon render spec */
755 float Toon_Spec( float *n, float *l, float *v, float size, float smooth )
756 {
757         float h[3];
758         float ang;
759         float rslt;
760         
761         h[0] = l[0] + v[0];
762         h[1] = l[1] + v[1];
763         h[2] = l[2] + v[2];
764         Normalise(h);
765         
766         rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2];
767         
768         ang = acos( rslt ); 
769         
770         if( ang < size ) rslt = 1.0;
771         else if( ang >= (size + smooth) || smooth == 0.0 ) rslt = 0.0;
772         else rslt = 1.0 - ((ang - size) / smooth);
773         
774         return rslt;
775 }
776
777 /* cartoon render diffuse */
778 float Toon_Diff( float *n, float *l, float *v, float size, float smooth )
779 {
780         float rslt, ang;
781
782         rslt = n[0]*l[0] + n[1]*l[1] + n[2]*l[2];
783
784         ang = acos( (double)(rslt) );
785
786         if( ang < size ) rslt = 1.0;
787         else if( ang >= (size + smooth) || smooth == 0.0 ) rslt = 0.0;
788         else rslt = 1.0 - ((ang - size) / smooth);
789
790         return rslt;
791 }
792
793 /* Oren Nayar diffuse */
794
795 /* 'nl' is either dot product, or return value of area light */
796 /* in latter case, only last multiplication uses 'nl' */
797 float OrenNayar_Diff_i(float nl, float *n, float *l, float *v, float rough )
798 {
799         float i, nh, nv, vh, realnl, h[3];
800         float a, b, t, A, B;
801         float Lit_A, View_A, Lit_B[3], View_B[3];
802         
803         h[0]= v[0]+l[0];
804         h[1]= v[1]+l[1];
805         h[2]= v[2]+l[2];
806         Normalise(h);
807         
808         nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
809         if(nh<0.0) nh = 0.0;
810         
811         nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
812         if(nv<=0.0) nv= 0.0;
813         
814         realnl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
815         if(realnl<=0.0) return 0.0;
816         if(nl<0.0) return 0.0;          /* value from area light */
817         
818         vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; /* Dot product between view vector and halfway vector */
819         if(vh<=0.0) vh= 0.0;
820         
821         Lit_A = acos(realnl);
822         View_A = acos( nv );
823         
824         Lit_B[0] = l[0] - (realnl * n[0]);
825         Lit_B[1] = l[1] - (realnl * n[1]);
826         Lit_B[2] = l[2] - (realnl * n[2]);
827         Normalise( Lit_B );
828         
829         View_B[0] = v[0] - (nv * n[0]);
830         View_B[1] = v[1] - (nv * n[1]);
831         View_B[2] = v[2] - (nv * n[2]);
832         Normalise( View_B );
833         
834         t = Lit_B[0]*View_B[0] + Lit_B[1]*View_B[1] + Lit_B[2]*View_B[2];
835         if( t < 0 ) t = 0;
836         
837         if( Lit_A > View_A ) {
838                 a = Lit_A;
839                 b = View_A;
840         }
841         else {
842                 a = View_A;
843                 b = Lit_A;
844         }
845         
846         A = 1 - (0.5 * ((rough * rough) / ((rough * rough) + 0.33)));
847         B = 0.45 * ((rough * rough) / ((rough * rough) + 0.09));
848         
849         b*= 0.95;       /* prevent tangens from shooting to inf, 'nl' can be not a dot product here. */
850                                 /* overflow only happens with extreme size area light, and higher roughness */
851         i = nl * ( A + ( B * t * sin(a) * tan(b) ) );
852         
853         return i;
854 }
855
856 /* Oren Nayar diffuse */
857 float OrenNayar_Diff(float *n, float *l, float *v, float rough )
858 {
859         float nl= n[0]*l[0] + n[1]*l[1] + n[2]*l[2];
860         return OrenNayar_Diff_i(nl, n, l, v, rough);
861 }
862
863
864 /* --------------------------------------------- */
865 /* also called from texture.c */
866 void calc_R_ref(ShadeInput *shi)
867 {
868         float i;
869
870         /* shi->vn dot shi->view */
871         i= -2*(shi->vn[0]*shi->view[0]+shi->vn[1]*shi->view[1]+shi->vn[2]*shi->view[2]);
872
873         shi->ref[0]= (shi->view[0]+i*shi->vn[0]);
874         shi->ref[1]= (shi->view[1]+i*shi->vn[1]);
875         shi->ref[2]= (shi->view[2]+i*shi->vn[2]);
876         if(shi->osatex) {
877                 if(shi->vlr->flag & R_SMOOTH) {
878                         i= -2*( (shi->vn[0]+shi->dxno[0])*(shi->view[0]+shi->dxview) +
879                                 (shi->vn[1]+shi->dxno[1])*shi->view[1]+ (shi->vn[2]+shi->dxno[2])*shi->view[2] );
880
881                         shi->dxref[0]= shi->ref[0]- ( shi->view[0]+shi->dxview+i*(shi->vn[0]+shi->dxno[0]));
882                         shi->dxref[1]= shi->ref[1]- (shi->view[1]+ i*(shi->vn[1]+shi->dxno[1]));
883                         shi->dxref[2]= shi->ref[2]- (shi->view[2]+ i*(shi->vn[2]+shi->dxno[2]));
884
885                         i= -2*( (shi->vn[0]+shi->dyno[0])*shi->view[0]+
886                                 (shi->vn[1]+shi->dyno[1])*(shi->view[1]+shi->dyview)+ (shi->vn[2]+shi->dyno[2])*shi->view[2] );
887
888                         shi->dyref[0]= shi->ref[0]- (shi->view[0]+ i*(shi->vn[0]+shi->dyno[0]));
889                         shi->dyref[1]= shi->ref[1]- (shi->view[1]+shi->dyview+i*(shi->vn[1]+shi->dyno[1]));
890                         shi->dyref[2]= shi->ref[2]- (shi->view[2]+ i*(shi->vn[2]+shi->dyno[2]));
891
892                 }
893                 else {
894
895                         i= -2*( shi->vn[0]*(shi->view[0]+shi->dxview) +
896                                 shi->vn[1]*shi->view[1]+ shi->vn[2]*shi->view[2] );
897
898                         shi->dxref[0]= shi->ref[0]- (shi->view[0]+shi->dxview+i*shi->vn[0]);
899                         shi->dxref[1]= shi->ref[1]- (shi->view[1]+ i*shi->vn[1]);
900                         shi->dxref[2]= shi->ref[2]- (shi->view[2]+ i*shi->vn[2]);
901
902                         i= -2*( shi->vn[0]*shi->view[0]+
903                                 shi->vn[1]*(shi->view[1]+shi->dyview)+ shi->vn[2]*shi->view[2] );
904
905                         shi->dyref[0]= shi->ref[0]- (shi->view[0]+ i*shi->vn[0]);
906                         shi->dyref[1]= shi->ref[1]- (shi->view[1]+shi->dyview+i*shi->vn[1]);
907                         shi->dyref[2]= shi->ref[2]- (shi->view[2]+ i*shi->vn[2]);
908                 }
909         }
910
911 }
912
913 /* mix of 'real' fresnel and allowing control. grad defines blending gradient */
914 float fresnel_fac(float *view, float *vn, float grad, float fac)
915 {
916         float t1, t2;
917         
918         if(fac==0.0) return 1.0;
919         
920         t1= (view[0]*vn[0] + view[1]*vn[1] + view[2]*vn[2]);
921         if(t1>0.0)  t2= 1.0+t1;
922         else t2= 1.0-t1;
923         
924         t2= grad + (1.0-grad)*pow(t2, fac);
925
926         if(t2<0.0) return 0.0;
927         else if(t2>1.0) return 1.0;
928         return t2;
929 }
930
931 void shade_color(ShadeInput *shi, ShadeResult *shr)
932 {
933         Material *ma= shi->mat;
934
935         if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
936                 shi->r= shi->vcol[0];
937                 shi->g= shi->vcol[1];
938                 shi->b= shi->vcol[2];
939         }
940         
941         if(ma->texco) {
942                 if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
943                         shi->r= shi->vcol[0];
944                         shi->g= shi->vcol[1];
945                         shi->b= shi->vcol[2];
946                 }
947                 do_material_tex(shi);
948         }
949
950         if(ma->mode & (MA_ZTRA|MA_RAYTRANSP)) {
951                 if(ma->fresnel_tra!=0.0) 
952                         shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra);
953         }
954
955         shr->diff[0]= shi->r;
956         shr->diff[1]= shi->g;
957         shr->diff[2]= shi->b;
958         shr->alpha= shi->alpha;
959 }
960
961 /* r g b = 1 value, col = vector */
962 static void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
963 {
964         float tmp, facm= 1.0-fac;
965         
966         switch (type) {
967         case MA_RAMP_BLEND:
968                 *r = facm*(*r) + fac*col[0];
969                 *g = facm*(*g) + fac*col[1];
970                 *b = facm*(*b) + fac*col[2];
971                 break;
972         case MA_RAMP_ADD:
973                 *r += fac*col[0];
974                 *g += fac*col[1];
975                 *b += fac*col[2];
976                 break;
977         case MA_RAMP_MULT:
978                 *r *= (facm + fac*col[0]);
979                 *g *= (facm + fac*col[1]);
980                 *b *= (facm + fac*col[2]);
981                 break;
982         case MA_RAMP_SCREEN:
983                 *r = 1.0-(facm + (1.0 - col[0]))*(1.0 - *r);
984                 *g = 1.0-(facm + (1.0 - col[1]))*(1.0 - *g);
985                 *b = 1.0-(facm + (1.0 - col[2]))*(1.0 - *b);
986                 break;
987         case MA_RAMP_SUB:
988                 *r -= fac*col[0];
989                 *g -= fac*col[1];
990                 *b -= fac*col[2];
991                 break;
992         case MA_RAMP_DIV:
993                 if(col[0]!=0.0)
994                         *r = facm*(*r) + fac*(*r)/col[0];
995                 if(col[1]!=0.0)
996                         *g = facm*(*g) + fac*(*g)/col[1];
997                 if(col[2]!=0.0)
998                         *b = facm*(*b) + fac*(*b)/col[2];
999                 break;
1000         case MA_RAMP_DIFF:
1001                 *r = facm*(*r) + fac*fabs(*r-col[0]);
1002                 *g = facm*(*g) + fac*fabs(*g-col[1]);
1003                 *b = facm*(*b) + fac*fabs(*b-col[2]);
1004                 break;
1005         case MA_RAMP_DARK:
1006                 tmp= fac*col[0];
1007                 if(tmp < *r) *r= tmp; 
1008                 tmp= fac*col[1];
1009                 if(tmp < *g) *g= tmp; 
1010                 tmp= fac*col[2];
1011                 if(tmp < *b) *b= tmp; 
1012                 break;
1013         case MA_RAMP_LIGHT:
1014                 tmp= fac*col[0];
1015                 if(tmp > *r) *r= tmp; 
1016                 tmp= fac*col[1];
1017                 if(tmp > *g) *g= tmp; 
1018                 tmp= fac*col[2];
1019                 if(tmp > *b) *b= tmp; 
1020                 break;
1021         }
1022
1023 }
1024
1025 /* ramp for at end of shade */
1026 void ramp_diffuse_result(float *diff, ShadeInput *shi)
1027 {
1028         Material *ma= shi->mat;
1029         float col[4], fac=0;
1030
1031         if(ma->ramp_col) {
1032                 if(ma->rampin_col==MA_RAMP_IN_RESULT) {
1033                         
1034                         fac= 0.3*diff[0] + 0.58*diff[1] + 0.12*diff[2];
1035                         do_colorband(ma->ramp_col, fac, col);
1036                         
1037                         /* blending method */
1038                         fac= col[3]*ma->rampfac_col;
1039                         
1040                         ramp_blend(ma->rampblend_col, diff, diff+1, diff+2, fac, col);
1041                 }
1042         }
1043 }
1044
1045 /* r,g,b denote energy, ramp is used with different values to make new material color */
1046 void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, float g, float b)
1047 {
1048         Material *ma= shi->mat;
1049         float col[4], colt[3], fac=0;
1050         
1051         if(ma->ramp_col && (ma->mode & MA_RAMP_COL)) {
1052                 
1053                 /* MA_RAMP_IN_RESULT is exceptional */
1054                 if(ma->rampin_col==MA_RAMP_IN_RESULT) {
1055                         // normal add
1056                         diff[0] += r * shi->r;
1057                         diff[1] += g * shi->g;
1058                         diff[2] += b * shi->b;
1059                 }
1060                 else {
1061                         /* input */
1062                         switch(ma->rampin_col) {
1063                         case MA_RAMP_IN_ENERGY:
1064                                 fac= 0.3*r + 0.58*g + 0.12*b;
1065                                 break;
1066                         case MA_RAMP_IN_SHADER:
1067                                 fac= is;
1068                                 break;
1069                         case MA_RAMP_IN_NOR:
1070                                 fac= shi->view[0]*shi->vn[0] + shi->view[1]*shi->vn[1] + shi->view[2]*shi->vn[2];
1071                                 break;
1072                         }
1073         
1074                         do_colorband(ma->ramp_col, fac, col);
1075                         
1076                         /* blending method */
1077                         fac= col[3]*ma->rampfac_col;
1078                         colt[0]= shi->r; colt[1]= shi->g; colt[2]= shi->b;
1079
1080                         ramp_blend(ma->rampblend_col, colt, colt+1, colt+2, fac, col);
1081
1082                         /* output to */
1083                         diff[0] += r * colt[0];
1084                         diff[1] += g * colt[1];
1085                         diff[2] += b * colt[2];
1086                 }
1087         }
1088         else {
1089                 diff[0] += r * shi->r;
1090                 diff[1] += g * shi->g;
1091                 diff[2] += b * shi->b;
1092         }
1093 }
1094
1095 void ramp_spec_result(float *specr, float *specg, float *specb, ShadeInput *shi)
1096 {
1097         Material *ma= shi->mat;
1098         float col[4];
1099         float fac;
1100         
1101         if(ma->ramp_spec && (ma->rampin_spec==MA_RAMP_IN_RESULT)) {
1102                 fac= 0.3*(*specr) + 0.58*(*specg) + 0.12*(*specb);
1103                 do_colorband(ma->ramp_spec, fac, col);
1104                 
1105                 /* blending method */
1106                 fac= col[3]*ma->rampfac_spec;
1107                 
1108                 ramp_blend(ma->rampblend_spec, specr, specg, specb, fac, col);
1109                 
1110         }
1111 }
1112
1113 /* is = dot product shade, t = spec energy */
1114 void do_specular_ramp(ShadeInput *shi, float is, float t, float *spec)
1115 {
1116         Material *ma= shi->mat;
1117         float col[4];
1118         float fac=0.0;
1119         
1120         spec[0]= shi->specr;
1121         spec[1]= shi->specg;
1122         spec[2]= shi->specb;
1123
1124         /* MA_RAMP_IN_RESULT is exception */
1125         if(ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) {
1126                 
1127                 /* input */
1128                 switch(ma->rampin_spec) {
1129                 case MA_RAMP_IN_ENERGY:
1130                         fac= t;
1131                         break;
1132                 case MA_RAMP_IN_SHADER:
1133                         fac= is;
1134                         break;
1135                 case MA_RAMP_IN_NOR:
1136                         fac= shi->view[0]*shi->vn[0] + shi->view[1]*shi->vn[1] + shi->view[2]*shi->vn[2];
1137                         break;
1138                 }
1139                 
1140                 do_colorband(ma->ramp_spec, fac, col);
1141                 
1142                 /* blending method */
1143                 fac= col[3]*ma->rampfac_spec;
1144                 
1145                 ramp_blend(ma->rampblend_spec, spec, spec+1, spec+2, fac, col);
1146         }
1147 }
1148
1149
1150
1151 static void ambient_occlusion(World *wrld, ShadeInput *shi, ShadeResult *shr)
1152 {
1153         float f, shadfac[4];
1154         
1155         if((wrld->mode & WO_AMB_OCC) && (R.r.mode & R_RAYTRACE) && shi->amb!=0.0) {
1156                 ray_ao(shi, wrld, shadfac);
1157
1158                 if(wrld->aocolor==WO_AOPLAIN) {
1159                         if (wrld->aomix==WO_AOADDSUB) shadfac[3] = 2.0*shadfac[3]-1.0;
1160                         else if (wrld->aomix==WO_AOSUB) shadfac[3] = shadfac[3]-1.0;
1161
1162                         f= wrld->aoenergy*shadfac[3]*shi->amb;
1163                         add_to_diffuse(shr->diff, shi, f, f, f, f);
1164                 }
1165                 else {
1166                         if (wrld->aomix==WO_AOADDSUB) {
1167                                 shadfac[0] = 2.0*shadfac[0]-1.0;
1168                                 shadfac[1] = 2.0*shadfac[1]-1.0;
1169                                 shadfac[2] = 2.0*shadfac[2]-1.0;
1170                         }
1171                         else if (wrld->aomix==WO_AOSUB) {
1172                                 shadfac[0] = shadfac[0]-1.0;
1173                                 shadfac[1] = shadfac[1]-1.0;
1174                                 shadfac[2] = shadfac[2]-1.0;
1175                         }
1176                         f= wrld->aoenergy*shi->amb;
1177                         add_to_diffuse(shr->diff, shi, f, f*shadfac[0], f*shadfac[1], f*shadfac[2]);
1178                 }
1179         }
1180 }
1181
1182 void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
1183 {
1184         LampRen *lar;
1185         Material *ma= shi->mat;
1186         VlakRen *vlr= shi->vlr;
1187         float i, inp, inpr, is, t, lv[3], lacol[3], lampdist, ld = 0;
1188         float lvrot[3], *vn, *view, shadfac[4], soft, phongcorr;        // shadfac = rgba
1189         int a;
1190
1191         vn= shi->vn;
1192         view= shi->view;
1193         
1194         memset(shr, 0, sizeof(ShadeResult));
1195         
1196         /* separate loop */
1197         if(ma->mode & MA_ONLYSHADOW) {
1198                 float ir;
1199                 
1200                 if(R.r.mode & R_SHADOW) {
1201                         
1202                         shadfac[3]= ir= 0.0;
1203                         for(a=0; a<R.totlamp; a++) {
1204                                 lar= R.la[a];
1205                                 /* yafray: ignore shading by photonlights, not used in Blender */
1206                                 if (lar->type==LA_YF_PHOTON) continue;
1207                                 
1208                                 if(lar->mode & LA_LAYER) if((lar->lay & vlr->lay)==0) continue;
1209                                 
1210                                 lv[0]= shi->co[0]-lar->co[0];
1211                                 lv[1]= shi->co[1]-lar->co[1];
1212                                 lv[2]= shi->co[2]-lar->co[2];
1213
1214                                 if(lar->type==LA_SPOT) {
1215                                         /* only test within spotbundel */
1216                                         if(lar->shb || (lar->mode & LA_SHAD_RAY)) {
1217
1218                                                 Normalise(lv);
1219                                                 inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
1220                                                 if(inpr>lar->spotsi) {
1221                                                         
1222                                                         inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
1223                                                         
1224                                                         if(lar->shb) i = testshadowbuf(lar->shb, shi->co, shi->dxco, shi->dyco, inp);
1225                                                         else {
1226                                                                 float shad[4];
1227                                                                 ray_shadow(shi, lar, shad);
1228                                                                 i= shad[3];
1229                                                         }
1230                                                         
1231                                                         t= inpr - lar->spotsi;
1232                                                         if(t<lar->spotbl && lar->spotbl!=0.0) {
1233                                                                 t/= lar->spotbl;
1234                                                                 t*= t;
1235                                                                 i= t*i+(1.0-t);
1236                                                         }
1237                                                         
1238                                                         shadfac[3]+= i;
1239                                                         ir+= 1.0;
1240                                                 }
1241                                                 else {
1242                                                         shadfac[3]+= 1.0;
1243                                                         ir+= 1.0;
1244                                                 }
1245                                         }
1246                                 }
1247                                 else if(lar->mode & LA_SHAD_RAY) {
1248                                         float shad[4];
1249                                         
1250                                         /* single sided? */
1251                                         if( vlr->n[0]*lv[0] + vlr->n[1]*lv[1] + vlr->n[2]*lv[2] > -0.01) {
1252                                                 ray_shadow(shi, lar, shad);
1253                                                 shadfac[3]+= shad[3];
1254                                                 ir+= 1.0;
1255                                         }
1256                                 }
1257
1258                         }
1259                         if(ir>0.0) {
1260                                 shadfac[3]/= ir;
1261                                 shr->alpha= (shi->alpha)*(1.0-shadfac[3]);
1262                         }
1263                 }
1264                 
1265                 if((R.wrld.mode & WO_AMB_OCC) && (R.r.mode & R_RAYTRACE) && shi->amb!=0.0) {
1266                         float f;
1267
1268                         ray_ao(shi, &R.wrld, shadfac);  // shadfac==0: full light
1269                         shadfac[3]= 1.0-shadfac[3];
1270                         
1271                         f= R.wrld.aoenergy*shadfac[3]*shi->amb;
1272                         
1273                         if(R.wrld.aomix==WO_AOADD) {
1274                                 shr->alpha += f;
1275                                 shr->alpha *= f;
1276                         }
1277                         else if(R.wrld.aomix==WO_AOSUB) {
1278                                 shr->alpha += f;
1279                         }
1280                         else {
1281                                 shr->alpha *= f;
1282                                 shr->alpha += f;
1283                         }
1284                 }
1285                 
1286                 return;
1287         }
1288                 
1289         if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
1290                 shi->r= shi->vcol[0];
1291                 shi->g= shi->vcol[1];
1292                 shi->b= shi->vcol[2];
1293         }
1294         
1295         /* envmap hack, always reset */
1296         shi->refcol[0]= shi->refcol[1]= shi->refcol[2]= shi->refcol[3]= 0.0;
1297
1298         if(ma->texco) {
1299                 if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
1300                         shi->r= shi->vcol[0];
1301                         shi->g= shi->vcol[1];
1302                         shi->b= shi->vcol[2];
1303                 }
1304                 do_material_tex(shi);
1305         }
1306         
1307         if(ma->mode & MA_SHLESS) {
1308                 shr->diff[0]= shi->r;
1309                 shr->diff[1]= shi->g;
1310                 shr->diff[2]= shi->b;
1311                 shr->alpha= shi->alpha;
1312                 return;
1313         }
1314
1315         if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
1316                 // add_to_diffuse(shr->diff, shi, 1.0, ma->emit+shi->vcol[0], ma->emit+shi->vcol[1], ma->emit+shi->vcol[2]);
1317                 shr->diff[0]= shi->r*(shi->emit+shi->vcol[0]);
1318                 shr->diff[1]= shi->g*(shi->emit+shi->vcol[1]);
1319                 shr->diff[2]= shi->b*(shi->emit+shi->vcol[2]);
1320         }
1321         else {
1322                 // add_to_diffuse(shr->diff, shi, 1.0, ma->emit, ma->emit, ma->emit);
1323                 shr->diff[0]= shi->r*shi->emit;
1324                 shr->diff[1]= shi->g*shi->emit;
1325                 shr->diff[2]= shi->b*shi->emit;
1326         }
1327         
1328         ambient_occlusion(&R.wrld, shi, shr);
1329
1330         for(a=0; a<R.totlamp; a++) {
1331                 lar= R.la[a];
1332                 /* yafray: ignore shading by photonlights, not used in Blender */
1333                 if (lar->type==LA_YF_PHOTON) continue;
1334
1335                 /* test for lamp layer */
1336                 if(lar->mode & LA_LAYER) if((lar->lay & vlr->lay)==0) continue;
1337                 
1338                 /* lampdist calculation */
1339                 if(lar->type==LA_SUN || lar->type==LA_HEMI) {
1340                         VECCOPY(lv, lar->vec);
1341                         lampdist= 1.0;
1342                 }
1343                 else {
1344                         lv[0]= shi->co[0]-lar->co[0];
1345                         lv[1]= shi->co[1]-lar->co[1];
1346                         lv[2]= shi->co[2]-lar->co[2];
1347                         ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
1348                         lv[0]/= ld;
1349                         lv[1]/= ld;
1350                         lv[2]/= ld;
1351                         
1352                         /* ld is re-used further on (texco's) */
1353                         if(lar->type==LA_AREA) {
1354                                 lampdist= 1.0;
1355                         }
1356                         else {
1357                                 if(lar->mode & LA_QUAD) {
1358                                         t= 1.0;
1359                                         if(lar->ld1>0.0)
1360                                                 t= lar->dist/(lar->dist+lar->ld1*ld);
1361                                         if(lar->ld2>0.0)
1362                                                 t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld);
1363         
1364                                         lampdist= t;
1365                                 }
1366                                 else {
1367                                         lampdist= (lar->dist/(lar->dist+ld));
1368                                 }
1369         
1370                                 if(lar->mode & LA_SPHERE) {
1371                                         t= lar->dist - ld;
1372                                         if(t<0.0) continue;
1373                                         
1374                                         t/= lar->dist;
1375                                         lampdist*= (t);
1376                                 }
1377                         }
1378                 }
1379
1380                 lacol[0]= lar->r;
1381                 lacol[1]= lar->g;
1382                 lacol[2]= lar->b;
1383                 
1384                 /* init transp shadow */
1385                 shadfac[3]= 1.0;
1386                 if(ma->mode & MA_SHADOW_TRA) shadfac[0]= shadfac[1]= shadfac[2]= 1.0;
1387
1388                 if(lar->type==LA_SPOT) {
1389                         
1390                         if(lar->mode & LA_SQUARE) {
1391                                 if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) {
1392                                         float x;
1393                                         
1394                                         /* rotate view to lampspace */
1395                                         VECCOPY(lvrot, lv);
1396                                         MTC_Mat3MulVecfl(lar->imat, lvrot);
1397                                         
1398                                         x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
1399                                         /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
1400
1401                                         inpr= 1.0/(sqrt(1+x*x));
1402                                 }
1403                                 else inpr= 0.0;
1404                         }
1405                         else {
1406                                 inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
1407                         }
1408
1409                         t= lar->spotsi;
1410                         if(inpr<t) continue;
1411                         else {
1412                                 t= inpr-t;
1413                                 i= 1.0;
1414                                 soft= 1.0;
1415                                 if(t<lar->spotbl && lar->spotbl!=0.0) {
1416                                         /* soft area */
1417                                         i= t/lar->spotbl;
1418                                         t= i*i;
1419                                         soft= (3.0*t-2.0*t*i);
1420                                         inpr*= soft;
1421                                 }
1422                                 lampdist*=inpr;
1423                         }
1424
1425                         if(lar->mode & LA_OSATEX) {
1426                                 shi->osatex= 1; /* signal for multitex() */
1427                                 
1428                                 shi->dxlv[0]= lv[0] - (shi->co[0]-lar->co[0]+shi->dxco[0])/ld;
1429                                 shi->dxlv[1]= lv[1] - (shi->co[1]-lar->co[1]+shi->dxco[1])/ld;
1430                                 shi->dxlv[2]= lv[2] - (shi->co[2]-lar->co[2]+shi->dxco[2])/ld;
1431
1432                                 shi->dylv[0]= lv[0] - (shi->co[0]-lar->co[0]+shi->dyco[0])/ld;
1433                                 shi->dylv[1]= lv[1] - (shi->co[1]-lar->co[1]+shi->dyco[1])/ld;
1434                                 shi->dylv[2]= lv[2] - (shi->co[2]-lar->co[2]+shi->dyco[2])/ld;
1435                         }
1436                         
1437                 }
1438
1439                 if(lar->mode & LA_TEXTURE)  do_lamp_tex(lar, lv, shi, lacol);
1440                 
1441                 /* dot product and reflectivity */
1442                 /* inp = dotproduct, is = shader result, i = lamp energy (with shadow) */
1443                 
1444                 inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
1445
1446                 /* phong threshold to prevent backfacing faces having artefacts on ray shadow (terminator problem) */
1447                 if((ma->mode & MA_RAYBIAS) && (lar->mode & LA_SHAD_RAY) && (vlr->flag & R_SMOOTH)) {
1448                         float thresh= vlr->ob->smoothresh;
1449                         if(inp>thresh)
1450                                 phongcorr= (inp-thresh)/(inp*(1.0-thresh));
1451                         else
1452                                 phongcorr= 0.0;
1453                 }
1454                 else phongcorr= 1.0;
1455                 
1456                 /* diffuse shaders */
1457                 if(lar->mode & LA_NO_DIFF) {
1458                         is= 0.0;        // skip shaders
1459                 }
1460                 else if(lar->type==LA_HEMI) {
1461                         is= 0.5*inp + 0.5;
1462                 }
1463                 else {
1464                 
1465                         if(lar->type==LA_AREA) {
1466                                 /* single sided */
1467                                 if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0)
1468                                         inp= area_lamp_energy(shi->co, shi->vn, lar);
1469                                 else inp= 0.0;
1470                         }
1471                         
1472                         /* diffuse shaders (oren nayer gets inp from area light) */
1473                         if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff_i(inp, vn, lv, view, ma->roughness);
1474                         else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(vn, lv, view, ma->param[0], ma->param[1]);
1475                         else is= inp;   // Lambert
1476                 }
1477                 
1478                 i= is*phongcorr;
1479                 
1480                 if(i>0.0) {
1481                         i*= lampdist*shi->refl;
1482                 }
1483
1484                 /* shadow and spec, (lampdist==0 outside spot) */
1485                 if(lampdist> 0.0) {
1486                         
1487                         if(i>0.0 && (R.r.mode & R_SHADOW)) {
1488                                 if(ma->mode & MA_SHADOW) {
1489                                         if(lar->type==LA_HEMI); // no shadow
1490                                         else {
1491                                                 if(lar->shb) {
1492                                                         shadfac[3] = testshadowbuf(lar->shb, shi->co, shi->dxco, shi->dyco, inp);
1493                                                 }
1494                                                 else if(lar->mode & LA_SHAD_RAY) {
1495                                                         ray_shadow(shi, lar, shadfac);
1496                                                 }
1497         
1498                                                 /* warning, here it skips the loop */
1499                                                 if(lar->mode & LA_ONLYSHADOW) {
1500                                                         
1501                                                         shadfac[3]= i*lar->energy*(1.0-shadfac[3]);
1502                                                         shr->diff[0] -= shadfac[3]*shi->r;
1503                                                         shr->diff[1] -= shadfac[3]*shi->g;
1504                                                         shr->diff[2] -= shadfac[3]*shi->b;
1505                                                         
1506                                                         continue;
1507                                                 }
1508                                                 
1509                                                 if(shadfac[3]==0.0) continue;
1510         
1511                                                 i*= shadfac[3];
1512                                         }
1513                                 }
1514                         }
1515                 
1516                         /* specularity */
1517                         if(shadfac[3]>0.0 && shi->spec!=0.0 && !(lar->mode & LA_NO_SPEC)) {
1518                                 
1519                                 if(lar->type==LA_HEMI) {
1520                                         /* hemi uses no spec shaders (yet) */
1521                                         
1522                                         lv[0]+= view[0];
1523                                         lv[1]+= view[1];
1524                                         lv[2]+= view[2];
1525                                         
1526                                         Normalise(lv);
1527                                         
1528                                         t= vn[0]*lv[0]+vn[1]*lv[1]+vn[2]*lv[2];
1529                                         
1530                                         if(lar->type==LA_HEMI) {
1531                                                 t= 0.5*t+0.5;
1532                                         }
1533                                         
1534                                         t= shadfac[3]*shi->spec*spec(t, shi->har);
1535                                         shr->spec[0]+= t*(lacol[0] * shi->specr);
1536                                         shr->spec[1]+= t*(lacol[1] * shi->specg);
1537                                         shr->spec[2]+= t*(lacol[2] * shi->specb);
1538                                 }
1539                                 else {
1540                                         /* specular shaders */
1541                                         float specfac;
1542
1543                                         if(ma->spec_shader==MA_SPEC_PHONG) 
1544                                                 specfac= Phong_Spec(vn, lv, view, shi->har);
1545                                         else if(ma->spec_shader==MA_SPEC_COOKTORR) 
1546                                                 specfac= CookTorr_Spec(vn, lv, view, shi->har);
1547                                         else if(ma->spec_shader==MA_SPEC_BLINN) 
1548                                                 specfac= Blinn_Spec(vn, lv, view, ma->refrac, (float)shi->har);
1549                                         else 
1550                                                 specfac= Toon_Spec(vn, lv, view, ma->param[2], ma->param[3]);
1551                                 
1552                                         /* area lamp correction */
1553                                         if(lar->type==LA_AREA) specfac*= inp;
1554                                         
1555                                         t= shadfac[3]*shi->spec*lampdist*specfac;
1556                                         
1557                                         if(ma->mode & MA_RAMP_SPEC) {
1558                                                 float spec[3];
1559                                                 do_specular_ramp(shi, specfac, t, spec);
1560                                                 shr->spec[0]+= t*(lacol[0] * spec[0]);
1561                                                 shr->spec[1]+= t*(lacol[1] * spec[1]);
1562                                                 shr->spec[2]+= t*(lacol[2] * spec[2]);
1563                                         }
1564                                         else {
1565                                                 shr->spec[0]+= t*(lacol[0] * shi->specr);
1566                                                 shr->spec[1]+= t*(lacol[1] * shi->specg);
1567                                                 shr->spec[2]+= t*(lacol[2] * shi->specb);
1568                                         }
1569                                 }
1570                         }
1571                 }
1572                 
1573                 /* in case 'no diffuse' we still do most calculus, spec can be in shadow */
1574                 if(i>0.0 && !(lar->mode & LA_NO_DIFF)) {
1575                         if(ma->mode & MA_SHADOW_TRA) {
1576                                 add_to_diffuse(shr->diff, shi, is, i*shadfac[0]*lacol[0], i*shadfac[1]*lacol[1], i*shadfac[2]*lacol[2]);
1577                         }
1578                         else {
1579                                 add_to_diffuse(shr->diff, shi, is, i*lacol[0], i*lacol[1], i*lacol[2]);
1580                         }
1581                 }
1582         }
1583
1584         if(ma->mode & (MA_ZTRA|MA_RAYTRANSP)) {
1585                 if(ma->fresnel_tra!=0.0) 
1586                         shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra);
1587
1588                 if(shi->spectra!=0.0) {
1589
1590                         t = MAX3(shr->spec[0], shr->spec[1], shr->spec[2]);
1591                         t *= shi->spectra;
1592                         if(t>1.0) t= 1.0;
1593                         shi->alpha= (1.0-t)*shi->alpha+t;
1594                 }
1595         }
1596
1597         shr->alpha= shi->alpha;
1598
1599         if(shr->spec[0]<0.0) shr->spec[0]= 0.0;
1600         if(shr->spec[1]<0.0) shr->spec[1]= 0.0;
1601         if(shr->spec[2]<0.0) shr->spec[2]= 0.0;
1602
1603         shr->diff[0]+= shi->r*shi->amb*shi->rad[0];
1604         shr->diff[0]+= shi->ambr;
1605         if(shr->diff[0]<0.0) shr->diff[0]= 0.0;
1606         
1607         shr->diff[1]+= shi->g*shi->amb*shi->rad[1];
1608         shr->diff[1]+= shi->ambg;
1609         if(shr->diff[1]<0.0) shr->diff[1]= 0.0;
1610         
1611         shr->diff[2]+= shi->b*shi->amb*shi->rad[2];
1612         shr->diff[2]+= shi->ambb;
1613         if(shr->diff[2]<0.0) shr->diff[2]= 0.0;
1614         
1615         if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(shr->diff, shi);
1616         if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(shr->spec, shr->spec+1, shr->spec+2, shi);
1617         
1618         /* refcol is for envmap only */
1619         if(shi->refcol[0]!=0.0) {
1620                 shr->diff[0]= shi->mirr*shi->refcol[1] + (1.0 - shi->mirr*shi->refcol[0])*shr->diff[0];
1621                 shr->diff[1]= shi->mirg*shi->refcol[2] + (1.0 - shi->mirg*shi->refcol[0])*shr->diff[1];
1622                 shr->diff[2]= shi->mirb*shi->refcol[3] + (1.0 - shi->mirb*shi->refcol[0])*shr->diff[2];
1623         }
1624
1625 }
1626
1627 void shade_input_set_coords(ShadeInput *shi, float u, float v, int i1, int i2, int i3)
1628 {
1629         VertRen *v1, *v2, *v3;
1630         VlakRen *vlr= shi->vlr;
1631         float l, dl;
1632         short texco= shi->mat->texco;
1633         int mode= shi->mat->mode;
1634         char p1, p2, p3;
1635         
1636         /* for rendering of quads, the following values are used to denote vertices:
1637            0 1 2        scanline tria & first half quad, and ray tria
1638            0 2 3    scanline 2nd half quad
1639            0 1 3    raytracer first half quad
1640            2 1 3    raytracer 2nd half quad
1641         */
1642
1643         if(i1==0) {
1644                 v1= vlr->v1;
1645                 p1= ME_FLIPV1;
1646         } else {
1647                 v1= vlr->v3;
1648                 p1= ME_FLIPV3;
1649         }
1650
1651         if(i2==1) {
1652                 v2= vlr->v2;
1653                 p2= ME_FLIPV2;
1654         } else {
1655                 v2= vlr->v3;
1656                 p2= ME_FLIPV3;
1657         }
1658         
1659         if(i3==2) {
1660                 v3= vlr->v3;
1661                 p3= ME_FLIPV3;
1662         } else {
1663                 v3= vlr->v4;
1664                 p3= ME_FLIPV4;
1665         }
1666
1667         /* calculate U and V, for scanline (normal u and v are -1 to 0) */
1668         if(u==1.0) {
1669                 /* exception case for wire render of edge */
1670                 if(vlr->v2==vlr->v3);
1671                 else if( (vlr->flag & R_SMOOTH) || (texco & NEED_UV)) {
1672                         float detsh, t00, t10, t01, t11;
1673                         
1674                         if(vlr->snproj==0) {
1675                                 t00= v3->co[0]-v1->co[0]; t01= v3->co[1]-v1->co[1];
1676                                 t10= v3->co[0]-v2->co[0]; t11= v3->co[1]-v2->co[1];
1677                         }
1678                         else if(vlr->snproj==1) {
1679                                 t00= v3->co[0]-v1->co[0]; t01= v3->co[2]-v1->co[2];
1680                                 t10= v3->co[0]-v2->co[0]; t11= v3->co[2]-v2->co[2];
1681                         }
1682                         else {
1683                                 t00= v3->co[1]-v1->co[1]; t01= v3->co[2]-v1->co[2];
1684                                 t10= v3->co[1]-v2->co[1]; t11= v3->co[2]-v2->co[2];
1685                         }
1686                         
1687                         detsh= t00*t11-t10*t01;
1688                         t00/= detsh; t01/=detsh; 
1689                         t10/=detsh; t11/=detsh;
1690                 
1691                         if(vlr->snproj==0) {
1692                                 u= (shi->co[0]-v3->co[0])*t11-(shi->co[1]-v3->co[1])*t10;
1693                                 v= (shi->co[1]-v3->co[1])*t00-(shi->co[0]-v3->co[0])*t01;
1694                                 if(shi->osatex) {
1695                                         shi->dxuv[0]=  shi->dxco[0]*t11- shi->dxco[1]*t10;
1696                                         shi->dxuv[1]=  shi->dxco[1]*t00- shi->dxco[0]*t01;
1697                                         shi->dyuv[0]=  shi->dyco[0]*t11- shi->dyco[1]*t10;
1698                                         shi->dyuv[1]=  shi->dyco[1]*t00- shi->dyco[0]*t01;
1699                                 }
1700                         }
1701                         else if(vlr->snproj==1) {
1702                                 u= (shi->co[0]-v3->co[0])*t11-(shi->co[2]-v3->co[2])*t10;
1703                                 v= (shi->co[2]-v3->co[2])*t00-(shi->co[0]-v3->co[0])*t01;
1704                                 if(shi->osatex) {
1705                                         shi->dxuv[0]=  shi->dxco[0]*t11- shi->dxco[2]*t10;
1706                                         shi->dxuv[1]=  shi->dxco[2]*t00- shi->dxco[0]*t01;
1707                                         shi->dyuv[0]=  shi->dyco[0]*t11- shi->dyco[2]*t10;
1708                                         shi->dyuv[1]=  shi->dyco[2]*t00- shi->dyco[0]*t01;
1709                                 }
1710                         }
1711                         else {
1712                                 u= (shi->co[1]-v3->co[1])*t11-(shi->co[2]-v3->co[2])*t10;
1713                                 v= (shi->co[2]-v3->co[2])*t00-(shi->co[1]-v3->co[1])*t01;
1714                                 if(shi->osatex) {
1715                                         shi->dxuv[0]=  shi->dxco[1]*t11- shi->dxco[2]*t10;
1716                                         shi->dxuv[1]=  shi->dxco[2]*t00- shi->dxco[1]*t01;
1717                                         shi->dyuv[0]=  shi->dyco[1]*t11- shi->dyco[2]*t10;
1718                                         shi->dyuv[1]=  shi->dyco[2]*t00- shi->dyco[1]*t01;
1719                                 }
1720                         }
1721                 }
1722         
1723         }
1724         l= 1.0+u+v;
1725         
1726         /* calculate punos (vertexnormals) */
1727         if(vlr->flag & R_SMOOTH) { 
1728                 float n1[3], n2[3], n3[3];
1729                 
1730                 if(vlr->puno & p1) {
1731                         n1[0]= -v1->n[0]; n1[1]= -v1->n[1]; n1[2]= -v1->n[2];
1732                 } else {
1733                         n1[0]= v1->n[0]; n1[1]= v1->n[1]; n1[2]= v1->n[2];
1734                 }
1735                 if(vlr->puno & p2) {
1736                         n2[0]= -v2->n[0]; n2[1]= -v2->n[1]; n2[2]= -v2->n[2];
1737                 } else {
1738                         n2[0]= v2->n[0]; n2[1]= v2->n[1]; n2[2]= v2->n[2];
1739                 }
1740                 
1741                 if(vlr->puno & p3) {
1742                         n3[0]= -v3->n[0]; n3[1]= -v3->n[1]; n3[2]= -v3->n[2];
1743                 } else {
1744                         n3[0]= v3->n[0]; n3[1]= v3->n[1]; n3[2]= v3->n[2];
1745                 }
1746
1747                 shi->vn[0]= l*n3[0]-u*n1[0]-v*n2[0];
1748                 shi->vn[1]= l*n3[1]-u*n1[1]-v*n2[1];
1749                 shi->vn[2]= l*n3[2]-u*n1[2]-v*n2[2];
1750
1751                 Normalise(shi->vn);
1752
1753                 if(shi->osatex && (texco & (TEXCO_NORM|TEXCO_REFL)) ) {
1754                         dl= shi->dxuv[0]+shi->dxuv[1];
1755                         shi->dxno[0]= dl*n3[0]-shi->dxuv[0]*n1[0]-shi->dxuv[1]*n2[0];
1756                         shi->dxno[1]= dl*n3[1]-shi->dxuv[0]*n1[1]-shi->dxuv[1]*n2[1];
1757                         shi->dxno[2]= dl*n3[2]-shi->dxuv[0]*n1[2]-shi->dxuv[1]*n2[2];
1758                         dl= shi->dyuv[0]+shi->dyuv[1];
1759                         shi->dyno[0]= dl*n3[0]-shi->dyuv[0]*n1[0]-shi->dyuv[1]*n2[0];
1760                         shi->dyno[1]= dl*n3[1]-shi->dyuv[0]*n1[1]-shi->dyuv[1]*n2[1];
1761                         shi->dyno[2]= dl*n3[2]-shi->dyuv[0]*n1[2]-shi->dyuv[1]*n2[2];
1762
1763                 }
1764         }
1765         else {
1766                 VECCOPY(shi->vn, vlr->n);
1767         }
1768
1769         /* texture coordinates. shi->dxuv shi->dyuv have been set */
1770         if(texco & NEED_UV) {
1771                 if(texco & TEXCO_ORCO) {
1772                         if(v1->orco) {
1773                                 float *o1, *o2, *o3;
1774                                 
1775                                 o1= v1->orco;
1776                                 o2= v2->orco;
1777                                 o3= v3->orco;
1778                                 
1779                                 shi->lo[0]= l*o3[0]-u*o1[0]-v*o2[0];
1780                                 shi->lo[1]= l*o3[1]-u*o1[1]-v*o2[1];
1781                                 shi->lo[2]= l*o3[2]-u*o1[2]-v*o2[2];
1782         
1783                                 if(shi->osatex) {
1784                                         dl= shi->dxuv[0]+shi->dxuv[1];
1785                                         shi->dxlo[0]= dl*o3[0]-shi->dxuv[0]*o1[0]-shi->dxuv[1]*o2[0];
1786                                         shi->dxlo[1]= dl*o3[1]-shi->dxuv[0]*o1[1]-shi->dxuv[1]*o2[1];
1787                                         shi->dxlo[2]= dl*o3[2]-shi->dxuv[0]*o1[2]-shi->dxuv[1]*o2[2];
1788                                         dl= shi->dyuv[0]+shi->dyuv[1];
1789                                         shi->dylo[0]= dl*o3[0]-shi->dyuv[0]*o1[0]-shi->dyuv[1]*o2[0];
1790                                         shi->dylo[1]= dl*o3[1]-shi->dyuv[0]*o1[1]-shi->dyuv[1]*o2[1];
1791                                         shi->dylo[2]= dl*o3[2]-shi->dyuv[0]*o1[2]-shi->dyuv[1]*o2[2];
1792                                 }
1793                         }
1794                 }
1795                 
1796                 if(texco & TEXCO_GLOB) {
1797                         VECCOPY(shi->gl, shi->co);
1798                         MTC_Mat4MulVecfl(R.viewinv, shi->gl);
1799                         if(shi->osatex) {
1800                                 VECCOPY(shi->dxgl, shi->dxco);
1801                                 MTC_Mat3MulVecfl(R.imat, shi->dxco);
1802                                 VECCOPY(shi->dygl, shi->dyco);
1803                                 MTC_Mat3MulVecfl(R.imat, shi->dyco);
1804                         }
1805                 }
1806                 if((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL|MA_FACETEXTURE)))  {
1807                         int j1=i1, j2=i2, j3=i3;
1808                         
1809                         /* to prevent storing new tfaces or vcols, we check a split runtime */
1810                         /*              4---3           4---3 */
1811                         /*              |\ 1|   or  |1 /| */
1812                         /*              |0\ |           |/ 0| */
1813                         /*              1---2           1---2   0 = orig face, 1 = new face */
1814                         
1815                         /* Update vert nums to point to correct verts of original face */
1816                         if(vlr->flag & R_DIVIDE_24) {  
1817                                 if(vlr->flag & R_FACE_SPLIT) {
1818                                         j1++; j2++; j3++;
1819                                 }
1820                                 else {
1821                                         j3++;
1822                                 }
1823                         }
1824                         else if(vlr->flag & R_FACE_SPLIT) {
1825                                 j2++; j3++; 
1826                         }
1827                         
1828                         if(mode & MA_VERTEXCOL) {
1829                                 
1830                                 if(vlr->vcol) {
1831                                         char *cp1, *cp2, *cp3;
1832                                         
1833                                         cp1= (char *)(vlr->vcol+j1);
1834                                         cp2= (char *)(vlr->vcol+j2);
1835                                         cp3= (char *)(vlr->vcol+j3);
1836
1837                                         shi->vcol[0]= (l*cp3[3]-u*cp1[3]-v*cp2[3])/255.0;
1838                                         shi->vcol[1]= (l*cp3[2]-u*cp1[2]-v*cp2[2])/255.0;
1839                                         shi->vcol[2]= (l*cp3[1]-u*cp1[1]-v*cp2[1])/255.0;
1840                                         
1841                                 }
1842                                 else {
1843                                         shi->vcol[0]= 0.0;
1844                                         shi->vcol[1]= 0.0;
1845                                         shi->vcol[2]= 0.0;
1846                                 }
1847                         }
1848                         if(vlr->tface) {
1849                                 float *uv1, *uv2, *uv3;
1850                                 
1851                                 uv1= vlr->tface->uv[j1];
1852                                 uv2= vlr->tface->uv[j2];
1853                                 uv3= vlr->tface->uv[j3];
1854                                 
1855                                 shi->uv[0]= -1.0 + 2.0*(l*uv3[0]-u*uv1[0]-v*uv2[0]);
1856                                 shi->uv[1]= -1.0 + 2.0*(l*uv3[1]-u*uv1[1]-v*uv2[1]);
1857                                 shi->uv[2]= 0.0;        // texture.c assumes there are 3 coords
1858                                 
1859                                 if(shi->osatex) {
1860                                         float duv[2];
1861                                         
1862                                         dl= shi->dxuv[0]+shi->dxuv[1];
1863                                         duv[0]= shi->dxuv[0]; 
1864                                         duv[1]= shi->dxuv[1];
1865                                         
1866                                         shi->dxuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
1867                                         shi->dxuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
1868         
1869                                         dl= shi->dyuv[0]+shi->dyuv[1];
1870                                         duv[0]= shi->dyuv[0]; 
1871                                         duv[1]= shi->dyuv[1];
1872         
1873                                         shi->dyuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
1874                                         shi->dyuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
1875                                 }
1876                                 
1877                                 if(mode & MA_FACETEXTURE) {
1878                                         if((mode & MA_VERTEXCOL)==0) {
1879                                                 shi->vcol[0]= 1.0;
1880                                                 shi->vcol[1]= 1.0;
1881                                                 shi->vcol[2]= 1.0;
1882                                         }
1883                                         if(vlr->tface) render_realtime_texture(shi);
1884                                 }
1885                         }
1886                         else {
1887                                 shi->uv[0]= 2.0*(u+.5);
1888                                 shi->uv[1]= 2.0*(v+.5);
1889                                 shi->uv[2]= 0.0;        // texture.c assumes there are 3 coords
1890                                 if(mode & MA_FACETEXTURE) {
1891                                         /* no tface? set at 1.0 */
1892                                         shi->vcol[0]= 1.0;
1893                                         shi->vcol[1]= 1.0;
1894                                         shi->vcol[2]= 1.0;
1895                                 }
1896                         }
1897                 }
1898                 if(texco & TEXCO_NORM) {
1899                         shi->orn[0]= -shi->vn[0];
1900                         shi->orn[1]= -shi->vn[1];
1901                         shi->orn[2]= -shi->vn[2];
1902                 }
1903                                 
1904                 if(mode & MA_RADIO) {
1905                         shi->rad[0]= (l*v3->rad[0] - u*v1->rad[0] - v*v2->rad[0]);
1906                         shi->rad[1]= (l*v3->rad[1] - u*v1->rad[1] - v*v2->rad[1]);
1907                         shi->rad[2]= (l*v3->rad[2] - u*v1->rad[2] - v*v2->rad[2]);
1908                 }
1909                 else {
1910                         shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0;
1911                 }
1912                         
1913                 if(texco & TEXCO_REFL) {
1914                         /* mirror reflection colour textures (and envmap) */
1915                         calc_R_ref(shi);
1916                 }
1917                 
1918         }
1919         else {
1920                 shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0;
1921         }
1922 }
1923
1924   /* x,y: window coordinate from 0 to rectx,y */
1925   /* return pointer to rendered face */
1926   
1927 float bluroffsx, bluroffsy;     // set in initrender.c (ton)
1928
1929 void *shadepixel(float x, float y, int vlaknr, int mask, float *col)
1930 {
1931         ShadeResult shr;
1932         ShadeInput shi;
1933         VlakRen *vlr=NULL;
1934         
1935         if(vlaknr< 0) { /* error */
1936                 return NULL;
1937         }
1938         /* currently in use for dithering soft shadow */
1939         shi.xs= x;
1940         shi.ys= y;
1941         
1942         /* mask is used to indicate amount of samples (ray shad/mir and AO) */
1943         shi.mask= mask;
1944         shi.depth= 0;   // means first hit, not raytracing
1945         
1946         if(vlaknr==0) { /* sky */
1947                 col[0]= 0.0; col[1]= 0.0; col[2]= 0.0; col[3]= 0.0;
1948         }
1949         else if( (vlaknr & 0x7FFFFF) <= R.totvlak) {
1950                 VertRen *v1, *v2, *v3;
1951                 float alpha, fac, dvlak, deler;
1952                 
1953                 vlr= RE_findOrAddVlak( (vlaknr-1) & 0x7FFFFF);
1954                 
1955                 shi.vlr= vlr;
1956                 shi.mat= vlr->mat;
1957                 
1958                 // copy all relevant material vars, note, keep this synced with render_types.h
1959                 memcpy(&shi.r, &shi.mat->r, 23*sizeof(float));
1960                 // set special cases:
1961                 shi.har= shi.mat->har;
1962                 if((shi.mat->mode & MA_RAYMIRROR)==0) shi.ray_mirror= 0.0;
1963                 shi.osatex= (shi.mat->texco & TEXCO_OSA);
1964
1965                 v1= vlr->v1;
1966                 dvlak= v1->co[0]*vlr->n[0]+v1->co[1]*vlr->n[1]+v1->co[2]*vlr->n[2];
1967
1968                 /* COXYZ AND VIEW VECTOR  */
1969                 shi.view[0]= (x+(R.xstart)+bluroffsx +0.5);
1970
1971                 if(R.flag & R_SEC_FIELD) {
1972                         if(R.r.mode & R_ODDFIELD) shi.view[1]= (y+R.ystart)*R.ycor;
1973                         else shi.view[1]= (y+R.ystart+1.0)*R.ycor;
1974                 }
1975                 else shi.view[1]= (y+R.ystart+bluroffsy+0.5)*R.ycor;
1976                 
1977                 shi.view[2]= -R.viewfac;
1978
1979                 if(R.r.mode & R_PANORAMA) {
1980                         float panoco, panosi, u, v;
1981                         panoco = getPanovCo();
1982                         panosi = getPanovSi();
1983
1984                         u= shi.view[0]; v= shi.view[2];
1985                         shi.view[0]= panoco*u + panosi*v;
1986                         shi.view[2]= -panosi*u + panoco*v;
1987                 }
1988
1989                 deler= vlr->n[0]*shi.view[0] + vlr->n[1]*shi.view[1] + vlr->n[2]*shi.view[2];
1990                 if (deler!=0.0) fac= R.zcor= dvlak/deler;
1991                 else fac= R.zcor= 0.0;
1992                 
1993                 shi.co[0]= fac*shi.view[0];
1994                 shi.co[1]= fac*shi.view[1];
1995                 shi.co[2]= fac*shi.view[2];
1996                 
1997                 /* pixel dx/dy for render coord */
1998                 if(shi.osatex || (R.r.mode & R_SHADOW) ) {
1999                         float u= dvlak/(deler-vlr->n[0]);
2000                         float v= dvlak/(deler- R.ycor*vlr->n[1]);
2001
2002                         shi.dxco[0]= shi.co[0]- (shi.view[0]-1.0)*u;
2003                         shi.dxco[1]= shi.co[1]- (shi.view[1])*u;
2004                         shi.dxco[2]= shi.co[2]- (shi.view[2])*u;
2005
2006                         shi.dyco[0]= shi.co[0]- (shi.view[0])*v;
2007                         shi.dyco[1]= shi.co[1]- (shi.view[1]-1.0*R.ycor)*v;
2008                         shi.dyco[2]= shi.co[2]- (shi.view[2])*v;
2009
2010                 }
2011
2012                 fac= Normalise(shi.view);
2013                 R.zcor*= fac;   /* for mist */
2014                 
2015                 if(shi.osatex) {
2016                         if( (shi.mat->texco & TEXCO_REFL) ) {
2017                                 shi.dxview= -1.0/fac;
2018                                 shi.dyview= -R.ycor/fac;
2019                         }
2020                 }
2021                 
2022                 /* calcuate normals, texture coords, vertex colors, etc */
2023                 if(vlaknr & 0x800000)
2024                         shade_input_set_coords(&shi, 1.0, 1.0, 0, 2, 3);
2025                 else 
2026                         shade_input_set_coords(&shi, 1.0, 1.0, 0, 1, 2);
2027
2028                 /* this only avalailable for scanline */
2029                 if(shi.mat->texco & TEXCO_WINDOW) {
2030                         shi.winco[0]= (x+(R.xstart))/(float)R.afmx;
2031                         shi.winco[1]= (y+(R.ystart))/(float)R.afmy;
2032                         shi.winco[2]= 0.0;
2033                         if(shi.osatex) {
2034                                 shi.dxwin[0]= 0.5/(float)R.r.xsch;
2035                                 shi.dywin[1]= 0.5/(float)R.r.ysch;
2036                                 shi.dxwin[1]= shi.dxwin[2]= 0.0;
2037                                 shi.dywin[0]= shi.dywin[2]= 0.0;
2038                         }
2039                 }
2040                 /* after this the u and v AND shi.dxuv and shi.dyuv are incorrect */
2041                 if(shi.mat->texco & TEXCO_STICKY) {
2042                         if(v1->sticky) {
2043                                 extern float Zmulx, Zmuly;
2044                                 float *o1, *o2, *o3, hox, hoy, l, dl, u, v;
2045                                 float s00, s01, s10, s11, detsh;
2046                                 
2047                                 if(vlaknr & 0x800000) {
2048                                         v2= vlr->v3; v3= vlr->v4;
2049                                 } else {
2050                                         v2= vlr->v2; v3= vlr->v3;
2051                                 }
2052                                 
2053                                 s00= v3->ho[0]/v3->ho[3] - v1->ho[0]/v1->ho[3];
2054                                 s01= v3->ho[1]/v3->ho[3] - v1->ho[1]/v1->ho[3];
2055                                 s10= v3->ho[0]/v3->ho[3] - v2->ho[0]/v2->ho[3];
2056                                 s11= v3->ho[1]/v3->ho[3] - v2->ho[1]/v2->ho[3];
2057                                 
2058                                 detsh= s00*s11-s10*s01;
2059                                 s00/= detsh; s01/=detsh; 
2060                                 s10/=detsh; s11/=detsh;
2061         
2062                                 /* recalc u and v again */
2063                                 hox= x/Zmulx -1.0;
2064                                 hoy= y/Zmuly -1.0;
2065                                 u= (hox - v3->ho[0]/v3->ho[3])*s11 - (hoy - v3->ho[1]/v3->ho[3])*s10;
2066                                 v= (hoy - v3->ho[1]/v3->ho[3])*s00 - (hox - v3->ho[0]/v3->ho[3])*s01;
2067                                 l= 1.0+u+v;
2068                                 
2069                                 o1= v1->sticky;
2070                                 o2= v2->sticky;
2071                                 o3= v3->sticky;
2072                                 
2073                                 shi.sticky[0]= l*o3[0]-u*o1[0]-v*o2[0];
2074                                 shi.sticky[1]= l*o3[1]-u*o1[1]-v*o2[1];
2075                                 shi.sticky[2]= 0.0;
2076                                 
2077                                 if(shi.osatex) {
2078                                         shi.dxuv[0]=  s11/Zmulx;
2079                                         shi.dxuv[1]=  - s01/Zmulx;
2080                                         shi.dyuv[0]=  - s10/Zmuly;
2081                                         shi.dyuv[1]=  s00/Zmuly;
2082                                         
2083                                         dl= shi.dxuv[0]+shi.dxuv[1];
2084                                         shi.dxsticky[0]= dl*o3[0]-shi.dxuv[0]*o1[0]-shi.dxuv[1]*o2[0];
2085                                         shi.dxsticky[1]= dl*o3[1]-shi.dxuv[0]*o1[1]-shi.dxuv[1]*o2[1];
2086                                         dl= shi.dyuv[0]+shi.dyuv[1];
2087                                         shi.dysticky[0]= dl*o3[0]-shi.dyuv[0]*o1[0]-shi.dyuv[1]*o2[0];
2088                                         shi.dysticky[1]= dl*o3[1]-shi.dyuv[0]*o1[1]-shi.dyuv[1]*o2[1];
2089                                 }
2090                         }
2091                 }
2092                 
2093                 /* ------  main shading loop */
2094                 shade_lamp_loop(&shi, &shr);
2095
2096                 if(shi.translucency!=0.0) {
2097                         ShadeResult shr_t;
2098                         
2099                         VecMulf(shi.vn, -1.0);
2100                         VecMulf(shi.vlr->n, -1.0);
2101                         shade_lamp_loop(&shi, &shr_t);
2102                         shr.diff[0]+= shi.translucency*shr_t.diff[0];
2103                         shr.diff[1]+= shi.translucency*shr_t.diff[1];
2104                         shr.diff[2]+= shi.translucency*shr_t.diff[2];
2105                         VecMulf(shi.vn, -1.0);
2106                         VecMulf(shi.vlr->n, -1.0);
2107                 }
2108                 
2109                 if(R.r.mode & R_RAYTRACE) {
2110                         if(shi.ray_mirror!=0.0 || ((shi.mat->mode & MA_RAYTRANSP) && shr.alpha!=1.0)) {
2111                                 ray_trace(&shi, &shr);
2112                         }
2113                 }
2114                 else {
2115                         // doesnt look 'correct', but is better for preview, plus envmaps dont raytrace this
2116                         if(shi.mat->mode & MA_RAYTRANSP) shr.alpha= 1.0;
2117                 }
2118                 
2119                 VECADD(col, shr.diff, shr.spec);
2120                 
2121                 /* exposure correction */
2122                 if(R.wrld.exp!=0.0 || R.wrld.range!=1.0) {
2123                         if((shi.mat->mode & MA_SHLESS)==0) {
2124                                 col[0]= R.wrld.linfac*(1.0-exp( col[0]*R.wrld.logfac) );
2125                                 col[1]= R.wrld.linfac*(1.0-exp( col[1]*R.wrld.logfac) );
2126                                 col[2]= R.wrld.linfac*(1.0-exp( col[2]*R.wrld.logfac) );
2127                         }
2128                 }
2129                 
2130                 /* MIST */
2131                 if( (R.wrld.mode & WO_MIST) && (shi.mat->mode & MA_NOMIST)==0 ){
2132                         alpha= mistfactor(shi.co);
2133                 }
2134                 else alpha= 1.0;
2135
2136                 if(shr.alpha!=1.0 || alpha!=1.0) {
2137                         fac= alpha*(shr.alpha);
2138                         
2139                         col[3]= fac;
2140                         col[0]*= fac;
2141                         col[1]*= fac;
2142                         col[2]*= fac;
2143                 }
2144                 else col[3]= 1.0;
2145         }
2146         
2147         if(R.flag & R_LAMPHALO) {
2148                 if(vlaknr<=0) { /* calc view vector and put shi.co at far */
2149                 
2150                         shi.view[0]= (x+(R.xstart)+0.5);
2151
2152                         if(R.flag & R_SEC_FIELD) {
2153                                 if(R.r.mode & R_ODDFIELD) shi.view[1]= (y+R.ystart)*R.ycor;
2154                                 else shi.view[1]= (y+R.ystart+1.0)*R.ycor;
2155                         }
2156                         else shi.view[1]= (y+R.ystart+0.5)*R.ycor;
2157                         
2158                         shi.view[2]= -R.viewfac;
2159                         
2160                         if(R.r.mode & R_PANORAMA) {
2161                                 float u,v, panoco, panosi;
2162                                 panoco = getPanovCo();
2163                                 panosi = getPanovSi();
2164                                 
2165                                 u= shi.view[0]; v= shi.view[2];
2166                                 shi.view[0]= panoco*u + panosi*v;
2167                                 shi.view[2]= -panosi*u + panoco*v;
2168                         }
2169
2170                         shi.co[2]= 0.0;
2171                         
2172                 }
2173                 renderspothalo(&shi, col);
2174         }
2175         
2176         return vlr;
2177 }
2178
2179 static void shadepixel_sky(float x, float y, int vlaknr, int mask, float *colf)
2180 {
2181         float collector[4];
2182         
2183         shadepixel(x, y, vlaknr, mask, colf);
2184         if(colf[3] != 1.0) {
2185                 renderSkyPixelFloat(collector, x, y);
2186                 addAlphaOverFloat(collector, colf);
2187                 QUATCOPY(colf, collector);
2188         }
2189 }
2190
2191 /* ************* pixel struct ******** */
2192
2193 PixStrMain psmfirst;
2194 int psmteller;
2195
2196 static PixStr *addpsmain(void)
2197 {
2198         PixStrMain *psm;
2199
2200         psm= &psmfirst;
2201
2202         while(psm->next) {
2203                 psm= psm->next;
2204         }
2205
2206         psm->next= (PixStrMain *)MEM_mallocN(sizeof(PixStrMain),"pixstrMain");
2207
2208         psm= psm->next;
2209         psm->next=0;
2210         psm->ps= (PixStr *)MEM_mallocN(4096*sizeof(PixStr),"pixstr");
2211         psmteller= 0;
2212
2213         return psm->ps;
2214 }
2215
2216 static void freeps(void)
2217 {
2218         PixStrMain *psm,*next;
2219
2220         psm= &psmfirst;
2221
2222         while(psm) {
2223                 next= psm->next;
2224                 if(psm->ps) {
2225                         MEM_freeN(psm->ps);
2226                         psm->ps= 0;
2227                 }
2228                 if(psm!= &psmfirst) MEM_freeN(psm);
2229                 psm= next;
2230         }
2231
2232         psmfirst.next= 0;
2233         psmfirst.ps= 0;
2234 }
2235
2236 static void addps(long *rd, int vlak, unsigned int z, short ronde)
2237 {
2238         static PixStr *prev;
2239         PixStr *ps, *last = NULL;
2240
2241         if( IS_A_POINTER_CODE(*rd)) {   
2242                 ps= (PixStr *) POINTER_FROM_CODE(*rd);
2243                 
2244                 if(ps->vlak0==vlak) return; 
2245                 
2246                 while(ps) {
2247                         if( ps->vlak == vlak ) {
2248                                 ps->mask |= (1<<ronde);
2249                                 return;
2250                         }
2251                         last= ps;
2252                         ps= ps->next;
2253                 }
2254
2255                 if((psmteller & 4095)==0) prev= addpsmain();
2256                 else prev++;
2257                 psmteller++;
2258
2259                 last->next= prev;
2260                 prev->next= 0;
2261                 prev->vlak= vlak;
2262                 prev->z= z;
2263                 prev->mask = (1<<ronde);
2264                 prev->ronde= ronde;
2265                 
2266                 return;
2267         }
2268
2269         /* make first PS (pixel struct) */
2270         if((psmteller & 4095)==0) prev= addpsmain();
2271         else prev++;
2272         psmteller++;
2273
2274         prev->next= 0;
2275         prev->vlak0= (int) *rd;
2276         prev->vlak= vlak;
2277         prev->z= z;
2278         prev->mask = (1<<ronde);
2279         prev->ronde= ronde;
2280         *rd= POINTER_TO_CODE(prev);
2281 }
2282
2283
2284 int count_mask(unsigned short mask)
2285 {
2286         extern char cmask[256];
2287         return (cmask[mask & 255]+cmask[mask>>8]);
2288 }
2289
2290 static void edge_enhance(void)
2291 {
2292         /* use zbuffer to define edges, add it to the image */
2293         int val, y, x, col, *rz, *rz1, *rz2, *rz3;
2294         char *cp;
2295         
2296         /* shift values in zbuffer 3 to the right */
2297         rz= (int *)R.rectz;
2298         if(rz==0) return;
2299         
2300         for(y=0; y<R.recty; y++) {
2301                 for(x=0; x<R.rectx; x++, rz++) {
2302                         (*rz)>>= 3;
2303                 }
2304         }
2305
2306         rz1= (int *)R.rectz;
2307         rz2= rz1+R.rectx;
2308         rz3= rz2+R.rectx;
2309
2310         if(R.r.mode & R_OSA) {
2311                 cp= (char *)(R.rectaccu+R.rectx);
2312         }
2313         else {
2314                 cp= (char *)(R.rectot+R.rectx);
2315         }
2316         cp+= 4;
2317         
2318         for(y=0; y<R.recty-2; y++) {
2319
2320                 for(x=0; x<R.rectx-2; x++, rz++, rz1++, rz2++, rz3++, cp+=4) {
2321
2322                         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;
2323                         /* removed the abs... now, only front/back? pixels are           */
2324                         /* accentuated? No, the lines seem shifted strangely. the does   */
2325                         /* not seem to be any overlap? strange...                        */
2326 /*                      col= -( 12*rz2[1] */
2327 /*                                      -   rz1[0] - 2*rz1[1] -   rz1[2] */
2328 /*                                      - 2*rz2[0]            - 2*rz2[2] */
2329 /*                                      -   rz3[0] - 2*rz3[1] -   rz3[2]) /3; */
2330                         
2331                         col= (R.r.edgeint*col)>>14;
2332                         if(col>255) col= 255;
2333                         
2334                         if(col>0) {
2335                                 if(R.r.mode & R_OSA) {
2336                                         col/= R.osa;
2337                                         
2338                                         val= cp[3]+col;
2339                                         if(val>255) cp[3]= 255; else cp[3]= val;
2340                                 }
2341                                 else {
2342                                         val= cp[0]- col;
2343                                         if(val<0) cp[0]= 0; else cp[0]= val;
2344                                         val= cp[1]- col;
2345                                         if(val<0) cp[1]= 0; else cp[1]= val;
2346                                         val= cp[2]- col;
2347                                         if(val<0) cp[2]= 0; else cp[2]= val;
2348                                 }
2349                         }
2350                 }
2351                 rz++;
2352                 rz1+= 2;
2353                 rz2+= 2;
2354                 rz3+= 2;
2355                 cp+= 8;
2356         }
2357
2358 }
2359
2360 /* ********************* MAINLOOPS ******************** */
2361 struct renderlineDA {
2362         long *rd;
2363         unsigned int *rz;
2364         float *rb1, *rb2, *rb3;
2365         float *acol;
2366         int y;
2367 };
2368
2369 static int do_renderlineDA(void *poin)
2370 {
2371         struct renderlineDA *rl= poin;
2372         PixStr *ps;
2373         float xs, ys;
2374         float fcol[4], *acol=NULL;
2375         long *rd= rl->rd;
2376         int samp, curmask, face, mask, fullmask;
2377         int b, x, full_osa, face0;
2378                 
2379         fullmask= (1<<R.osa)-1;
2380         
2381         if(R.flag & R_ZTRA) {           /* zbuf tra */
2382                 abufsetrow(rl->acol, rl->y); 
2383                 acol= rl->acol;
2384         }
2385
2386         for(x=0; x<R.rectx; x++, rd++) {
2387                                 
2388                 if( IS_A_POINTER_CODE(*rd))
2389                         ps= (PixStr *) POINTER_FROM_CODE(*rd);
2390                 else ps= NULL;
2391                 
2392                 if(ps) face0= ps->vlak0;
2393                 else face0= (int)*rd;
2394                 mask= 0;
2395                 
2396                 /* complex loop, because first pixelstruct has a vlak0, without mask */
2397                 while(TRUE) {
2398                         
2399                         if(ps==NULL) {
2400                                 face= face0;
2401                                 curmask= (~mask) & fullmask;
2402                         }
2403                         else {
2404                                 face= ps->vlak;
2405                                 curmask= ps->mask;
2406                         }
2407                         
2408                         /* check osa level */
2409                         if(face==0) full_osa= 0;
2410                         else {
2411                                 VlakRen *vlr= RE_findOrAddVlak( (face-1) & 0x7FFFFF);
2412                                 full_osa= (vlr->flag & R_FULL_OSA);
2413                         }
2414                         
2415                         if(full_osa) {
2416                                 for(samp=0; samp<R.osa; samp++) {
2417                                         if(curmask & (1<<samp)) {
2418                                                 xs= (float)x + jit[samp][0];
2419                                                 ys= (float)rl->y + jit[samp][1];
2420                                                 shadepixel_sky(xs, ys, face, (1<<samp), fcol);
2421                                                 
2422                                                 if(acol && acol[3]!=0.0) addAlphaOverFloat(fcol, acol);
2423                                                 if(do_gamma) {
2424                                                         fcol[0]= gammaCorrect(fcol[0]);
2425                                                         fcol[1]= gammaCorrect(fcol[1]);
2426                                                         fcol[2]= gammaCorrect(fcol[2]);
2427                                                 }
2428                                                 add_filt_fmask(1<<samp, fcol, rl->rb1, rl->rb2, rl->rb3);
2429                                         }
2430                                 }
2431                         }
2432                         else {
2433                                 extern char *centmask;  // initrender.c
2434                                 extern float centLut[16];
2435                                 
2436                                 b= centmask[curmask];
2437                                 xs= (float)x+centLut[b & 15];
2438                                 ys= (float)rl->y+centLut[b>>4];
2439                                 shadepixel_sky(xs, ys, face, curmask, fcol);
2440                                 
2441                                 if(acol && acol[3]!=0.0) addAlphaOverFloat(fcol, acol);
2442                                 
2443                                 if(do_gamma) {
2444                                         fcol[0]= gammaCorrect(fcol[0]);
2445                                         fcol[1]= gammaCorrect(fcol[1]);
2446                                         fcol[2]= gammaCorrect(fcol[2]);
2447                                 }
2448                                 add_filt_fmask(curmask, fcol, rl->rb1, rl->rb2, rl->rb3);
2449                         }
2450                         
2451                         mask |= curmask;
2452                         
2453                         if(ps==NULL) break;
2454                         else ps= ps->next;
2455                 }
2456                 
2457                 rl->rb1+=4; 
2458                 rl->rb2+=4; 
2459                 rl->rb3+=4;
2460                 if(acol) acol+=4;
2461         }
2462
2463         if(R.flag & R_HALO) {
2464                 /* from these pixels the pixstr is 1 scanline old */
2465                 scanlinehaloPS(rl->rz, rl->rd, rl->rb2-4*R.rectx + 4, rl->y);
2466         }
2467
2468         return 1;
2469 }
2470
2471 void zbufshadeDA(void)  /* Delta Accum Pixel Struct */
2472 {
2473         extern float Zjitx,Zjity;
2474         struct renderlineDA rl1, rl2;
2475         float xd, yd, *rf;
2476         long *rd;
2477         unsigned int *rz, *rp, *rt;
2478         float  *rowbuf1, *rowbuf2, *rowbuf3, *rowbuf0, *rowbuf1a, *rowbuf2a, *rb3;
2479         int a;
2480         short v, x, y;
2481
2482         R.rectdaps= MEM_callocN(sizeof(long)*R.rectx*R.recty+4,"zbufDArectd");
2483         
2484         if(R.flag & R_ZTRA) {
2485                 bgnaccumbuf();
2486                 rl1.acol= MEM_callocN((R.rectx+4)*4*sizeof(float), "Acol");
2487                 rl2.acol= MEM_callocN((R.rectx+4)*4*sizeof(float), "Acol");
2488         }
2489         
2490         psmteller= 0;
2491
2492         if(R.r.mode & R_EDGE) {
2493                 R.rectaccu= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty,"zbufshadeDA");
2494         }
2495
2496         for(v=0; v<R.osa; v++) {
2497
2498                 xd= jit[v][0];
2499                 yd= jit[v][1];
2500                 Zjitx= -xd -0.5;
2501                 Zjity= -yd -0.5;
2502
2503                 if((R.r.mode & R_MBLUR)==0) RE_local_printrenderinfo(0.0, v);
2504
2505                 /* RECTDELTA  */
2506                 fillrect(R.rectot,R.rectx,R.recty,0);
2507
2508                 zbufferall();
2509
2510                 if(v==0) {
2511                         a= R.rectx*R.recty;
2512                         rt= R.rectot;
2513                         rd= R.rectdaps;
2514                         while(a--) {
2515                                 *rd= (long)*rt;
2516                                 rd++; rt++;
2517                         }
2518                 }
2519                 else {
2520                         rd= R.rectdaps;
2521                         rp= R.rectot;
2522                         rz= R.rectz;
2523                         for(y=0; y<R.recty; y++) {
2524                                 for(x=0; x<R.rectx; x++, rp++, rd++) {
2525                                         if(*rd!= (long) *rp) {
2526                                                 addps(rd, *rp, *(rz+x), v);
2527                                         }
2528                                 }
2529                                 rz+= R.rectx;
2530                         }
2531                 }
2532                         /* 1 is for osa */
2533                 if(R.r.mode & R_EDGE) edge_enhance();
2534                 
2535                 if(RE_local_test_break()) break; 
2536         }
2537         
2538         if(R.flag & (R_ZTRA+R_HALO) ) {  /* to get back correct values of zbuffer Z for transp and halos */
2539                 xd= jit[0][0];
2540                 yd= jit[0][1];
2541                 Zjitx= -xd -0.5;
2542                 Zjity= -yd -0.5;
2543                 RE_setwindowclip(0, -1);
2544                 if((R.r.mode & R_MBLUR)==0) RE_local_printrenderinfo(0.0, v);
2545                 zbufferall();
2546         }
2547
2548         rd= R.rectdaps;
2549         rz= R.rectz;
2550         rt= R.rectot;
2551         rf= R.rectftot;
2552
2553         /* the rowbuf is 4 pixels larger than an image! */
2554         rowbuf0= MEM_callocN((R.rectx+4)*4*sizeof(float), "ZbufshadeDA3");
2555         rowbuf1= MEM_callocN((R.rectx+4)*4*sizeof(float), "ZbufshadeDA3");
2556         rowbuf2= MEM_callocN((R.rectx+4)*4*sizeof(float), "ZbufshadeDA3");
2557         rowbuf1a= MEM_callocN((R.rectx+4)*4*sizeof(float), "ZbufshadeDA3");
2558         rowbuf2a= MEM_callocN((R.rectx+4)*4*sizeof(float), "ZbufshadeDA3");
2559         rowbuf3= MEM_callocN((R.rectx+4)*4*sizeof(float), "ZbufshadeDA3");
2560
2561         for(y=0; y<=R.recty; y++, rd+=R.rectx, rt+=R.rectx, rz+= R.rectx) {
2562
2563                 if(y<R.recty) {
2564                         rl1.rd= rd;
2565                         rl1.rz= rz;
2566                         rl1.y= y;
2567                         rl1.rb1= rowbuf1;
2568                         rl1.rb2= rowbuf2;
2569                         rl1.rb3= rowbuf3;
2570                         
2571                         if(R.r.mode & R_THREADS) {
2572                                 if((y & 1)==0) {
2573                                         SDL_Thread *thread;
2574
2575                                         thread = SDL_CreateThread(do_renderlineDA, &rl1);
2576                                         if ( thread == NULL ) {
2577                                                 fprintf(stderr, "Unable to create thread");
2578                                                 G.afbreek= 1;
2579                                                 break;
2580                                         }
2581                                         
2582                                         rl2.rd= rd+R.rectx;
2583                                         rl2.rz= rz+R.rectx;
2584                                         rl2.y= y+1;
2585                                         rl2.rb1= rowbuf0;
2586                                         rl2.rb2= rowbuf1a;
2587                                         rl2.rb3= rowbuf2a;
2588                                         
2589                                         do_renderlineDA(&rl2);
2590                                         SDL_WaitThread(thread, NULL);
2591                                         
2592                                         if(R.r.mode & R_GAUSS) {
2593                                                 float *rb1= rowbuf1, *rb2= rowbuf2, *rb1a= rowbuf1a, *rb2a= rowbuf2a;
2594                                                 a= 4*(R.rectx + 4);
2595                                                 while(a--) {
2596                                                         *rb1 += *rb1a;
2597                                                         *rb2 += *rb2a;
2598                                                         *(rb1a++)= 0; rb1++;
2599                                                         *(rb2a++)= 0; rb2++;
2600                                                 }
2601                                         }
2602                                         else {
2603                                                 SWAP(float *, rowbuf1a, rowbuf1);
2604                                         }
2605                                 }
2606                         }
2607                         else do_renderlineDA(&rl1);
2608                         
2609                 }
2610                 /* convert 4x32 bits buffer to 4x8, add halos. this can't be threaded due to gauss */
2611                 if(y>0) {
2612                         transferColourBufferToOutput(rowbuf3+4, y-1);
2613                         if(R.rectftot) {
2614                                 memcpy(rf, rowbuf3+4, 4*sizeof(float)*R.rectx);
2615                                 rf+= 4*R.rectx;
2616                         }
2617                         
2618                 }
2619                 if(y<R.recty) {
2620                         memset(rowbuf3, 0, (R.rectx+4)*4*sizeof(int));
2621                         rb3= rowbuf3;
2622                         rowbuf3= rowbuf2;
2623                         rowbuf2= rowbuf1;
2624                         rowbuf1= rowbuf0;
2625                         rowbuf0= rb3;
2626
2627                         if( y>0) {
2628                                 if((y & 1)==0) {
2629                                         RE_local_render_display(y-2, y-1,  R.rectx, R.recty, R.rectot);
2630                                 }
2631                         }
2632                 }
2633                 if(RE_local_test_break()) break; 
2634         }
2635
2636         if( (R.r.mode & R_EDGE) && RE_local_test_break()==0) {
2637                 if(R.rectftot) {
2638                         float *rtf= R.rectftot, colf[4];
2639                         rp= R.rectaccu;
2640                         for(a= R.rectx*R.recty; a>0; a--, rtf+=4, rp++) {
2641                                 cpCharColV2FloatColV((char *)rp, colf);
2642                                 addAlphaOverFloat(rtf, colf);
2643                         }
2644                         RE_floatbuffer_to_output();
2645                 }
2646                 else {
2647                         rt= R.rectot;
2648                         rp= R.rectaccu;
2649                         for(a= R.rectx*R.recty; a>0; a--, rt++, rp++) {
2650                                 addalphaOver((char *)rt, (char *)rp);
2651                         }
2652                 }
2653         }
2654         
2655         MEM_freeN(R.rectdaps); 
2656         freeps();
2657         MEM_freeN(rowbuf0); 
2658         MEM_freeN(rowbuf1); 
2659         MEM_freeN(rowbuf2); 
2660         MEM_freeN(rowbuf1a); 
2661         MEM_freeN(rowbuf2a); 
2662         MEM_freeN(rowbuf3);
2663         R.rectdaps= NULL;
2664
2665         if(R.r.mode & R_EDGE) if(R.rectaccu) MEM_freeN(R.rectaccu);
2666         R.rectaccu= NULL;
2667         if(R.flag & R_ZTRA) {
2668                 endaccumbuf();
2669                 MEM_freeN(rl1.acol);
2670                 MEM_freeN(rl2.acol);
2671         }
2672
2673 } /* end of void zbufshadeDA() */
2674
2675 /* ------------------------------------------------------------------------ */
2676
2677 struct renderline {
2678         float *rowbuf, *acol;
2679         unsigned int *rp, *rz;
2680         short ys;
2681         float y;
2682 };
2683
2684 static int do_renderline(void *poin)
2685 {
2686         struct renderline *rl= poin;
2687         float *fcol= rl->rowbuf;
2688         float *acol=NULL;
2689         int x;
2690         
2691         if(R.flag & R_ZTRA) {           /* zbuf tra */
2692                 abufsetrow(rl->acol, rl->ys); 
2693                 acol= rl->acol;
2694         }
2695
2696         for(x=0; x<R.rectx; x++, (rl->rp)++, fcol+=4) {
2697                 
2698                 shadepixel_sky((float)x, rl->y, *(rl->rp), 0, fcol);
2699                 if(acol) {
2700                         if(acol[3]!=0.0) addAlphaOverFloat(fcol, acol);
2701                         acol+= 4;
2702                 }
2703         }
2704
2705         if(R.flag & R_HALO) {
2706                 scanlinehalo(rl->rz, rl->rowbuf, rl->ys);
2707         }
2708
2709         transferColourBufferToOutput(rl->rowbuf, rl->y);
2710
2711         if(R.rectftot) {
2712                 memcpy(R.rectftot + 4*rl->ys*R.rectx, rl->rowbuf, 4*sizeof(float)*R.rectx);
2713         }
2714
2715         return 1;
2716 }
2717
2718
2719 void zbufshade(void)
2720 {
2721         struct renderline rl1, rl2;
2722         extern float Zjitx,Zjity;
2723         unsigned int *rz,*rp;
2724         float fy;
2725         int y;
2726
2727         rl1.rowbuf= MEM_callocN((R.rectx+4)*4*sizeof(float), "Zbufshade");
2728         rl2.rowbuf= MEM_callocN((R.rectx+4)*4*sizeof(float), "Zbufshade");
2729         
2730         Zjitx=Zjity= -0.5;
2731
2732         zbufferall();
2733
2734         /* SHADE */
2735         rp= R.rectot;
2736         rz= R.rectz;
2737
2738         if(R.flag & R_ZTRA) {
2739                 rl1.acol= MEM_callocN((R.rectx+4)*4*sizeof(float), "Acol");
2740                 rl2.acol= MEM_callocN((R.rectx+4)*4*sizeof(float), "Acol");
2741                 bgnaccumbuf();
2742         }
2743
2744         for(y=0; y<R.recty; y++) {
2745                 fy= y;
2746                 
2747                 rl1.rp= rp;
2748                 rl1.rz= rz;
2749                 rl1.y= fy;
2750                 rl1.ys= y;
2751                 
2752                 if(R.r.mode & R_THREADS) {
2753                         SDL_Thread *thread;
2754                         
2755                         thread = SDL_CreateThread(do_renderline, &rl1);
2756                         if ( thread == NULL ) {
2757                                 fprintf(stderr, "Unable to create thread");
2758                                 G.afbreek= 1;
2759                                 break;
2760                         }
2761                         rp+= R.rectx;
2762                         rz+= R.rectx;
2763                         
2764                         if(y < R.recty-1) {
2765                                 rl2.rp= rp;
2766                                 rl2.rz= rz;
2767                                 rl2.y= fy+1.0;
2768                                 rl2.ys= y+1;
2769                                 do_renderline(&rl2);
2770                                 rp+= R.rectx;
2771                                 rz+= R.rectx;
2772                                 y++;
2773                         }                       
2774                         SDL_WaitThread(thread, NULL);
2775                 }
2776                 else {
2777                         do_renderline(&rl1);
2778                         rp+= R.rectx;
2779                         rz+= R.rectx;
2780                 }
2781                 
2782                 if(y & 1) {
2783                         RE_local_render_display(y-1, y, R.rectx, R.recty, R.rectot);
2784                 }
2785                 
2786                 if(RE_local_test_break()) break; 
2787         }
2788         
2789         MEM_freeN(rl1.rowbuf);
2790         MEM_freeN(rl2.rowbuf);
2791         
2792         if(R.flag & R_ZTRA) {
2793                 endaccumbuf();
2794                 MEM_freeN(rl1.acol);
2795                 MEM_freeN(rl2.acol);
2796         }
2797         
2798         if(R.r.mode & R_EDGE) edge_enhance();
2799
2800 } /* end of void zbufshade() */
2801
2802 /* ------------------------------------------------------------------------ */
2803
2804 void RE_shadehalo(HaloRen *har, char *col, float *colf, unsigned int zz, float dist, float xn, float yn, short flarec)
2805 {
2806
2807         shadeHaloFloat(har, colf, zz, dist, xn, yn, flarec);
2808         
2809         if(colf[0]<=0.0) col[0]= 0; else if(colf[0]>=1.0) col[0]= 255; else col[0]= 255.0*colf[0];
2810         if(colf[1]<=0.0) col[1]= 0; else if(colf[1]>=1.0) col[1]= 255; else col[1]= 255.0*colf[1];
2811         if(colf[2]<=0.0) col[2]= 0; else if(colf[2]>=1.0) col[2]= 255; else col[2]= 255.0*colf[2];
2812         if(colf[3]<=0.0) col[3]= 0; else if(colf[3]>=1.0) col[3]= 255; else col[3]= 255.0*colf[3];
2813         
2814 }
2815
2816 static void renderhalo(HaloRen *har)    /* postprocess version */
2817 {
2818         
2819         float dist, xsq, ysq, xn, yn, colf[4], *rectft, *rtf;
2820         unsigned int *rectt, *rt;
2821         int minx, maxx, miny, maxy, x, y;
2822         char col[4];
2823
2824         har->miny= miny= har->ys - har->rad/R.ycor;
2825         har->maxy= maxy= har->ys + har->rad/R.ycor;
2826
2827         if(maxy<0);
2828         else if(R.recty<miny);
2829         else {
2830                 minx= floor(har->xs-har->rad);
2831                 maxx= ceil(har->xs+har->rad);
2832                         
2833                 if(maxx<0);
2834                 else if(R.rectx<minx);
2835                 else {
2836                 
2837                         if(minx<0) minx= 0;
2838                         if(maxx>=R.rectx) maxx= R.rectx-1;
2839                         if(miny<0) miny= 0;
2840                         if(maxy>R.recty) maxy= R.recty;
2841         
2842                         rectt= R.rectot+ R.rectx*miny;
2843                         rectft= R.rectftot+ 4*R.rectx*miny;
2844                                 
2845                         for(y=miny; y<maxy; y++) {
2846         
2847                                 rt= rectt+minx;
2848                                 rtf= rectft+4*minx;
2849                                 
2850                                 yn= (y - har->ys)*R.ycor;
2851                                 ysq= yn*yn;
2852                                 
2853                                 for(x=minx; x<=maxx; x++) {
2854                                         xn= x - har->xs;
2855                                         xsq= xn*xn;
2856                                         dist= xsq+ysq;
2857                                         if(dist<har->radsq) {
2858                                                 
2859                                                 shadeHaloFloat(har, colf, 0, dist, xn, yn, har->flarec);
2860                                                 if(R.rectftot) addalphaAddfacFloat(rtf, colf, har-&g