llvosky.cpp

Go to the documentation of this file.
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 // Heavenly body constants
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 // Texture coordinates:
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 // Exported globals
00081 LLUUID gSunTextureID = IMG_SUN;
00082 LLUUID gMoonTextureID = IMG_MOON;
00083 
00084 //static 
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]; // index 0 is unused
00141 };
00142 
00143 static LLFastLn gFastLn;
00144 
00145 
00146 // Functions used a lot.
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                 SkyTex
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                 Sky
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         // Don't delete images - it'll get deleted by gImageList on shutdown
00392         // This needs to be done for each texture
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         // Initialize the cached normalized direction vectors
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; // 0/1 = Z axis, 2/3 = Y, 4/5 = X
00516         const S32 side_dir = (((side & 1) << 1) - 1);  // even = -1, odd = 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         // uniform parameters for convenience
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         //lightnorm = LLWLParamManager::instance()->mCurParams.getVector("lightnorm", error);
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         // light norm is different.  We need the sun's direction, not the light direction
00659         // which could be from the moon.  And we need to clamp it
00660         // just like for the gpu
00661         LLVector3 sunDir = gSky.getSunDirection();
00662 
00663         // CFR_TO_OGL
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                         // So that shiny somewhat shows up at night.
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         // undo OGL_TO_CFR_ROTATION and negate vertical direction.
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 // turn on floating point precision
00735 // in vs2003 for this function.  Otherwise
00736 // sky is aliased looking 7:10 - 8:50
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         // project the direction ray onto the sky dome.
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         // Set altitude
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         // Initialize temp variables
00769         LLColor3 sunlight = sunlight_color;
00770 
00771         // Sunlight attenuation effect (hue and brightness) due to atmosphere
00772         // this is used later for sunlight modulation at various altitudes
00773         LLColor3 light_atten =
00774                 (blue_density * 1.0 + smear(haze_density * 0.25f)) * (density_multiplier * max_y);
00775 
00776         // Calculate relative weights
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         // Compute sunlight from P & lightnorm (for long rays like sky)
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         // Distance
00789         temp2.mV[2] = Plen * density_multiplier;
00790 
00791         // Transparency (-> temp1)
00792         temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]);
00793 
00794 
00795         // Compute haze glow
00796         temp2.mV[0] = Pn * LLVector3(lightnorm);
00797 
00798         temp2.mV[0] = 1.f - temp2.mV[0];
00799                 // temp2.x is 0 at the sun and increases away from sun
00800         temp2.mV[0] = llmax(temp2.mV[0], .001f);        
00801                 // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
00802         temp2.mV[0] *= glow.mV[0];
00803                 // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
00804         temp2.mV[0] = pow(temp2.mV[0], glow.mV[2]);
00805                 // glow.z should be negative, so we're doing a sort of (1 / "angle") function
00806 
00807         // Add "minimum anti-solar illumination"
00808         temp2.mV[0] += .25f;
00809 
00810 
00811         // Haze color above cloud
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         // Increase ambient when there are more clouds
00817         LLColor3 tmpAmbient = ambient + (LLColor3::white - ambient) * cloud_shadow * 0.5f;
00818 
00819         // Dim sunlight by cloud shadow percentage
00820         sunlight *= (1.f - cloud_shadow);
00821 
00822         // Haze color below cloud
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         // Final atmosphere additive
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         // Attenuate cloud color by atmosphere
00836         temp1 = componentSqrt(temp1);   //less atmos opacity (more transparency) below clouds
00837 
00838         // At horizon, blend high altitude sky color towards the darker color below the clouds
00839         vary_HazeColor +=
00840                 componentMult(additiveColorBelowCloud - vary_HazeColor, LLColor3::white - componentSqrt(temp1));
00841                 
00842         if (Pn[1] < 0.f)
00843         {
00844                 // Eric's original: 
00845                 // LLColor3 dark_brown(0.143f, 0.129f, 0.114f);
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                 // Initialize temp variables
00945                 LLColor3 sunlight = sunlight_color;
00946 
00947                 // Sunlight attenuation effect (hue and brightness) due to atmosphere
00948                 // this is used later for sunlight modulation at various altitudes
00949                 LLColor3 light_atten =
00950                         (blue_density * 1.0 + smear(haze_density * 0.25f)) * (density_multiplier * max_y);
00951 
00952                 // Calculate relative weights
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                 // Compute sunlight from P & lightnorm (for long rays like sky)
00960                 // temp2[1] = llmax(0.f, llmax(0.f, Pn[1]) * 1.0f + lightnorm[1] );
00961                 
00962                 // and vary_sunlight will work properly with moon light
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                 // Distance
00974                 temp2.mV[2] = density_multiplier;
00975 
00976                 // Transparency (-> temp1)
00977                 temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]);
00978 
00979                 // vary_AtmosAttenuation = temp1; 
00980 
00981                 //increase ambient when there are more clouds
00982                 LLColor3 tmpAmbient = ambient + (smear(1.f) - ambient) * cloud_shadow * 0.5f;
00983 
00984                 //haze color
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                 //brightness of surface both sunlight and ambient
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         // Since WL scales everything by 2, there should always be at least a 2:1 brightness ratio
01021         // between sunlight and point lights in windlight to normalize point lights.
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                 // It's dead.  Don't update it.
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                 // sInterpVal = (F32)next_frame / cycle_frame_no;
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                         // update the sky texture
01139                         for (S32 i = 0; i < 6; ++i)
01140                         {
01141                                 mSkyTex[i].create(1.0f);
01142                                 mShinyTex[i].create(1.0f);
01143                         }
01144                         
01145                         // update the environment map
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                         // *TODO: decide whether we need to update the stars vertex buffer in LLVOWLSky -Brad.
01159                         //gPipeline.markRebuild(gSky.mVOWLSkyp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
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 //by bao
01212 //fake vertex buffer updating
01213 //to guaranttee at least updating one VBO buffer every frame
01214 //to walk around the bug caused by ATI card --> DEV-3855
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 //end of fake vertex buffer updating
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; // 0/1 = Z axis, 2/3 = Y, 4/5 = X
01304                         S32 side_dir = side & 1;  // even - 0, odd - 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                         // Triangles for each side
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                 // LLWorld::getInstance()->getWaterHeight() + 0.01f;
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         //const static F32 cos_max_turn = sqrt(3.f) / 2; // 30 degrees
01424         //const F32 cos_turn_right = 1. / (llmax(cos_max_turn, hb_right * right));
01425         //const F32 cos_turn_up = 1. / llmax(cos_max_turn, hb_up * up);
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         // Parameters for the water reflection
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         // End of parameters for the water reflection
01435 
01436         const LLVector3 scaled_right = HEAVENLY_BODY_DIST * hb.getU();
01437         const LLVector3 scaled_up = HEAVENLY_BODY_DIST * hb.getV();
01438 
01439         //const LLVector3 scaled_right = horiz_enlargement * HEAVENLY_BODY_SCALE * hb.getDiskRadius() * hb_right;//right;
01440         //const LLVector3 scaled_up = vert_enlargement * HEAVENLY_BODY_SCALE * hb.getDiskRadius() * hb_up;//up;
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 // Clips quads with top and bottom sides parallel to horizon.
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         //const BOOL left_clip = (t_left > 0);
01530         //const BOOL right_clip = (t_right > 0);
01531 
01532         //if (!left_clip && !right_clip)
01533         {
01534                 for (S32 vtx = 0; vtx < 4; ++vtx)
01535                 {
01536                         v_clipped[vtx]  = v_corner[vtx];
01537                 }
01538         }
01539 /*      else
01540         {
01541                 v_clipped[0] = v_corner[0];
01542                 v_clipped[1] = left_clip ? ((1 - t_left) * v_corner[1] + t_left * v_corner[0])
01543                                                                         : v_corner[1];
01544                 v_clipped[2] = v_corner[2];
01545                 v_clipped[3] = right_clip ? ((1 - t_right) * v_corner[3] + t_right * v_corner[2])
01546                                                                         : v_corner[3];
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;   // v0 is cone origin and v1 is on the surface of the cone.
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         // const F32 water_height = gAgent.getRegion()->getWaterHeight() + 0.001f;
01698         // LLWorld::getInstance()->getWaterHeight() + 0.001f;
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         // finding angle between  look direction and sprite.
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         //const static F32 horizon_angle = acos(cos_horizon_angle);
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 *= /*cos_lookAt_toDir */ 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         //const F32 far_clip = (LLViewerCamera::getInstance()->getFar() - 0.01) / far_clip_factor;
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                 // whole thing is sprite: reflection is beyond far clip plane.
01839                 dt_clip = 1.1f;
01840                 quads = 1;
01841         }
01842         else if ((vtx_near2 = v_refl_corner[side+1].magVecSquared()) > far_clip2)
01843         {
01844                 // part is reflection, the rest is sprite.
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                 // whole thing is correct reflection.
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         // LLWorld::getInstance()->getWaterHeight();
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         // Sky colors, just slightly above the horizon in the direction of the sun, perpendicular to the sun, and at a 45 degree angle to the sun.
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         // We need to clamp these to non-zero, in order for the gamma correction to work. 0^y = ???
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                         // For now, set the density to extend to the cull distance.
02095                         const F32 f_log = 2.14596602628934723963618357029f; // sqrt(fabs(log(0.01f)))
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; // fabs(log(0.01f))
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                 // get the water param manager variables
02111                 float water_fog_density = LLWaterParamManager::instance()->getFogDensity();
02112                 LLColor4 water_fog_color = LLDrawPoolWater::sWaterFogColor.mV;
02113                 
02114                 // adjust the color based on depth.  We're doing linear approximations
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                 // set the gl fog color
02123                 glFogfv(GL_FOG_COLOR, (F32 *) &fogCol.mV);
02124                 mGLFogCol = fogCol;
02125 
02126                 // set the density based on what the shaders use
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 // static
02144 void LLHaze::initClass()
02145 {
02146         sAirScaSeaLevel = LLHaze::calcAirScaSeaLevel();
02147 }
02148 
02149 
02150 
02151 // Functions used a lot.
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 // Returns angle (RADIANs) between the horizontal projection of "v" and the x_axis.
02172 // Range of output is 0.0f to 2pi //359.99999...f
02173 // Returns 0.0f when "v" = +/- z_axis.
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;// 270.f;
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         // Push the sun "South" as it approaches directly overhead so that we can always see bump mapping
02229         // on the upward facing faces of cubes.
02230         LLVector3 newDir = sun_direction;
02231 
02232         // Same as dot product with the up direction + clamp.
02233         F32 sunDot = llmax(0.f, newDir.mV[2]);
02234         sunDot *= sunDot;       
02235 
02236         // Create normalized vector that has the sunDir pushed south about an hour and change.
02237         LLVector3 adjustedDir = (newDir + LLVector3(0.f, -0.70711f, 0.70711f)) * 0.5f;
02238 
02239         // Blend between normal sun dir and adjusted sun dir based on how close we are
02240         // to having the sun overhead.
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) { //the sun jumped a great deal, update immediately
02250                 mForceUpdate = TRUE;
02251         }
02252 }

Generated on Fri May 16 08:34:23 2008 for SecondLife by  doxygen 1.5.5