resolved conflict state with HEAD r14096
[blender.git] / source / blender / render / intern / source / pixelshading.c
1 /**
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. 
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * Contributor(s): 2004-2006, Blender Foundation, full recode
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 #include <math.h>
28 #include <string.h>
29 #include "BLI_arithb.h"
30
31 /* External modules: */
32 #include "IMB_imbuf_types.h"
33 #include "IMB_imbuf.h"
34 #include "MTC_matrixops.h"
35 #include "MTC_vectorops.h"
36
37 #include "DNA_camera_types.h"
38 #include "DNA_group_types.h"
39 #include "DNA_material_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_image_types.h"
42 #include "DNA_texture_types.h"
43 #include "DNA_lamp_types.h"
44
45 #include "BKE_image.h"
46 #include "BKE_global.h"
47 #include "BKE_texture.h"
48 #include "BKE_utildefines.h"
49
50 /* own module */
51 #include "render_types.h"
52 #include "renderpipeline.h"
53 #include "renderdatabase.h"
54 #include "texture.h"
55 #include "pixelblending.h"
56 #include "rendercore.h"
57 #include "shadbuf.h"
58 #include "pixelshading.h"
59
60 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
61 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
62 /* only to be used here in this file, it's for speed */
63 extern struct Render R;
64 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
65
66
67 extern float hashvectf[];
68
69 static void render_lighting_halo(HaloRen *har, float *colf)
70 {
71         GroupObject *go;
72         LampRen *lar;
73         float i, inp, inpr, rco[3], dco[3], lv[3], lampdist, ld, t, *vn;
74         float ir, ig, ib, shadfac, soft, lacol[3];
75         
76         ir= ig= ib= 0.0;
77         
78         VECCOPY(rco, har->co);  
79         dco[0]=dco[1]=dco[2]= 1.0/har->rad;
80         
81         vn= har->no;
82         
83         for(go=R.lights.first; go; go= go->next) {
84                 lar= go->lampren;
85                 
86                 /* test for lamplayer */
87                 if(lar->mode & LA_LAYER) if((lar->lay & har->lay)==0) continue;
88                 
89                 /* lampdist cacluation */
90                 if(lar->type==LA_SUN || lar->type==LA_HEMI) {
91                         VECCOPY(lv, lar->vec);
92                         lampdist= 1.0;
93                 }
94                 else {
95                         lv[0]= rco[0]-lar->co[0];
96                         lv[1]= rco[1]-lar->co[1];
97                         lv[2]= rco[2]-lar->co[2];
98                         ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
99                         lv[0]/= ld;
100                         lv[1]/= ld;
101                         lv[2]/= ld;
102                         
103                         /* ld is re-used further on (texco's) */
104                         
105                         if(lar->mode & LA_QUAD) {
106                                 t= 1.0;
107                                 if(lar->ld1>0.0)
108                                         t= lar->dist/(lar->dist+lar->ld1*ld);
109                                 if(lar->ld2>0.0)
110                                         t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld);
111                                 
112                                 lampdist= t;
113                         }
114                         else {
115                                 lampdist= (lar->dist/(lar->dist+ld));
116                         }
117                         
118                         if(lar->mode & LA_SPHERE) {
119                                 t= lar->dist - ld;
120                                 if(t<0.0) continue;
121                                 
122                                 t/= lar->dist;
123                                 lampdist*= (t);
124                         }
125                         
126                 }
127                 
128                 lacol[0]= lar->r;
129                 lacol[1]= lar->g;
130                 lacol[2]= lar->b;
131                 
132                 if(lar->mode & LA_TEXTURE) {
133                         ShadeInput shi;
134                         
135                         /* Warning, This is not that nice, and possibly a bit slow,
136                         however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */
137                         memset(&shi, 0, sizeof(ShadeInput)); 
138                         /* end warning! - Campbell */
139                         
140                         VECCOPY(shi.co, rco);
141                         shi.osatex= 0;
142                         do_lamp_tex(lar, lv, &shi, lacol);
143                 }
144                 
145                 if(lar->type==LA_SPOT) {
146                         
147                         if(lar->mode & LA_SQUARE) {
148                                 if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) {
149                                         float x, lvrot[3];
150                                         
151                                         /* rotate view to lampspace */
152                                         VECCOPY(lvrot, lv);
153                                         MTC_Mat3MulVecfl(lar->imat, lvrot);
154                                         
155                                         x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
156                                         /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
157                                         
158                                         inpr= 1.0/(sqrt(1.0+x*x));
159                                 }
160                                 else inpr= 0.0;
161                         }
162                         else {
163                                 inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
164                         }
165                         
166                         t= lar->spotsi;
167                         if(inpr<t) continue;
168                         else {
169                                 t= inpr-t;
170                                 i= 1.0;
171                                 soft= 1.0;
172                                 if(t<lar->spotbl && lar->spotbl!=0.0) {
173                                         /* soft area */
174                                         i= t/lar->spotbl;
175                                         t= i*i;
176                                         soft= (3.0*t-2.0*t*i);
177                                         inpr*= soft;
178                                 }
179                                 if(lar->mode & LA_ONLYSHADOW) {
180                                         /* if(ma->mode & MA_SHADOW) { */
181                                         /* dot product positive: front side face! */
182                                         inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
183                                         if(inp>0.0) {
184                                                 /* testshadowbuf==0.0 : 100% shadow */
185                                                 shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f);
186                                                 if( shadfac>0.0 ) {
187                                                         shadfac*= inp*soft*lar->energy;
188                                                         ir -= shadfac;
189                                                         ig -= shadfac;
190                                                         ib -= shadfac;
191                                                         
192                                                         continue;
193                                                 }
194                                         }
195                                         /* } */
196                                 }
197                                 lampdist*=inpr;
198                         }
199                         if(lar->mode & LA_ONLYSHADOW) continue;
200                         
201                 }
202                 
203                 /* dot product and  reflectivity*/
204                 
205                 inp= 1.0-fabs(vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]);
206                 
207                 /* inp= cos(0.5*M_PI-acos(inp)); */
208                 
209                 i= inp;
210                 
211                 if(lar->type==LA_HEMI) {
212                         i= 0.5*i+0.5;
213                 }
214                 if(i>0.0) {
215                         i*= lampdist;
216                 }
217                 
218                 /* shadow  */
219                 if(i> -0.41) {                  /* heuristic valua! */
220                         shadfac= 1.0;
221                         if(lar->shb) {
222                                 shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f);
223                                 if(shadfac==0.0) continue;
224                                 i*= shadfac;
225                         }
226                 }
227                 
228                 if(i>0.0) {
229                         ir+= i*lacol[0];
230                         ig+= i*lacol[1];
231                         ib+= i*lacol[2];
232                 }
233         }
234         
235         if(ir<0.0) ir= 0.0;
236         if(ig<0.0) ig= 0.0;
237         if(ib<0.0) ib= 0.0;
238
239         colf[0]*= ir;
240         colf[1]*= ig;
241         colf[2]*= ib;
242         
243 }
244
245
246
247 void shadeHaloFloat(HaloRen *har,  float *col, int zz, 
248                                         float dist, float xn,  float yn, short flarec)
249 {
250         /* fill in col */
251         float t, zn, radist, ringf=0.0f, linef=0.0f, alpha, si, co;
252         int a;
253    
254         if(R.wrld.mode & WO_MIST) {
255        if(har->type & HA_ONLYSKY) {
256            /* stars but no mist */
257            alpha= har->alfa;
258        }
259        else {
260            /* a bit patchy... */
261            alpha= mistfactor(-har->co[2], har->co)*har->alfa;
262        }
263         }
264         else alpha= har->alfa;
265         
266         if(alpha==0.0) {
267                 col[0] = 0.0;
268                 col[1] = 0.0;
269                 col[2] = 0.0;
270                 col[3] = 0.0;
271                 return;
272         }
273
274         radist= sqrt(dist);
275
276         /* watch it: not used nicely: flarec is set at zero in pixstruct */
277         if(flarec) har->pixels+= (int)(har->rad-radist);
278
279         if(har->ringc) {
280                 float *rc, fac;
281                 int ofs;
282                 
283                 /* per ring an antialised circle */
284                 ofs= har->seed;
285                 
286                 for(a= har->ringc; a>0; a--, ofs+=2) {
287                         
288                         rc= hashvectf + (ofs % 768);
289                         
290                         fac= fabs( rc[1]*(har->rad*fabs(rc[0]) - radist) );
291                         
292                         if(fac< 1.0) {
293                                 ringf+= (1.0-fac);
294                         }
295                 }
296         }
297
298         if(har->type & HA_VECT) {
299                 dist= fabs( har->cos*(yn) - har->sin*(xn) )/har->rad;
300                 if(dist>1.0) dist= 1.0;
301                 if(har->tex) {
302                         zn= har->sin*xn - har->cos*yn;
303                         yn= har->cos*xn + har->sin*yn;
304                         xn= zn;
305                 }
306         }
307         else dist= dist/har->radsq;
308
309         if(har->type & HA_FLARECIRC) {
310                 
311                 dist= 0.5+fabs(dist-0.5);
312                 
313         }
314
315         if(har->hard>=30) {
316                 dist= sqrt(dist);
317                 if(har->hard>=40) {
318                         dist= sin(dist*M_PI_2);
319                         if(har->hard>=50) {
320                                 dist= sqrt(dist);
321                         }
322                 }
323         }
324         else if(har->hard<20) dist*=dist;
325
326         if(dist < 1.0f)
327                 dist= (1.0f-dist);
328         else
329                 dist= 0.0f;
330         
331         if(har->linec) {
332                 float *rc, fac;
333                 int ofs;
334                 
335                 /* per starpoint an antialiased line */
336                 ofs= har->seed;
337                 
338                 for(a= har->linec; a>0; a--, ofs+=3) {
339                         
340                         rc= hashvectf + (ofs % 768);
341                         
342                         fac= fabs( (xn)*rc[0]+(yn)*rc[1]);
343                         
344                         if(fac< 1.0f )
345                                 linef+= (1.0f-fac);
346                 }
347                 
348                 linef*= dist;
349         }
350
351         if(har->starpoints) {
352                 float ster, angle;
353                 /* rotation */
354                 angle= atan2(yn, xn);
355                 angle*= (1.0+0.25*har->starpoints);
356                 
357                 co= cos(angle);
358                 si= sin(angle);
359                 
360                 angle= (co*xn+si*yn)*(co*yn-si*xn);
361                 
362                 ster= fabs(angle);
363                 if(ster>1.0) {
364                         ster= (har->rad)/(ster);
365                         
366                         if(ster<1.0) dist*= sqrt(ster);
367                 }
368         }
369         
370         /* halo being intersected? */
371         if(har->zs> zz-har->zd) {
372                 t= ((float)(zz-har->zs))/(float)har->zd;
373                 alpha*= sqrt(sqrt(t));
374         }
375
376         /* disputable optimize... (ton) */
377         if(dist<=0.00001) {
378                 col[0] = 0.0;
379                 col[1] = 0.0;
380                 col[2] = 0.0;
381                 col[3] = 0.0;
382                 return;
383         }
384         
385         dist*= alpha;
386         ringf*= dist;
387         linef*= alpha;
388         
389         /* The color is either the rgb spec-ed by the user, or extracted from   */
390         /* the texture                                                           */
391         if(har->tex) {
392                 col[0]= har->r; 
393                 col[1]= har->g; 
394                 col[2]= har->b;
395                 col[3]= dist;
396                 
397                 do_halo_tex(har, xn, yn, col);
398                 
399                 col[0]*= col[3];
400                 col[1]*= col[3];
401                 col[2]*= col[3];
402                 
403         }
404         else {
405                 col[0]= dist*har->r;
406                 col[1]= dist*har->g;
407                 col[2]= dist*har->b;
408                 if(har->type & HA_XALPHA) col[3]= dist*dist;
409                 else col[3]= dist;
410         }
411
412         if(har->mat) {
413                 if(har->mat->mode & MA_HALO_SHADE) {
414                         /* we test for lights because of preview... */
415                         if(R.lights.first) render_lighting_halo(har, col);
416                 }
417
418                 /* Next, we do the line and ring factor modifications. */
419                 if(linef!=0.0) {
420                         Material *ma= har->mat;
421                         
422                         col[0]+= linef * ma->specr;
423                         col[1]+= linef * ma->specg;
424                         col[2]+= linef * ma->specb;
425                         
426                         if(har->type & HA_XALPHA) col[3]+= linef*linef;
427                         else col[3]+= linef;
428                 }
429                 if(ringf!=0.0) {
430                         Material *ma= har->mat;
431
432                         col[0]+= ringf * ma->mirr;
433                         col[1]+= ringf * ma->mirg;
434                         col[2]+= ringf * ma->mirb;
435                         
436                         if(har->type & HA_XALPHA) col[3]+= ringf*ringf;
437                         else col[3]+= ringf;
438                 }
439         }
440         
441         /* alpha requires clip, gives black dots */
442         if(col[3] > 1.0f)
443                 col[3]= 1.0f;
444 }
445
446 /* ------------------------------------------------------------------------- */
447
448 static void fillBackgroundImage(float *collector, float fx, float fy)
449 {
450         collector[0] = 0.0; 
451         collector[1] = 0.0; 
452         collector[2] = 0.0; 
453         collector[3] = 0.0; 
454         
455         if(R.backbuf) {
456                 float dx= 1.0f/(float)R.winx;
457                 float dy= 1.0f/(float)R.winy;
458                 
459                 image_sample(R.backbuf, fx*dx, fy*dy, dx, dy, collector);
460         }
461 }
462
463 /* Only view vector is important here. Result goes to colf[3] */
464 void shadeSkyView(float *colf, float *rco, float *view, float *dxyview)
465 {
466         float lo[3], zen[3], hor[3], blend, blendm;
467         int skyflag;
468         
469         /* flag indicating if we render the top hemisphere */
470         skyflag = WO_ZENUP;
471         
472         /* Some view vector stuff. */
473         if(R.wrld.skytype & WO_SKYREAL) {
474                 
475                 blend= view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2];
476                 
477                 if(blend<0.0) skyflag= 0;
478                 
479                 blend= fabs(blend);
480         }
481         else if(R.wrld.skytype & WO_SKYPAPER) {
482                 blend= 0.5+ 0.5*view[1];
483         }
484         else {
485                 /* the fraction of how far we are above the bottom of the screen */
486                 blend= fabs(0.5+ view[1]);
487         }
488         
489         hor[0]= R.wrld.horr; hor[1]= R.wrld.horg; hor[2]= R.wrld.horb;
490         zen[0]= R.wrld.zenr; zen[1]= R.wrld.zeng; zen[2]= R.wrld.zenb;
491         
492         /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If           */
493         /* SKYBLEND is active, the texture and color blend are added.           */
494         if(R.wrld.skytype & WO_SKYTEX) {
495                 VECCOPY(lo, view);
496                 if(R.wrld.skytype & WO_SKYREAL) {
497                         
498                         MTC_Mat3MulVecfl(R.imat, lo);
499                         
500                         SWAP(float, lo[1],  lo[2]);
501                         
502                 }
503                 do_sky_tex(rco, lo, dxyview, hor, zen, &blend, skyflag);
504         }
505         
506         if(blend>1.0) blend= 1.0;
507         blendm= 1.0-blend;
508         
509         /* No clipping, no conversion! */
510         if(R.wrld.skytype & WO_SKYBLEND) {
511                 colf[0] = (blendm*hor[0] + blend*zen[0]);
512                 colf[1] = (blendm*hor[1] + blend*zen[1]);
513                 colf[2] = (blendm*hor[2] + blend*zen[2]);
514         } else {
515                 /* Done when a texture was grabbed. */
516                 colf[0]= hor[0];
517                 colf[1]= hor[1];
518                 colf[2]= hor[2];
519         }
520 }
521
522 /*
523   Stuff the sky color into the collector.
524  */
525 void shadeSkyPixel(float *collector, float fx, float fy) 
526 {
527         float view[3], dxyview[2];
528         
529         /*
530           The rules for sky:
531           1. Draw an image, if a background image was provided. Stop
532           2. get texture and color blend, and combine these.
533         */
534
535         float fac;
536
537         /* 1. Do a backbuffer image: */ 
538         if(R.r.bufflag & 1) {
539                 fillBackgroundImage(collector, fx, fy);
540                 return;
541         } 
542         else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
543                 /* 2. solid color */
544                 collector[0] = R.wrld.horr;
545                 collector[1] = R.wrld.horg;
546                 collector[2] = R.wrld.horb;
547                 collector[3] = 0.0f;
548         } 
549         else {
550                 /* 3. */
551
552                 /* This one true because of the context of this routine  */
553                 if(R.wrld.skytype & WO_SKYPAPER) {
554                         view[0]= -1.0f + 2.0f*(fx/(float)R.winx);
555                         view[1]= -1.0f + 2.0f*(fy/(float)R.winy);
556                         view[2]= 0.0;
557                         
558                         dxyview[0]= 1.0f/(float)R.winx;
559                         dxyview[1]= 1.0f/(float)R.winy;
560                 }
561                 else {
562                         calc_view_vector(view, fx, fy);
563                         fac= Normalize(view);
564                         
565                         if(R.wrld.skytype & WO_SKYTEX) {
566                                 dxyview[0]= -R.viewdx/fac;
567                                 dxyview[1]= -R.viewdy/fac;
568                         }
569                 }
570                 
571                 /* get sky color in the collector */
572                 shadeSkyView(collector, NULL, view, dxyview);
573                 collector[3] = 0.0f;
574         }
575 }
576
577
578 /* eof */