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