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