diff options
author | Brad Kittenbrink <brad@lindenlab.com> | 2008-02-27 18:58:14 +0000 |
---|---|---|
committer | Brad Kittenbrink <brad@lindenlab.com> | 2008-02-27 18:58:14 +0000 |
commit | 6d52efe452aa8469e0343da1c7d108f3f52ab651 (patch) | |
tree | a87be48e9840d7fc1f7ee514d7c7f994e71fdb3c /indra/newview/llvosky.cpp | |
parent | 6027ad2630b8650cabcf00628ee9b0d25bedd67f (diff) |
Merge of windlight into release (QAR-286). This includes all changes in
windlight14 which have passed QA (up through r79932).
svn merge -r 80831:80833 svn+ssh://svn.lindenlab.com/svn/linden/branches/merge_windlight14_r80620
Diffstat (limited to 'indra/newview/llvosky.cpp')
-rw-r--r-- | indra/newview/llvosky.cpp | 1505 |
1 files changed, 640 insertions, 865 deletions
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index b8d994d095..ba06083fd3 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -53,23 +53,29 @@ #include "llviewerregion.h" #include "llworld.h" #include "pipeline.h" +#include "lldrawpoolwlsky.h" +#include "llwlparammanager.h" +#include "llwaterparammanager.h" -const S32 NUM_TILES_X = 8; -const S32 NUM_TILES_Y = 4; -const S32 NUM_TILES = NUM_TILES_X * NUM_TILES_Y; +#undef min +#undef max + +static const S32 NUM_TILES_X = 8; +static const S32 NUM_TILES_Y = 4; +static const S32 NUM_TILES = NUM_TILES_X * NUM_TILES_Y; // Heavenly body constants -const F32 SUN_DISK_RADIUS = 0.5f; -const F32 MOON_DISK_RADIUS = SUN_DISK_RADIUS * 0.9f; -const F32 SUN_INTENSITY = 1e5; -const F32 SUN_DISK_INTENSITY = 24.f; +static const F32 SUN_DISK_RADIUS = 0.5f; +static const F32 MOON_DISK_RADIUS = SUN_DISK_RADIUS * 0.9f; +static const F32 SUN_INTENSITY = 1e5; +static const F32 SUN_DISK_INTENSITY = 24.f; // Texture coordinates: -const LLVector2 TEX00 = LLVector2(0.f, 0.f); -const LLVector2 TEX01 = LLVector2(0.f, 1.f); -const LLVector2 TEX10 = LLVector2(1.f, 0.f); -const LLVector2 TEX11 = LLVector2(1.f, 1.f); +static const LLVector2 TEX00 = LLVector2(0.f, 0.f); +static const LLVector2 TEX01 = LLVector2(0.f, 1.f); +static const LLVector2 TEX10 = LLVector2(1.f, 0.f); +static const LLVector2 TEX11 = LLVector2(1.f, 1.f); // Exported globals LLUUID gSunTextureID = IMG_SUN; @@ -134,7 +140,7 @@ private: F32 mTable[257]; // index 0 is unused }; -LLFastLn gFastLn; +static LLFastLn gFastLn; // Functions used a lot. @@ -163,42 +169,6 @@ inline LLColor3 color_norm(const LLColor3 &col) else return col; } -inline LLColor3 color_norm_fog(const LLColor3 &col) -{ - const F32 m = color_max(col); - if (m > 0.75f) - { - return 0.75f/m * col; - } - else return col; -} - - -inline LLColor4 color_norm_abs(const LLColor4 &col) -{ - const F32 m = color_max(col); - if (m > 1e-6) - { - return 1.f/m * col; - } - else - { - return col; - } -} - - -inline F32 color_intens ( const LLColor4 &col ) -{ - return col.mV[0] + col.mV[1] + col.mV[2]; -} - - -inline F32 color_avg ( const LLColor3 &col ) -{ - return color_intens(col) / 3.f; -} - inline void color_gamma_correct(LLColor3 &col) { const F32 gamma_inv = 1.f/1.2f; @@ -216,164 +186,6 @@ inline void color_gamma_correct(LLColor3 &col) } } -inline F32 min_intens_factor( LLColor3& col, F32 min_intens, BOOL postmultiply = FALSE); -inline F32 min_intens_factor( LLColor3& col, F32 min_intens, BOOL postmultiply) -{ - const F32 intens = color_intens(col); - F32 factor = 1; - if (0 == intens) - { - return 0; - } - - if (intens < min_intens) - { - factor = min_intens / intens; - if (postmultiply) - col *= factor; - } - return factor; -} - -inline LLVector3 move_vec(const LLVector3& v, const F32 cos_max_angle) -{ - LLVector3 v_norm = v; - v_norm.normVec(); - - LLVector2 v_norm_proj(v_norm.mV[0], v_norm.mV[1]); - const F32 projection2 = v_norm_proj.magVecSquared(); - const F32 scale = sqrt((1 - cos_max_angle * cos_max_angle) / projection2); - return LLVector3(scale * v_norm_proj.mV[0], scale * v_norm_proj.mV[1], cos_max_angle); -} - - -/*************************************** - Transparency Map -***************************************/ - -void LLTranspMap::init(const F32 elev, const F32 step, const F32 h, const LLHaze* const haze) -{ - mHaze = haze; - mAtmHeight = h; - mElevation = elev; - mStep = step; - mStepInv = 1.f / step; - F32 sin_angle = EARTH_RADIUS/(EARTH_RADIUS + mElevation); - mCosMaxAngle = -sqrt(1 - sin_angle * sin_angle); - mMapSize = S32(ceil((1 - mCosMaxAngle) * mStepInv + 1) + 0.5); - delete mT; - mT = new LLColor3[mMapSize]; - - for (S32 i = 0; i < mMapSize; ++i) - { - const F32 cos_a = 1 - i*mStep; - const LLVector3 dir(0, sqrt(1-cos_a*cos_a), cos_a); - mT[i] = calcAirTranspDir(mElevation, dir); - } -} - - - -LLColor3 LLTranspMap::calcAirTranspDir(const F32 elevation, const LLVector3 &dir) const -{ - LLColor3 opt_depth(0, 0, 0); - const LLVector3 point(0, 0, EARTH_RADIUS + elevation); - F32 dist = -dir * point; - LLVector3 cur_point; - S32 s; - - if (dist > 0) - { - cur_point = point + dist * dir; -// const F32 K = log(dist * INV_FIRST_STEP + 1) * INV_NO_STEPS; -// const F32 e_pow_k = LL_FAST_EXP(K); - const F32 e_pow_k = gFastLn.pow( dist * INV_FIRST_STEP + 1, INV_NO_STEPS ); - F32 step = FIRST_STEP * (1 - 1 / e_pow_k); - - for (s = 0; s < NO_STEPS; ++s) - { - const F32 h = cur_point.magVec() - EARTH_RADIUS; - step *= e_pow_k; - opt_depth += calcSigExt(h) * step; - cur_point -= dir * step; - } - opt_depth *= 2; - cur_point = point + 2 * dist * dir; - } - else - { - cur_point = point; - } - - dist = hitsAtmEdge(cur_point, dir); -// const F32 K = log(dist * INV_FIRST_STEP + 1) * INV_NO_STEPS; -// const F32 e_pow_k = LL_FAST_EXP(K); - const F32 e_pow_k = gFastLn.pow( dist * INV_FIRST_STEP + 1, INV_NO_STEPS ); - F32 step = FIRST_STEP * (1 - 1 / e_pow_k); - - for (s = 0; s < NO_STEPS; ++s) - { - const F32 h = cur_point.magVec() - EARTH_RADIUS; - step *= e_pow_k; - opt_depth += calcSigExt(h) * step; - cur_point += dir * step; - } - - opt_depth *= -4.0f*F_PI; - opt_depth.exp(); - return opt_depth; -} - - - -F32 LLTranspMap::hitsAtmEdge(const LLVector3& X, const LLVector3& dir) const -{ - const F32 tca = -dir * X; - const F32 R = EARTH_RADIUS + mAtmHeight; - const F32 thc2 = R * R - X.magVecSquared() + tca * tca; - return tca + sqrt ( thc2 ); -} - - - - - -void LLTranspMapSet::init(const S32 size, const F32 first_step, const F32 media_height, const LLHaze* const haze) -{ - const F32 angle_step = 0.005f; - mSize = size; - mMediaHeight = media_height; - - delete[] mTransp; - mTransp = new LLTranspMap[mSize]; - - delete[] mHeights; - mHeights = new F32[mSize]; - - F32 h = 0; - mHeights[0] = h; - mTransp[0].init(h, angle_step, mMediaHeight, haze); - const F32 K = log(mMediaHeight / first_step + 1) / (mSize - 1); - const F32 e_pow_k = exp(K); - F32 step = first_step * (e_pow_k - 1); - - for (S32 s = 1; s < mSize; ++s) - { - h += step; - mHeights[s] = h; - mTransp[s].init(h, angle_step, mMediaHeight, haze); - step *= e_pow_k; - } -} - -LLTranspMapSet::~LLTranspMapSet() -{ - delete[] mTransp; - mTransp = NULL; - delete[] mHeights; - mHeights = NULL; -} - /*************************************** @@ -392,7 +204,7 @@ LLSkyTex::LLSkyTex() void LLSkyTex::init() { - mSkyData = new LLColor3[sResolution * sResolution]; + mSkyData = new LLColor4[sResolution * sResolution]; mSkyDirs = new LLVector3[sResolution * sResolution]; for (S32 i = 0; i < 2; ++i) @@ -451,9 +263,9 @@ void LLSkyTex::initEmpty(const S32 tex) createGLImage(tex); } - -void LLSkyTex::create(const F32 brightness_scale, const LLColor3& multiscatt) +void LLSkyTex::create(const F32 brightness) { + /// Brightness ignored for now. U8* data = mImageRaw[sCurrent]->getData(); for (S32 i = 0; i < sResolution; ++i) { @@ -461,23 +273,17 @@ void LLSkyTex::create(const F32 brightness_scale, const LLColor3& multiscatt) { const S32 basic_offset = (i * sResolution + j); S32 offset = basic_offset * sComponents; - LLColor3 col(mSkyData[basic_offset]); - if (getDir(i, j).mV[VZ] >= -0.02f) { - col += 0.1f * multiscatt; - col *= brightness_scale; - col.clamp(); - color_gamma_correct(col); - } - U32* pix = (U32*)(data + offset); - LLColor4 temp = LLColor4(col, 0); - LLColor4U temp1 = LLColor4U(temp); - *pix = temp1.mAll; + LLColor4U temp = LLColor4U(mSkyData[basic_offset]); + *pix = temp.mAll; } } createGLImage(sCurrent); } + + + void LLSkyTex::createGLImage(S32 which) { mImageGL[which]->createGLTexture(0, mImageRaw[which]); @@ -495,8 +301,6 @@ void LLSkyTex::bindTexture(BOOL curr) F32 LLHeavenBody::sInterpVal = 0; -F32 LLVOSky::sNighttimeBrightness = 1.5f; - S32 LLVOSky::sResolution = LLSkyTex::getResolution(); S32 LLVOSky::sTileResX = sResolution/NUM_TILES_X; S32 LLVOSky::sTileResY = sResolution/NUM_TILES_Y; @@ -511,8 +315,32 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) mCloudDensity(0.2f), mWind(0.f), mForceUpdate(FALSE), - mWorldScale(1.f) + mWorldScale(1.f), + mBumpSunDir(0.f, 0.f, 1.f) { + bool error = false; + + /// WL PARAMS + dome_radius = 1.f; + dome_offset_ratio = 0.f; + sunlight_color = LLColor3(); + ambient = LLColor3(); + gamma = 1.f; + lightnorm = LLVector4(); + blue_density = LLColor3(); + blue_horizon = LLColor3(); + haze_density = 0.f; + haze_horizon = LLColor3(); + density_multiplier = 0.f; + max_y = 0.f; + glow = LLColor3(); + cloud_shadow = 0.f; + cloud_color = LLColor3(); + cloud_scale = 0.f; + cloud_pos_density1 = LLColor3(); + cloud_pos_density2 = LLColor3(); + + mInitialized = FALSE; mbCanSelect = FALSE; mUpdateTimer.reset(); @@ -520,6 +348,7 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) for (S32 i = 0; i < 6; i++) { mSkyTex[i].init(); + mShinyTex[i].init(); } for (S32 i=0; i<FACE_COUNT; i++) { @@ -529,9 +358,8 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) mCameraPosAgent = gAgent.getCameraPositionAgent(); mAtmHeight = ATM_HEIGHT; mEarthCenter = LLVector3(mCameraPosAgent.mV[0], mCameraPosAgent.mV[1], -EARTH_RADIUS); - updateHaze(); - mSunDefaultPosition = gSavedSettings.getVector3("SkySunDefaultPosition"); + mSunDefaultPosition = LLVector3(LLWLParamManager::instance()->mCurParams.getVector("lightnorm", error)); if (gSavedSettings.getBOOL("SkyOverrideSimSunPosition")) { initSunDirection(mSunDefaultPosition, LLVector3(0, 0, 0)); @@ -551,6 +379,8 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) mMoonTexturep->setClamp(TRUE, TRUE); mBloomTexturep = gImageList.getImage(IMG_BLOOM1); mBloomTexturep->setClamp(TRUE, TRUE); + + mHeavenlyBodyUpdated = FALSE ; } @@ -570,14 +400,11 @@ void LLVOSky::initClass() void LLVOSky::init() { - // index of refraction calculation. - mTransp.init(NO_STEPS+1+4, FIRST_STEP, mAtmHeight, &mHaze); - - const F32 haze_int = color_intens(mHaze.calcSigSca(0)); + const F32 haze_int = color_intens(mHaze.calcSigSca(0)); mHazeConcentration = haze_int / (color_intens(LLHaze::calcAirSca(0)) + haze_int); - mBrightnessScaleNew = 0; + calcAtmospherics(); // Initialize the cached normalized direction vectors for (S32 side = 0; side < 6; ++side) @@ -589,8 +416,16 @@ void LLVOSky::init() } } - calcBrightnessScaleAndColors(); + for (S32 i = 0; i < 6; ++i) + { + mSkyTex[i].create(1.0f); + mShinyTex[i].create(1.0f); + } + initCubeMap(); + mInitialized = true; + + mHeavenlyBodyUpdated = FALSE ; } void LLVOSky::initCubeMap() @@ -598,7 +433,7 @@ void LLVOSky::initCubeMap() std::vector<LLPointer<LLImageRaw> > images; for (S32 side = 0; side < 6; side++) { - images.push_back(mSkyTex[side].getImageRaw()); + images.push_back(mShinyTex[side].getImageRaw()); } if (mCubeMap) { @@ -639,7 +474,7 @@ void LLVOSky::restoreGL() mBloomTexturep = gImageList.getImage(IMG_BLOOM1); mBloomTexturep->setClamp(TRUE, TRUE); - calcBrightnessScaleAndColors(); + calcAtmospherics(); if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && gFeatureManagerp->isFeatureAvailable("RenderCubeMap")) @@ -649,7 +484,7 @@ void LLVOSky::restoreGL() std::vector<LLPointer<LLImageRaw> > images; for (S32 side = 0; side < 6; side++) { - images.push_back(mSkyTex[side].getImageRaw()); + images.push_back(mShinyTex[side].getImageRaw()); } if(cube_map) @@ -666,67 +501,6 @@ void LLVOSky::restoreGL() } - -void LLVOSky::updateHaze() -{ - static LLRandLagFib607 weather_generator(LLUUID::getRandomSeed()); - if (gSavedSettings.getBOOL("FixedWeather")) - { - weather_generator.seed(8008135); - } - - const F32 fo_upper_bound = 5; - const F32 sca_upper_bound = 6; - const F32 fo = 1 + (F32)weather_generator() *(fo_upper_bound - 1); - const static F32 upper = 0.5f / gFastLn.ln(fo_upper_bound); - mHaze.setFalloff(fo); - mHaze.setG((F32)weather_generator() * (0.0f + upper * gFastLn.ln(fo))); - LLColor3 sca; - const F32 cd = mCloudDensity * 3; - F32 min_r = cd - 1; - if (min_r < 0) - { - min_r = 0; - } - F32 max_r = cd + 1; - if (max_r > sca_upper_bound) - { - max_r = sca_upper_bound; - } - - sca.mV[0] = min_r + (F32)weather_generator() * (max_r - min_r); - - min_r = sca.mV[0] - 0.1f; - if (min_r < 0) - { - min_r = 0; - } - max_r = sca.mV[0] + 0.5f; - if (max_r > sca_upper_bound) - { - max_r = sca_upper_bound; - } - - sca.mV[1] = min_r + (F32)weather_generator() * (max_r - min_r); - - min_r = sca.mV[1]; - if (min_r < 0) - { - min_r = 0; - } - max_r = sca.mV[1] + 1; - if (max_r > sca_upper_bound) - { - max_r = sca_upper_bound; - } - - sca.mV[2] = min_r + (F32)weather_generator() * (max_r - min_r); - - sca = AIR_SCA_AVG * sca; - - mHaze.setSigSca(sca); -} - void LLVOSky::initSkyTextureDirs(const S32 side, const S32 tile) { S32 tile_x = tile % NUM_TILES_X; @@ -754,6 +528,7 @@ void LLVOSky::initSkyTextureDirs(const S32 side, const S32 tile) LLVector3 dir(coeff[0], coeff[1], coeff[2]); dir.normVec(); mSkyTex[side].setDir(dir, x, y); + mShinyTex[side].setDir(dir, x, y); } } } @@ -772,404 +547,491 @@ void LLVOSky::createSkyTexture(const S32 side, const S32 tile) for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x) { mSkyTex[side].setPixel(calcSkyColorInDir(mSkyTex[side].getDir(x, y)), x, y); + mShinyTex[side].setPixel(calcSkyColorInDir(mSkyTex[side].getDir(x, y), true), x, y); } } } - -LLColor3 LLVOSky::calcSkyColorInDir(const LLVector3 &dir) +static inline LLColor3 componentDiv(LLColor3 const &left, LLColor3 const & right) { - LLColor3 col, transp; - - if (dir.mV[VZ] < -0.02f) - { - col = LLColor3(llmax(mFogColor[0],0.2f), llmax(mFogColor[1],0.2f), llmax(mFogColor[2],0.27f)); - float x = 1.0f-fabsf(-0.1f-dir.mV[VZ]); - x *= x; - col.mV[0] *= x*x; - col.mV[1] *= powf(x, 2.5f); - col.mV[2] *= x*x*x; - return col; - } + return LLColor3(left.mV[0]/right.mV[0], + left.mV[1]/right.mV[1], + left.mV[2]/right.mV[2]); +} - calcSkyColorInDir(col, transp, dir); - F32 br = color_max(col); - if (br > mBrightnessScaleNew) - { - mBrightnessScaleNew = br; - mBrightestPointNew = col; - } - return col; +static inline LLColor3 componentMult(LLColor3 const &left, LLColor3 const & right) +{ + return LLColor3(left.mV[0]*right.mV[0], + left.mV[1]*right.mV[1], + left.mV[2]*right.mV[2]); } -LLColor4 LLVOSky::calcInScatter(LLColor4& transp, const LLVector3 &point, F32 exager = 1) const +static inline LLColor3 componentExp(LLColor3 const &v) { - LLColor3 col, tr; - calcInScatter(col, tr, point, exager); - col *= mBrightnessScaleGuess; - transp = LLColor4(tr); - return LLColor4(col); + return LLColor3(exp(v.mV[0]), + exp(v.mV[1]), + exp(v.mV[2])); } +static inline LLColor3 componentPow(LLColor3 const &v, F32 exponent) +{ + return LLColor3(pow(v.mV[0], exponent), + pow(v.mV[1], exponent), + pow(v.mV[2], exponent)); +} - -void LLVOSky::calcSkyColorInDir(LLColor3& res, LLColor3& transp, const LLVector3& dir) const +static inline LLColor3 componentSaturate(LLColor3 const &v) { - const LLVector3& tosun = getToSunLast(); - res.setToBlack(); - LLColor3 haze_res(0.f, 0.f, 0.f); - transp.setToWhite(); - LLVector3 step_v ; - LLVector3 cur_pos = mCameraPosAgent; - F32 h; - - F32 dist = calcHitsAtmEdge(mCameraPosAgent, dir); -// const F32 K = log(dist / FIRST_STEP + 1) / NO_STEPS; - const F32 K = gFastLn.ln(dist / FIRST_STEP + 1) / NO_STEPS; - const F32 e_pow_k = (F32)LL_FAST_EXP(K); - F32 step = FIRST_STEP * (1 - 1 / e_pow_k); - - // Initialize outside the loop because we write into them every iteration. JC - LLColor3 air_sca_opt_depth; - LLColor3 haze_sca_opt_depth; - LLColor3 air_transp; - - for (S32 s = 0; s < NO_STEPS; ++s) - { - h = calcHeight(cur_pos); - step *= e_pow_k; - LLHaze::calcAirSca(h, air_sca_opt_depth); - air_sca_opt_depth *= step; - - mHaze.calcSigSca(h, haze_sca_opt_depth); - haze_sca_opt_depth *= step; - - LLColor3 haze_ext_opt_depth = haze_sca_opt_depth; - haze_ext_opt_depth *= (1.f + mHaze.getAbsCoef()); - - if (calcHitsEarth(cur_pos, tosun) < 0) // calculates amount of in-scattered light from the sun - { - //visibility check is too expensive - mTransp.calcTransp(calcUpVec(cur_pos) * tosun, h, air_transp); - air_transp *= transp; - res += air_sca_opt_depth * air_transp; - haze_res += haze_sca_opt_depth * air_transp; - } - LLColor3 temp(-4.f * F_PI * (air_sca_opt_depth + haze_ext_opt_depth)); - temp.exp(); - transp *= temp; - step_v = dir * step; - cur_pos += step_v; - } - const F32 cos_dir = dir * tosun; - res *= calcAirPhaseFunc(cos_dir); - res += haze_res * mHaze.calcPhase(cos_dir); - res *= mSun.getIntensity(); + return LLColor3(std::max(std::min(v.mV[0], 1.f), 0.f), + std::max(std::min(v.mV[1], 1.f), 0.f), + std::max(std::min(v.mV[2], 1.f), 0.f)); } +static inline LLColor3 componentSqrt(LLColor3 const &v) +{ + return LLColor3(sqrt(v.mV[0]), + sqrt(v.mV[1]), + sqrt(v.mV[2])); +} +static inline void componentMultBy(LLColor3 & left, LLColor3 const & right) +{ + left.mV[0] *= right.mV[0]; + left.mV[1] *= right.mV[1]; + left.mV[2] *= right.mV[2]; +} -void LLVOSky::calcInScatter(LLColor3& res, LLColor3& transp, - const LLVector3& P, const F32 exaggeration) const +static inline LLColor3 colorMix(LLColor3 const & left, LLColor3 const & right, F32 amount) { - const LLVector3& tosun = getToSunLast(); - res.setToBlack(); - transp.setToWhite(); + return (left + ((right - left) * amount)); +} - LLVector3 lower, upper; - LLVector3 dir = P - mCameraPosAgent; +static inline F32 texture2D(LLPointer<LLImageRaw> const & tex, LLVector2 const & uv) +{ + U16 w = tex->getWidth(); + U16 h = tex->getHeight(); - F32 dist = exaggeration * dir.normVec(); + U16 r = U16(uv[0] * w) % w; + U16 c = U16(uv[1] * h) % h; - const F32 cos_dir = dir * tosun; + U8 const * imageBuffer = tex->getData(); - if (dir.mV[VZ] > 0) - { - lower = mCameraPosAgent; - upper = P; - } - else - { - lower = P; - upper = mCameraPosAgent; - dir = -dir; - } + U8 sample = imageBuffer[r * w + c]; - const F32 lower_h = calcHeight(lower); - const F32 upper_h = calcHeight(upper); - const LLVector3 up_upper = calcUpVec(upper); - const LLVector3 up_lower = calcUpVec(lower); + return sample / 255.f; +} + +static inline LLColor3 smear(F32 val) +{ + return LLColor3(val, val, val); +} - transp = color_div(mTransp.calcTransp(up_lower * dir, lower_h), - mTransp.calcTransp(up_upper * dir, upper_h)); - color_pow(transp, exaggeration); +void LLVOSky::initAtmospherics(void) +{ + bool error; + + // uniform parameters for convenience + dome_radius = LLWLParamManager::instance()->getDomeRadius(); + dome_offset_ratio = LLWLParamManager::instance()->getDomeOffset(); + sunlight_color = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("sunlight_color", error)); + ambient = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("ambient", error)); + //lightnorm = LLWLParamManager::instance()->mCurParams.getVector("lightnorm", error); + gamma = LLWLParamManager::instance()->mCurParams.getVector("gamma", error)[0]; + blue_density = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("blue_density", error)); + blue_horizon = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("blue_horizon", error)); + haze_density = LLWLParamManager::instance()->mCurParams.getVector("haze_density", error)[0]; + haze_horizon = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("haze_horizon", error)); + density_multiplier = LLWLParamManager::instance()->mCurParams.getVector("density_multiplier", error)[0]; + max_y = LLWLParamManager::instance()->mCurParams.getVector("max_y", error)[0]; + glow = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("glow", error)); + cloud_shadow = LLWLParamManager::instance()->mCurParams.getVector("cloud_shadow", error)[0]; + cloud_color = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("cloud_color", error)); + cloud_scale = LLWLParamManager::instance()->mCurParams.getVector("cloud_scale", error)[0]; + cloud_pos_density1 = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("cloud_pos_density1", error)); + cloud_pos_density2 = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("cloud_pos_density2", error)); + + // light norm is different. We need the sun's direction, not the light direction + // which could be from the moon. And we need to clamp it + // just like for the gpu + LLVector3 sunDir = gSky.getSunDirection(); + + // CFR_TO_OGL + lightnorm = LLVector4(sunDir.mV[1], sunDir.mV[2], sunDir.mV[0], 0); + unclamped_lightnorm = lightnorm; + if(lightnorm.mV[1] < -0.1f) + { + lightnorm.mV[1] = -0.1f; + } + +} - if (calcHitsEarth(upper, tosun) > 0) +LLColor4 LLVOSky::calcSkyColorInDir(const LLVector3 &dir, bool isShiny) +{ + F32 saturation = 0.3f; + if (dir.mV[VZ] < -0.02f) { - const F32 avg = color_avg(transp); - //const F32 avg = llmin(1.f, 1.2f * color_avg(transp)); - transp.setVec(avg, avg, avg); - return; + LLColor4 col = LLColor4(llmax(mFogColor[0],0.2f), llmax(mFogColor[1],0.2f), llmax(mFogColor[2],0.22f),0.f); + if (isShiny) + { + LLColor3 desat_fog = LLColor3(mFogColor); + F32 brightness = desat_fog.brightness(); + // So that shiny somewhat shows up at night. + if (brightness < 0.15f) + { + brightness = 0.15f; + desat_fog = smear(0.15f); + } + LLColor3 greyscale = smear(brightness); + desat_fog = desat_fog * saturation + greyscale * (1.0f - saturation); + if (!gPipeline.canUseWindLightShaders()) + { + col = LLColor4(desat_fog, 0.f); + } + else + { + col = LLColor4(desat_fog * 0.5f, 0.f); + } + } + float x = 1.0f-fabsf(-0.1f-dir.mV[VZ]); + x *= x; + col.mV[0] *= x*x; + col.mV[1] *= powf(x, 2.5f); + col.mV[2] *= x*x*x; + return col; } - LLColor3 air_sca_opt_depth = LLHaze::calcAirSca(upper_h); - LLColor3 haze_sca_opt_depth = mHaze.calcSigSca(upper_h); - LLColor3 sun_transp; - mTransp.calcTransp(up_upper * tosun, upper_h, sun_transp); + // undo OGL_TO_CFR_ROTATION and negate vertical direction. + LLVector3 Pn = LLVector3(-dir[1] , -dir[2], -dir[0]); - if (calcHitsEarth(lower, tosun) < 0) + LLColor3 vary_HazeColor(0,0,0); + LLColor3 vary_CloudColorSun(0,0,0); + LLColor3 vary_CloudColorAmbient(0,0,0); + F32 vary_CloudDensity(0); + LLVector2 vary_HorizontalProjection[2]; + vary_HorizontalProjection[0] = LLVector2(0,0); + vary_HorizontalProjection[1] = LLVector2(0,0); + + calcSkyColorWLVert(Pn, vary_HazeColor, vary_CloudColorSun, vary_CloudColorAmbient, + vary_CloudDensity, vary_HorizontalProjection); + + LLColor3 sky_color = calcSkyColorWLFrag(Pn, vary_HazeColor, vary_CloudColorSun, vary_CloudColorAmbient, + vary_CloudDensity, vary_HorizontalProjection); + if (isShiny) { - air_sca_opt_depth += LLHaze::calcAirSca(lower_h); - air_sca_opt_depth *= 0.5; - haze_sca_opt_depth += mHaze.calcSigSca(lower_h); - haze_sca_opt_depth *= 0.5; - sun_transp += mTransp.calcTransp(up_lower * tosun, lower_h); - sun_transp *= 0.5; + F32 brightness = sky_color.brightness(); + LLColor3 greyscale = smear(brightness); + sky_color = sky_color * saturation + greyscale * (1.0f - saturation); + sky_color *= (0.5f + 0.5f * brightness); } - - res = calcAirPhaseFunc(cos_dir) * air_sca_opt_depth; - res += mHaze.calcPhase(cos_dir) * haze_sca_opt_depth; - res = mSun.getIntensity() * dist * sun_transp * res; + return LLColor4(sky_color, 0.0f); } +// turn on floating point precision +// in vs2003 for this function. Otherwise +// sky is aliased looking 7:10 - 8:50 +#if LL_MSVC && __MSVC_VER__ < 8 +#pragma optimize("p", on) +#endif +void LLVOSky::calcSkyColorWLVert(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLColor3 & vary_CloudColorSun, + LLColor3 & vary_CloudColorAmbient, F32 & vary_CloudDensity, + LLVector2 vary_HorizontalProjection[2]) +{ + // project the direction ray onto the sky dome. + F32 phi = acos(Pn[1]); + F32 sinA = sin(F_PI - phi); + F32 Plen = dome_radius * sin(F_PI + phi + asin(dome_offset_ratio * sinA)) / sinA; + Pn *= Plen; + vary_HorizontalProjection[0] = LLVector2(Pn[0], Pn[2]); + vary_HorizontalProjection[0] /= - 2.f * Plen; - -F32 LLVOSky::calcHitsEarth(const LLVector3& orig, const LLVector3& dir) const -{ - const LLVector3 from_earth_center = mEarthCenter - orig; - const F32 tca = dir * from_earth_center; - if ( tca < 0 ) + // Set altitude + if (Pn[1] > 0.f) { - return -1; + Pn *= (max_y / Pn[1]); } - - const F32 thc2 = EARTH_RADIUS * EARTH_RADIUS - - from_earth_center.magVecSquared() + tca * tca; - if (thc2 < 0 ) + else { - return -1; + Pn *= (-32000.f / Pn[1]); } - return tca - sqrt ( thc2 ); -} + Plen = Pn.magVec(); + Pn /= Plen; -F32 LLVOSky::calcHitsAtmEdge(const LLVector3& orig, const LLVector3& dir) const -{ - const LLVector3 from_earth_center = mEarthCenter - orig; - const F32 tca = dir * from_earth_center; + // Initialize temp variables + LLColor3 sunlight = sunlight_color; - const F32 thc2 = (EARTH_RADIUS + mAtmHeight) * (EARTH_RADIUS + mAtmHeight) - - from_earth_center.magVecSquared() + tca * tca; - return tca + sqrt(thc2); -} + // Sunlight attenuation effect (hue and brightness) due to atmosphere + // this is used later for sunlight modulation at various altitudes + LLColor3 light_atten = + (blue_density * 1.0 + smear(haze_density * 0.25f)) * (density_multiplier * max_y); + // Calculate relative weights + LLColor3 temp2(0.f, 0.f, 0.f); + LLColor3 temp1 = blue_density + smear(haze_density); + LLColor3 blue_weight = componentDiv(blue_density, temp1); + LLColor3 haze_weight = componentDiv(smear(haze_density), temp1); -void LLVOSky::updateBrightestDir() -{ - LLColor3 br_pt, transp; - const S32 test_no = 5; - const F32 step = F_PI_BY_TWO / (test_no + 1); - for (S32 i = 0; i < test_no; ++i) - { - F32 cos_dir = cos ((i + 1) * step); - calcSkyColorInDir(br_pt, transp, move_vec(getToSunLast(), cos_dir)); - const F32 br = color_max(br_pt); - if (br > mBrightnessScaleGuess) - { - mBrightnessScaleGuess = br; - mBrightestPointGuess = br_pt; - } - } -} + // Compute sunlight from P & lightnorm (for long rays like sky) + temp2.mV[1] = llmax(F_APPROXIMATELY_ZERO, llmax(0.f, Pn[1]) * 1.0f + lightnorm[1] ); + temp2.mV[1] = 1.f / temp2.mV[1]; + componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1])); -void LLVOSky::calcBrightnessScaleAndColors() -{ - // new correct normalization. - if (mBrightnessScaleNew < 1e-7) - { - mBrightnessScale = 1; - mBrightestPoint.setToBlack(); - } - else - { - mBrightnessScale = 1.f/mBrightnessScaleNew; - mBrightestPoint = mBrightestPointNew; - } + // Distance + temp2.mV[2] = Plen * density_multiplier; - mBrightnessScaleNew = 0; - // and addition + // Transparency (-> temp1) + temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]); - // Calculate Sun and Moon color - const F32 h = llmax(0.0f, mCameraPosAgent.mV[2]); - const LLColor3 sun_color = mSun.getIntensity() * mTransp.calcTransp(getToSunLast().mV[2], h); - const LLColor3 moon_color = mNightColorShift * - mMoon.getIntensity() * mTransp.calcTransp(getToMoonLast().mV[2], h); - F32 intens = color_intens(sun_color); - F32 increase_sun_br = (intens > 0) ? 1.2f * color_intens(mBrightestPoint) / intens : 1; + // Compute haze glow + temp2.mV[0] = Pn * LLVector3(lightnorm); - intens = color_intens(moon_color); - F32 increase_moon_br = (intens > 0) ? 1.2f * llmax(1.0f, color_intens(mBrightestPoint) / intens) : 1; + temp2.mV[0] = 1.f - temp2.mV[0]; + // temp2.x is 0 at the sun and increases away from sun + temp2.mV[0] = llmax(temp2.mV[0], .001f); + // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) + temp2.mV[0] *= glow.mV[0]; + // Higher glow.x gives dimmer glow (because next step is 1 / "angle") + temp2.mV[0] = pow(temp2.mV[0], glow.mV[2]); + // glow.z should be negative, so we're doing a sort of (1 / "angle") function - mSun.setColor(mBrightnessScale * increase_sun_br * sun_color); - mMoon.setColor(mBrightnessScale * increase_moon_br * moon_color); + // Add "minimum anti-solar illumination" + temp2.mV[0] += .25f; - const LLColor3 haze_col = color_norm_abs(mHaze.getSigSca()); - for (S32 i = 0; i < 6; ++i) - { - mSkyTex[i].create(mBrightnessScale, mHazeConcentration * mBrightestPoint * haze_col); - } - mBrightnessScaleGuess = mBrightnessScale; - mBrightestPointGuess = mBrightestPoint; + // Haze color above cloud + vary_HazeColor = (blue_horizon * blue_weight * (sunlight + ambient) + + componentMult(haze_horizon.mV[0] * haze_weight, sunlight * temp2.mV[0] + ambient) + ); -// calculateColors(); // MSMSM Moving this down to before generateScatterMap(), per Milo Lindens suggestion, to fix orange flashing bug. + // Increase ambient when there are more clouds + LLColor3 tmpAmbient = ambient + (LLColor3::white - ambient) * cloud_shadow * 0.5f; - mSun.renewDirection(); - mSun.renewColor(); - mMoon.renewDirection(); - mMoon.renewColor(); + // Dim sunlight by cloud shadow percentage + sunlight *= (1.f - cloud_shadow); - LLColor3 transp; + // Haze color below cloud + LLColor3 additiveColorBelowCloud = (blue_horizon * blue_weight * (sunlight + tmpAmbient) + + componentMult(haze_horizon.mV[0] * haze_weight, sunlight * temp2.mV[0] + tmpAmbient) + ); - if (calcHitsEarth(mCameraPosAgent, getToSunLast()) < 0) - { - calcSkyColorInDir(mBrightestPointGuess, transp, getToSunLast()); - mBrightnessScaleGuess = color_max(mBrightestPointGuess); - updateBrightestDir(); - mBrightnessScaleGuess = 1.f / llmax(1.0f, mBrightnessScaleGuess); - } - else if (getToSunLast().mV[2] > -0.5) - { - const LLVector3 almost_to_sun = toHorizon(getToSunLast()); - calcSkyColorInDir(mBrightestPointGuess, transp, almost_to_sun); - mBrightnessScaleGuess = color_max(mBrightestPointGuess); - updateBrightestDir(); - mBrightnessScaleGuess = 1.f / llmax(1.0f, mBrightnessScaleGuess); - } - else + // Final atmosphere additive + componentMultBy(vary_HazeColor, LLColor3::white - temp1); + + sunlight = sunlight_color; + temp2.mV[1] = llmax(0.f, lightnorm[1] * 2.f); + temp2.mV[1] = 1.f / temp2.mV[1]; + componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1])); + + // Attenuate cloud color by atmosphere + temp1 = componentSqrt(temp1); //less atmos opacity (more transparency) below clouds + + // At horizon, blend high altitude sky color towards the darker color below the clouds + vary_HazeColor += + componentMult(additiveColorBelowCloud - vary_HazeColor, LLColor3::white - componentSqrt(temp1)); + + if (Pn[1] < 0.f) { - mBrightestPointGuess.setToBlack(); - mBrightnessScaleGuess = 1; - } + // Eric's original: + // LLColor3 dark_brown(0.143f, 0.129f, 0.114f); + LLColor3 dark_brown(0.082f, 0.076f, 0.066f); + LLColor3 brown(0.430f, 0.386f, 0.322f); + LLColor3 sky_lighting = sunlight + ambient; + F32 haze_brightness = vary_HazeColor.brightness(); - calculateColors(); // MSMSM Moved this down here per Milo Lindens suggestion, to fix orange flashing bug at sunset. + if (Pn[1] < -0.05f) + { + vary_HazeColor = colorMix(dark_brown, brown, -Pn[1] * 0.9f) * sky_lighting * haze_brightness; + } + + if (Pn[1] > -0.1f) + { + vary_HazeColor = colorMix(LLColor3::white * haze_brightness, vary_HazeColor, fabs((Pn[1] + 0.05f) * -20.f)); + } + } } +#if LL_MSVC && __MSVC_VER__ < 8 +#pragma optimize("p", off) +#endif -void LLVOSky::calculateColors() +LLColor3 LLVOSky::calcSkyColorWLFrag(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLColor3 & vary_CloudColorSun, + LLColor3 & vary_CloudColorAmbient, F32 & vary_CloudDensity, + LLVector2 vary_HorizontalProjection[2]) { - const F32 h = -0.1f; - const LLVector3& tosun = getToSunLast(); + LLColor3 res; - F32 full_on, full_off, on, on_cl; - F32 sun_factor = 1; + LLColor3 color0 = vary_HazeColor; - // Sun Diffuse - F32 sun_height = tosun.mV[2]; + if (!gPipeline.canUseWindLightShaders()) + { + LLColor3 color1 = color0 * 2.0f; + color1 = smear(1.f) - componentSaturate(color1); + componentPow(color1, gamma); + res = smear(1.f) - color1; + } + else + { + res = color0; + } + +# ifndef LL_RELEASE_FOR_DOWNLOAD + + LLColor3 color2 = 2.f * color0; + + LLColor3 color3 = LLColor3(1.f, 1.f, 1.f) - componentSaturate(color2); + componentPow(color3, gamma); + color3 = LLColor3(1.f, 1.f, 1.f) - color3; + + static enum { + OUT_DEFAULT = 0, + OUT_SKY_BLUE = 1, + OUT_RED = 2, + OUT_PN = 3, + OUT_HAZE = 4, + } debugOut = OUT_DEFAULT; + + switch(debugOut) + { + case OUT_DEFAULT: + break; + case OUT_SKY_BLUE: + res = LLColor3(0.4f, 0.4f, 0.9f); + break; + case OUT_RED: + res = LLColor3(1.f, 0.f, 0.f); + break; + case OUT_PN: + res = LLColor3(Pn[0], Pn[1], Pn[2]); + break; + case OUT_HAZE: + res = vary_HazeColor; + break; + } +# endif // LL_RELEASE_FOR_DOWNLOAD + return res; +} - if (sun_height <= 0.0) - sun_height = 0.0; - - mSunDiffuse = mBrightnessScaleGuess * mSun.getIntensity() * mTransp.calcTransp(sun_height, h); +LLColor3 LLVOSky::createDiffuseFromWL(LLColor3 diffuse, LLColor3 ambient, LLColor3 sundiffuse, LLColor3 sunambient) +{ + return componentMult(diffuse, sundiffuse) * 4.0f + + componentMult(ambient, sundiffuse) * 2.0f + sunambient; +} - mSunDiffuse = 1.0f * color_norm(mSunDiffuse); +LLColor3 LLVOSky::createAmbientFromWL(LLColor3 ambient, LLColor3 sundiffuse, LLColor3 sunambient) +{ + return (componentMult(ambient, sundiffuse) + sunambient) * 0.8f; +} - // Sun Ambient - full_off = -0.3f; - full_on = -0.03f; - if (tosun.mV[2] < full_off) - { - mSunAmbient.setToBlack(); - } - else + +void LLVOSky::calcAtmospherics(void) +{ + initAtmospherics(); + + LLColor3 vary_HazeColor; + LLColor3 vary_SunlightColor; + LLColor3 vary_AmbientColor; { - on = (tosun.mV[2] - full_off) / (full_on - full_off); - sun_factor = llmax(0.0f, llmin(on, 1.0f)); + // Initialize temp variables + LLColor3 sunlight = sunlight_color; - LLColor3 sun_amb = mAmbientScale * (0.8f * mSunDiffuse + - 0.2f * mBrightnessScaleGuess * mBrightestPointGuess); + // Sunlight attenuation effect (hue and brightness) due to atmosphere + // this is used later for sunlight modulation at various altitudes + LLColor3 light_atten = + (blue_density * 1.0 + smear(haze_density * 0.25f)) * (density_multiplier * max_y); - color_norm_pow(sun_amb, 0.1f, TRUE); - sun_factor *= min_intens_factor(sun_amb, 1.9f); - mSunAmbient = LLColor4(sun_factor * sun_amb); - } + // Calculate relative weights + LLColor3 temp2(0.f, 0.f, 0.f); + LLColor3 temp1 = blue_density + smear(haze_density); + LLColor3 blue_weight = componentDiv(blue_density, temp1); + LLColor3 haze_weight = componentDiv(smear(haze_density), temp1); + // Compute sunlight from P & lightnorm (for long rays like sky) + /// USE only lightnorm. + // temp2[1] = llmax(0.f, llmax(0.f, Pn[1]) * 1.0f + lightnorm[1] ); + + // and vary_sunlight will work properly with moon light + F32 lighty = unclamped_lightnorm[1]; + if(lighty < NIGHTTIME_ELEVATION_COS) + { + lighty = -lighty; + } - // Moon Diffuse - full_on = 0.3f; - full_off = 0.01f; - if (getToMoonLast().mV[2] < full_off) - { - mMoonDiffuse.setToBlack(); - } - else - { - // Steve: Added moonlight diffuse factor scalar (was constant .3) - F32 diffuse_factor = .1f + sNighttimeBrightness * .2f; // [.1, .5] default = .3 - on = (getToMoonLast().mV[2] - full_off) / (full_on - full_off); - on_cl = llmin(on, 1.0f); - mMoonDiffuse = on_cl * mNightColorShift * diffuse_factor; - } + temp2.mV[1] = llmax(0.f, lighty); + temp2.mV[1] = 1.f / temp2.mV[1]; + componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1])); - // Moon Ambient + // Distance + temp2.mV[2] = density_multiplier; - F32 moon_amb_factor = 1.f; + // Transparency (-> temp1) + temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]); - if (gAgent.inPrelude()) - { - moon_amb_factor *= 2.0f; - } + // vary_AtmosAttenuation = temp1; + + //increase ambient when there are more clouds + LLColor3 tmpAmbient = ambient + (smear(1.f) - ambient) * cloud_shadow * 0.5f; + + //haze color + vary_HazeColor = + (blue_horizon * blue_weight * (sunlight*(1.f - cloud_shadow) + tmpAmbient) + + componentMult(haze_horizon.mV[0] * haze_weight, sunlight*(1.f - cloud_shadow) * temp2.mV[0] + tmpAmbient) + ); + + //brightness of surface both sunlight and ambient + vary_SunlightColor = componentMult(sunlight, temp1) * 1.f; + vary_SunlightColor.clamp(); + vary_SunlightColor = smear(1.0f) - vary_SunlightColor; + vary_SunlightColor = componentPow(vary_SunlightColor, gamma); + vary_SunlightColor = smear(1.0f) - vary_SunlightColor; + vary_AmbientColor = componentMult(tmpAmbient, temp1) * 0.5; + vary_AmbientColor.clamp(); + vary_AmbientColor = smear(1.0f) - vary_AmbientColor; + vary_AmbientColor = componentPow(vary_AmbientColor, gamma); + vary_AmbientColor = smear(1.0f) - vary_AmbientColor; + + componentMultBy(vary_HazeColor, LLColor3(1.f, 1.f, 1.f) - temp1); - full_on = 0.30f; - full_off = 0.01f; - if (getToMoonLast().mV[2] < full_off) - { - mMoonAmbient.setToBlack(); - } - else - { - on = (getToMoonLast().mV[2] - full_off) / (full_on - full_off); - on_cl = llmax(0.0f, llmin(on, 1.0f)); - mMoonAmbient = on_cl * moon_amb_factor * mMoonDiffuse; } + mSun.setColor(vary_SunlightColor); + mMoon.setColor(LLColor3(1.0f, 1.0f, 1.0f)); - // Sun Diffuse - full_off = -0.05f; - full_on = -0.00f; - if (tosun.mV[2] < full_off) + mSun.renewDirection(); + mSun.renewColor(); + mMoon.renewDirection(); + mMoon.renewColor(); + + float dp = getToSunLast() * LLVector3(0,0,1.f); + if (dp < 0) { - mSunDiffuse.setToBlack(); + dp = 0; } - else - { - on = (getToSunLast().mV[2] - full_off) / (full_on - full_off); - sun_factor = llmax(0.0f, llmin(on, 1.0f)); - color_norm_pow(mSunDiffuse, 0.12f, TRUE); - sun_factor *= min_intens_factor(mSunDiffuse, 2.1f); - mSunDiffuse *= sun_factor; - } + // Since WL scales everything by 2, there should always be at least a 2:1 brightness ratio + // between sunlight and point lights in windlight to normalize point lights. + F32 sun_dynamic_range = llmax(gSavedSettings.getF32("RenderSunDynamicRange"), 0.0001f); + LLWLParamManager::instance()->mSceneLightStrength = 2.0f * (1.0f + sun_dynamic_range * dp); + mSunDiffuse = vary_SunlightColor; + mSunAmbient = vary_AmbientColor; + mMoonDiffuse = vary_SunlightColor; + mMoonAmbient = vary_AmbientColor; - mTotalAmbient = mSunAmbient + mMoonAmbient; + mTotalAmbient = vary_AmbientColor; mTotalAmbient.setAlpha(1); - //llinfos << "MoonDiffuse: " << mMoonDiffuse << llendl; - //llinfos << "TotalAmbient: " << mTotalAmbient << llendl; - + mFadeColor = mTotalAmbient + (mSunDiffuse + mMoonDiffuse) * 0.5f; mFadeColor.setAlpha(0); } - BOOL LLVOSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { return TRUE; @@ -1177,7 +1039,7 @@ BOOL LLVOSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) BOOL LLVOSky::updateSky() { - if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))) + if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))) { return TRUE; } @@ -1196,7 +1058,7 @@ BOOL LLVOSky::updateSky() const S32 total_no_tiles = 6 * NUM_TILES; const S32 cycle_frame_no = total_no_tiles + 1; -// if (mUpdateTimer.getElapsedTimeF32() > 0.1f) + if (mUpdateTimer.getElapsedTimeF32() > 0.001f) { mUpdateTimer.reset(); const S32 frame = next_frame; @@ -1205,12 +1067,13 @@ BOOL LLVOSky::updateSky() next_frame = next_frame % cycle_frame_no; sInterpVal = (!mInitialized) ? 1 : (F32)next_frame / cycle_frame_no; + // sInterpVal = (F32)next_frame / cycle_frame_no; LLSkyTex::setInterpVal( sInterpVal ); LLHeavenBody::setInterpVal( sInterpVal ); - calculateColors(); + calcAtmospherics(); + if (mForceUpdate || total_no_tiles == frame) { - calcBrightnessScaleAndColors(); LLSkyTex::stepCurrent(); const static F32 LIGHT_DIRECTION_THRESHOLD = (F32) cos(DEG_TO_RAD * 1.f); @@ -1248,7 +1111,7 @@ BOOL LLVOSky::updateSky() } } - calcBrightnessScaleAndColors(); + calcAtmospherics(); for (int side = 0; side < 6; side++) { @@ -1256,21 +1119,42 @@ BOOL LLVOSky::updateSky() LLImageRaw* raw2 = mSkyTex[side].getImageRaw(FALSE); raw2->copy(raw1); mSkyTex[side].createGLImage(mSkyTex[side].getWhich(FALSE)); + + raw1 = mShinyTex[side].getImageRaw(TRUE); + raw2 = mShinyTex[side].getImageRaw(FALSE); + raw2->copy(raw1); + mShinyTex[side].createGLImage(mShinyTex[side].getWhich(FALSE)); } next_frame = 0; } + } + } - std::vector<LLPointer<LLImageRaw> > images; - for (S32 side = 0; side < 6; side++) - { - images.push_back(mSkyTex[side].getImageRaw(FALSE)); - } - mCubeMap->init(images); + /// *TODO really, sky texture and env map should be shared on a single texture + /// I'll let Brad take this at some point + + // update the sky texture + for (S32 i = 0; i < 6; ++i) + { + mSkyTex[i].create(1.0f); + mShinyTex[i].create(1.0f); + } + + // update the environment map + if (mCubeMap) + { + std::vector<LLPointer<LLImageRaw> > images; + images.reserve(6); + for (S32 side = 0; side < 6; side++) + { + images.push_back(mShinyTex[side].getImageRaw(TRUE)); } + mCubeMap->init(images); } gPipeline.markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); - gPipeline.markRebuild(gSky.mVOStarsp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); + // *TODO: decide whether we need to update the stars vertex buffer in LLVOWLSky -Brad. + //gPipeline.markRebuild(gSky.mVOWLSkyp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); mForceUpdate = FALSE; } @@ -1282,15 +1166,13 @@ BOOL LLVOSky::updateSky() } } - - if (mDrawable) + if (mDrawable.notNull() && mDrawable->getFace(0) && mDrawable->getFace(0)->mVertexBuffer.isNull()) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); } return TRUE; } - void LLVOSky::updateTextures(LLAgent &agent) { if (mSunTexturep) @@ -1324,12 +1206,61 @@ LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline) return mDrawable; } +//by bao +//fake vertex buffer updating +//to guaranttee at least updating one VBO buffer every frame +//to walk around the bug caused by ATI card --> DEV-3855 +// +void LLVOSky::createDummyVertexBuffer() +{ + if(!mFace[FACE_DUMMY]) + { + LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY); + mFace[FACE_DUMMY] = mDrawable->addFace(poolp, NULL); + } + + if(mFace[FACE_DUMMY]->mVertexBuffer.isNull()) + { + mFace[FACE_DUMMY]->mVertexBuffer = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB); + mFace[FACE_DUMMY]->mVertexBuffer->allocateBuffer(1, 1, TRUE); + } +} + +void LLVOSky::updateDummyVertexBuffer() +{ + if(!LLVertexBuffer::sEnableVBOs) + return ; + + if(mHeavenlyBodyUpdated) + { + mHeavenlyBodyUpdated = FALSE ; + return ; + } + + LLFastTimer t(LLFastTimer::FTM_RENDER_FAKE_VBO_UPDATE) ; + + if(!mFace[FACE_DUMMY] || mFace[FACE_DUMMY]->mVertexBuffer.isNull()) + createDummyVertexBuffer() ; + + LLStrider<LLVector3> vertices ; + mFace[FACE_DUMMY]->mVertexBuffer->getVertexStrider(vertices, 0); + *vertices = mCameraPosAgent ; + mFace[FACE_DUMMY]->mVertexBuffer->setBuffer(0) ; +} +//---------------------------------- +//end of fake vertex buffer updating +//---------------------------------- + BOOL LLVOSky::updateGeometry(LLDrawable *drawable) { + LLFastTimer ftm(LLFastTimer::FTM_GEO_SKY); if (mFace[FACE_REFLECTION] == NULL) { LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER); - mFace[FACE_REFLECTION] = drawable->addFace(poolp, NULL); + if (gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() != 0) + { + mFace[FACE_REFLECTION] = drawable->addFace(poolp, NULL); + } } mCameraPosAgent = drawable->getPositionAgent(); @@ -1342,14 +1273,14 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) F32 x_sgn = (i&1) ? 1.f : -1.f; F32 y_sgn = (i&2) ? 1.f : -1.f; F32 z_sgn = (i&4) ? 1.f : -1.f; - v_agent[i] = HORIZON_DIST*0.25f * LLVector3(x_sgn, y_sgn, z_sgn); + v_agent[i] = HORIZON_DIST * SKY_BOX_MULT * LLVector3(x_sgn, y_sgn, z_sgn); } LLStrider<LLVector3> verticesp; LLStrider<LLVector3> normalsp; LLStrider<LLVector2> texCoordsp; - LLStrider<U32> indicesp; - S32 index_offset; + LLStrider<U16> indicesp; + U16 index_offset; LLFace *face; for (S32 side = 0; side < 6; ++side) @@ -1395,6 +1326,8 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) *indicesp++ = index_offset + 0; *indicesp++ = index_offset + 3; *indicesp++ = index_offset + 2; + + face->mVertexBuffer->setBuffer(0); } } @@ -1430,11 +1363,8 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) if (height_above_water > 0) { -#if 1 //1.9.1 BOOL render_ref = gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() == 0; -#else - BOOL render_ref = !(gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT) >= LLDrawPoolWater::SHADER_LEVEL_RIPPLE); -#endif + if (sun_flag) { setDrawRefl(0); @@ -1457,24 +1387,29 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) setDrawRefl(-1); } - LLPipeline::sCompiles++; return TRUE; } - BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, const BOOL is_sun, LLHeavenBody& hb, const F32 cos_max_angle, const LLVector3 &up, const LLVector3 &right) { + mHeavenlyBodyUpdated = TRUE ; + LLStrider<LLVector3> verticesp; LLStrider<LLVector3> normalsp; LLStrider<LLVector2> texCoordsp; - LLStrider<U32> indicesp; + LLStrider<U16> indicesp; S32 index_offset; LLFace *facep; LLVector3 to_dir = hb.getDirection(); + + if (!is_sun) + { + to_dir.mV[2] = llmax(to_dir.mV[2]+0.1f, 0.1f); + } LLVector3 draw_pos = to_dir * HEAVENLY_BODY_DIST; @@ -1521,14 +1456,15 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons if (facep->mVertexBuffer.isNull()) { - facep->setSize(4, 6); - facep->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + facep->setSize(4, 6); + facep->mVertexBuffer = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); facep->mVertexBuffer->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount(), TRUE); facep->setGeomIndex(0); facep->setIndicesIndex(0); } index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp); + if (-1 == index_offset) { return TRUE; @@ -1542,10 +1478,8 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons *(texCoordsp++) = TEX01; *(texCoordsp++) = TEX00; - //*(texCoordsp++) = (t_left > 0) ? LLVector2(0, t_left) : TEX00; *(texCoordsp++) = TEX11; *(texCoordsp++) = TEX10; - //*(texCoordsp++) = (t_right > 0) ? LLVector2(1, t_right) : TEX10; *indicesp++ = index_offset + 0; *indicesp++ = index_offset + 2; @@ -1555,6 +1489,8 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons *indicesp++ = index_offset + 2; *indicesp++ = index_offset + 3; + facep->mVertexBuffer->setBuffer(0); + if (is_sun) { if ((t_left > 0) && (t_right > 0)) @@ -1651,12 +1587,13 @@ F32 clip_side_to_horizon(const LLVector3& V0, const LLVector3& V1, const F32 cos void LLVOSky::updateSunHaloGeometry(LLDrawable *drawable ) { +#if 0 const LLVector3* v_corner = mSun.corners(); LLStrider<LLVector3> verticesp; LLStrider<LLVector3> normalsp; LLStrider<LLVector2> texCoordsp; - LLStrider<U32> indicesp; + LLStrider<U16> indicesp; S32 index_offset; LLFace *face; @@ -1708,6 +1645,7 @@ void LLVOSky::updateSunHaloGeometry(LLDrawable *drawable ) *indicesp++ = index_offset + 1; *indicesp++ = index_offset + 2; *indicesp++ = index_offset + 3; +#endif } @@ -1932,7 +1870,7 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H, LLStrider<LLVector3> verticesp; LLStrider<LLVector3> normalsp; LLStrider<LLVector2> texCoordsp; - LLStrider<U32> indicesp; + LLStrider<U16> indicesp; S32 index_offset; index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); @@ -2063,6 +2001,8 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H, } } } + + face->mVertexBuffer->setBuffer(0); } @@ -2072,37 +2012,11 @@ void LLVOSky::updateFog(const F32 distance) { if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG)) { - /*gGLSFog.addCap(GL_FOG, FALSE); - gGLSPipeline.addCap(GL_FOG, FALSE); - gGLSPipelineAlpha.addCap(GL_FOG, FALSE); - gGLSPipelinePixieDust.addCap(GL_FOG, FALSE); - gGLSPipelineSelection.addCap(GL_FOG, FALSE); - gGLSPipelineAvatar.addCap(GL_FOG, FALSE); - gGLSPipelineAvatarAlphaOnePass.addCap(GL_FOG, FALSE); - gGLSPipelineAvatarAlphaPass1.addCap(GL_FOG, FALSE); - gGLSPipelineAvatarAlphaPass2.addCap(GL_FOG, FALSE); - gGLSPipelineAvatarAlphaPass3.addCap(GL_FOG, FALSE);*/ glFogf(GL_FOG_DENSITY, 0); glFogfv(GL_FOG_COLOR, (F32 *) &LLColor4::white.mV); glFogf(GL_FOG_END, 1000000.f); return; } - else - { - /*gGLSFog.addCap(GL_FOG, TRUE); - gGLSPipeline.addCap(GL_FOG, TRUE); - gGLSPipelineAlpha.addCap(GL_FOG, TRUE); - gGLSPipelinePixieDust.addCap(GL_FOG, TRUE); - gGLSPipelineSelection.addCap(GL_FOG, TRUE); - if (!gGLManager.mIsATI) - { - gGLSPipelineAvatar.addCap(GL_FOG, TRUE); - gGLSPipelineAvatarAlphaOnePass.addCap(GL_FOG, TRUE); - gGLSPipelineAvatarAlphaPass1.addCap(GL_FOG, TRUE); - gGLSPipelineAvatarAlphaPass2.addCap(GL_FOG, TRUE); - gGLSPipelineAvatarAlphaPass3.addCap(GL_FOG, TRUE); - }*/ - } const BOOL hide_clip_plane = TRUE; LLColor4 target_fog(0.f, 0.2f, 0.5f, 0.f); @@ -2120,7 +2034,6 @@ void LLVOSky::updateFog(const F32 distance) LLColor3 sky_fog_color = LLColor3::white; LLColor3 render_fog_color = LLColor3::white; - LLColor3 transp; LLVector3 tosun = getToSunLast(); const F32 tosun_z = tosun.mV[VZ]; tosun.mV[VZ] = 0.f; @@ -2140,9 +2053,10 @@ void LLVOSky::updateFog(const F32 distance) tosun_45.normVec(); // 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. - calcSkyColorInDir(res_color[0],transp, tosun); - calcSkyColorInDir(res_color[1],transp, perp_tosun); - calcSkyColorInDir(res_color[2],transp, tosun_45); + initAtmospherics(); + res_color[0] = calcSkyColorInDir(tosun); + res_color[1] = calcSkyColorInDir(perp_tosun); + res_color[2] = calcSkyColorInDir(tosun_45); sky_fog_color = color_norm(res_color[0] + res_color[1] + res_color[2]); @@ -2163,54 +2077,59 @@ void LLVOSky::updateFog(const F32 distance) color_gamma_correct(sky_fog_color); render_fog_color = sky_fog_color; + + F32 fog_density = 0.f; + fog_distance = mFogRatio * distance; if (camera_height > water_height) { - fog_distance = mFogRatio * distance; LLColor4 fog(render_fog_color); glFogfv(GL_FOG_COLOR, fog.mV); mGLFogCol = fog; + + if (hide_clip_plane) + { + // For now, set the density to extend to the cull distance. + const F32 f_log = 2.14596602628934723963618357029f; // sqrt(fabs(log(0.01f))) + fog_density = f_log/fog_distance; + glFogi(GL_FOG_MODE, GL_EXP2); + } + else + { + const F32 f_log = 4.6051701859880913680359829093687f; // fabs(log(0.01f)) + fog_density = (f_log)/fog_distance; + glFogi(GL_FOG_MODE, GL_EXP); + } } else { - // Interpolate between sky fog and water fog... F32 depth = water_height - camera_height; - F32 depth_frac = 1.f/(1.f + 200.f*depth); - F32 color_frac = 1.f/(1.f + 0.5f* depth)* 0.2f; - fog_distance = (mFogRatio * distance) * depth_frac + 30.f * (1.f-depth_frac); - fog_distance = llmin(75.f, fog_distance); - - F32 brightness = 1.f/(1.f + 0.05f*depth); - F32 sun_brightness = getSunDiffuseColor().magVec() * 0.3f; - brightness = llmin(1.f, brightness); - brightness = llmin(brightness, sun_brightness); - color_frac = llmin(0.7f, color_frac); - - LLColor4 fogCol = brightness * (color_frac * render_fog_color + (1.f - color_frac) * LLColor4(0.f, 0.2f, 0.3f, 1.f)); + + // get the water param manager variables + float water_fog_density = LLWaterParamManager::instance()->getFogDensity(); + LLColor4 water_fog_color = LLDrawPoolWater::sWaterFogColor.mV; + + // adjust the color based on depth. We're doing linear approximations + float depth_scale = gSavedSettings.getF32("WaterGLFogDepthScale"); + float depth_modifier = 1.0f - llmin(llmax(depth / depth_scale, 0.01f), + gSavedSettings.getF32("WaterGLFogDepthFloor")); + + LLColor4 fogCol = water_fog_color * depth_modifier; fogCol.setAlpha(1); + + // set the gl fog color glFogfv(GL_FOG_COLOR, (F32 *) &fogCol.mV); mGLFogCol = fogCol; + + // set the density based on what the shaders use + fog_density = water_fog_density * gSavedSettings.getF32("WaterGLFogDensityScale"); + glFogi(GL_FOG_MODE, GL_EXP2); } mFogColor = sky_fog_color; mFogColor.setAlpha(1); LLGLSFog gls_fog; - F32 fog_density; - if (hide_clip_plane) - { - // For now, set the density to extend to the cull distance. - const F32 f_log = 2.14596602628934723963618357029f; // sqrt(fabs(log(0.01f))) - fog_density = f_log/fog_distance; - glFogi(GL_FOG_MODE, GL_EXP2); - } - else - { - const F32 f_log = 4.6051701859880913680359829093687f; // fabs(log(0.01f)) - fog_density = (f_log)/fog_distance; - glFogi(GL_FOG_MODE, GL_EXP); - } - glFogf(GL_FOG_END, fog_distance*2.2f); glFogf(GL_FOG_DENSITY, fog_density); @@ -2279,197 +2198,53 @@ F32 azimuth(const LLVector3 &v) return azimuth; } - -#if 0 -// Not currently used -LLColor3 LLVOSky::calcGroundFog(LLColor3& transp, const LLVector3 &view_dir, F32 obj_dist) const -{ - LLColor3 col; - calcGroundFog(col, transp, view_dir, obj_dist); - col *= mBrightnessScaleGuess; - return col; -} -#endif - -void LLVOSky::setSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity) +void LLVOSky::initSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity) { LLVector3 sun_direction = (sun_dir.magVec() == 0) ? LLVector3::x_axis : sun_dir; sun_direction.normVec(); - F32 dp = mSun.getDirection() * sun_direction; mSun.setDirection(sun_direction); + mSun.renewDirection(); mSun.setAngularVelocity(sun_ang_velocity); - mMoon.setDirection(-sun_direction); - if (dp < 0.995f) { //the sun jumped a great deal, update immediately - updateHaze(); - mWeatherChange = FALSE; - mForceUpdate = TRUE; - } - else if (mWeatherChange && (mSun.getDirection().mV[VZ] > -0.5) ) - { - updateHaze(); - init(); - mWeatherChange = FALSE; - } - else if (mSun.getDirection().mV[VZ] < -0.5) - { - mWeatherChange = TRUE; - } -} - -#define INV_WAVELENGTH_R_POW4 (1.f/0.2401f) // = 1/0.7^4 -#define INV_WAVELENGTH_G_POW4 (1.f/0.0789f) // = 1/0.53^4 -#define INV_WAVELENGTH_B_POW4 (1.f/0.03748f) // = 1/0.44^4 - -// Dummy class for globals used below. Replace when KILLERSKY is merged in. -class LLKillerSky -{ -public: - static F32 sRaleighGroundDensity; - static F32 sMieFactor; - static F32 sNearFalloffFactor; - static F32 sSkyContrib; - - static void getRaleighCoefficients(float eye_sun_dp, float density, float *coefficients) - { - float dp = eye_sun_dp; - float angle_dep = density*(1 + dp*dp); - coefficients[0] = angle_dep * INV_WAVELENGTH_R_POW4; - coefficients[1] = angle_dep * INV_WAVELENGTH_G_POW4; - coefficients[2] = angle_dep * INV_WAVELENGTH_B_POW4; - } - - static void getMieCoefficients(float eye_sun_dp, float density, float *coefficient) - { - // TOTALLY ARBITRARY FUNCTION. Seems to work though - // If anyone can replace this with some *actual* mie function, that'd be great - float dp = eye_sun_dp; - float dp_highpower = dp*dp; - float angle_dep = density * (llclamp(dp_highpower*dp, 0.f, 1.f) + 0.4f); - *coefficient = angle_dep; - } -}; - -F32 LLKillerSky::sRaleighGroundDensity = 0.013f; -F32 LLKillerSky::sMieFactor = 50; -F32 LLKillerSky::sNearFalloffFactor = 1.5f; -F32 LLKillerSky::sSkyContrib = 0.06f; - -void LLVOSky::generateScatterMap() -{ - float raleigh[3], mie; - - mScatterMap = new LLImageGL(FALSE); - mScatterMapRaw = new LLImageRaw(256, 256, 4); - U8 *data = mScatterMapRaw->getData(); + mMoon.setDirection(-mSun.getDirection()); + mMoon.renewDirection(); + mLastLightingDirection = mSun.getDirection(); - F32 light_brightness = gSky.getSunDirection().mV[VZ]+0.1f; - LLColor4 light_color; - LLColor4 sky_color; - if (light_brightness > 0) - { - F32 interp = sqrtf(light_brightness); - light_brightness = sqrt(sqrtf(interp)); - light_color = lerp(gSky.getSunDiffuseColor(), LLColor4(1,1,1,1), interp) * light_brightness; - sky_color = lerp(LLColor4(0,0,0,0), LLColor4(0.4f, 0.6f, 1.f, 1.f), light_brightness)*LLKillerSky::sSkyContrib; - } - else - { - light_brightness = /*0.3f*/sqrt(-light_brightness); - light_color = gSky.getMoonDiffuseColor() * light_brightness; - sky_color = LLColor4(0,0,0,1); - } + calcAtmospherics(); - // x = distance [0..1024m] - // y = dot product [-1,1] - for (int y=0;y<256;y++) + if ( !mInitialized ) { - // Accumulate outward - float accum_r = 0, accum_g = 0, accum_b = 0; - - float dp = (((float)y)/255.f)*1.95f - 0.975f; - U8 *scanline = &data[y*256*4]; - for (int x=0;x<256;x++) - { - float dist = ((float)x+1)*4; // x -> 2048 - - float raleigh_density = LLKillerSky::sRaleighGroundDensity * 0.05f; // Arbitrary? Perhaps... - float mie_density = raleigh_density*LLKillerSky::sMieFactor; - - float extinction_factor = dist/LLKillerSky::sNearFalloffFactor; - - LLKillerSky::getRaleighCoefficients(dp, raleigh_density, raleigh); - LLKillerSky::getMieCoefficients(dp, mie_density, &mie); - - float falloff_r = pow(llclamp(0.985f-raleigh[0],0.f,1.f), extinction_factor); - float falloff_g = pow(llclamp(0.985f-raleigh[1],0.f,1.f), extinction_factor); - float falloff_b = pow(llclamp(0.985f-raleigh[2],0.f,1.f), extinction_factor); - - float light_r = light_color.mV[0] * (raleigh[0]+mie+sky_color.mV[0]) * falloff_r; - float light_g = light_color.mV[1] * (raleigh[1]+mie+sky_color.mV[1]) * falloff_g; - float light_b = light_color.mV[2] * (raleigh[2]+mie+sky_color.mV[2]) * falloff_b; - - accum_r += light_r; - accum_g += light_g; - accum_b += light_b; - - scanline[x*4] = (U8)llclamp(accum_r*255.f, 0.f, 255.f); - scanline[x*4+1] = (U8)llclamp(accum_g*255.f, 0.f, 255.f); - scanline[x*4+2] = (U8)llclamp(accum_b*255.f, 0.f, 255.f); - float alpha = ((falloff_r+falloff_g+falloff_b)*0.33f); - scanline[x*4+3] = (U8)llclamp(alpha*255.f, 0.f, 255.f); // Avg falloff - - // Output color Co, Input color Ci, Map channels Mrgb, Ma: - // Co = (Ci * Ma) + Mrgb - } - } - - mScatterMap->createGLTexture(0, mScatterMapRaw); - mScatterMap->bind(0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + init(); + LLSkyTex::stepCurrent(); + } } -#if 0 -// Not currently used -void LLVOSky::calcGroundFog(LLColor3& res, LLColor3& transp, const LLVector3 view_dir, F32 obj_dist) const +void LLVOSky::setSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity) { - const LLVector3& tosun = getToSunLast();//use_old_value ? sunDir() : toSunLast(); - res.setToBlack(); - transp.setToWhite(); - const F32 dist = obj_dist * mWorldScale; - - //LLVector3 view_dir = gCamera->getAtAxis(); - - const F32 cos_dir = view_dir * tosun; - LLVector3 dir = view_dir; - LLVector3 virtual_P = mCameraPosAgent + dist * dir; + LLVector3 sun_direction = (sun_dir.magVec() == 0) ? LLVector3::x_axis : sun_dir; + sun_direction.normVec(); - if (dir.mV[VZ] < 0) - { - dir = -dir; - } + // Push the sun "South" as it approaches directly overhead so that we can always see bump mapping + // on the upward facing faces of cubes. + LLVector3 newDir = sun_direction; - const F32 z_dir = dir.mV[2]; + // Same as dot product with the up direction + clamp. + F32 sunDot = llmax(0.f, newDir.mV[2]); + sunDot *= sunDot; - const F32 h = mCameraPosAgent.mV[2]; + // Create normalized vector that has the sunDir pushed south about an hour and change. + LLVector3 adjustedDir = (newDir + LLVector3(0.f, -0.70711f, 0.70711f)) * 0.5f; - transp = color_div(mTransp.calcTransp(dir * calcUpVec(virtual_P), 0), - mTransp.calcTransp(z_dir, h)); + // Blend between normal sun dir and adjusted sun dir based on how close we are + // to having the sun overhead. + mBumpSunDir = adjustedDir * sunDot + newDir * (1.0f - sunDot); + mBumpSunDir.normVec(); - if (calcHitsEarth(mCameraPosAgent, tosun) > 0) - { - const F32 avg = llmin(1.f, 1.2f * color_avg(transp)); - transp = LLColor3(avg, avg, avg); - return; + F32 dp = mLastLightingDirection * sun_direction; + mSun.setDirection(sun_direction); + mSun.setAngularVelocity(sun_ang_velocity); + mMoon.setDirection(-sun_direction); + calcAtmospherics(); + if (dp < 0.995f) { //the sun jumped a great deal, update immediately + mForceUpdate = TRUE; } - - LLColor3 haze_sca_opt_depth = mHaze.getSigSca(); - LLColor3 sun_transp; - mTransp.calcTransp(tosun.mV[2], -0.1f, sun_transp); - - res = calcAirPhaseFunc(cos_dir) * LLHaze::getAirScaSeaLevel(); - res += mHaze.calcPhase(cos_dir) * mHaze.getSigSca(); - res = mSun.getIntensity() * dist * sun_transp * res; } - -#endif |