svn merge -r36583:36603 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / render / intern / source / sunsky.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  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/render/intern/source/sunsky.c
22  *  \ingroup render
23  */
24
25
26
27 #include "sunsky.h"
28 #include "math.h"
29 #include "BLI_math.h"
30 #include "BKE_global.h"
31
32 /**
33  * These macros are defined for vector operations
34  * */
35
36 /**
37  * compute v1 = v2 op v3
38  * v1, v2 and v3 are vectors contains 3 float
39  * */
40 #define vec3opv(v1, v2, op, v3) \
41         v1[0] = (v2[0] op v3[0]); \
42         v1[1] = (v2[1] op v3[1]);\
43         v1[2] = (v2[2] op v3[2]);
44
45 /**
46  * compute v1 = v2 op f1
47  * v1, v2 are vectors contains 3 float
48  * and f1 is a float
49  * */
50 #define vec3opf(v1, v2, op, f1)\
51         v1[0] = (v2[0] op (f1));\
52         v1[1] = (v2[1] op (f1));\
53         v1[2] = (v2[2] op (f1));
54
55 /**
56  * compute v1 = f1 op v2
57  * v1, v2 are vectors contains 3 float
58  * and f1 is a float
59  * */
60 #define fopvec3(v1, f1, op, v2)\
61         v1[0] = ((f1) op v2[0]);\
62         v1[1] = ((f1) op v2[1]);\
63         v1[2] = ((f1) op v2[2]);
64
65 /**
66  * ClipColor:
67  * clip a color to range [0,1];
68  * */
69 void ClipColor(float c[3])
70 {
71         if (c[0] > 1.0) c[0] = 1.0;
72         if (c[0] < 0.0) c[0] = 0.0;
73         if (c[1] > 1.0) c[1] = 1.0;
74         if (c[1] < 0.0) c[1] = 0.0;
75         if (c[2] > 1.0) c[2] = 1.0;
76         if (c[2] < 0.0) c[2] = 0.0;
77 }
78
79 /**
80  * AngleBetween:
81  * compute angle between to direction 
82  * all angles are in radians
83  * */
84 static float AngleBetween(float thetav, float phiv, float theta, float phi)
85 {
86         float cospsi = sin(thetav) * sin(theta) * cos(phi - phiv) + cos(thetav) * cos(theta);
87
88         if (cospsi > 1.0)
89                 return 0;
90         if (cospsi < -1.0)
91                 return M_PI;
92
93         return acos(cospsi);
94 }
95
96 /**
97  * DirectionToThetaPhi:
98  * this function convert a direction to it's theta and phi value
99  * parameters:
100  * toSun: contains direction information
101  * theta, phi, are return values from this conversion
102  * */
103 static void DirectionToThetaPhi(float *toSun, float *theta, float *phi)
104 {
105         *theta = acos(toSun[2]);
106         if (fabs(*theta) < 1e-5)
107                 *phi = 0;
108         else
109                 *phi = atan2(toSun[1], toSun[0]);
110 }
111
112 /**
113  * PerezFunction:
114  * compute perez function value based on input paramters
115  * */
116 static float PerezFunction(struct SunSky *sunsky, const float *lam, float theta, float gamma, float lvz)
117 {
118         float den, num;
119         
120         den = ((1 + lam[0] * exp(lam[1])) *
121                    (1 + lam[2] * exp(lam[3] * sunsky->theta) + lam[4] * cos(sunsky->theta) * cos(sunsky->theta)));
122         
123         num = ((1 + lam[0] * exp(lam[1] / cos(theta))) *
124                    (1 + lam[2] * exp(lam[3] * gamma) + lam[4] * cos(gamma) * cos(gamma)));
125         
126         return(lvz * num / den);}
127
128 /**
129  * InitSunSky:
130  * this function compute some sun,sky parameters according to input parameters and also initiate some other sun, sky parameters
131  * parameters:
132  * sunSky, is a structure that contains informtion about sun, sky and atmosphere, in this function, most of its values initiated
133  * turb, is atmosphere turbidity
134  * toSun, contains sun direction
135  * horizon_brighness, controls the brightness of the horizon colors
136  * spread, controls colors spreed at horizon
137  * sun_brightness, controls sun's brightness
138  * sun_size, controls sun's size
139  * back_scatter, controls back scatter light
140  * */
141 void InitSunSky(struct SunSky *sunsky, float turb, float *toSun, float horizon_brightness, 
142                                 float spread,float sun_brightness, float sun_size, float back_scatter,
143                                 float skyblendfac, short skyblendtype, float sky_exposure, float sky_colorspace)
144 {
145         float theta2;
146         float theta3;
147         float T;
148         float T2;
149         float chi;
150
151         sunsky->turbidity = turb;
152
153         sunsky->horizon_brightness = horizon_brightness;
154         sunsky->spread = spread;
155         sunsky->sun_brightness = sun_brightness;
156         sunsky->sun_size = sun_size;
157         sunsky->backscattered_light = back_scatter;
158         sunsky->skyblendfac= skyblendfac;
159         sunsky->skyblendtype= skyblendtype;
160         sunsky->sky_exposure= -sky_exposure;
161         sunsky->sky_colorspace= sky_colorspace;
162         
163         sunsky->toSun[0] = toSun[0];
164         sunsky->toSun[1] = toSun[1];
165         sunsky->toSun[2] = toSun[2];
166
167         DirectionToThetaPhi(sunsky->toSun, &sunsky->theta, &sunsky->phi);
168
169         sunsky->sunSolidAngle = 0.25 * M_PI * 1.39 * 1.39 / (150 * 150);   // = 6.7443e-05
170
171         theta2 = sunsky->theta*sunsky->theta;
172         theta3 = theta2 * sunsky->theta;
173         T = turb;
174         T2 = turb*turb;
175
176         chi = (4.0 / 9.0 - T / 120.0) * (M_PI - 2 * sunsky->theta);
177         sunsky->zenith_Y = (4.0453 * T - 4.9710) * tan(chi) - .2155 * T + 2.4192;
178         sunsky->zenith_Y *= 1000;   // conversion from kcd/m^2 to cd/m^2
179
180         if (sunsky->zenith_Y<=0)
181                 sunsky->zenith_Y = 1e-6;
182         
183         sunsky->zenith_x =
184                 ( + 0.00165 * theta3 - 0.00374 * theta2 + 0.00208 * sunsky->theta + 0) * T2 +
185                 ( -0.02902 * theta3 + 0.06377 * theta2 - 0.03202 * sunsky->theta + 0.00394) * T +
186                 ( + 0.11693 * theta3 - 0.21196 * theta2 + 0.06052 * sunsky->theta + 0.25885);
187
188         sunsky->zenith_y =
189                 ( + 0.00275 * theta3 - 0.00610 * theta2 + 0.00316 * sunsky->theta + 0) * T2 +
190                 ( -0.04214 * theta3 + 0.08970 * theta2 - 0.04153 * sunsky->theta + 0.00515) * T +
191                 ( + 0.15346 * theta3 - 0.26756 * theta2 + 0.06669 * sunsky->theta + 0.26688);
192
193         
194         sunsky->perez_Y[0] = 0.17872 * T - 1.46303;
195         sunsky->perez_Y[1] = -0.35540 * T + 0.42749;
196         sunsky->perez_Y[2] = -0.02266 * T + 5.32505;
197         sunsky->perez_Y[3] = 0.12064 * T - 2.57705;
198         sunsky->perez_Y[4] = -0.06696 * T + 0.37027;
199
200         sunsky->perez_x[0] = -0.01925 * T - 0.25922;
201         sunsky->perez_x[1] = -0.06651 * T + 0.00081;
202         sunsky->perez_x[2] = -0.00041 * T + 0.21247;
203         sunsky->perez_x[3] = -0.06409 * T - 0.89887;
204         sunsky->perez_x[4] = -0.00325 * T + 0.04517;
205
206         sunsky->perez_y[0] = -0.01669 * T - 0.26078;
207         sunsky->perez_y[1] = -0.09495 * T + 0.00921;
208         sunsky->perez_y[2] = -0.00792 * T + 0.21023;
209         sunsky->perez_y[3] = -0.04405 * T - 1.65369;
210         sunsky->perez_y[4] = -0.01092 * T + 0.05291;
211         
212         /* suggested by glome in 
213          * http://projects.blender.org/tracker/?func=detail&atid=127&aid=8063&group_id=9*/
214         sunsky->perez_Y[0] *= sunsky->horizon_brightness;
215         sunsky->perez_x[0] *= sunsky->horizon_brightness;
216         sunsky->perez_y[0] *= sunsky->horizon_brightness;
217         
218         sunsky->perez_Y[1] *= sunsky->spread;
219         sunsky->perez_x[1] *= sunsky->spread;
220         sunsky->perez_y[1] *= sunsky->spread;
221
222         sunsky->perez_Y[2] *= sunsky->sun_brightness;
223         sunsky->perez_x[2] *= sunsky->sun_brightness;
224         sunsky->perez_y[2] *= sunsky->sun_brightness;
225         
226         sunsky->perez_Y[3] *= sunsky->sun_size;
227         sunsky->perez_x[3] *= sunsky->sun_size;
228         sunsky->perez_y[3] *= sunsky->sun_size;
229         
230         sunsky->perez_Y[4] *= sunsky->backscattered_light;
231         sunsky->perez_x[4] *= sunsky->backscattered_light;
232         sunsky->perez_y[4] *= sunsky->backscattered_light;
233 }
234
235 /**
236  * GetSkyXYZRadiance:
237  * this function compute sky radiance according to a view parameters `theta' and `phi'and sunSky values
238  * parameters:
239  * sunSky, sontains sun and sky parameters
240  * theta, is sun's theta
241  * phi, is sun's phi
242  * color_out, is computed color that shows sky radiance in XYZ color format
243  * */
244 void GetSkyXYZRadiance(struct SunSky* sunsky, float theta, float phi, float color_out[3])
245 {
246         float gamma;
247         float x,y,Y,X,Z;
248         float hfade=1, nfade=1;
249
250
251         if (theta>(0.5*M_PI)) {
252                 hfade = 1.0-(theta*M_1_PI-0.5)*2.0;
253                 hfade = hfade*hfade*(3.0-2.0*hfade);
254                 theta = 0.5*M_PI;
255         }
256
257         if (sunsky->theta>(0.5*M_PI)) {
258                 if (theta<=0.5*M_PI) {
259                         nfade = 1.0-(0.5-theta*M_1_PI)*2.0;
260                         nfade *= 1.0-(sunsky->theta*M_1_PI-0.5)*2.0;
261                         nfade = nfade*nfade*(3.0-2.0*nfade);
262                 }
263         }
264
265         gamma = AngleBetween(theta, phi, sunsky->theta, sunsky->phi);
266         
267         // Compute xyY values
268         x = PerezFunction(sunsky, sunsky->perez_x, theta, gamma, sunsky->zenith_x);
269         y = PerezFunction(sunsky, sunsky->perez_y, theta, gamma, sunsky->zenith_y);
270         Y = 6.666666667e-5 * nfade * hfade * PerezFunction(sunsky, sunsky->perez_Y, theta, gamma, sunsky->zenith_Y);
271
272         if(sunsky->sky_exposure!=0.0f)
273                 Y = 1.0 - exp(Y*sunsky->sky_exposure);
274         
275         X = (x / y) * Y;
276         Z = ((1 - x - y) / y) * Y;
277
278         color_out[0] = X;
279         color_out[1] = Y;
280         color_out[2] = Z;
281 }
282
283 /**
284  * GetSkyXYZRadiancef:
285  * this function compute sky radiance according to a view direction `varg' and sunSky values
286  * parameters:
287  * sunSky, sontains sun and sky parameters
288  * varg, shows direction
289  * color_out, is computed color that shows sky radiance in XYZ color format
290  * */
291 void GetSkyXYZRadiancef(struct SunSky* sunsky, const float varg[3], float color_out[3])
292 {
293         float   theta, phi;
294         float   v[3];
295
296         copy_v3_v3(v, (float*)varg);
297         normalize_v3(v);
298
299         if (v[2] < 0.001){
300                 v[2] = 0.001;
301                 normalize_v3(v);
302         }
303
304         DirectionToThetaPhi(v, &theta, &phi);
305         GetSkyXYZRadiance(sunsky, theta, phi, color_out);
306 }
307
308 /**
309  * ComputeAttenuatedSunlight:
310  * this function compute attenuated sun light based on sun's theta and atmosphere turbidity
311  * parameters:
312  * theta, is sun's theta
313  * turbidity: is atmosphere turbidity
314  * fTau: contains computed attenuated sun light
315  * */
316 static void ComputeAttenuatedSunlight(float theta, int turbidity, float fTau[3])
317 {
318         float fBeta ;
319         float fTauR, fTauA;
320         float m ;
321         float fAlpha;
322
323         int i;
324         float fLambda[3]; 
325         fLambda[0] = 0.65f;     
326         fLambda[1] = 0.57f;     
327         fLambda[2] = 0.475f;
328
329         fAlpha = 1.3f;
330         fBeta = 0.04608365822050f * turbidity - 0.04586025928522f;
331         
332         m =  1.0/(cos(theta) + 0.15f*pow(93.885f-theta/M_PI*180.0f,-1.253f));  
333
334         for(i = 0; i < 3; i++)
335         {
336                 // Rayleigh Scattering
337                 fTauR = exp( -m * 0.008735f * pow(fLambda[i], (float)(-4.08f)));
338
339                 // Aerosal (water + dust) attenuation
340                 fTauA = exp(-m * fBeta * pow(fLambda[i], -fAlpha));  
341
342                 fTau[i] = fTauR * fTauA; 
343         }
344 }
345
346 /**
347  * InitAtmosphere:
348  * this function intiate sunSky structure with user input parameters.
349  * parameters:
350  * sunSky, contains information about sun, and in this function some atmosphere parameters will initiated
351  * sun_intens, shows sun intensity value
352  * mief, Mie scattering factor this factor currently call with 1.0 
353  * rayf, Rayleigh scattering factor, this factor currently call with 1.0
354  * inscattf, inscatter light factor that range from 0.0 to 1.0, 0.0 means no inscatter light and 1.0 means full inscatter light
355  * extincf, extinction light factor that range from 0.0 to 1.0, 0.0 means no extinction and 1.0 means full extinction
356  * disf, is distance factor, multiplyed to pixle's z value to compute each pixle's distance to camera, 
357  * */
358 void InitAtmosphere(struct SunSky *sunSky, float sun_intens, float mief, float rayf,
359                                                         float inscattf, float extincf, float disf)
360 {
361         const float pi = 3.14159265358f;
362         const float n = 1.003f; // refractive index
363         const float N = 2.545e25;
364         const float pn = 0.035f;
365         const float T = 2.0f;
366         float fTemp, fTemp2, fTemp3, fBeta, fBetaDash;
367         float c = (6.544*T - 6.51)*1e-17; 
368         float K[3] = {0.685f, 0.679f, 0.670f}; 
369         float vBetaMieTemp[3];
370         
371         float fLambda[3],fLambda2[3], fLambda4[3];
372         float vLambda2[3];
373         float vLambda4[3];
374         
375         int i;
376
377         sunSky->atm_SunIntensity = sun_intens;
378         sunSky->atm_BetaMieMultiplier  = mief;
379         sunSky->atm_BetaRayMultiplier = rayf;
380         sunSky->atm_InscatteringMultiplier = inscattf;
381         sunSky->atm_ExtinctionMultiplier = extincf;
382         sunSky->atm_DistanceMultiplier = disf;
383                 
384         sunSky->atm_HGg=0.8;
385
386         fLambda[0]  = 1/650e-9f; 
387         fLambda[1]  = 1/570e-9f;
388         fLambda[2]  = 1/475e-9f;
389         for (i=0; i < 3; i++)
390         {
391                 fLambda2[i] = fLambda[i]*fLambda[i];
392                 fLambda4[i] = fLambda2[i]*fLambda2[i];
393         }
394
395         vLambda2[0] = fLambda2[0];
396         vLambda2[1] = fLambda2[1];
397         vLambda2[2] = fLambda2[2];
398  
399         vLambda4[0] = fLambda4[0];
400         vLambda4[1] = fLambda4[1];
401         vLambda4[2] = fLambda4[2];
402
403         // Rayleigh scattering constants.
404         fTemp = pi*pi*(n*n-1)*(n*n-1)*(6+3*pn)/(6-7*pn)/N;
405         fBeta = 8*fTemp*pi/3;
406                 
407         vec3opf(sunSky->atm_BetaRay, vLambda4, *, fBeta);
408         fBetaDash = fTemp/2;
409         vec3opf(sunSky->atm_BetaDashRay, vLambda4,*, fBetaDash);
410         
411
412         // Mie scattering constants.
413         fTemp2 = 0.434*c*(2*pi)*(2*pi)*0.5f;
414         vec3opf(sunSky->atm_BetaDashMie, vLambda2, *, fTemp2);
415         
416         fTemp3 = 0.434f*c*pi*(2*pi)*(2*pi);
417         
418         vec3opv(vBetaMieTemp, K, *, fLambda);
419         vec3opf(sunSky->atm_BetaMie, vBetaMieTemp,*, fTemp3);
420         
421 }
422
423 /**
424  * AtmospherePixleShader:
425  * this function apply atmosphere effect on a pixle color `rgb' at distance `s'
426  * parameters:
427  * sunSky, contains information about sun parameters and user values
428  * view, is camera view vector
429  * s, is distance 
430  * rgb, contains rendered color value for a pixle
431  * */
432 void AtmospherePixleShader( struct SunSky* sunSky, float view[3], float s, float rgb[3])
433 {
434         float costheta;
435         float Phase_1;
436         float Phase_2;
437         float sunColor[3];
438         
439         float E[3];
440         float E1[3];
441         
442         
443         float I[3];
444         float fTemp;
445         float vTemp1[3], vTemp2[3];
446
447         float sunDirection[3];
448         
449         s *= sunSky->atm_DistanceMultiplier;
450         
451         sunDirection[0] = sunSky->toSun[0];
452         sunDirection[1] = sunSky->toSun[1];
453         sunDirection[2] = sunSky->toSun[2];
454         
455         costheta = dot_v3v3(view, sunDirection); // cos(theta)
456         Phase_1 = 1 + (costheta * costheta); // Phase_1
457         
458         vec3opf(sunSky->atm_BetaRay, sunSky->atm_BetaRay, *, sunSky->atm_BetaRayMultiplier);
459         vec3opf(sunSky->atm_BetaMie, sunSky->atm_BetaMie, *, sunSky->atm_BetaMieMultiplier);
460         vec3opv(sunSky->atm_BetaRM, sunSky->atm_BetaRay, +, sunSky->atm_BetaMie);
461         
462         //e^(-(beta_1 + beta_2) * s) = E1
463         vec3opf(E1, sunSky->atm_BetaRM, *, -s/log(2));
464         E1[0] = exp(E1[0]);
465         E1[1] = exp(E1[1]);
466         E1[2] = exp(E1[2]);
467
468         copy_v3_v3(E, E1);
469                 
470         //Phase2(theta) = (1-g^2)/(1+g-2g*cos(theta))^(3/2)
471         fTemp = 1 + sunSky->atm_HGg - 2 * sunSky->atm_HGg * costheta;
472         fTemp = fTemp * sqrt(fTemp);
473         Phase_2 = (1 - sunSky->atm_HGg * sunSky->atm_HGg)/fTemp;
474         
475         vec3opf(vTemp1, sunSky->atm_BetaDashRay, *, Phase_1);
476         vec3opf(vTemp2, sunSky->atm_BetaDashMie, *, Phase_2);   
477
478         vec3opv(vTemp1, vTemp1, +, vTemp2);
479         fopvec3(vTemp2, 1.0, -, E1);
480         vec3opv(vTemp1, vTemp1, *, vTemp2);
481
482         fopvec3(vTemp2, 1.0, / , sunSky->atm_BetaRM);
483
484         vec3opv(I, vTemp1, *, vTemp2);
485                 
486         vec3opf(I, I, *, sunSky->atm_InscatteringMultiplier);
487         vec3opf(E, E, *, sunSky->atm_ExtinctionMultiplier);
488                 
489         //scale to color sun
490         ComputeAttenuatedSunlight(sunSky->theta, sunSky->turbidity, sunColor);
491         vec3opv(E, E, *, sunColor);
492
493         vec3opf(I, I, *, sunSky->atm_SunIntensity);
494
495         vec3opv(rgb, rgb, *, E);
496         vec3opv(rgb, rgb, +, I);
497 }
498
499 #undef vec3opv
500 #undef vec3opf
501 #undef fopvec3
502
503 /* EOF */