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