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