converted more mixed tab/space indentations to tabs. only whitespace changes.
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 /** \file blender/render/intern/source/pixelshading.c
28  *  \ingroup render
29  */
30
31
32 #include <float.h>
33 #include <math.h>
34 #include <string.h>
35
36 #include "BLI_math.h"
37 #include "BLI_utildefines.h"
38
39 /* External modules: */
40 #include "IMB_imbuf_types.h"
41 #include "IMB_imbuf.h"
42
43 #include "DNA_camera_types.h"
44 #include "DNA_group_types.h"
45 #include "DNA_material_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_image_types.h"
48 #include "DNA_texture_types.h"
49 #include "DNA_lamp_types.h"
50
51 #include "BKE_colortools.h"
52 #include "BKE_image.h"
53 #include "BKE_global.h"
54 #include "BKE_material.h"
55 #include "BKE_texture.h"
56
57
58 /* own module */
59 #include "render_types.h"
60 #include "renderpipeline.h"
61 #include "renderdatabase.h"
62 #include "texture.h"
63 #include "pixelblending.h"
64 #include "rendercore.h"
65 #include "shadbuf.h"
66 #include "pixelshading.h"
67 #include "shading.h"
68 #include "sunsky.h"
69
70 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
71 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
72 /* only to be used here in this file, it's for speed */
73 extern struct Render R;
74 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
75
76
77 extern float hashvectf[];
78
79 static void render_lighting_halo(HaloRen *har, float *colf)
80 {
81         GroupObject *go;
82         LampRen *lar;
83         float i, inp, inpr, rco[3], dco[3], lv[3], lampdist, ld, t, *vn;
84         float ir, ig, ib, shadfac, soft, lacol[3];
85         
86         ir= ig= ib= 0.0;
87         
88         VECCOPY(rco, har->co);  
89         dco[0]=dco[1]=dco[2]= 1.0/har->rad;
90         
91         vn= har->no;
92         
93         for(go=R.lights.first; go; go= go->next) {
94                 lar= go->lampren;
95                 
96                 /* test for lamplayer */
97                 if(lar->mode & LA_LAYER) if((lar->lay & har->lay)==0) continue;
98                 
99                 /* lampdist cacluation */
100                 if(lar->type==LA_SUN || lar->type==LA_HEMI) {
101                         VECCOPY(lv, lar->vec);
102                         lampdist= 1.0;
103                 }
104                 else {
105                         lv[0]= rco[0]-lar->co[0];
106                         lv[1]= rco[1]-lar->co[1];
107                         lv[2]= rco[2]-lar->co[2];
108                         ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
109                         lv[0]/= ld;
110                         lv[1]/= ld;
111                         lv[2]/= ld;
112                         
113                         /* ld is re-used further on (texco's) */
114                         
115                         if(lar->mode & LA_QUAD) {
116                                 t= 1.0;
117                                 if(lar->ld1>0.0)
118                                         t= lar->dist/(lar->dist+lar->ld1*ld);
119                                 if(lar->ld2>0.0)
120                                         t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld);
121                                 
122                                 lampdist= t;
123                         }
124                         else {
125                                 lampdist= (lar->dist/(lar->dist+ld));
126                         }
127                         
128                         if(lar->mode & LA_SPHERE) {
129                                 t= lar->dist - ld;
130                                 if(t<0.0) continue;
131                                 
132                                 t/= lar->dist;
133                                 lampdist*= (t);
134                         }
135                         
136                 }
137                 
138                 lacol[0]= lar->r;
139                 lacol[1]= lar->g;
140                 lacol[2]= lar->b;
141                 
142                 if(lar->mode & LA_TEXTURE) {
143                         ShadeInput shi;
144                         
145                         /* Warning, This is not that nice, and possibly a bit slow,
146                         however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */
147                         memset(&shi, 0, sizeof(ShadeInput)); 
148                         /* end warning! - Campbell */
149                         
150                         VECCOPY(shi.co, rco);
151                         shi.osatex= 0;
152                         do_lamp_tex(lar, lv, &shi, lacol, LA_TEXTURE);
153                 }
154                 
155                 if(lar->type==LA_SPOT) {
156                         
157                         if(lar->mode & LA_SQUARE) {
158                                 if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) {
159                                         float x, lvrot[3];
160                                         
161                                         /* rotate view to lampspace */
162                                         VECCOPY(lvrot, lv);
163                                         mul_m3_v3(lar->imat, lvrot);
164                                         
165                                         x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
166                                         /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
167                                         
168                                         inpr= 1.0/(sqrt(1.0+x*x));
169                                 }
170                                 else inpr= 0.0;
171                         }
172                         else {
173                                 inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
174                         }
175                         
176                         t= lar->spotsi;
177                         if(inpr<t) continue;
178                         else {
179                                 t= inpr-t;
180                                 i= 1.0;
181                                 soft= 1.0;
182                                 if(t<lar->spotbl && lar->spotbl!=0.0) {
183                                         /* soft area */
184                                         i= t/lar->spotbl;
185                                         t= i*i;
186                                         soft= (3.0*t-2.0*t*i);
187                                         inpr*= soft;
188                                 }
189                                 if(lar->mode & LA_ONLYSHADOW) {
190                                         /* if(ma->mode & MA_SHADOW) { */
191                                         /* dot product positive: front side face! */
192                                         inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
193                                         if(inp>0.0) {
194                                                 /* testshadowbuf==0.0 : 100% shadow */
195                                                 shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f);
196                                                 if( shadfac>0.0 ) {
197                                                         shadfac*= inp*soft*lar->energy;
198                                                         ir -= shadfac;
199                                                         ig -= shadfac;
200                                                         ib -= shadfac;
201                                                         
202                                                         continue;
203                                                 }
204                                         }
205                                         /* } */
206                                 }
207                                 lampdist*=inpr;
208                         }
209                         if(lar->mode & LA_ONLYSHADOW) continue;
210                         
211                 }
212                 
213                 /* dot product and  reflectivity*/
214                 
215                 inp= 1.0-fabs(vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]);
216                 
217                 /* inp= cos(0.5*M_PI-acos(inp)); */
218                 
219                 i= inp;
220                 
221                 if(lar->type==LA_HEMI) {
222                         i= 0.5*i+0.5;
223                 }
224                 if(i>0.0) {
225                         i*= lampdist;
226                 }
227                 
228                 /* shadow  */
229                 if(i> -0.41) {                  /* heuristic valua! */
230                         shadfac= 1.0;
231                         if(lar->shb) {
232                                 shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f);
233                                 if(shadfac==0.0) continue;
234                                 i*= shadfac;
235                         }
236                 }
237                 
238                 if(i>0.0) {
239                         ir+= i*lacol[0];
240                         ig+= i*lacol[1];
241                         ib+= i*lacol[2];
242                 }
243         }
244         
245         if(ir<0.0) ir= 0.0;
246         if(ig<0.0) ig= 0.0;
247         if(ib<0.0) ib= 0.0;
248
249         colf[0]*= ir;
250         colf[1]*= ig;
251         colf[2]*= ib;
252         
253 }
254
255
256 /**
257  * Converts a halo z-buffer value to distance from the camera's near plane
258  * @param z The z-buffer value to convert
259  * @return a distance from the camera's near plane in blender units
260  */
261 static float haloZtoDist(int z)
262 {
263         float zco = 0;
264
265         if(z >= 0x7FFFFF)
266                 return 10e10;
267         else {
268                 zco = (float)z/(float)0x7FFFFF;
269                 if(R.r.mode & R_ORTHO)
270                         return (R.winmat[3][2] - zco*R.winmat[3][3])/(R.winmat[2][2]);
271                 else
272                         return (R.winmat[3][2])/(R.winmat[2][2] - R.winmat[2][3]*zco);
273         }
274 }
275
276 /**
277  * @param col (float[4]) Store the rgb color here (with alpha)
278  * The alpha is used to blend the color to the background 
279  * color_new = (1-alpha)*color_background + color
280  * @param zz The current zbuffer value at the place of this pixel
281  * @param dist Distance of the pixel from the center of the halo squared. Given in pixels
282  * @param xn The x coordinate of the pixel relaticve to the center of the halo. given in pixels
283  * @param yn The y coordinate of the pixel relaticve to the center of the halo. given in pixels
284  */
285 int shadeHaloFloat(HaloRen *har,  float *col, int zz, 
286                                         float dist, float xn,  float yn, short flarec)
287 {
288         /* fill in col */
289         float t, zn, radist, ringf=0.0f, linef=0.0f, alpha, si, co;
290         int a;
291    
292         if(R.wrld.mode & WO_MIST) {
293                 if(har->type & HA_ONLYSKY) {
294                         /* stars but no mist */
295                         alpha= har->alfa;
296                 }
297                 else {
298                         /* a bit patchy... */
299                         alpha= mistfactor(-har->co[2], har->co)*har->alfa;
300                 }
301         }
302         else alpha= har->alfa;
303         
304         if(alpha==0.0)
305                 return 0;
306
307         /* soften the halo if it intersects geometry */
308         if(har->mat && har->mat->mode & MA_HALO_SOFT) {
309                 float segment_length, halo_depth, distance_from_z, visible_depth, soften;
310                 
311                 /* calculate halo depth */
312                 segment_length= har->hasize*sasqrt(1.0f - dist/(har->rad*har->rad));
313                 halo_depth= 2.0f*segment_length;
314
315                 if(halo_depth < FLT_EPSILON)
316                         return 0;
317
318                 /* calculate how much of this depth is visible */
319                 distance_from_z = haloZtoDist(zz) - haloZtoDist(har->zs);
320                 visible_depth = halo_depth;
321                 if(distance_from_z < segment_length) {
322                         soften= (segment_length + distance_from_z)/halo_depth;
323
324                         /* apply softening to alpha */
325                         if(soften < 1.0f)
326                                 alpha *= soften;
327                         if(alpha <= 0.0f)
328                                 return 0;
329                 }
330         }
331         else {
332                 /* not a soft halo. use the old softening code */
333                 /* halo being intersected? */
334                 if(har->zs> zz-har->zd) {
335                         t= ((float)(zz-har->zs))/(float)har->zd;
336                         alpha*= sqrt(sqrt(t));
337                 }
338         }
339
340         radist= sqrt(dist);
341
342         /* watch it: not used nicely: flarec is set at zero in pixstruct */
343         if(flarec) har->pixels+= (int)(har->rad-radist);
344
345         if(har->ringc) {
346                 float *rc, fac;
347                 int ofs;
348                 
349                 /* per ring an antialised circle */
350                 ofs= har->seed;
351                 
352                 for(a= har->ringc; a>0; a--, ofs+=2) {
353                         
354                         rc= hashvectf + (ofs % 768);
355                         
356                         fac= fabs( rc[1]*(har->rad*fabs(rc[0]) - radist) );
357                         
358                         if(fac< 1.0) {
359                                 ringf+= (1.0-fac);
360                         }
361                 }
362         }
363
364         if(har->type & HA_VECT) {
365                 dist= fabs( har->cos*(yn) - har->sin*(xn) )/har->rad;
366                 if(dist>1.0) dist= 1.0;
367                 if(har->tex) {
368                         zn= har->sin*xn - har->cos*yn;
369                         yn= har->cos*xn + har->sin*yn;
370                         xn= zn;
371                 }
372         }
373         else dist= dist/har->radsq;
374
375         if(har->type & HA_FLARECIRC) {
376                 
377                 dist= 0.5+fabs(dist-0.5);
378                 
379         }
380
381         if(har->hard>=30) {
382                 dist= sqrt(dist);
383                 if(har->hard>=40) {
384                         dist= sin(dist*M_PI_2);
385                         if(har->hard>=50) {
386                                 dist= sqrt(dist);
387                         }
388                 }
389         }
390         else if(har->hard<20) dist*=dist;
391
392         if(dist < 1.0f)
393                 dist= (1.0f-dist);
394         else
395                 dist= 0.0f;
396         
397         if(har->linec) {
398                 float *rc, fac;
399                 int ofs;
400                 
401                 /* per starpoint an antialiased line */
402                 ofs= har->seed;
403                 
404                 for(a= har->linec; a>0; a--, ofs+=3) {
405                         
406                         rc= hashvectf + (ofs % 768);
407                         
408                         fac= fabs( (xn)*rc[0]+(yn)*rc[1]);
409                         
410                         if(fac< 1.0f )
411                                 linef+= (1.0f-fac);
412                 }
413                 
414                 linef*= dist;
415         }
416
417         if(har->starpoints) {
418                 float ster, angle;
419                 /* rotation */
420                 angle= atan2(yn, xn);
421                 angle*= (1.0+0.25*har->starpoints);
422                 
423                 co= cos(angle);
424                 si= sin(angle);
425                 
426                 angle= (co*xn+si*yn)*(co*yn-si*xn);
427                 
428                 ster= fabs(angle);
429                 if(ster>1.0) {
430                         ster= (har->rad)/(ster);
431                         
432                         if(ster<1.0) dist*= sqrt(ster);
433                 }
434         }
435
436         /* disputable optimize... (ton) */
437         if(dist<=0.00001)
438                 return 0;
439         
440         dist*= alpha;
441         ringf*= dist;
442         linef*= alpha;
443         
444         /* The color is either the rgb spec-ed by the user, or extracted from   */
445         /* the texture                                                           */
446         if(har->tex) {
447                 col[0]= har->r; 
448                 col[1]= har->g; 
449                 col[2]= har->b;
450                 col[3]= dist;
451                 
452                 do_halo_tex(har, xn, yn, col);
453                 
454                 col[0]*= col[3];
455                 col[1]*= col[3];
456                 col[2]*= col[3];
457                 
458         }
459         else {
460                 col[0]= dist*har->r;
461                 col[1]= dist*har->g;
462                 col[2]= dist*har->b;
463                 if(har->type & HA_XALPHA) col[3]= dist*dist;
464                 else col[3]= dist;
465         }
466
467         if(har->mat) {
468                 if(har->mat->mode & MA_HALO_SHADE) {
469                         /* we test for lights because of preview... */
470                         if(R.lights.first) render_lighting_halo(har, col);
471                 }
472
473                 /* Next, we do the line and ring factor modifications. */
474                 if(linef!=0.0) {
475                         Material *ma= har->mat;
476                         
477                         col[0]+= linef * ma->specr;
478                         col[1]+= linef * ma->specg;
479                         col[2]+= linef * ma->specb;
480                         
481                         if(har->type & HA_XALPHA) col[3]+= linef*linef;
482                         else col[3]+= linef;
483                 }
484                 if(ringf!=0.0) {
485                         Material *ma= har->mat;
486
487                         col[0]+= ringf * ma->mirr;
488                         col[1]+= ringf * ma->mirg;
489                         col[2]+= ringf * ma->mirb;
490                         
491                         if(har->type & HA_XALPHA) col[3]+= ringf*ringf;
492                         else col[3]+= ringf;
493                 }
494         }
495         
496         /* alpha requires clip, gives black dots */
497         if(col[3] > 1.0f)
498                 col[3]= 1.0f;
499
500         return 1;
501 }
502
503 /* ------------------------------------------------------------------------- */
504
505 static void fillBackgroundImage(float *collector, float fx, float fy)
506 {
507         collector[0] = 0.0; 
508         collector[1] = 0.0; 
509         collector[2] = 0.0; 
510         collector[3] = 0.0; 
511         
512         if(R.backbuf) {
513                 float dx= 1.0f/(float)R.winx;
514                 float dy= 1.0f/(float)R.winy;
515                 
516                 image_sample(R.backbuf, fx*dx, fy*dy, dx, dy, collector);
517         }
518 }
519
520 /* Only view vector is important here. Result goes to colf[3] */
521 void shadeSkyView(float *colf, float *rco, float *view, float *dxyview, short thread)
522 {
523         float lo[3], zen[3], hor[3], blend, blendm;
524         int skyflag;
525         
526         /* flag indicating if we render the top hemisphere */
527         skyflag = WO_ZENUP;
528         
529         /* Some view vector stuff. */
530         if(R.wrld.skytype & WO_SKYREAL) {
531                 
532                 blend= view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2];
533                 
534                 if(blend<0.0) skyflag= 0;
535                 
536                 blend= fabs(blend);
537         }
538         else if(R.wrld.skytype & WO_SKYPAPER) {
539                 blend= 0.5+ 0.5*view[1];
540         }
541         else {
542                 /* the fraction of how far we are above the bottom of the screen */
543                 blend= fabs(0.5+ view[1]);
544         }
545
546         VECCOPY(hor, &R.wrld.horr);
547         VECCOPY(zen, &R.wrld.zenr);
548
549         /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If           */
550         /* SKYBLEND is active, the texture and color blend are added.           */
551         if(R.wrld.skytype & WO_SKYTEX) {
552                 VECCOPY(lo, view);
553                 if(R.wrld.skytype & WO_SKYREAL) {
554                         
555                         mul_m3_v3(R.imat, lo);
556                         
557                         SWAP(float, lo[1],  lo[2]);
558                         
559                 }
560                 do_sky_tex(rco, lo, dxyview, hor, zen, &blend, skyflag, thread);
561         }
562         
563         if(blend>1.0) blend= 1.0;
564         blendm= 1.0-blend;
565         
566         /* No clipping, no conversion! */
567         if(R.wrld.skytype & WO_SKYBLEND) {
568                 colf[0] = (blendm*hor[0] + blend*zen[0]);
569                 colf[1] = (blendm*hor[1] + blend*zen[1]);
570                 colf[2] = (blendm*hor[2] + blend*zen[2]);
571         } else {
572                 /* Done when a texture was grabbed. */
573                 colf[0]= hor[0];
574                 colf[1]= hor[1];
575                 colf[2]= hor[2];
576         }
577 }
578
579 /* shade sky according to sun lamps, all parameters are like shadeSkyView except sunsky*/
580 void shadeSunView(float *colf, float *view)
581 {
582         GroupObject *go;
583         LampRen *lar;
584         float sview[3];
585         int do_init= 1;
586         
587         for(go=R.lights.first; go; go= go->next) {
588                 lar= go->lampren;
589                 if(lar->type==LA_SUN && lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_SKY)){
590                         float sun_collector[3];
591                         float colorxyz[3];
592                         
593                         if(do_init) {
594                                 
595                                 VECCOPY(sview, view);
596                                 normalize_v3(sview);
597                                 mul_m3_v3(R.imat, sview);
598                                 if (sview[2] < 0.0)
599                                         sview[2] = 0.0;
600                                 normalize_v3(sview);
601                                 do_init= 0;
602                         }
603                         
604                         GetSkyXYZRadiancef(lar->sunsky, sview, colorxyz);
605                         xyz_to_rgb(colorxyz[0], colorxyz[1], colorxyz[2], &sun_collector[0], &sun_collector[1], &sun_collector[2], 
606                                            lar->sunsky->sky_colorspace);
607                         
608                         ramp_blend(lar->sunsky->skyblendtype, colf, colf+1, colf+2, lar->sunsky->skyblendfac, sun_collector);
609                 }
610         }
611 }
612
613
614 /*
615   Stuff the sky color into the collector.
616  */
617 void shadeSkyPixel(float *collector, float fx, float fy, short thread) 
618 {
619         float view[3], dxyview[2];
620
621         /*
622           The rules for sky:
623           1. Draw an image, if a background image was provided. Stop
624           2. get texture and color blend, and combine these.
625         */
626
627         float fac;
628
629         /* 1. Do a backbuffer image: */ 
630         if(R.r.bufflag & 1) {
631                 fillBackgroundImage(collector, fx, fy);
632         } 
633         else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
634                 /* 2. solid color */
635                 VECCOPY(collector, &R.wrld.horr);
636
637                 collector[3] = 0.0f;
638         } 
639         else {
640                 /* 3. */
641
642                 /* This one true because of the context of this routine  */
643                 if(R.wrld.skytype & WO_SKYPAPER) {
644                         view[0]= -1.0f + 2.0f*(fx/(float)R.winx);
645                         view[1]= -1.0f + 2.0f*(fy/(float)R.winy);
646                         view[2]= 0.0;
647                         
648                         dxyview[0]= 1.0f/(float)R.winx;
649                         dxyview[1]= 1.0f/(float)R.winy;
650                 }
651                 else {
652                         calc_view_vector(view, fx, fy);
653                         fac= normalize_v3(view);
654                         
655                         if(R.wrld.skytype & WO_SKYTEX) {
656                                 dxyview[0]= -R.viewdx/fac;
657                                 dxyview[1]= -R.viewdy/fac;
658                         }
659                 }
660                 
661                 /* get sky color in the collector */
662                 shadeSkyView(collector, NULL, view, dxyview, thread);
663                 collector[3] = 0.0f;
664         }
665         
666         calc_view_vector(view, fx, fy);
667         shadeSunView(collector, view);
668 }
669
670 /* aerial perspective */
671 void shadeAtmPixel(struct SunSky *sunsky, float *collector, float fx, float fy, float distance)
672 {
673         float view[3];
674                 
675         calc_view_vector(view, fx, fy);
676         normalize_v3(view);
677         /*mul_m3_v3(R.imat, view);*/
678         AtmospherePixleShader(sunsky, view, distance, collector);
679 }
680
681 /* eof */