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