00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llvosky.h"
00035
00036 #include "imageids.h"
00037 #include "llfeaturemanager.h"
00038 #include "llviewercontrol.h"
00039 #include "llframetimer.h"
00040 #include "timing.h"
00041
00042 #include "llagent.h"
00043 #include "lldrawable.h"
00044 #include "llface.h"
00045 #include "llcubemap.h"
00046 #include "lldrawpoolsky.h"
00047 #include "lldrawpoolwater.h"
00048 #include "llglheaders.h"
00049 #include "llsky.h"
00050 #include "llviewercamera.h"
00051 #include "llviewerimagelist.h"
00052 #include "llviewerobjectlist.h"
00053 #include "llviewerregion.h"
00054 #include "llworld.h"
00055 #include "pipeline.h"
00056 #include "lldrawpoolwlsky.h"
00057 #include "llwlparammanager.h"
00058 #include "llwaterparammanager.h"
00059
00060 #undef min
00061 #undef max
00062
00063 static const S32 NUM_TILES_X = 8;
00064 static const S32 NUM_TILES_Y = 4;
00065 static const S32 NUM_TILES = NUM_TILES_X * NUM_TILES_Y;
00066
00067
00068 static const F32 SUN_DISK_RADIUS = 0.5f;
00069 static const F32 MOON_DISK_RADIUS = SUN_DISK_RADIUS * 0.9f;
00070 static const F32 SUN_INTENSITY = 1e5;
00071 static const F32 SUN_DISK_INTENSITY = 24.f;
00072
00073
00074
00075 static const LLVector2 TEX00 = LLVector2(0.f, 0.f);
00076 static const LLVector2 TEX01 = LLVector2(0.f, 1.f);
00077 static const LLVector2 TEX10 = LLVector2(1.f, 0.f);
00078 static const LLVector2 TEX11 = LLVector2(1.f, 1.f);
00079
00080
00081 LLUUID gSunTextureID = IMG_SUN;
00082 LLUUID gMoonTextureID = IMG_MOON;
00083
00084
00085 LLColor3 LLHaze::sAirScaSeaLevel;
00086
00087 class LLFastLn
00088 {
00089 public:
00090 LLFastLn()
00091 {
00092 mTable[0] = 0;
00093 for( S32 i = 1; i < 257; i++ )
00094 {
00095 mTable[i] = log((F32)i);
00096 }
00097 }
00098
00099 F32 ln( F32 x )
00100 {
00101 const F32 OO_255 = 0.003921568627450980392156862745098f;
00102 const F32 LN_255 = 5.5412635451584261462455391880218f;
00103
00104 if( x < OO_255 )
00105 {
00106 return log(x);
00107 }
00108 else
00109 if( x < 1 )
00110 {
00111 x *= 255.f;
00112 S32 index = llfloor(x);
00113 F32 t = x - index;
00114 F32 low = mTable[index];
00115 F32 high = mTable[index + 1];
00116 return low + t * (high - low) - LN_255;
00117 }
00118 else
00119 if( x <= 255 )
00120 {
00121 S32 index = llfloor(x);
00122 F32 t = x - index;
00123 F32 low = mTable[index];
00124 F32 high = mTable[index + 1];
00125 return low + t * (high - low);
00126 }
00127 else
00128 {
00129 return log( x );
00130 }
00131 }
00132
00133 F32 pow( F32 x, F32 y )
00134 {
00135 return (F32)LL_FAST_EXP(y * ln(x));
00136 }
00137
00138
00139 private:
00140 F32 mTable[257];
00141 };
00142
00143 static LLFastLn gFastLn;
00144
00145
00146
00147
00148 inline F32 LLHaze::calcPhase(const F32 cos_theta) const
00149 {
00150 const F32 g2 = mG * mG;
00151 const F32 den = 1 + g2 - 2 * mG * cos_theta;
00152 return (1 - g2) * gFastLn.pow(den, -1.5);
00153 }
00154
00155 inline void color_pow(LLColor3 &col, const F32 e)
00156 {
00157 col.mV[0] = gFastLn.pow(col.mV[0], e);
00158 col.mV[1] = gFastLn.pow(col.mV[1], e);
00159 col.mV[2] = gFastLn.pow(col.mV[2], e);
00160 }
00161
00162 inline LLColor3 color_norm(const LLColor3 &col)
00163 {
00164 const F32 m = color_max(col);
00165 if (m > 1.f)
00166 {
00167 return 1.f/m * col;
00168 }
00169 else return col;
00170 }
00171
00172 inline void color_gamma_correct(LLColor3 &col)
00173 {
00174 const F32 gamma_inv = 1.f/1.2f;
00175 if (col.mV[0] != 0.f)
00176 {
00177 col.mV[0] = gFastLn.pow(col.mV[0], gamma_inv);
00178 }
00179 if (col.mV[1] != 0.f)
00180 {
00181 col.mV[1] = gFastLn.pow(col.mV[1], gamma_inv);
00182 }
00183 if (col.mV[2] != 0.f)
00184 {
00185 col.mV[2] = gFastLn.pow(col.mV[2], gamma_inv);
00186 }
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 S32 LLSkyTex::sComponents = 4;
00196 S32 LLSkyTex::sResolution = 64;
00197 F32 LLSkyTex::sInterpVal = 0.f;
00198 S32 LLSkyTex::sCurrent = 0;
00199
00200
00201 LLSkyTex::LLSkyTex() :
00202 mSkyData(NULL),
00203 mSkyDirs(NULL)
00204 {
00205 }
00206
00207 void LLSkyTex::init()
00208 {
00209 mSkyData = new LLColor4[sResolution * sResolution];
00210 mSkyDirs = new LLVector3[sResolution * sResolution];
00211
00212 for (S32 i = 0; i < 2; ++i)
00213 {
00214 mImageGL[i] = new LLImageGL(FALSE);
00215 mImageGL[i]->setClamp(TRUE, TRUE);
00216 mImageRaw[i] = new LLImageRaw(sResolution, sResolution, sComponents);
00217
00218 initEmpty(i);
00219 }
00220 }
00221
00222 void LLSkyTex::cleanupGL()
00223 {
00224 mImageGL[0] = NULL;
00225 mImageGL[1] = NULL;
00226 }
00227
00228 void LLSkyTex::restoreGL()
00229 {
00230 for (S32 i = 0; i < 2; i++)
00231 {
00232 mImageGL[i] = new LLImageGL(FALSE);
00233 mImageGL[i]->setClamp(TRUE, TRUE);
00234 }
00235 }
00236
00237 LLSkyTex::~LLSkyTex()
00238 {
00239 delete[] mSkyData;
00240 mSkyData = NULL;
00241
00242 delete[] mSkyDirs;
00243 mSkyDirs = NULL;
00244 }
00245
00246
00247 void LLSkyTex::initEmpty(const S32 tex)
00248 {
00249 U8* data = mImageRaw[tex]->getData();
00250 for (S32 i = 0; i < sResolution; ++i)
00251 {
00252 for (S32 j = 0; j < sResolution; ++j)
00253 {
00254 const S32 basic_offset = (i * sResolution + j);
00255 S32 offset = basic_offset * sComponents;
00256 data[offset] = 0;
00257 data[offset+1] = 0;
00258 data[offset+2] = 0;
00259 data[offset+3] = 255;
00260
00261 mSkyData[basic_offset].setToBlack();
00262 }
00263 }
00264
00265 createGLImage(tex);
00266 }
00267
00268 void LLSkyTex::create(const F32 brightness)
00269 {
00271 U8* data = mImageRaw[sCurrent]->getData();
00272 for (S32 i = 0; i < sResolution; ++i)
00273 {
00274 for (S32 j = 0; j < sResolution; ++j)
00275 {
00276 const S32 basic_offset = (i * sResolution + j);
00277 S32 offset = basic_offset * sComponents;
00278 U32* pix = (U32*)(data + offset);
00279 LLColor4U temp = LLColor4U(mSkyData[basic_offset]);
00280 *pix = temp.mAll;
00281 }
00282 }
00283 createGLImage(sCurrent);
00284 }
00285
00286
00287
00288
00289 void LLSkyTex::createGLImage(S32 which)
00290 {
00291 mImageGL[which]->createGLTexture(0, mImageRaw[which]);
00292 mImageGL[which]->setClamp(TRUE, TRUE);
00293 }
00294
00295 void LLSkyTex::bindTexture(BOOL curr)
00296 {
00297 mImageGL[getWhich(curr)]->bind();
00298 }
00299
00300
00301
00302
00303
00304 F32 LLHeavenBody::sInterpVal = 0;
00305
00306 S32 LLVOSky::sResolution = LLSkyTex::getResolution();
00307 S32 LLVOSky::sTileResX = sResolution/NUM_TILES_X;
00308 S32 LLVOSky::sTileResY = sResolution/NUM_TILES_Y;
00309
00310 LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
00311 : LLStaticViewerObject(id, pcode, regionp),
00312 mSun(SUN_DISK_RADIUS), mMoon(MOON_DISK_RADIUS),
00313 mBrightnessScale(1.f),
00314 mBrightnessScaleNew(0.f),
00315 mBrightnessScaleGuess(1.f),
00316 mWeatherChange(FALSE),
00317 mCloudDensity(0.2f),
00318 mWind(0.f),
00319 mForceUpdate(FALSE),
00320 mWorldScale(1.f),
00321 mBumpSunDir(0.f, 0.f, 1.f)
00322 {
00323 bool error = false;
00324
00326 dome_radius = 1.f;
00327 dome_offset_ratio = 0.f;
00328 sunlight_color = LLColor3();
00329 ambient = LLColor3();
00330 gamma = 1.f;
00331 lightnorm = LLVector4();
00332 blue_density = LLColor3();
00333 blue_horizon = LLColor3();
00334 haze_density = 0.f;
00335 haze_horizon = LLColor3();
00336 density_multiplier = 0.f;
00337 max_y = 0.f;
00338 glow = LLColor3();
00339 cloud_shadow = 0.f;
00340 cloud_color = LLColor3();
00341 cloud_scale = 0.f;
00342 cloud_pos_density1 = LLColor3();
00343 cloud_pos_density2 = LLColor3();
00344
00345
00346 mInitialized = FALSE;
00347 mbCanSelect = FALSE;
00348 mUpdateTimer.reset();
00349
00350 for (S32 i = 0; i < 6; i++)
00351 {
00352 mSkyTex[i].init();
00353 mShinyTex[i].init();
00354 }
00355 for (S32 i=0; i<FACE_COUNT; i++)
00356 {
00357 mFace[i] = NULL;
00358 }
00359
00360 mCameraPosAgent = gAgent.getCameraPositionAgent();
00361 mAtmHeight = ATM_HEIGHT;
00362 mEarthCenter = LLVector3(mCameraPosAgent.mV[0], mCameraPosAgent.mV[1], -EARTH_RADIUS);
00363
00364 mSunDefaultPosition = LLVector3(LLWLParamManager::instance()->mCurParams.getVector("lightnorm", error));
00365 if (gSavedSettings.getBOOL("SkyOverrideSimSunPosition"))
00366 {
00367 initSunDirection(mSunDefaultPosition, LLVector3(0, 0, 0));
00368 }
00369 mAmbientScale = gSavedSettings.getF32("SkyAmbientScale");
00370 mNightColorShift = gSavedSettings.getColor3("SkyNightColorShift");
00371 mFogColor.mV[VRED] = mFogColor.mV[VGREEN] = mFogColor.mV[VBLUE] = 0.5f;
00372 mFogColor.mV[VALPHA] = 0.0f;
00373 mFogRatio = 1.2f;
00374
00375 mSun.setIntensity(SUN_INTENSITY);
00376 mMoon.setIntensity(0.1f * SUN_INTENSITY);
00377
00378 mSunTexturep = gImageList.getImage(gSunTextureID, TRUE, TRUE);
00379 mSunTexturep->setClamp(TRUE, TRUE);
00380 mMoonTexturep = gImageList.getImage(gMoonTextureID, TRUE, TRUE);
00381 mMoonTexturep->setClamp(TRUE, TRUE);
00382 mBloomTexturep = gImageList.getImage(IMG_BLOOM1);
00383 mBloomTexturep->setClamp(TRUE, TRUE);
00384
00385 mHeavenlyBodyUpdated = FALSE ;
00386 }
00387
00388
00389 LLVOSky::~LLVOSky()
00390 {
00391
00392
00393
00394 mCubeMap = NULL;
00395 }
00396
00397 void LLVOSky::initClass()
00398 {
00399 LLHaze::initClass();
00400 }
00401
00402
00403 void LLVOSky::init()
00404 {
00405 const F32 haze_int = color_intens(mHaze.calcSigSca(0));
00406 mHazeConcentration = haze_int /
00407 (color_intens(LLHaze::calcAirSca(0)) + haze_int);
00408
00409 calcAtmospherics();
00410
00411
00412 for (S32 side = 0; side < 6; ++side)
00413 {
00414 for (S32 tile = 0; tile < NUM_TILES; ++tile)
00415 {
00416 initSkyTextureDirs(side, tile);
00417 createSkyTexture(side, tile);
00418 }
00419 }
00420
00421 for (S32 i = 0; i < 6; ++i)
00422 {
00423 mSkyTex[i].create(1.0f);
00424 mShinyTex[i].create(1.0f);
00425 }
00426
00427 initCubeMap();
00428 mInitialized = true;
00429
00430 mHeavenlyBodyUpdated = FALSE ;
00431 }
00432
00433 void LLVOSky::initCubeMap()
00434 {
00435 std::vector<LLPointer<LLImageRaw> > images;
00436 for (S32 side = 0; side < 6; side++)
00437 {
00438 images.push_back(mShinyTex[side].getImageRaw());
00439 }
00440 if (mCubeMap)
00441 {
00442 mCubeMap->init(images);
00443 }
00444 else if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"))
00445 {
00446 mCubeMap = new LLCubeMap();
00447 mCubeMap->init(images);
00448 }
00449 }
00450
00451
00452 void LLVOSky::cleanupGL()
00453 {
00454 S32 i;
00455 for (i = 0; i < 6; i++)
00456 {
00457 mSkyTex[i].cleanupGL();
00458 }
00459 if (getCubeMap())
00460 {
00461 getCubeMap()->destroyGL();
00462 }
00463 }
00464
00465 void LLVOSky::restoreGL()
00466 {
00467 S32 i;
00468 for (i = 0; i < 6; i++)
00469 {
00470 mSkyTex[i].restoreGL();
00471 }
00472 mSunTexturep = gImageList.getImage(gSunTextureID, TRUE, TRUE);
00473 mSunTexturep->setClamp(TRUE, TRUE);
00474 mMoonTexturep = gImageList.getImage(gMoonTextureID, TRUE, TRUE);
00475 mMoonTexturep->setClamp(TRUE, TRUE);
00476 mBloomTexturep = gImageList.getImage(IMG_BLOOM1);
00477 mBloomTexturep->setClamp(TRUE, TRUE);
00478
00479 calcAtmospherics();
00480
00481 if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap
00482 && LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"))
00483 {
00484 LLCubeMap* cube_map = getCubeMap();
00485
00486 std::vector<LLPointer<LLImageRaw> > images;
00487 for (S32 side = 0; side < 6; side++)
00488 {
00489 images.push_back(mShinyTex[side].getImageRaw());
00490 }
00491
00492 if(cube_map)
00493 {
00494 cube_map->init(images);
00495 mForceUpdate = TRUE;
00496 }
00497 }
00498
00499 if (mDrawable)
00500 {
00501 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
00502 }
00503
00504 }
00505
00506 void LLVOSky::initSkyTextureDirs(const S32 side, const S32 tile)
00507 {
00508 S32 tile_x = tile % NUM_TILES_X;
00509 S32 tile_y = tile / NUM_TILES_X;
00510
00511 S32 tile_x_pos = tile_x * sTileResX;
00512 S32 tile_y_pos = tile_y * sTileResY;
00513
00514 F32 coeff[3] = {0, 0, 0};
00515 const S32 curr_coef = side >> 1;
00516 const S32 side_dir = (((side & 1) << 1) - 1);
00517 const S32 x_coef = (curr_coef + 1) % 3;
00518 const S32 y_coef = (x_coef + 1) % 3;
00519
00520 coeff[curr_coef] = (F32)side_dir;
00521
00522 F32 inv_res = 1.f/sResolution;
00523 S32 x, y;
00524 for (y = tile_y_pos; y < (tile_y_pos + sTileResY); ++y)
00525 {
00526 for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x)
00527 {
00528 coeff[x_coef] = F32((x<<1) + 1) * inv_res - 1.f;
00529 coeff[y_coef] = F32((y<<1) + 1) * inv_res - 1.f;
00530 LLVector3 dir(coeff[0], coeff[1], coeff[2]);
00531 dir.normVec();
00532 mSkyTex[side].setDir(dir, x, y);
00533 mShinyTex[side].setDir(dir, x, y);
00534 }
00535 }
00536 }
00537
00538 void LLVOSky::createSkyTexture(const S32 side, const S32 tile)
00539 {
00540 S32 tile_x = tile % NUM_TILES_X;
00541 S32 tile_y = tile / NUM_TILES_X;
00542
00543 S32 tile_x_pos = tile_x * sTileResX;
00544 S32 tile_y_pos = tile_y * sTileResY;
00545
00546 S32 x, y;
00547 for (y = tile_y_pos; y < (tile_y_pos + sTileResY); ++y)
00548 {
00549 for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x)
00550 {
00551 mSkyTex[side].setPixel(calcSkyColorInDir(mSkyTex[side].getDir(x, y)), x, y);
00552 mShinyTex[side].setPixel(calcSkyColorInDir(mSkyTex[side].getDir(x, y), true), x, y);
00553 }
00554 }
00555 }
00556
00557 static inline LLColor3 componentDiv(LLColor3 const &left, LLColor3 const & right)
00558 {
00559 return LLColor3(left.mV[0]/right.mV[0],
00560 left.mV[1]/right.mV[1],
00561 left.mV[2]/right.mV[2]);
00562 }
00563
00564
00565 static inline LLColor3 componentMult(LLColor3 const &left, LLColor3 const & right)
00566 {
00567 return LLColor3(left.mV[0]*right.mV[0],
00568 left.mV[1]*right.mV[1],
00569 left.mV[2]*right.mV[2]);
00570 }
00571
00572
00573 static inline LLColor3 componentExp(LLColor3 const &v)
00574 {
00575 return LLColor3(exp(v.mV[0]),
00576 exp(v.mV[1]),
00577 exp(v.mV[2]));
00578 }
00579
00580 static inline LLColor3 componentPow(LLColor3 const &v, F32 exponent)
00581 {
00582 return LLColor3(pow(v.mV[0], exponent),
00583 pow(v.mV[1], exponent),
00584 pow(v.mV[2], exponent));
00585 }
00586
00587 static inline LLColor3 componentSaturate(LLColor3 const &v)
00588 {
00589 return LLColor3(std::max(std::min(v.mV[0], 1.f), 0.f),
00590 std::max(std::min(v.mV[1], 1.f), 0.f),
00591 std::max(std::min(v.mV[2], 1.f), 0.f));
00592 }
00593
00594
00595 static inline LLColor3 componentSqrt(LLColor3 const &v)
00596 {
00597 return LLColor3(sqrt(v.mV[0]),
00598 sqrt(v.mV[1]),
00599 sqrt(v.mV[2]));
00600 }
00601
00602 static inline void componentMultBy(LLColor3 & left, LLColor3 const & right)
00603 {
00604 left.mV[0] *= right.mV[0];
00605 left.mV[1] *= right.mV[1];
00606 left.mV[2] *= right.mV[2];
00607 }
00608
00609 static inline LLColor3 colorMix(LLColor3 const & left, LLColor3 const & right, F32 amount)
00610 {
00611 return (left + ((right - left) * amount));
00612 }
00613
00614 static inline F32 texture2D(LLPointer<LLImageRaw> const & tex, LLVector2 const & uv)
00615 {
00616 U16 w = tex->getWidth();
00617 U16 h = tex->getHeight();
00618
00619 U16 r = U16(uv[0] * w) % w;
00620 U16 c = U16(uv[1] * h) % h;
00621
00622 U8 const * imageBuffer = tex->getData();
00623
00624 U8 sample = imageBuffer[r * w + c];
00625
00626 return sample / 255.f;
00627 }
00628
00629 static inline LLColor3 smear(F32 val)
00630 {
00631 return LLColor3(val, val, val);
00632 }
00633
00634 void LLVOSky::initAtmospherics(void)
00635 {
00636 bool error;
00637
00638
00639 dome_radius = LLWLParamManager::instance()->getDomeRadius();
00640 dome_offset_ratio = LLWLParamManager::instance()->getDomeOffset();
00641 sunlight_color = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("sunlight_color", error));
00642 ambient = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("ambient", error));
00643
00644 gamma = LLWLParamManager::instance()->mCurParams.getVector("gamma", error)[0];
00645 blue_density = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("blue_density", error));
00646 blue_horizon = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("blue_horizon", error));
00647 haze_density = LLWLParamManager::instance()->mCurParams.getVector("haze_density", error)[0];
00648 haze_horizon = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("haze_horizon", error));
00649 density_multiplier = LLWLParamManager::instance()->mCurParams.getVector("density_multiplier", error)[0];
00650 max_y = LLWLParamManager::instance()->mCurParams.getVector("max_y", error)[0];
00651 glow = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("glow", error));
00652 cloud_shadow = LLWLParamManager::instance()->mCurParams.getVector("cloud_shadow", error)[0];
00653 cloud_color = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("cloud_color", error));
00654 cloud_scale = LLWLParamManager::instance()->mCurParams.getVector("cloud_scale", error)[0];
00655 cloud_pos_density1 = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("cloud_pos_density1", error));
00656 cloud_pos_density2 = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("cloud_pos_density2", error));
00657
00658
00659
00660
00661 LLVector3 sunDir = gSky.getSunDirection();
00662
00663
00664 lightnorm = LLVector4(sunDir.mV[1], sunDir.mV[2], sunDir.mV[0], 0);
00665 unclamped_lightnorm = lightnorm;
00666 if(lightnorm.mV[1] < -0.1f)
00667 {
00668 lightnorm.mV[1] = -0.1f;
00669 }
00670
00671 }
00672
00673 LLColor4 LLVOSky::calcSkyColorInDir(const LLVector3 &dir, bool isShiny)
00674 {
00675 F32 saturation = 0.3f;
00676 if (dir.mV[VZ] < -0.02f)
00677 {
00678 LLColor4 col = LLColor4(llmax(mFogColor[0],0.2f), llmax(mFogColor[1],0.2f), llmax(mFogColor[2],0.22f),0.f);
00679 if (isShiny)
00680 {
00681 LLColor3 desat_fog = LLColor3(mFogColor);
00682 F32 brightness = desat_fog.brightness();
00683
00684 if (brightness < 0.15f)
00685 {
00686 brightness = 0.15f;
00687 desat_fog = smear(0.15f);
00688 }
00689 LLColor3 greyscale = smear(brightness);
00690 desat_fog = desat_fog * saturation + greyscale * (1.0f - saturation);
00691 if (!gPipeline.canUseWindLightShaders())
00692 {
00693 col = LLColor4(desat_fog, 0.f);
00694 }
00695 else
00696 {
00697 col = LLColor4(desat_fog * 0.5f, 0.f);
00698 }
00699 }
00700 float x = 1.0f-fabsf(-0.1f-dir.mV[VZ]);
00701 x *= x;
00702 col.mV[0] *= x*x;
00703 col.mV[1] *= powf(x, 2.5f);
00704 col.mV[2] *= x*x*x;
00705 return col;
00706 }
00707
00708
00709 LLVector3 Pn = LLVector3(-dir[1] , -dir[2], -dir[0]);
00710
00711 LLColor3 vary_HazeColor(0,0,0);
00712 LLColor3 vary_CloudColorSun(0,0,0);
00713 LLColor3 vary_CloudColorAmbient(0,0,0);
00714 F32 vary_CloudDensity(0);
00715 LLVector2 vary_HorizontalProjection[2];
00716 vary_HorizontalProjection[0] = LLVector2(0,0);
00717 vary_HorizontalProjection[1] = LLVector2(0,0);
00718
00719 calcSkyColorWLVert(Pn, vary_HazeColor, vary_CloudColorSun, vary_CloudColorAmbient,
00720 vary_CloudDensity, vary_HorizontalProjection);
00721
00722 LLColor3 sky_color = calcSkyColorWLFrag(Pn, vary_HazeColor, vary_CloudColorSun, vary_CloudColorAmbient,
00723 vary_CloudDensity, vary_HorizontalProjection);
00724 if (isShiny)
00725 {
00726 F32 brightness = sky_color.brightness();
00727 LLColor3 greyscale = smear(brightness);
00728 sky_color = sky_color * saturation + greyscale * (1.0f - saturation);
00729 sky_color *= (0.5f + 0.5f * brightness);
00730 }
00731 return LLColor4(sky_color, 0.0f);
00732 }
00733
00734
00735
00736
00737 #if LL_MSVC && __MSVC_VER__ < 8
00738 #pragma optimize("p", on)
00739 #endif
00740
00741 void LLVOSky::calcSkyColorWLVert(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLColor3 & vary_CloudColorSun,
00742 LLColor3 & vary_CloudColorAmbient, F32 & vary_CloudDensity,
00743 LLVector2 vary_HorizontalProjection[2])
00744 {
00745
00746 F32 phi = acos(Pn[1]);
00747 F32 sinA = sin(F_PI - phi);
00748 F32 Plen = dome_radius * sin(F_PI + phi + asin(dome_offset_ratio * sinA)) / sinA;
00749
00750 Pn *= Plen;
00751
00752 vary_HorizontalProjection[0] = LLVector2(Pn[0], Pn[2]);
00753 vary_HorizontalProjection[0] /= - 2.f * Plen;
00754
00755
00756 if (Pn[1] > 0.f)
00757 {
00758 Pn *= (max_y / Pn[1]);
00759 }
00760 else
00761 {
00762 Pn *= (-32000.f / Pn[1]);
00763 }
00764
00765 Plen = Pn.magVec();
00766 Pn /= Plen;
00767
00768
00769 LLColor3 sunlight = sunlight_color;
00770
00771
00772
00773 LLColor3 light_atten =
00774 (blue_density * 1.0 + smear(haze_density * 0.25f)) * (density_multiplier * max_y);
00775
00776
00777 LLColor3 temp2(0.f, 0.f, 0.f);
00778 LLColor3 temp1 = blue_density + smear(haze_density);
00779 LLColor3 blue_weight = componentDiv(blue_density, temp1);
00780 LLColor3 haze_weight = componentDiv(smear(haze_density), temp1);
00781
00782
00783 temp2.mV[1] = llmax(F_APPROXIMATELY_ZERO, llmax(0.f, Pn[1]) * 1.0f + lightnorm[1] );
00784
00785 temp2.mV[1] = 1.f / temp2.mV[1];
00786 componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1]));
00787
00788
00789 temp2.mV[2] = Plen * density_multiplier;
00790
00791
00792 temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]);
00793
00794
00795
00796 temp2.mV[0] = Pn * LLVector3(lightnorm);
00797
00798 temp2.mV[0] = 1.f - temp2.mV[0];
00799
00800 temp2.mV[0] = llmax(temp2.mV[0], .001f);
00801
00802 temp2.mV[0] *= glow.mV[0];
00803
00804 temp2.mV[0] = pow(temp2.mV[0], glow.mV[2]);
00805
00806
00807
00808 temp2.mV[0] += .25f;
00809
00810
00811
00812 vary_HazeColor = (blue_horizon * blue_weight * (sunlight + ambient)
00813 + componentMult(haze_horizon.mV[0] * haze_weight, sunlight * temp2.mV[0] + ambient)
00814 );
00815
00816
00817 LLColor3 tmpAmbient = ambient + (LLColor3::white - ambient) * cloud_shadow * 0.5f;
00818
00819
00820 sunlight *= (1.f - cloud_shadow);
00821
00822
00823 LLColor3 additiveColorBelowCloud = (blue_horizon * blue_weight * (sunlight + tmpAmbient)
00824 + componentMult(haze_horizon.mV[0] * haze_weight, sunlight * temp2.mV[0] + tmpAmbient)
00825 );
00826
00827
00828 componentMultBy(vary_HazeColor, LLColor3::white - temp1);
00829
00830 sunlight = sunlight_color;
00831 temp2.mV[1] = llmax(0.f, lightnorm[1] * 2.f);
00832 temp2.mV[1] = 1.f / temp2.mV[1];
00833 componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1]));
00834
00835
00836 temp1 = componentSqrt(temp1);
00837
00838
00839 vary_HazeColor +=
00840 componentMult(additiveColorBelowCloud - vary_HazeColor, LLColor3::white - componentSqrt(temp1));
00841
00842 if (Pn[1] < 0.f)
00843 {
00844
00845
00846 LLColor3 dark_brown(0.082f, 0.076f, 0.066f);
00847 LLColor3 brown(0.430f, 0.386f, 0.322f);
00848 LLColor3 sky_lighting = sunlight + ambient;
00849 F32 haze_brightness = vary_HazeColor.brightness();
00850
00851 if (Pn[1] < -0.05f)
00852 {
00853 vary_HazeColor = colorMix(dark_brown, brown, -Pn[1] * 0.9f) * sky_lighting * haze_brightness;
00854 }
00855
00856 if (Pn[1] > -0.1f)
00857 {
00858 vary_HazeColor = colorMix(LLColor3::white * haze_brightness, vary_HazeColor, fabs((Pn[1] + 0.05f) * -20.f));
00859 }
00860 }
00861 }
00862
00863 #if LL_MSVC && __MSVC_VER__ < 8
00864 #pragma optimize("p", off)
00865 #endif
00866
00867 LLColor3 LLVOSky::calcSkyColorWLFrag(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLColor3 & vary_CloudColorSun,
00868 LLColor3 & vary_CloudColorAmbient, F32 & vary_CloudDensity,
00869 LLVector2 vary_HorizontalProjection[2])
00870 {
00871 LLColor3 res;
00872
00873 LLColor3 color0 = vary_HazeColor;
00874
00875 if (!gPipeline.canUseWindLightShaders())
00876 {
00877 LLColor3 color1 = color0 * 2.0f;
00878 color1 = smear(1.f) - componentSaturate(color1);
00879 componentPow(color1, gamma);
00880 res = smear(1.f) - color1;
00881 }
00882 else
00883 {
00884 res = color0;
00885 }
00886
00887 # ifndef LL_RELEASE_FOR_DOWNLOAD
00888
00889 LLColor3 color2 = 2.f * color0;
00890
00891 LLColor3 color3 = LLColor3(1.f, 1.f, 1.f) - componentSaturate(color2);
00892 componentPow(color3, gamma);
00893 color3 = LLColor3(1.f, 1.f, 1.f) - color3;
00894
00895 static enum {
00896 OUT_DEFAULT = 0,
00897 OUT_SKY_BLUE = 1,
00898 OUT_RED = 2,
00899 OUT_PN = 3,
00900 OUT_HAZE = 4,
00901 } debugOut = OUT_DEFAULT;
00902
00903 switch(debugOut)
00904 {
00905 case OUT_DEFAULT:
00906 break;
00907 case OUT_SKY_BLUE:
00908 res = LLColor3(0.4f, 0.4f, 0.9f);
00909 break;
00910 case OUT_RED:
00911 res = LLColor3(1.f, 0.f, 0.f);
00912 break;
00913 case OUT_PN:
00914 res = LLColor3(Pn[0], Pn[1], Pn[2]);
00915 break;
00916 case OUT_HAZE:
00917 res = vary_HazeColor;
00918 break;
00919 }
00920 # endif // LL_RELEASE_FOR_DOWNLOAD
00921 return res;
00922 }
00923
00924 LLColor3 LLVOSky::createDiffuseFromWL(LLColor3 diffuse, LLColor3 ambient, LLColor3 sundiffuse, LLColor3 sunambient)
00925 {
00926 return componentMult(diffuse, sundiffuse) * 4.0f +
00927 componentMult(ambient, sundiffuse) * 2.0f + sunambient;
00928 }
00929
00930 LLColor3 LLVOSky::createAmbientFromWL(LLColor3 ambient, LLColor3 sundiffuse, LLColor3 sunambient)
00931 {
00932 return (componentMult(ambient, sundiffuse) + sunambient) * 0.8f;
00933 }
00934
00935
00936 void LLVOSky::calcAtmospherics(void)
00937 {
00938 initAtmospherics();
00939
00940 LLColor3 vary_HazeColor;
00941 LLColor3 vary_SunlightColor;
00942 LLColor3 vary_AmbientColor;
00943 {
00944
00945 LLColor3 sunlight = sunlight_color;
00946
00947
00948
00949 LLColor3 light_atten =
00950 (blue_density * 1.0 + smear(haze_density * 0.25f)) * (density_multiplier * max_y);
00951
00952
00953 LLColor3 temp2(0.f, 0.f, 0.f);
00954 LLColor3 temp1 = blue_density + smear(haze_density);
00955 LLColor3 blue_weight = componentDiv(blue_density, temp1);
00956 LLColor3 haze_weight = componentDiv(smear(haze_density), temp1);
00957
00958
00960
00961
00962
00963 F32 lighty = unclamped_lightnorm[1];
00964 if(lighty < NIGHTTIME_ELEVATION_COS)
00965 {
00966 lighty = -lighty;
00967 }
00968
00969 temp2.mV[1] = llmax(0.f, lighty);
00970 temp2.mV[1] = 1.f / temp2.mV[1];
00971 componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1]));
00972
00973
00974 temp2.mV[2] = density_multiplier;
00975
00976
00977 temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]);
00978
00979
00980
00981
00982 LLColor3 tmpAmbient = ambient + (smear(1.f) - ambient) * cloud_shadow * 0.5f;
00983
00984
00985 vary_HazeColor =
00986 (blue_horizon * blue_weight * (sunlight*(1.f - cloud_shadow) + tmpAmbient)
00987 + componentMult(haze_horizon.mV[0] * haze_weight, sunlight*(1.f - cloud_shadow) * temp2.mV[0] + tmpAmbient)
00988 );
00989
00990
00991 vary_SunlightColor = componentMult(sunlight, temp1) * 1.f;
00992 vary_SunlightColor.clamp();
00993 vary_SunlightColor = smear(1.0f) - vary_SunlightColor;
00994 vary_SunlightColor = componentPow(vary_SunlightColor, gamma);
00995 vary_SunlightColor = smear(1.0f) - vary_SunlightColor;
00996 vary_AmbientColor = componentMult(tmpAmbient, temp1) * 0.5;
00997 vary_AmbientColor.clamp();
00998 vary_AmbientColor = smear(1.0f) - vary_AmbientColor;
00999 vary_AmbientColor = componentPow(vary_AmbientColor, gamma);
01000 vary_AmbientColor = smear(1.0f) - vary_AmbientColor;
01001
01002 componentMultBy(vary_HazeColor, LLColor3(1.f, 1.f, 1.f) - temp1);
01003
01004 }
01005
01006 mSun.setColor(vary_SunlightColor);
01007 mMoon.setColor(LLColor3(1.0f, 1.0f, 1.0f));
01008
01009 mSun.renewDirection();
01010 mSun.renewColor();
01011 mMoon.renewDirection();
01012 mMoon.renewColor();
01013
01014 float dp = getToSunLast() * LLVector3(0,0,1.f);
01015 if (dp < 0)
01016 {
01017 dp = 0;
01018 }
01019
01020
01021
01022 F32 sun_dynamic_range = llmax(gSavedSettings.getF32("RenderSunDynamicRange"), 0.0001f);
01023 LLWLParamManager::instance()->mSceneLightStrength = 2.0f * (1.0f + sun_dynamic_range * dp);
01024
01025 mSunDiffuse = vary_SunlightColor;
01026 mSunAmbient = vary_AmbientColor;
01027 mMoonDiffuse = vary_SunlightColor;
01028 mMoonAmbient = vary_AmbientColor;
01029
01030 mTotalAmbient = vary_AmbientColor;
01031 mTotalAmbient.setAlpha(1);
01032
01033 mFadeColor = mTotalAmbient + (mSunDiffuse + mMoonDiffuse) * 0.5f;
01034 mFadeColor.setAlpha(0);
01035 }
01036
01037 BOOL LLVOSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
01038 {
01039 return TRUE;
01040 }
01041
01042 BOOL LLVOSky::updateSky()
01043 {
01044 if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)))
01045 {
01046 return TRUE;
01047 }
01048
01049 if (mDead)
01050 {
01051
01052 return TRUE;
01053 }
01054 if (gGLManager.mIsDisabled)
01055 {
01056 return TRUE;
01057 }
01058
01059 static S32 next_frame = 0;
01060 const S32 total_no_tiles = 6 * NUM_TILES;
01061 const S32 cycle_frame_no = total_no_tiles + 1;
01062
01063 if (mUpdateTimer.getElapsedTimeF32() > 0.001f)
01064 {
01065 mUpdateTimer.reset();
01066 const S32 frame = next_frame;
01067
01068 ++next_frame;
01069 next_frame = next_frame % cycle_frame_no;
01070
01071 sInterpVal = (!mInitialized) ? 1 : (F32)next_frame / cycle_frame_no;
01072
01073 LLSkyTex::setInterpVal( sInterpVal );
01074 LLHeavenBody::setInterpVal( sInterpVal );
01075 calcAtmospherics();
01076
01077 if (mForceUpdate || total_no_tiles == frame)
01078 {
01079 LLSkyTex::stepCurrent();
01080
01081 const static F32 LIGHT_DIRECTION_THRESHOLD = (F32) cos(DEG_TO_RAD * 1.f);
01082 const static F32 COLOR_CHANGE_THRESHOLD = 0.01f;
01083
01084 LLVector3 direction = mSun.getDirection();
01085 direction.normVec();
01086 const F32 dot_lighting = direction * mLastLightingDirection;
01087
01088 LLColor3 delta_color;
01089 delta_color.setVec(mLastTotalAmbient.mV[0] - mTotalAmbient.mV[0],
01090 mLastTotalAmbient.mV[1] - mTotalAmbient.mV[1],
01091 mLastTotalAmbient.mV[2] - mTotalAmbient.mV[2]);
01092
01093 if ( mForceUpdate
01094 || ((dot_lighting < LIGHT_DIRECTION_THRESHOLD)
01095 || (delta_color.magVec() > COLOR_CHANGE_THRESHOLD)
01096 || !mInitialized)
01097 && !direction.isExactlyZero())
01098 {
01099 mLastLightingDirection = direction;
01100 mLastTotalAmbient = mTotalAmbient;
01101 mInitialized = TRUE;
01102
01103 if (mCubeMap)
01104 {
01105 if (mForceUpdate)
01106 {
01107 updateFog(LLViewerCamera::getInstance()->getFar());
01108 for (int side = 0; side < 6; side++)
01109 {
01110 for (int tile = 0; tile < NUM_TILES; tile++)
01111 {
01112 createSkyTexture(side, tile);
01113 }
01114 }
01115
01116 calcAtmospherics();
01117
01118 for (int side = 0; side < 6; side++)
01119 {
01120 LLImageRaw* raw1 = mSkyTex[side].getImageRaw(TRUE);
01121 LLImageRaw* raw2 = mSkyTex[side].getImageRaw(FALSE);
01122 raw2->copy(raw1);
01123 mSkyTex[side].createGLImage(mSkyTex[side].getWhich(FALSE));
01124
01125 raw1 = mShinyTex[side].getImageRaw(TRUE);
01126 raw2 = mShinyTex[side].getImageRaw(FALSE);
01127 raw2->copy(raw1);
01128 mShinyTex[side].createGLImage(mShinyTex[side].getWhich(FALSE));
01129 }
01130 next_frame = 0;
01131 }
01132 }
01133 }
01134
01137
01138
01139 for (S32 i = 0; i < 6; ++i)
01140 {
01141 mSkyTex[i].create(1.0f);
01142 mShinyTex[i].create(1.0f);
01143 }
01144
01145
01146 if (mCubeMap)
01147 {
01148 std::vector<LLPointer<LLImageRaw> > images;
01149 images.reserve(6);
01150 for (S32 side = 0; side < 6; side++)
01151 {
01152 images.push_back(mShinyTex[side].getImageRaw(TRUE));
01153 }
01154 mCubeMap->init(images);
01155 }
01156
01157 gPipeline.markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
01158
01159
01160
01161 mForceUpdate = FALSE;
01162 }
01163 else
01164 {
01165 const S32 side = frame / NUM_TILES;
01166 const S32 tile = frame % NUM_TILES;
01167 createSkyTexture(side, tile);
01168 }
01169 }
01170
01171 if (mDrawable.notNull() && mDrawable->getFace(0) && mDrawable->getFace(0)->mVertexBuffer.isNull())
01172 {
01173 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
01174 }
01175 return TRUE;
01176 }
01177
01178 void LLVOSky::updateTextures(LLAgent &agent)
01179 {
01180 if (mSunTexturep)
01181 {
01182 mSunTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
01183 mMoonTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
01184 mBloomTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
01185 }
01186 }
01187
01188 LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline)
01189 {
01190 pipeline->allocDrawable(this);
01191 mDrawable->setLit(FALSE);
01192
01193 LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY);
01194 poolp->setSkyTex(mSkyTex);
01195 poolp->setSun(&mSun);
01196 poolp->setMoon(&mMoon);
01197 mDrawable->setRenderType(LLPipeline::RENDER_TYPE_SKY);
01198
01199 for (S32 i = 0; i < 6; ++i)
01200 {
01201 mFace[FACE_SIDE0 + i] = mDrawable->addFace(poolp, NULL);
01202 }
01203
01204 mFace[FACE_SUN] = mDrawable->addFace(poolp, mSunTexturep);
01205 mFace[FACE_MOON] = mDrawable->addFace(poolp, mMoonTexturep);
01206 mFace[FACE_BLOOM] = mDrawable->addFace(poolp, mBloomTexturep);
01207
01208 return mDrawable;
01209 }
01210
01211
01212
01213
01214
01215
01216 void LLVOSky::createDummyVertexBuffer()
01217 {
01218 if(!mFace[FACE_DUMMY])
01219 {
01220 LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY);
01221 mFace[FACE_DUMMY] = mDrawable->addFace(poolp, NULL);
01222 }
01223
01224 if(mFace[FACE_DUMMY]->mVertexBuffer.isNull())
01225 {
01226 mFace[FACE_DUMMY]->mVertexBuffer = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
01227 mFace[FACE_DUMMY]->mVertexBuffer->allocateBuffer(1, 1, TRUE);
01228 }
01229 }
01230
01231 void LLVOSky::updateDummyVertexBuffer()
01232 {
01233 if(!LLVertexBuffer::sEnableVBOs)
01234 return ;
01235
01236 if(mHeavenlyBodyUpdated)
01237 {
01238 mHeavenlyBodyUpdated = FALSE ;
01239 return ;
01240 }
01241
01242 LLFastTimer t(LLFastTimer::FTM_RENDER_FAKE_VBO_UPDATE) ;
01243
01244 if(!mFace[FACE_DUMMY] || mFace[FACE_DUMMY]->mVertexBuffer.isNull())
01245 createDummyVertexBuffer() ;
01246
01247 LLStrider<LLVector3> vertices ;
01248 mFace[FACE_DUMMY]->mVertexBuffer->getVertexStrider(vertices, 0);
01249 *vertices = mCameraPosAgent ;
01250 mFace[FACE_DUMMY]->mVertexBuffer->setBuffer(0) ;
01251 }
01252
01253
01254
01255
01256 BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
01257 {
01258 LLFastTimer ftm(LLFastTimer::FTM_GEO_SKY);
01259 if (mFace[FACE_REFLECTION] == NULL)
01260 {
01261 LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
01262 if (gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() != 0)
01263 {
01264 mFace[FACE_REFLECTION] = drawable->addFace(poolp, NULL);
01265 }
01266 }
01267
01268 mCameraPosAgent = drawable->getPositionAgent();
01269 mEarthCenter.mV[0] = mCameraPosAgent.mV[0];
01270 mEarthCenter.mV[1] = mCameraPosAgent.mV[1];
01271
01272 LLVector3 v_agent[8];
01273 for (S32 i = 0; i < 8; ++i)
01274 {
01275 F32 x_sgn = (i&1) ? 1.f : -1.f;
01276 F32 y_sgn = (i&2) ? 1.f : -1.f;
01277 F32 z_sgn = (i&4) ? 1.f : -1.f;
01278 v_agent[i] = HORIZON_DIST * SKY_BOX_MULT * LLVector3(x_sgn, y_sgn, z_sgn);
01279 }
01280
01281 LLStrider<LLVector3> verticesp;
01282 LLStrider<LLVector3> normalsp;
01283 LLStrider<LLVector2> texCoordsp;
01284 LLStrider<U16> indicesp;
01285 U16 index_offset;
01286 LLFace *face;
01287
01288 for (S32 side = 0; side < 6; ++side)
01289 {
01290 face = mFace[FACE_SIDE0 + side];
01291
01292 if (face->mVertexBuffer.isNull())
01293 {
01294 face->setSize(4, 6);
01295 face->setGeomIndex(0);
01296 face->setIndicesIndex(0);
01297 face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
01298 face->mVertexBuffer->allocateBuffer(4, 6, TRUE);
01299
01300 index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
01301
01302 S32 vtx = 0;
01303 S32 curr_bit = side >> 1;
01304 S32 side_dir = side & 1;
01305 S32 i_bit = (curr_bit + 2) % 3;
01306 S32 j_bit = (i_bit + 2) % 3;
01307
01308 LLVector3 axis;
01309 axis.mV[curr_bit] = 1;
01310 face->mCenterAgent = (F32)((side_dir << 1) - 1) * axis * HORIZON_DIST;
01311
01312 vtx = side_dir << curr_bit;
01313 *(verticesp++) = v_agent[vtx];
01314 *(verticesp++) = v_agent[vtx | 1 << j_bit];
01315 *(verticesp++) = v_agent[vtx | 1 << i_bit];
01316 *(verticesp++) = v_agent[vtx | 1 << i_bit | 1 << j_bit];
01317
01318 *(texCoordsp++) = TEX00;
01319 *(texCoordsp++) = TEX01;
01320 *(texCoordsp++) = TEX10;
01321 *(texCoordsp++) = TEX11;
01322
01323
01324 *indicesp++ = index_offset + 0;
01325 *indicesp++ = index_offset + 1;
01326 *indicesp++ = index_offset + 3;
01327
01328 *indicesp++ = index_offset + 0;
01329 *indicesp++ = index_offset + 3;
01330 *indicesp++ = index_offset + 2;
01331
01332 face->mVertexBuffer->setBuffer(0);
01333 }
01334 }
01335
01336 const LLVector3 &look_at = LLViewerCamera::getInstance()->getAtAxis();
01337 LLVector3 right = look_at % LLVector3::z_axis;
01338 LLVector3 up = right % look_at;
01339 right.normVec();
01340 up.normVec();
01341
01342 const static F32 elevation_factor = 0.0f/sResolution;
01343 const F32 cos_max_angle = cosHorizon(elevation_factor);
01344 mSun.setDraw(updateHeavenlyBodyGeometry(drawable, FACE_SUN, TRUE, mSun, cos_max_angle, up, right));
01345 mMoon.setDraw(updateHeavenlyBodyGeometry(drawable, FACE_MOON, FALSE, mMoon, cos_max_angle, up, right));
01346
01347 const F32 water_height = gAgent.getRegion()->getWaterHeight() + 0.01f;
01348
01349 const F32 camera_height = mCameraPosAgent.mV[2];
01350 const F32 height_above_water = camera_height - water_height;
01351
01352 BOOL sun_flag = FALSE;
01353
01354 if (mSun.isVisible())
01355 {
01356 if (mMoon.isVisible())
01357 {
01358 sun_flag = look_at * mSun.getDirection() > 0;
01359 }
01360 else
01361 {
01362 sun_flag = TRUE;
01363 }
01364 }
01365
01366 if (height_above_water > 0)
01367 {
01368 BOOL render_ref = gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() == 0;
01369
01370 if (sun_flag)
01371 {
01372 setDrawRefl(0);
01373 if (render_ref)
01374 {
01375 updateReflectionGeometry(drawable, height_above_water, mSun);
01376 }
01377 }
01378 else
01379 {
01380 setDrawRefl(1);
01381 if (render_ref)
01382 {
01383 updateReflectionGeometry(drawable, height_above_water, mMoon);
01384 }
01385 }
01386 }
01387 else
01388 {
01389 setDrawRefl(-1);
01390 }
01391
01392 LLPipeline::sCompiles++;
01393 return TRUE;
01394 }
01395
01396 BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, const BOOL is_sun,
01397 LLHeavenBody& hb, const F32 cos_max_angle,
01398 const LLVector3 &up, const LLVector3 &right)
01399 {
01400 mHeavenlyBodyUpdated = TRUE ;
01401
01402 LLStrider<LLVector3> verticesp;
01403 LLStrider<LLVector3> normalsp;
01404 LLStrider<LLVector2> texCoordsp;
01405 LLStrider<U16> indicesp;
01406 S32 index_offset;
01407 LLFace *facep;
01408
01409 LLVector3 to_dir = hb.getDirection();
01410
01411 if (!is_sun)
01412 {
01413 to_dir.mV[2] = llmax(to_dir.mV[2]+0.1f, 0.1f);
01414 }
01415 LLVector3 draw_pos = to_dir * HEAVENLY_BODY_DIST;
01416
01417
01418 LLVector3 hb_right = to_dir % LLVector3::z_axis;
01419 LLVector3 hb_up = hb_right % to_dir;
01420 hb_right.normVec();
01421 hb_up.normVec();
01422
01423
01424
01425
01426
01427 const F32 enlargm_factor = ( 1 - to_dir.mV[2] );
01428 F32 horiz_enlargement = 1 + enlargm_factor * 0.3f;
01429 F32 vert_enlargement = 1 + enlargm_factor * 0.2f;
01430
01431
01432 hb.setU(HEAVENLY_BODY_FACTOR * horiz_enlargement * hb.getDiskRadius() * hb_right);
01433 hb.setV(HEAVENLY_BODY_FACTOR * vert_enlargement * hb.getDiskRadius() * hb_up);
01434
01435
01436 const LLVector3 scaled_right = HEAVENLY_BODY_DIST * hb.getU();
01437 const LLVector3 scaled_up = HEAVENLY_BODY_DIST * hb.getV();
01438
01439
01440
01441 LLVector3 v_clipped[4];
01442
01443 hb.corner(0) = draw_pos - scaled_right + scaled_up;
01444 hb.corner(1) = draw_pos - scaled_right - scaled_up;
01445 hb.corner(2) = draw_pos + scaled_right + scaled_up;
01446 hb.corner(3) = draw_pos + scaled_right - scaled_up;
01447
01448
01449 F32 t_left, t_right;
01450 if (!clip_quad_to_horizon(t_left, t_right, v_clipped, hb.corners(), cos_max_angle))
01451 {
01452 hb.setVisible(FALSE);
01453 return FALSE;
01454 }
01455 hb.setVisible(TRUE);
01456
01457 facep = mFace[f];
01458
01459 if (facep->mVertexBuffer.isNull())
01460 {
01461 facep->setSize(4, 6);
01462 facep->mVertexBuffer = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
01463 facep->mVertexBuffer->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount(), TRUE);
01464 facep->setGeomIndex(0);
01465 facep->setIndicesIndex(0);
01466 }
01467
01468 index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
01469
01470 if (-1 == index_offset)
01471 {
01472 return TRUE;
01473 }
01474
01475 for (S32 vtx = 0; vtx < 4; ++vtx)
01476 {
01477 hb.corner(vtx) = v_clipped[vtx];
01478 *(verticesp++) = hb.corner(vtx) + mCameraPosAgent;
01479 }
01480
01481 *(texCoordsp++) = TEX01;
01482 *(texCoordsp++) = TEX00;
01483 *(texCoordsp++) = TEX11;
01484 *(texCoordsp++) = TEX10;
01485
01486 *indicesp++ = index_offset + 0;
01487 *indicesp++ = index_offset + 2;
01488 *indicesp++ = index_offset + 1;
01489
01490 *indicesp++ = index_offset + 1;
01491 *indicesp++ = index_offset + 2;
01492 *indicesp++ = index_offset + 3;
01493
01494 facep->mVertexBuffer->setBuffer(0);
01495
01496 if (is_sun)
01497 {
01498 if ((t_left > 0) && (t_right > 0))
01499 {
01500 F32 t = (t_left + t_right) * 0.5f;
01501 mSun.setHorizonVisibility(0.5f * (1 + cos(t * F_PI)));
01502 }
01503 else
01504 {
01505 mSun.setHorizonVisibility();
01506 }
01507 updateSunHaloGeometry(drawable);
01508 }
01509
01510 return TRUE;
01511 }
01512
01513
01514
01515
01516
01517
01518 BOOL clip_quad_to_horizon(F32& t_left, F32& t_right, LLVector3 v_clipped[4],
01519 const LLVector3 v_corner[4], const F32 cos_max_angle)
01520 {
01521 t_left = clip_side_to_horizon(v_corner[1], v_corner[0], cos_max_angle);
01522 t_right = clip_side_to_horizon(v_corner[3], v_corner[2], cos_max_angle);
01523
01524 if ((t_left >= 1) || (t_right >= 1))
01525 {
01526 return FALSE;
01527 }
01528
01529
01530
01531
01532
01533 {
01534 for (S32 vtx = 0; vtx < 4; ++vtx)
01535 {
01536 v_clipped[vtx] = v_corner[vtx];
01537 }
01538 }
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549 return TRUE;
01550 }
01551
01552
01553 F32 clip_side_to_horizon(const LLVector3& V0, const LLVector3& V1, const F32 cos_max_angle)
01554 {
01555 const LLVector3 V = V1 - V0;
01556 const F32 k2 = 1.f/(cos_max_angle * cos_max_angle) - 1;
01557 const F32 A = V.mV[0] * V.mV[0] + V.mV[1] * V.mV[1] - k2 * V.mV[2] * V.mV[2];
01558 const F32 B = V0.mV[0] * V.mV[0] + V0.mV[1] * V.mV[1] - k2 * V0.mV[2] * V.mV[2];
01559 const F32 C = V0.mV[0] * V0.mV[0] + V0.mV[1] * V0.mV[1] - k2 * V0.mV[2] * V0.mV[2];
01560
01561 if (fabs(A) < 1e-7)
01562 {
01563 return -0.1f;
01564 }
01565
01566 const F32 det = sqrt(B*B - A*C);
01567 const F32 t1 = (-B - det) / A;
01568 const F32 t2 = (-B + det) / A;
01569 const F32 z1 = V0.mV[2] + t1 * V.mV[2];
01570 const F32 z2 = V0.mV[2] + t2 * V.mV[2];
01571 if (z1 * cos_max_angle < 0)
01572 {
01573 return t2;
01574 }
01575 else if (z2 * cos_max_angle < 0)
01576 {
01577 return t1;
01578 }
01579 else if ((t1 < 0) || (t1 > 1))
01580 {
01581 return t2;
01582 }
01583 else
01584 {
01585 return t1;
01586 }
01587 }
01588
01589
01590 void LLVOSky::updateSunHaloGeometry(LLDrawable *drawable )
01591 {
01592 #if 0
01593 const LLVector3* v_corner = mSun.corners();
01594
01595 LLStrider<LLVector3> verticesp;
01596 LLStrider<LLVector3> normalsp;
01597 LLStrider<LLVector2> texCoordsp;
01598 LLStrider<U16> indicesp;
01599 S32 index_offset;
01600 LLFace *face;
01601
01602 const LLVector3 right = 2 * (v_corner[2] - v_corner[0]);
01603 LLVector3 up = 2 * (v_corner[2] - v_corner[3]);
01604 up.normVec();
01605 F32 size = right.magVec();
01606 up = size * up;
01607 const LLVector3 draw_pos = 0.25 * (v_corner[0] + v_corner[1] + v_corner[2] + v_corner[3]);
01608
01609 LLVector3 v_glow_corner[4];
01610
01611 v_glow_corner[0] = draw_pos - right + up;
01612 v_glow_corner[1] = draw_pos - right - up;
01613 v_glow_corner[2] = draw_pos + right + up;
01614 v_glow_corner[3] = draw_pos + right - up;
01615
01616 face = mFace[FACE_BLOOM];
01617
01618 if (face->mVertexBuffer.isNull())
01619 {
01620 face->setSize(4, 6);
01621 face->setGeomIndex(0);
01622 face->setIndicesIndex(0);
01623 face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
01624 face->mVertexBuffer->allocateBuffer(4, 6, TRUE);
01625 }
01626
01627 index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
01628 if (-1 == index_offset)
01629 {
01630 return;
01631 }
01632
01633 for (S32 vtx = 0; vtx < 4; ++vtx)
01634 {
01635 *(verticesp++) = v_glow_corner[vtx] + mCameraPosAgent;
01636 }
01637
01638 *(texCoordsp++) = TEX01;
01639 *(texCoordsp++) = TEX00;
01640 *(texCoordsp++) = TEX11;
01641 *(texCoordsp++) = TEX10;
01642
01643 *indicesp++ = index_offset + 0;
01644 *indicesp++ = index_offset + 2;
01645 *indicesp++ = index_offset + 1;
01646
01647 *indicesp++ = index_offset + 1;
01648 *indicesp++ = index_offset + 2;
01649 *indicesp++ = index_offset + 3;
01650 #endif
01651 }
01652
01653
01654 F32 dtReflection(const LLVector3& p, F32 cos_dir_from_top, F32 sin_dir_from_top, F32 diff_angl_dir)
01655 {
01656 LLVector3 P = p;
01657 P.normVec();
01658
01659 const F32 cos_dir_angle = -P.mV[VZ];
01660 const F32 sin_dir_angle = sqrt(1 - cos_dir_angle * cos_dir_angle);
01661
01662 F32 cos_diff_angles = cos_dir_angle * cos_dir_from_top
01663 + sin_dir_angle * sin_dir_from_top;
01664
01665 F32 diff_angles;
01666 if (cos_diff_angles > (1 - 1e-7))
01667 diff_angles = 0;
01668 else
01669 diff_angles = acos(cos_diff_angles);
01670
01671 const F32 rel_diff_angles = diff_angles / diff_angl_dir;
01672 const F32 dt = 1 - rel_diff_angles;
01673
01674 return (dt < 0) ? 0 : dt;
01675 }
01676
01677
01678 F32 dtClip(const LLVector3& v0, const LLVector3& v1, F32 far_clip2)
01679 {
01680 F32 dt_clip;
01681 const LLVector3 otrezok = v1 - v0;
01682 const F32 A = otrezok.magVecSquared();
01683 const F32 B = v0 * otrezok;
01684 const F32 C = v0.magVecSquared() - far_clip2;
01685 const F32 det = sqrt(B*B - A*C);
01686 dt_clip = (-B - det) / A;
01687 if ((dt_clip < 0) || (dt_clip > 1))
01688 dt_clip = (-B + det) / A;
01689 return dt_clip;
01690 }
01691
01692
01693 void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
01694 const LLHeavenBody& HB)
01695 {
01696 const LLVector3 &look_at = LLViewerCamera::getInstance()->getAtAxis();
01697
01698
01699
01700 LLVector3 to_dir = HB.getDirection();
01701 LLVector3 hb_pos = to_dir * (HORIZON_DIST - 10);
01702 LLVector3 to_dir_proj = to_dir;
01703 to_dir_proj.mV[VZ] = 0;
01704 to_dir_proj.normVec();
01705
01706 LLVector3 Right = to_dir % LLVector3::z_axis;
01707 LLVector3 Up = Right % to_dir;
01708 Right.normVec();
01709 Up.normVec();
01710
01711
01712 LLVector3 look_at_right = look_at % LLVector3::z_axis;
01713 look_at_right.normVec();
01714
01715 const static F32 cos_horizon_angle = cosHorizon(0.0f/sResolution);
01716
01717
01718 const F32 enlargm_factor = ( 1 - to_dir.mV[2] );
01719 F32 horiz_enlargement = 1 + enlargm_factor * 0.3f;
01720 F32 vert_enlargement = 1 + enlargm_factor * 0.2f;
01721
01722 F32 vert_size = vert_enlargement * HEAVENLY_BODY_SCALE * HB.getDiskRadius();
01723 Right *= horiz_enlargement * HEAVENLY_BODY_SCALE * HB.getDiskRadius();
01724 Up *= vert_size;
01725
01726 LLVector3 v_corner[2];
01727 LLVector3 stretch_corner[2];
01728
01729 LLVector3 top_hb = v_corner[0] = stretch_corner[0] = hb_pos - Right + Up;
01730 v_corner[1] = stretch_corner[1] = hb_pos - Right - Up;
01731
01732 F32 dt_hor, dt;
01733 dt_hor = clip_side_to_horizon(v_corner[1], v_corner[0], cos_horizon_angle);
01734
01735 LLVector2 TEX0t = TEX00;
01736 LLVector2 TEX1t = TEX10;
01737 LLVector3 lower_corner = v_corner[1];
01738
01739 if ((dt_hor > 0) && (dt_hor < 1))
01740 {
01741 TEX0t = LLVector2(0, dt_hor);
01742 TEX1t = LLVector2(1, dt_hor);
01743 lower_corner = (1 - dt_hor) * v_corner[1] + dt_hor * v_corner[0];
01744 }
01745 else
01746 dt_hor = llmax(0.0f, llmin(1.0f, dt_hor));
01747
01748 top_hb.normVec();
01749 const F32 cos_angle_of_view = fabs(top_hb.mV[VZ]);
01750 const F32 extension = llmin (5.0f, 1.0f / cos_angle_of_view);
01751
01752 const S32 cols = 1;
01753 const S32 raws = lltrunc(16 * extension);
01754 S32 quads = cols * raws;
01755
01756 stretch_corner[0] = lower_corner + extension * (stretch_corner[0] - lower_corner);
01757 stretch_corner[1] = lower_corner + extension * (stretch_corner[1] - lower_corner);
01758
01759 dt = dt_hor;
01760
01761
01762 F32 cos_dir_from_top[2];
01763
01764 LLVector3 dir = stretch_corner[0];
01765 dir.normVec();
01766 cos_dir_from_top[0] = dir.mV[VZ];
01767
01768 dir = stretch_corner[1];
01769 dir.normVec();
01770 cos_dir_from_top[1] = dir.mV[VZ];
01771
01772 const F32 sin_dir_from_top = sqrt(1 - cos_dir_from_top[0] * cos_dir_from_top[0]);
01773 const F32 sin_dir_from_top2 = sqrt(1 - cos_dir_from_top[1] * cos_dir_from_top[1]);
01774 const F32 cos_diff_dir = cos_dir_from_top[0] * cos_dir_from_top[1]
01775 + sin_dir_from_top * sin_dir_from_top2;
01776 const F32 diff_angl_dir = acos(cos_diff_dir);
01777
01778 v_corner[0] = stretch_corner[0];
01779 v_corner[1] = lower_corner;
01780
01781
01782 LLVector2 TEX0tt = TEX01;
01783 LLVector2 TEX1tt = TEX11;
01784
01785 LLVector3 v_refl_corner[4];
01786 LLVector3 v_sprite_corner[4];
01787
01788 S32 vtx;
01789 for (vtx = 0; vtx < 2; ++vtx)
01790 {
01791 LLVector3 light_proj = v_corner[vtx];
01792 light_proj.normVec();
01793
01794 const F32 z = light_proj.mV[VZ];
01795 const F32 sin_angle = sqrt(1 - z * z);
01796 light_proj *= 1.f / sin_angle;
01797 light_proj.mV[VZ] = 0;
01798 const F32 to_refl_point = H * sin_angle / fabs(z);
01799
01800 v_refl_corner[vtx] = to_refl_point * light_proj;
01801 }
01802
01803
01804 for (vtx = 2; vtx < 4; ++vtx)
01805 {
01806 const LLVector3 to_dir_vec = (to_dir_proj * v_refl_corner[vtx-2]) * to_dir_proj;
01807 v_refl_corner[vtx] = v_refl_corner[vtx-2] + 2 * (to_dir_vec - v_refl_corner[vtx-2]);
01808 }
01809
01810 for (vtx = 0; vtx < 4; ++vtx)
01811 v_refl_corner[vtx].mV[VZ] -= H;
01812
01813 S32 side = 0;
01814 LLVector3 refl_corn_norm[2];
01815 refl_corn_norm[0] = v_refl_corner[1];
01816 refl_corn_norm[0].normVec();
01817 refl_corn_norm[1] = v_refl_corner[3];
01818 refl_corn_norm[1].normVec();
01819
01820 F32 cos_refl_look_at[2];
01821 cos_refl_look_at[0] = refl_corn_norm[0] * look_at;
01822 cos_refl_look_at[1] = refl_corn_norm[1] * look_at;
01823
01824 if (cos_refl_look_at[1] > cos_refl_look_at[0])
01825 {
01826 side = 2;
01827 }
01828
01829
01830 const F32 far_clip = 512;
01831 const F32 far_clip2 = far_clip*far_clip;
01832
01833 F32 dt_clip;
01834 F32 vtx_near2, vtx_far2;
01835
01836 if ((vtx_far2 = v_refl_corner[side].magVecSquared()) > far_clip2)
01837 {
01838
01839 dt_clip = 1.1f;
01840 quads = 1;
01841 }
01842 else if ((vtx_near2 = v_refl_corner[side+1].magVecSquared()) > far_clip2)
01843 {
01844
01845 dt_clip = dtClip(v_refl_corner[side + 1], v_refl_corner[side], far_clip2);
01846 const LLVector3 P = (1 - dt_clip) * v_refl_corner[side + 1] + dt_clip * v_refl_corner[side];
01847
01848 F32 dt_tex = dtReflection(P, cos_dir_from_top[0], sin_dir_from_top, diff_angl_dir);
01849
01850 dt = dt_tex;
01851 TEX0tt = LLVector2(0, dt);
01852 TEX1tt = LLVector2(1, dt);
01853 quads++;
01854 }
01855 else
01856 {
01857
01858 dt_clip = -0.1f;
01859 }
01860
01861 LLFace *face = mFace[FACE_REFLECTION];
01862
01863 if (face->mVertexBuffer.isNull() || quads*4 != face->getGeomCount())
01864 {
01865 face->setSize(quads * 4, quads * 6);
01866 face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
01867 face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
01868 face->setIndicesIndex(0);
01869 face->setGeomIndex(0);
01870 }
01871
01872 LLStrider<LLVector3> verticesp;
01873 LLStrider<LLVector3> normalsp;
01874 LLStrider<LLVector2> texCoordsp;
01875 LLStrider<U16> indicesp;
01876 S32 index_offset;
01877
01878 index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
01879 if (-1 == index_offset)
01880 {
01881 return;
01882 }
01883
01884 LLColor3 hb_col3 = HB.getInterpColor();
01885 hb_col3.clamp();
01886 const LLColor4 hb_col = LLColor4(hb_col3);
01887
01888 const F32 min_attenuation = 0.4f;
01889 const F32 max_attenuation = 0.7f;
01890 const F32 attenuation = min_attenuation
01891 + cos_angle_of_view * (max_attenuation - min_attenuation);
01892
01893 LLColor4 hb_refl_col = (1-attenuation) * hb_col + attenuation * mFogColor;
01894 face->setFaceColor(hb_refl_col);
01895
01896 LLVector3 v_far[2];
01897 v_far[0] = v_refl_corner[1];
01898 v_far[1] = v_refl_corner[3];
01899
01900 if(dt_clip > 0)
01901 {
01902 if (dt_clip >= 1)
01903 {
01904 for (S32 vtx = 0; vtx < 4; ++vtx)
01905 {
01906 F32 ratio = far_clip / v_refl_corner[vtx].magVec();
01907 *(verticesp++) = v_refl_corner[vtx] = ratio * v_refl_corner[vtx] + mCameraPosAgent;
01908 }
01909 const LLVector3 draw_pos = 0.25 *
01910 (v_refl_corner[0] + v_refl_corner[1] + v_refl_corner[2] + v_refl_corner[3]);
01911 face->mCenterAgent = draw_pos;
01912 }
01913 else
01914 {
01915 F32 ratio = far_clip / v_refl_corner[1].magVec();
01916 v_sprite_corner[1] = v_refl_corner[1] * ratio;
01917
01918 ratio = far_clip / v_refl_corner[3].magVec();
01919 v_sprite_corner[3] = v_refl_corner[3] * ratio;
01920
01921 v_refl_corner[1] = (1 - dt_clip) * v_refl_corner[1] + dt_clip * v_refl_corner[0];
01922 v_refl_corner[3] = (1 - dt_clip) * v_refl_corner[3] + dt_clip * v_refl_corner[2];
01923 v_sprite_corner[0] = v_refl_corner[1];
01924 v_sprite_corner[2] = v_refl_corner[3];
01925
01926 for (S32 vtx = 0; vtx < 4; ++vtx)
01927 {
01928 *(verticesp++) = v_sprite_corner[vtx] + mCameraPosAgent;
01929 }
01930
01931 const LLVector3 draw_pos = 0.25 *
01932 (v_refl_corner[0] + v_sprite_corner[1] + v_refl_corner[2] + v_sprite_corner[3]);
01933 face->mCenterAgent = draw_pos;
01934 }
01935
01936 *(texCoordsp++) = TEX0tt;
01937 *(texCoordsp++) = TEX0t;
01938 *(texCoordsp++) = TEX1tt;
01939 *(texCoordsp++) = TEX1t;
01940
01941 *indicesp++ = index_offset + 0;
01942 *indicesp++ = index_offset + 2;
01943 *indicesp++ = index_offset + 1;
01944
01945 *indicesp++ = index_offset + 1;
01946 *indicesp++ = index_offset + 2;
01947 *indicesp++ = index_offset + 3;
01948
01949 index_offset += 4;
01950 }
01951
01952 if (dt_clip < 1)
01953 {
01954 if (dt_clip <= 0)
01955 {
01956 const LLVector3 draw_pos = 0.25 *
01957 (v_refl_corner[0] + v_refl_corner[1] + v_refl_corner[2] + v_refl_corner[3]);
01958 face->mCenterAgent = draw_pos;
01959 }
01960
01961 const F32 raws_inv = 1.f/raws;
01962 const F32 cols_inv = 1.f/cols;
01963 LLVector3 left = v_refl_corner[0] - v_refl_corner[1];
01964 LLVector3 right = v_refl_corner[2] - v_refl_corner[3];
01965 left *= raws_inv;
01966 right *= raws_inv;
01967
01968 F32 dt_raw = dt;
01969
01970 for (S32 raw = 0; raw < raws; ++raw)
01971 {
01972 F32 dt_v0 = raw * raws_inv;
01973 F32 dt_v1 = (raw + 1) * raws_inv;
01974 const LLVector3 BL = v_refl_corner[1] + (F32)raw * left;
01975 const LLVector3 BR = v_refl_corner[3] + (F32)raw * right;
01976 const LLVector3 EL = BL + left;
01977 const LLVector3 ER = BR + right;
01978 dt_v0 = dt_raw;
01979 dt_raw = dt_v1 = dtReflection(EL, cos_dir_from_top[0], sin_dir_from_top, diff_angl_dir);
01980 for (S32 col = 0; col < cols; ++col)
01981 {
01982 F32 dt_h0 = col * cols_inv;
01983 *(verticesp++) = (1 - dt_h0) * EL + dt_h0 * ER + mCameraPosAgent;
01984 *(verticesp++) = (1 - dt_h0) * BL + dt_h0 * BR + mCameraPosAgent;
01985 F32 dt_h1 = (col + 1) * cols_inv;
01986 *(verticesp++) = (1 - dt_h1) * EL + dt_h1 * ER + mCameraPosAgent;
01987 *(verticesp++) = (1 - dt_h1) * BL + dt_h1 * BR + mCameraPosAgent;
01988
01989 *(texCoordsp++) = LLVector2(dt_h0, dt_v1);
01990 *(texCoordsp++) = LLVector2(dt_h0, dt_v0);
01991 *(texCoordsp++) = LLVector2(dt_h1, dt_v1);
01992 *(texCoordsp++) = LLVector2(dt_h1, dt_v0);
01993
01994 *indicesp++ = index_offset + 0;
01995 *indicesp++ = index_offset + 2;
01996 *indicesp++ = index_offset + 1;
01997
01998 *indicesp++ = index_offset + 1;
01999 *indicesp++ = index_offset + 2;
02000 *indicesp++ = index_offset + 3;
02001
02002 index_offset += 4;
02003 }
02004 }
02005 }
02006
02007 face->mVertexBuffer->setBuffer(0);
02008 }
02009
02010
02011
02012
02013 void LLVOSky::updateFog(const F32 distance)
02014 {
02015 if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG))
02016 {
02017 glFogf(GL_FOG_DENSITY, 0);
02018 glFogfv(GL_FOG_COLOR, (F32 *) &LLColor4::white.mV);
02019 glFogf(GL_FOG_END, 1000000.f);
02020 return;
02021 }
02022
02023 const BOOL hide_clip_plane = TRUE;
02024 LLColor4 target_fog(0.f, 0.2f, 0.5f, 0.f);
02025
02026 const F32 water_height = gAgent.getRegion()->getWaterHeight();
02027
02028 F32 camera_height = gAgent.getCameraPositionAgent().mV[2];
02029
02030 F32 near_clip_height = LLViewerCamera::getInstance()->getAtAxis().mV[VZ] * LLViewerCamera::getInstance()->getNear();
02031 camera_height += near_clip_height;
02032
02033 F32 fog_distance = 0.f;
02034 LLColor3 res_color[3];
02035
02036 LLColor3 sky_fog_color = LLColor3::white;
02037 LLColor3 render_fog_color = LLColor3::white;
02038
02039 LLVector3 tosun = getToSunLast();
02040 const F32 tosun_z = tosun.mV[VZ];
02041 tosun.mV[VZ] = 0.f;
02042 tosun.normVec();
02043 LLVector3 perp_tosun;
02044 perp_tosun.mV[VX] = -tosun.mV[VY];
02045 perp_tosun.mV[VY] = tosun.mV[VX];
02046 LLVector3 tosun_45 = tosun + perp_tosun;
02047 tosun_45.normVec();
02048
02049 F32 delta = 0.06f;
02050 tosun.mV[VZ] = delta;
02051 perp_tosun.mV[VZ] = delta;
02052 tosun_45.mV[VZ] = delta;
02053 tosun.normVec();
02054 perp_tosun.normVec();
02055 tosun_45.normVec();
02056
02057
02058 initAtmospherics();
02059 res_color[0] = calcSkyColorInDir(tosun);
02060 res_color[1] = calcSkyColorInDir(perp_tosun);
02061 res_color[2] = calcSkyColorInDir(tosun_45);
02062
02063 sky_fog_color = color_norm(res_color[0] + res_color[1] + res_color[2]);
02064
02065 F32 full_off = -0.25f;
02066 F32 full_on = 0.00f;
02067 F32 on = (tosun_z - full_off) / (full_on - full_off);
02068 on = llclamp(on, 0.01f, 1.f);
02069 sky_fog_color *= 0.5f * on;
02070
02071
02072
02073 S32 i;
02074 for (i = 0; i < 3; i++)
02075 {
02076 sky_fog_color.mV[i] = llmax(0.0001f, sky_fog_color.mV[i]);
02077 }
02078
02079 color_gamma_correct(sky_fog_color);
02080
02081 render_fog_color = sky_fog_color;
02082
02083 F32 fog_density = 0.f;
02084 fog_distance = mFogRatio * distance;
02085
02086 if (camera_height > water_height)
02087 {
02088 LLColor4 fog(render_fog_color);
02089 glFogfv(GL_FOG_COLOR, fog.mV);
02090 mGLFogCol = fog;
02091
02092 if (hide_clip_plane)
02093 {
02094
02095 const F32 f_log = 2.14596602628934723963618357029f;
02096 fog_density = f_log/fog_distance;
02097 glFogi(GL_FOG_MODE, GL_EXP2);
02098 }
02099 else
02100 {
02101 const F32 f_log = 4.6051701859880913680359829093687f;
02102 fog_density = (f_log)/fog_distance;
02103 glFogi(GL_FOG_MODE, GL_EXP);
02104 }
02105 }
02106 else
02107 {
02108 F32 depth = water_height - camera_height;
02109
02110
02111 float water_fog_density = LLWaterParamManager::instance()->getFogDensity();
02112 LLColor4 water_fog_color = LLDrawPoolWater::sWaterFogColor.mV;
02113
02114
02115 float depth_scale = gSavedSettings.getF32("WaterGLFogDepthScale");
02116 float depth_modifier = 1.0f - llmin(llmax(depth / depth_scale, 0.01f),
02117 gSavedSettings.getF32("WaterGLFogDepthFloor"));
02118
02119 LLColor4 fogCol = water_fog_color * depth_modifier;
02120 fogCol.setAlpha(1);
02121
02122
02123 glFogfv(GL_FOG_COLOR, (F32 *) &fogCol.mV);
02124 mGLFogCol = fogCol;
02125
02126
02127 fog_density = water_fog_density * gSavedSettings.getF32("WaterGLFogDensityScale");
02128 glFogi(GL_FOG_MODE, GL_EXP2);
02129 }
02130
02131 mFogColor = sky_fog_color;
02132 mFogColor.setAlpha(1);
02133 LLGLSFog gls_fog;
02134
02135 glFogf(GL_FOG_END, fog_distance*2.2f);
02136
02137 glFogf(GL_FOG_DENSITY, fog_density);
02138
02139 glHint(GL_FOG_HINT, GL_NICEST);
02140 stop_glerror();
02141 }
02142
02143
02144 void LLHaze::initClass()
02145 {
02146 sAirScaSeaLevel = LLHaze::calcAirScaSeaLevel();
02147 }
02148
02149
02150
02151
02152
02153
02154 F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply)
02155 {
02156 F32 mv = color_max(col);
02157 if (0 == mv)
02158 {
02159 return 0;
02160 }
02161
02162 col *= 1.f / mv;
02163 color_pow(col, e);
02164 if (postmultiply)
02165 {
02166 col *= mv;
02167 }
02168 return mv;
02169 }
02170
02171
02172
02173
02174 F32 azimuth(const LLVector3 &v)
02175 {
02176 F32 azimuth = 0.0f;
02177 if (v.mV[VX] == 0.0f)
02178 {
02179 if (v.mV[VY] > 0.0f)
02180 {
02181 azimuth = F_PI * 0.5f;
02182 }
02183 else if (v.mV[VY] < 0.0f)
02184 {
02185 azimuth = F_PI * 1.5f;
02186 }
02187 }
02188 else
02189 {
02190 azimuth = (F32) atan(v.mV[VY] / v.mV[VX]);
02191 if (v.mV[VX] < 0.0f)
02192 {
02193 azimuth += F_PI;
02194 }
02195 else if (v.mV[VY] < 0.0f)
02196 {
02197 azimuth += F_PI * 2;
02198 }
02199 }
02200 return azimuth;
02201 }
02202
02203 void LLVOSky::initSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity)
02204 {
02205 LLVector3 sun_direction = (sun_dir.magVec() == 0) ? LLVector3::x_axis : sun_dir;
02206 sun_direction.normVec();
02207 mSun.setDirection(sun_direction);
02208 mSun.renewDirection();
02209 mSun.setAngularVelocity(sun_ang_velocity);
02210 mMoon.setDirection(-mSun.getDirection());
02211 mMoon.renewDirection();
02212 mLastLightingDirection = mSun.getDirection();
02213
02214 calcAtmospherics();
02215
02216 if ( !mInitialized )
02217 {
02218 init();
02219 LLSkyTex::stepCurrent();
02220 }
02221 }
02222
02223 void LLVOSky::setSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity)
02224 {
02225 LLVector3 sun_direction = (sun_dir.magVec() == 0) ? LLVector3::x_axis : sun_dir;
02226 sun_direction.normVec();
02227
02228
02229
02230 LLVector3 newDir = sun_direction;
02231
02232
02233 F32 sunDot = llmax(0.f, newDir.mV[2]);
02234 sunDot *= sunDot;
02235
02236
02237 LLVector3 adjustedDir = (newDir + LLVector3(0.f, -0.70711f, 0.70711f)) * 0.5f;
02238
02239
02240
02241 mBumpSunDir = adjustedDir * sunDot + newDir * (1.0f - sunDot);
02242 mBumpSunDir.normVec();
02243
02244 F32 dp = mLastLightingDirection * sun_direction;
02245 mSun.setDirection(sun_direction);
02246 mSun.setAngularVelocity(sun_ang_velocity);
02247 mMoon.setDirection(-sun_direction);
02248 calcAtmospherics();
02249 if (dp < 0.995f) {
02250 mForceUpdate = TRUE;
02251 }
02252 }