Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * ***** END GPL LICENSE BLOCK ***** 00019 */ 00020 00027 #include "sunsky.h" 00028 #include "math.h" 00029 #include "BLI_math.h" 00030 #include "BKE_global.h" 00031 00040 #define vec3opv(v1, v2, op, v3) \ 00041 v1[0] = (v2[0] op v3[0]); \ 00042 v1[1] = (v2[1] op v3[1]);\ 00043 v1[2] = (v2[2] op v3[2]); 00044 00050 #define vec3opf(v1, v2, op, f1)\ 00051 v1[0] = (v2[0] op (f1));\ 00052 v1[1] = (v2[1] op (f1));\ 00053 v1[2] = (v2[2] op (f1)); 00054 00060 #define fopvec3(v1, f1, op, v2)\ 00061 v1[0] = ((f1) op v2[0]);\ 00062 v1[1] = ((f1) op v2[1]);\ 00063 v1[2] = ((f1) op v2[2]); 00064 00069 void ClipColor(float c[3]) 00070 { 00071 if (c[0] > 1.0f) c[0] = 1.0f; 00072 if (c[0] < 0.0f) c[0] = 0.0f; 00073 if (c[1] > 1.0f) c[1] = 1.0f; 00074 if (c[1] < 0.0f) c[1] = 0.0f; 00075 if (c[2] > 1.0f) c[2] = 1.0f; 00076 if (c[2] < 0.0f) c[2] = 0.0f; 00077 } 00078 00084 static float AngleBetween(float thetav, float phiv, float theta, float phi) 00085 { 00086 float cospsi = sin(thetav) * sin(theta) * cos(phi - phiv) + cos(thetav) * cos(theta); 00087 00088 if (cospsi > 1.0f) 00089 return 0; 00090 if (cospsi < -1.0f) 00091 return M_PI; 00092 00093 return acos(cospsi); 00094 } 00095 00103 static void DirectionToThetaPhi(float *toSun, float *theta, float *phi) 00104 { 00105 *theta = acos(toSun[2]); 00106 if (fabs(*theta) < 1e-5) 00107 *phi = 0; 00108 else 00109 *phi = atan2(toSun[1], toSun[0]); 00110 } 00111 00116 static float PerezFunction(struct SunSky *sunsky, const float *lam, float theta, float gamma, float lvz) 00117 { 00118 float den, num; 00119 00120 den = ((1 + lam[0] * expf(lam[1])) * 00121 (1 + lam[2] * expf(lam[3] * sunsky->theta) + lam[4] * cosf(sunsky->theta) * cosf(sunsky->theta))); 00122 00123 num = ((1 + lam[0] * expf(lam[1] / cosf(theta))) * 00124 (1 + lam[2] * expf(lam[3] * gamma) + lam[4] * cosf(gamma) * cosf(gamma))); 00125 00126 return(lvz * num / den);} 00127 00141 void InitSunSky(struct SunSky *sunsky, float turb, float *toSun, float horizon_brightness, 00142 float spread,float sun_brightness, float sun_size, float back_scatter, 00143 float skyblendfac, short skyblendtype, float sky_exposure, float sky_colorspace) 00144 { 00145 float theta2; 00146 float theta3; 00147 float T; 00148 float T2; 00149 float chi; 00150 00151 sunsky->turbidity = turb; 00152 00153 sunsky->horizon_brightness = horizon_brightness; 00154 sunsky->spread = spread; 00155 sunsky->sun_brightness = sun_brightness; 00156 sunsky->sun_size = sun_size; 00157 sunsky->backscattered_light = back_scatter; 00158 sunsky->skyblendfac= skyblendfac; 00159 sunsky->skyblendtype= skyblendtype; 00160 sunsky->sky_exposure= -sky_exposure; 00161 sunsky->sky_colorspace= sky_colorspace; 00162 00163 sunsky->toSun[0] = toSun[0]; 00164 sunsky->toSun[1] = toSun[1]; 00165 sunsky->toSun[2] = toSun[2]; 00166 00167 DirectionToThetaPhi(sunsky->toSun, &sunsky->theta, &sunsky->phi); 00168 00169 sunsky->sunSolidAngle = 0.25 * M_PI * 1.39 * 1.39 / (150 * 150); // = 6.7443e-05 00170 00171 theta2 = sunsky->theta*sunsky->theta; 00172 theta3 = theta2 * sunsky->theta; 00173 T = turb; 00174 T2 = turb*turb; 00175 00176 chi = (4.0f / 9.0f - T / 120.0f) * ((float)M_PI - 2.0f * sunsky->theta); 00177 sunsky->zenith_Y = (4.0453f * T - 4.9710f) * tanf(chi) - 0.2155f * T + 2.4192f; 00178 sunsky->zenith_Y *= 1000; // conversion from kcd/m^2 to cd/m^2 00179 00180 if (sunsky->zenith_Y<=0) 00181 sunsky->zenith_Y = 1e-6; 00182 00183 sunsky->zenith_x = 00184 ( + 0.00165f * theta3 - 0.00374f * theta2 + 0.00208f * sunsky->theta + 0.0f) * T2 + 00185 ( -0.02902f * theta3 + 0.06377f * theta2 - 0.03202f * sunsky->theta + 0.00394f) * T + 00186 ( + 0.11693f * theta3 - 0.21196f * theta2 + 0.06052f * sunsky->theta + 0.25885f); 00187 00188 sunsky->zenith_y = 00189 ( + 0.00275f * theta3 - 0.00610f * theta2 + 0.00316f * sunsky->theta + 0.0f) * T2 + 00190 ( -0.04214f * theta3 + 0.08970f * theta2 - 0.04153f * sunsky->theta + 0.00515f) * T + 00191 ( + 0.15346f * theta3 - 0.26756f * theta2 + 0.06669f * sunsky->theta + 0.26688f); 00192 00193 00194 sunsky->perez_Y[0] = 0.17872f * T - 1.46303f; 00195 sunsky->perez_Y[1] = -0.35540f * T + 0.42749f; 00196 sunsky->perez_Y[2] = -0.02266f * T + 5.32505f; 00197 sunsky->perez_Y[3] = 0.12064f * T - 2.57705f; 00198 sunsky->perez_Y[4] = -0.06696f * T + 0.37027f; 00199 00200 sunsky->perez_x[0] = -0.01925f * T - 0.25922f; 00201 sunsky->perez_x[1] = -0.06651f * T + 0.00081f; 00202 sunsky->perez_x[2] = -0.00041f * T + 0.21247f; 00203 sunsky->perez_x[3] = -0.06409f * T - 0.89887f; 00204 sunsky->perez_x[4] = -0.00325f * T + 0.04517f; 00205 00206 sunsky->perez_y[0] = -0.01669f * T - 0.26078f; 00207 sunsky->perez_y[1] = -0.09495f * T + 0.00921f; 00208 sunsky->perez_y[2] = -0.00792f * T + 0.21023f; 00209 sunsky->perez_y[3] = -0.04405f * T - 1.65369f; 00210 sunsky->perez_y[4] = -0.01092f * T + 0.05291f; 00211 00212 /* suggested by glome in 00213 * http://projects.blender.org/tracker/?func=detail&atid=127&aid=8063&group_id=9*/ 00214 sunsky->perez_Y[0] *= sunsky->horizon_brightness; 00215 sunsky->perez_x[0] *= sunsky->horizon_brightness; 00216 sunsky->perez_y[0] *= sunsky->horizon_brightness; 00217 00218 sunsky->perez_Y[1] *= sunsky->spread; 00219 sunsky->perez_x[1] *= sunsky->spread; 00220 sunsky->perez_y[1] *= sunsky->spread; 00221 00222 sunsky->perez_Y[2] *= sunsky->sun_brightness; 00223 sunsky->perez_x[2] *= sunsky->sun_brightness; 00224 sunsky->perez_y[2] *= sunsky->sun_brightness; 00225 00226 sunsky->perez_Y[3] *= sunsky->sun_size; 00227 sunsky->perez_x[3] *= sunsky->sun_size; 00228 sunsky->perez_y[3] *= sunsky->sun_size; 00229 00230 sunsky->perez_Y[4] *= sunsky->backscattered_light; 00231 sunsky->perez_x[4] *= sunsky->backscattered_light; 00232 sunsky->perez_y[4] *= sunsky->backscattered_light; 00233 } 00234 00244 void GetSkyXYZRadiance(struct SunSky* sunsky, float theta, float phi, float color_out[3]) 00245 { 00246 float gamma; 00247 float x,y,Y,X,Z; 00248 float hfade=1, nfade=1; 00249 00250 00251 if (theta>(0.5f*(float)M_PI)) { 00252 hfade = 1.0f-(theta*(float)M_1_PI-0.5f)*2.0f; 00253 hfade = hfade*hfade*(3.0f-2.0f*hfade); 00254 theta = 0.5*M_PI; 00255 } 00256 00257 if (sunsky->theta>(0.5f*(float)M_PI)) { 00258 if (theta<=0.5f*(float)M_PI) { 00259 nfade = 1.0f-(0.5f-theta*(float)M_1_PI)*2.0f; 00260 nfade *= 1.0f-(sunsky->theta*(float)M_1_PI-0.5f)*2.0f; 00261 nfade = nfade*nfade*(3.0f-2.0f*nfade); 00262 } 00263 } 00264 00265 gamma = AngleBetween(theta, phi, sunsky->theta, sunsky->phi); 00266 00267 // Compute xyY values 00268 x = PerezFunction(sunsky, sunsky->perez_x, theta, gamma, sunsky->zenith_x); 00269 y = PerezFunction(sunsky, sunsky->perez_y, theta, gamma, sunsky->zenith_y); 00270 Y = 6.666666667e-5f * nfade * hfade * PerezFunction(sunsky, sunsky->perez_Y, theta, gamma, sunsky->zenith_Y); 00271 00272 if(sunsky->sky_exposure!=0.0f) 00273 Y = 1.0 - exp(Y*sunsky->sky_exposure); 00274 00275 X = (x / y) * Y; 00276 Z = ((1 - x - y) / y) * Y; 00277 00278 color_out[0] = X; 00279 color_out[1] = Y; 00280 color_out[2] = Z; 00281 } 00282 00291 void GetSkyXYZRadiancef(struct SunSky* sunsky, const float varg[3], float color_out[3]) 00292 { 00293 float theta, phi; 00294 float v[3]; 00295 00296 copy_v3_v3(v, (float*)varg); 00297 normalize_v3(v); 00298 00299 if (v[2] < 0.001f) { 00300 v[2] = 0.001f; 00301 normalize_v3(v); 00302 } 00303 00304 DirectionToThetaPhi(v, &theta, &phi); 00305 GetSkyXYZRadiance(sunsky, theta, phi, color_out); 00306 } 00307 00316 static void ComputeAttenuatedSunlight(float theta, int turbidity, float fTau[3]) 00317 { 00318 float fBeta ; 00319 float fTauR, fTauA; 00320 float m ; 00321 float fAlpha; 00322 00323 int i; 00324 float fLambda[3]; 00325 fLambda[0] = 0.65f; 00326 fLambda[1] = 0.57f; 00327 fLambda[2] = 0.475f; 00328 00329 fAlpha = 1.3f; 00330 fBeta = 0.04608365822050f * turbidity - 0.04586025928522f; 00331 00332 m = 1.0f/(cosf(theta) + 0.15f*powf(93.885f-theta/(float)M_PI*180.0f,-1.253f)); 00333 00334 for(i = 0; i < 3; i++) 00335 { 00336 // Rayleigh Scattering 00337 fTauR = expf( -m * 0.008735f * powf(fLambda[i], (float)(-4.08f))); 00338 00339 // Aerosal (water + dust) attenuation 00340 fTauA = exp(-m * fBeta * powf(fLambda[i], -fAlpha)); 00341 00342 fTau[i] = fTauR * fTauA; 00343 } 00344 } 00345 00358 void InitAtmosphere(struct SunSky *sunSky, float sun_intens, float mief, float rayf, 00359 float inscattf, float extincf, float disf) 00360 { 00361 const float pi = 3.14159265358f; 00362 const float n = 1.003f; // refractive index 00363 const float N = 2.545e25; 00364 const float pn = 0.035f; 00365 const float T = 2.0f; 00366 float fTemp, fTemp2, fTemp3, fBeta, fBetaDash; 00367 float c = (6.544f*T - 6.51f)*1e-17f; 00368 float K[3] = {0.685f, 0.679f, 0.670f}; 00369 float vBetaMieTemp[3]; 00370 00371 float fLambda[3],fLambda2[3], fLambda4[3]; 00372 float vLambda2[3]; 00373 float vLambda4[3]; 00374 00375 int i; 00376 00377 sunSky->atm_SunIntensity = sun_intens; 00378 sunSky->atm_BetaMieMultiplier = mief; 00379 sunSky->atm_BetaRayMultiplier = rayf; 00380 sunSky->atm_InscatteringMultiplier = inscattf; 00381 sunSky->atm_ExtinctionMultiplier = extincf; 00382 sunSky->atm_DistanceMultiplier = disf; 00383 00384 sunSky->atm_HGg=0.8; 00385 00386 fLambda[0] = 1/650e-9f; 00387 fLambda[1] = 1/570e-9f; 00388 fLambda[2] = 1/475e-9f; 00389 for (i=0; i < 3; i++) 00390 { 00391 fLambda2[i] = fLambda[i]*fLambda[i]; 00392 fLambda4[i] = fLambda2[i]*fLambda2[i]; 00393 } 00394 00395 vLambda2[0] = fLambda2[0]; 00396 vLambda2[1] = fLambda2[1]; 00397 vLambda2[2] = fLambda2[2]; 00398 00399 vLambda4[0] = fLambda4[0]; 00400 vLambda4[1] = fLambda4[1]; 00401 vLambda4[2] = fLambda4[2]; 00402 00403 // Rayleigh scattering constants. 00404 fTemp = pi*pi*(n*n-1)*(n*n-1)*(6+3*pn)/(6-7*pn)/N; 00405 fBeta = 8*fTemp*pi/3; 00406 00407 vec3opf(sunSky->atm_BetaRay, vLambda4, *, fBeta); 00408 fBetaDash = fTemp/2; 00409 vec3opf(sunSky->atm_BetaDashRay, vLambda4,*, fBetaDash); 00410 00411 00412 // Mie scattering constants. 00413 fTemp2 = 0.434f*c*(2*pi)*(2*pi)*0.5f; 00414 vec3opf(sunSky->atm_BetaDashMie, vLambda2, *, fTemp2); 00415 00416 fTemp3 = 0.434f*c*pi*(2*pi)*(2*pi); 00417 00418 vec3opv(vBetaMieTemp, K, *, fLambda); 00419 vec3opf(sunSky->atm_BetaMie, vBetaMieTemp,*, fTemp3); 00420 00421 } 00422 00432 void AtmospherePixleShader( struct SunSky* sunSky, float view[3], float s, float rgb[3]) 00433 { 00434 float costheta; 00435 float Phase_1; 00436 float Phase_2; 00437 float sunColor[3]; 00438 00439 float E[3]; 00440 float E1[3]; 00441 00442 00443 float I[3]; 00444 float fTemp; 00445 float vTemp1[3], vTemp2[3]; 00446 00447 float sunDirection[3]; 00448 00449 s *= sunSky->atm_DistanceMultiplier; 00450 00451 sunDirection[0] = sunSky->toSun[0]; 00452 sunDirection[1] = sunSky->toSun[1]; 00453 sunDirection[2] = sunSky->toSun[2]; 00454 00455 costheta = dot_v3v3(view, sunDirection); // cos(theta) 00456 Phase_1 = 1 + (costheta * costheta); // Phase_1 00457 00458 vec3opf(sunSky->atm_BetaRay, sunSky->atm_BetaRay, *, sunSky->atm_BetaRayMultiplier); 00459 vec3opf(sunSky->atm_BetaMie, sunSky->atm_BetaMie, *, sunSky->atm_BetaMieMultiplier); 00460 vec3opv(sunSky->atm_BetaRM, sunSky->atm_BetaRay, +, sunSky->atm_BetaMie); 00461 00462 //e^(-(beta_1 + beta_2) * s) = E1 00463 vec3opf(E1, sunSky->atm_BetaRM, *, -s/(float)M_LN2); 00464 E1[0] = exp(E1[0]); 00465 E1[1] = exp(E1[1]); 00466 E1[2] = exp(E1[2]); 00467 00468 copy_v3_v3(E, E1); 00469 00470 //Phase2(theta) = (1-g^2)/(1+g-2g*cos(theta))^(3/2) 00471 fTemp = 1 + sunSky->atm_HGg - 2 * sunSky->atm_HGg * costheta; 00472 fTemp = fTemp * sqrtf(fTemp); 00473 Phase_2 = (1 - sunSky->atm_HGg * sunSky->atm_HGg)/fTemp; 00474 00475 vec3opf(vTemp1, sunSky->atm_BetaDashRay, *, Phase_1); 00476 vec3opf(vTemp2, sunSky->atm_BetaDashMie, *, Phase_2); 00477 00478 vec3opv(vTemp1, vTemp1, +, vTemp2); 00479 fopvec3(vTemp2, 1.0f, -, E1); 00480 vec3opv(vTemp1, vTemp1, *, vTemp2); 00481 00482 fopvec3(vTemp2, 1.0f, / , sunSky->atm_BetaRM); 00483 00484 vec3opv(I, vTemp1, *, vTemp2); 00485 00486 vec3opf(I, I, *, sunSky->atm_InscatteringMultiplier); 00487 vec3opf(E, E, *, sunSky->atm_ExtinctionMultiplier); 00488 00489 //scale to color sun 00490 ComputeAttenuatedSunlight(sunSky->theta, sunSky->turbidity, sunColor); 00491 vec3opv(E, E, *, sunColor); 00492 00493 vec3opf(I, I, *, sunSky->atm_SunIntensity); 00494 00495 vec3opv(rgb, rgb, *, E); 00496 vec3opv(rgb, rgb, +, I); 00497 } 00498 00499 #undef vec3opv 00500 #undef vec3opf 00501 #undef fopvec3 00502 00503 /* EOF */