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