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