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