diff options
author | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 21:25:21 +0200 |
---|---|---|
committer | Andrey Lihatskiy <alihatskiy@productengine.com> | 2024-05-22 22:40:26 +0300 |
commit | e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 (patch) | |
tree | 1bb897489ce524986f6196201c10ac0d8861aa5f /indra/newview/llvosky.cpp | |
parent | 069ea06848f766466f1a281144c82a0f2bd79f3a (diff) |
Fix line endlings
Diffstat (limited to 'indra/newview/llvosky.cpp')
-rw-r--r-- | indra/newview/llvosky.cpp | 3182 |
1 files changed, 1591 insertions, 1591 deletions
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 0dff51c2f2..2b8ed74b0f 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -1,1591 +1,1591 @@ -/**
- * @file llvosky.cpp
- * @brief LLVOSky class implementation
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llvosky.h"
-
-#include "llfeaturemanager.h"
-#include "llviewercontrol.h"
-#include "llframetimer.h"
-
-#include "llagent.h"
-#include "llagentcamera.h"
-#include "lldrawable.h"
-#include "llface.h"
-#include "llcubemap.h"
-#include "lldrawpoolsky.h"
-#include "lldrawpoolwater.h"
-#include "llglheaders.h"
-#include "llsky.h"
-#include "llviewercamera.h"
-#include "llviewertexturelist.h"
-#include "llviewerobjectlist.h"
-#include "llviewerregion.h"
-#include "llworld.h"
-#include "pipeline.h"
-#include "lldrawpoolwlsky.h"
-#include "v3colorutil.h"
-
-#include "llsettingssky.h"
-#include "llenvironment.h"
-
-#include "lltrace.h"
-#include "llfasttimer.h"
-
-#undef min
-#undef max
-
-namespace
-{
- const S32 NUM_TILES_X = 8;
- const S32 NUM_TILES_Y = 4;
- const S32 NUM_TILES = NUM_TILES_X * NUM_TILES_Y;
- const S32 NUM_CUBEMAP_FACES = 6; // See SKYTEX_RESOLUTION for face dimensions
- const S32 TOTAL_TILES = NUM_CUBEMAP_FACES * NUM_TILES;
- const S32 MAX_TILES = TOTAL_TILES + 1;
-
-// 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;
-
-// 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);
-
- F32Seconds UPDATE_EXPRY(0.25f);
-
- const F32 UPDATE_MIN_DELTA_THRESHOLD = 0.0005f;
-}
-/***************************************
- SkyTex
-***************************************/
-
-S32 LLSkyTex::sCurrent = 0;
-
-
-LLSkyTex::LLSkyTex() :
- mSkyData(NULL),
- mSkyDirs(NULL),
- mIsShiny(false)
-{
-}
-
-void LLSkyTex::init(bool isShiny)
-{
- mIsShiny = isShiny;
- mSkyData = new LLColor4[(U32)(SKYTEX_RESOLUTION * SKYTEX_RESOLUTION)];
- mSkyDirs = new LLVector3[(U32)(SKYTEX_RESOLUTION * SKYTEX_RESOLUTION)];
-
- for (S32 i = 0; i < 2; ++i)
- {
- mTexture[i] = LLViewerTextureManager::getLocalTexture(false);
- mTexture[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
- mImageRaw[i] = new LLImageRaw(SKYTEX_RESOLUTION, SKYTEX_RESOLUTION, SKYTEX_COMPONENTS);
-
- initEmpty(i);
- }
-}
-
-void LLSkyTex::cleanupGL()
-{
- mTexture[0] = NULL;
- mTexture[1] = NULL;
-}
-
-void LLSkyTex::restoreGL()
-{
- for (S32 i = 0; i < 2; i++)
- {
- mTexture[i] = LLViewerTextureManager::getLocalTexture(false);
- mTexture[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
- }
-}
-
-LLSkyTex::~LLSkyTex()
-{
- delete[] mSkyData;
- mSkyData = NULL;
-
- delete[] mSkyDirs;
- mSkyDirs = NULL;
-}
-
-S32 LLSkyTex::getResolution()
-{
- return SKYTEX_RESOLUTION;
-}
-
-S32 LLSkyTex::getCurrent()
-{
- return sCurrent;
-}
-
-S32 LLSkyTex::stepCurrent() {
- sCurrent++;
- sCurrent &= 1;
- return sCurrent;
-}
-
-S32 LLSkyTex::getNext()
-{
- return ((sCurrent+1) & 1);
-}
-
-S32 LLSkyTex::getWhich(const bool curr)
-{
- int tex = curr ? sCurrent : getNext();
- return tex;
-}
-
-void LLSkyTex::initEmpty(const S32 tex)
-{
- LLImageDataLock lock(mImageRaw[tex]);
- U8* data = mImageRaw[tex]->getData();
- for (S32 i = 0; i < SKYTEX_RESOLUTION; ++i)
- {
- for (S32 j = 0; j < SKYTEX_RESOLUTION; ++j)
- {
- const S32 basic_offset = (i * SKYTEX_RESOLUTION + j);
- S32 offset = basic_offset * SKYTEX_COMPONENTS;
- data[offset] = 0;
- data[offset+1] = 0;
- data[offset+2] = 0;
- data[offset+3] = 255;
-
- mSkyData[basic_offset].setToBlack();
- }
- }
-
- createGLImage(tex);
-}
-
-void LLSkyTex::create()
-{
- LLImageDataSharedLock lock(mImageRaw[sCurrent]);
- const U8* data = mImageRaw[sCurrent]->getData();
- for (S32 i = 0; i < SKYTEX_RESOLUTION; ++i)
- {
- for (S32 j = 0; j < SKYTEX_RESOLUTION; ++j)
- {
- const S32 basic_offset = (i * SKYTEX_RESOLUTION + j);
- S32 offset = basic_offset * SKYTEX_COMPONENTS;
- U32* pix = (U32*)(data + offset);
- LLColor4U temp = LLColor4U(mSkyData[basic_offset]);
- *pix = temp.asRGBA();
- }
- }
- createGLImage(sCurrent);
-}
-
-void LLSkyTex::createGLImage(S32 which)
-{
- mTexture[which]->setExplicitFormat(GL_RGBA8, GL_RGBA);
- mTexture[which]->createGLTexture(0, mImageRaw[which], 0, true, LLGLTexture::LOCAL);
- mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP);
-}
-
-void LLSkyTex::bindTexture(bool curr)
-{
- int tex = getWhich(curr);
- gGL.getTexUnit(0)->bind(mTexture[tex], true);
-}
-
-LLImageRaw* LLSkyTex::getImageRaw(bool curr)
-{
- int tex = getWhich(curr);
- return mImageRaw[tex];
-}
-
-/***************************************
- LLHeavenBody
-***************************************/
-
-F32 LLHeavenBody::sInterpVal = 0;
-
-LLHeavenBody::LLHeavenBody(const F32 rad)
-: mDirectionCached(LLVector3(0,0,0)),
- mDirection(LLVector3(0,0,0)),
- mIntensity(0.f),
- mDiskRadius(rad),
- mDraw(false),
- mHorizonVisibility(1.f),
- mVisibility(1.f),
- mVisible(false)
-{
- mColor.setToBlack();
- mColorCached.setToBlack();
-}
-
-const LLQuaternion& LLHeavenBody::getRotation() const
-{
- return mRotation;
-}
-
-void LLHeavenBody::setRotation(const LLQuaternion& rot)
-{
- mRotation = rot;
-}
-
-const LLVector3& LLHeavenBody::getDirection() const
-{
- return mDirection;
-}
-
-void LLHeavenBody::setDirection(const LLVector3 &direction)
-{
- mDirection = direction;
-}
-
-void LLHeavenBody::setAngularVelocity(const LLVector3 &ang_vel)
-{
- mAngularVelocity = ang_vel;
-}
-
-const LLVector3& LLHeavenBody::getAngularVelocity() const
-{
- return mAngularVelocity;
-}
-
-const LLVector3& LLHeavenBody::getDirectionCached() const
-{
- return mDirectionCached;
-}
-
-void LLHeavenBody::renewDirection()
-{
- mDirectionCached = mDirection;
-}
-
-const LLColor3& LLHeavenBody::getColorCached() const
-{
- return mColorCached;
-}
-
-void LLHeavenBody::setColorCached(const LLColor3& c)
-{
- mColorCached = c;
-}
-
-const LLColor3& LLHeavenBody::getColor() const
-{
- return mColor;
-}
-
-void LLHeavenBody::setColor(const LLColor3& c)
-{
- mColor = c;
-}
-
-void LLHeavenBody::renewColor()
-{
- mColorCached = mColor;
-}
-
-F32 LLHeavenBody::interpVal()
-{
- return sInterpVal;
-}
-
-void LLHeavenBody::setInterpVal(const F32 v)
-{
- sInterpVal = v;
-}
-
-LLColor3 LLHeavenBody::getInterpColor() const
-{
- return sInterpVal * mColor + (1 - sInterpVal) * mColorCached;
-}
-
-const F32& LLHeavenBody::getVisibility() const
-{
- return mVisibility;
-}
-
-void LLHeavenBody::setVisibility(const F32 c)
-{
- mVisibility = c;
-}
-
-bool LLHeavenBody::isVisible() const
-{
- return mVisible;
-}
-
-void LLHeavenBody::setVisible(const bool v)
-{
- mVisible = v;
-}
-
-const F32& LLHeavenBody::getIntensity() const
-{
- return mIntensity;
-}
-
-void LLHeavenBody::setIntensity(const F32 c)
-{
- mIntensity = c;
-}
-
-void LLHeavenBody::setDiskRadius(const F32 radius)
-{
- mDiskRadius = radius;
-}
-
-F32 LLHeavenBody::getDiskRadius() const
-{
- return mDiskRadius;
-}
-
-void LLHeavenBody::setDraw(const bool draw)
-{
- mDraw = draw;
-}
-
-bool LLHeavenBody::getDraw() const
-{
- return mDraw;
-}
-
-const LLVector3& LLHeavenBody::corner(const S32 n) const
-{
- return mQuadCorner[n];
-}
-
-LLVector3& LLHeavenBody::corner(const S32 n)
-{
- return mQuadCorner[n];
-}
-
-const LLVector3* LLHeavenBody::corners() const
-{
- return mQuadCorner;
-}
-
-/***************************************
- Sky
-***************************************/
-
-const S32 SKYTEX_TILE_RES_X = SKYTEX_RESOLUTION / NUM_TILES_X;
-const S32 SKYTEX_TILE_RES_Y = SKYTEX_RESOLUTION / NUM_TILES_Y;
-
-LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
-: LLStaticViewerObject(id, pcode, regionp, true),
- mSun(SUN_DISK_RADIUS), mMoon(MOON_DISK_RADIUS),
- mBrightnessScale(1.f),
- mBrightnessScaleNew(0.f),
- mBrightnessScaleGuess(1.f),
- mWeatherChange(false),
- mCloudDensity(0.2f),
- mWind(0.f),
- mForceUpdate(false),
- mNeedUpdate(true),
- mCubeMapUpdateStage(-1),
- mWorldScale(1.f),
- mBumpSunDir(0.f, 0.f, 1.f)
-{
- /// WL PARAMS
-
- mInitialized = false;
- mbCanSelect = false;
- mUpdateTimer.reset();
-
- mForceUpdateThrottle.setTimerExpirySec(UPDATE_EXPRY);
- mForceUpdateThrottle.reset();
-
- for (S32 i = 0; i < NUM_CUBEMAP_FACES; i++)
- {
- mSkyTex[i].init(false);
- mShinyTex[i].init(true);
- }
- for (S32 i=0; i<FACE_COUNT; i++)
- {
- mFace[i] = NULL;
- }
-
- mCameraPosAgent = gAgentCamera.getCameraPositionAgent();
- mAtmHeight = ATM_HEIGHT;
- mEarthCenter = LLVector3(mCameraPosAgent.mV[0], mCameraPosAgent.mV[1], -EARTH_RADIUS);
-
- mSun.setIntensity(SUN_INTENSITY);
- mMoon.setIntensity(0.1f * SUN_INTENSITY);
-
- mHeavenlyBodyUpdated = false ;
-
- mDrawRefl = 0;
- mInterpVal = 0.f;
-}
-
-
-LLVOSky::~LLVOSky()
-{
- // Don't delete images - it'll get deleted by gTextureList on shutdown
- // This needs to be done for each texture
-
- mCubeMap = NULL;
-}
-
-void LLVOSky::init()
-{
- llassert(!mInitialized);
-
- // Update sky at least once to get correct initial sun/moon directions and lighting calcs performed
- LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
- psky->update();
-
- updateDirections(psky);
-
- cacheEnvironment(psky,m_atmosphericsVars);
-
- // Initialize the cached normalized direction vectors
- for (S32 side = 0; side < NUM_CUBEMAP_FACES; ++side)
- {
- for (S32 tile = 0; tile < NUM_TILES; ++tile)
- {
- initSkyTextureDirs(side, tile);
- createSkyTexture(psky, m_atmosphericsVars, side, tile);
- }
- mSkyTex[side].create();
- mShinyTex[side].create();
- }
-
- initCubeMap();
-
- mInitialized = true;
-
- mHeavenlyBodyUpdated = false ;
-
- mRainbowMap = LLViewerTextureManager::getFetchedTexture(psky->getRainbowTextureId(), FTT_DEFAULT, true, LLGLTexture::BOOST_UI);
- mHaloMap = LLViewerTextureManager::getFetchedTexture(psky->getHaloTextureId(), FTT_DEFAULT, true, LLGLTexture::BOOST_UI);
-}
-
-
-void LLVOSky::cacheEnvironment(LLSettingsSky::ptr_t psky,AtmosphericsVars& atmosphericsVars)
-{
- // NOTE: Also see: LLAtmospherics::updateFog()
- // invariants across whole sky tex process...
- atmosphericsVars.blue_density = psky->getBlueDensity();
- atmosphericsVars.blue_horizon = psky->getBlueHorizon();
- atmosphericsVars.haze_density = psky->getHazeDensity();
- atmosphericsVars.haze_horizon = psky->getHazeHorizon();
- atmosphericsVars.density_multiplier = psky->getDensityMultiplier();
- atmosphericsVars.distance_multiplier = psky->getDistanceMultiplier();
- atmosphericsVars.max_y = psky->getMaxY();
- atmosphericsVars.sun_norm = LLEnvironment::instance().getClampedSunNorm();
- atmosphericsVars.sunlight = psky->getIsSunUp() ? psky->getSunlightColor() : psky->getMoonlightColor();
- atmosphericsVars.ambient = psky->getAmbientColor();
- atmosphericsVars.glow = psky->getGlow();
- atmosphericsVars.cloud_shadow = psky->getCloudShadow();
- atmosphericsVars.dome_radius = psky->getDomeRadius();
- atmosphericsVars.dome_offset = psky->getDomeOffset();
- atmosphericsVars.light_atten = psky->getLightAttenuation(atmosphericsVars.max_y);
- atmosphericsVars.light_transmittance = psky->getLightTransmittance(atmosphericsVars.max_y);
- atmosphericsVars.total_density = psky->getTotalDensity();
- atmosphericsVars.gamma = psky->getGamma();
-}
-
-void LLVOSky::calc()
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT;
- LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
- cacheEnvironment(psky,m_atmosphericsVars);
-
- mSun.setColor(psky->getSunDiffuse());
- mMoon.setColor(LLColor3(1.0f, 1.0f, 1.0f));
-
- mSun.renewDirection();
- mSun.renewColor();
- mMoon.renewDirection();
- mMoon.renewColor();
-}
-
-void LLVOSky::initCubeMap()
-{
- std::vector<LLPointer<LLImageRaw> > images;
- for (S32 side = 0; side < NUM_CUBEMAP_FACES; side++)
- {
- images.push_back(mShinyTex[side].getImageRaw());
- }
-
- if (!mCubeMap && gSavedSettings.getBOOL("RenderWater") && LLCubeMap::sUseCubeMaps)
- {
- mCubeMap = new LLCubeMap(false);
- }
-
- if (mCubeMap)
- {
- mCubeMap->init(images);
- }
-
- gGL.getTexUnit(0)->disable();
-}
-
-
-void LLVOSky::cleanupGL()
-{
- S32 i;
- for (i = 0; i < NUM_CUBEMAP_FACES; i++)
- {
- mSkyTex[i].cleanupGL();
- }
- if (getCubeMap())
- {
- getCubeMap()->destroyGL();
- }
-}
-
-void LLVOSky::restoreGL()
-{
- S32 i;
- for (i = 0; i < NUM_CUBEMAP_FACES; i++)
- {
- mSkyTex[i].restoreGL();
- }
-
- LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
-
- if (psky)
- {
- setSunTextures(psky->getSunTextureId(), psky->getNextSunTextureId());
- setMoonTextures(psky->getMoonTextureId(), psky->getNextMoonTextureId());
- }
-
- updateDirections(psky);
-
- if (gSavedSettings.getBOOL("RenderWater") && LLCubeMap::sUseCubeMaps)
- {
- initCubeMap();
- }
-
- forceSkyUpdate();
-
- if (mDrawable)
- {
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME);
- }
-
-}
-
-void LLVOSky::initSkyTextureDirs(const S32 side, const S32 tile)
-{
- S32 tile_x = tile % NUM_TILES_X;
- S32 tile_y = tile / NUM_TILES_X;
-
- S32 tile_x_pos = tile_x * SKYTEX_TILE_RES_X;
- S32 tile_y_pos = tile_y * SKYTEX_TILE_RES_Y;
-
- F32 coeff[3] = {0, 0, 0};
- const S32 curr_coef = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X
- const S32 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1
- const S32 x_coef = (curr_coef + 1) % 3;
- const S32 y_coef = (x_coef + 1) % 3;
-
- coeff[curr_coef] = (F32)side_dir;
-
- F32 inv_res = 1.f/SKYTEX_RESOLUTION;
- S32 x, y;
- for (y = tile_y_pos; y < (tile_y_pos + SKYTEX_TILE_RES_Y); ++y)
- {
- for (x = tile_x_pos; x < (tile_x_pos + SKYTEX_TILE_RES_X); ++x)
- {
- coeff[x_coef] = F32((x<<1) + 1) * inv_res - 1.f;
- coeff[y_coef] = F32((y<<1) + 1) * inv_res - 1.f;
- LLVector3 dir(coeff[0], coeff[1], coeff[2]);
- dir.normalize();
- mSkyTex[side].setDir(dir, x, y);
- mShinyTex[side].setDir(dir, x, y);
- }
- }
-}
-
-void LLVOSky::createSkyTexture(const LLSettingsSky::ptr_t &psky, AtmosphericsVars& vars, const S32 side, const S32 tile)
-{
- const bool low_end = !gPipeline.canUseWindLightShaders();
-
- S32 tile_x = tile % NUM_TILES_X;
- S32 tile_y = tile / NUM_TILES_X;
-
- S32 tile_x_pos = tile_x * SKYTEX_TILE_RES_X;
- S32 tile_y_pos = tile_y * SKYTEX_TILE_RES_Y;
-
- S32 x, y;
- for (y = tile_y_pos; y < (tile_y_pos + SKYTEX_TILE_RES_Y); ++y)
- {
- for (x = tile_x_pos; x < (tile_x_pos + SKYTEX_TILE_RES_X); ++x)
- {
- mSkyTex [side].setPixel(m_legacyAtmospherics.calcSkyColorInDir(psky, vars, mSkyTex [side].getDir(x, y), false, low_end), x, y);
- mShinyTex[side].setPixel(m_legacyAtmospherics.calcSkyColorInDir(psky, vars, mShinyTex[side].getDir(x, y), true , low_end), x, y);
- }
- }
-}
-
-void LLVOSky::updateDirections(LLSettingsSky::ptr_t psky)
-{
- mSun.setDirection(psky->getSunDirection());
- mMoon.setDirection(psky->getMoonDirection());
- mSun.setRotation(psky->getSunRotation());
- mMoon.setRotation(psky->getMoonRotation());
- mSun.renewDirection();
- mMoon.renewDirection();
-}
-
-void LLVOSky::idleUpdate(LLAgent &agent, const F64 &time)
-{
-}
-
-void LLVOSky::forceSkyUpdate()
-{
- mForceUpdate = true;
- m_lastAtmosphericsVars = {};
- mCubeMapUpdateStage = -1;
-}
-
-bool LLVOSky::updateSky()
-{
- LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
-
- if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)))
- {
- // It's dead. Don't update it.
- return true;
- }
-
- if (gGLManager.mIsDisabled)
- {
- return true;
- }
-
- LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT;
-
- static S32 next_frame = 0;
-
- mNeedUpdate = mForceUpdate;
-
- ++next_frame;
- next_frame = next_frame % MAX_TILES;
-
- mInterpVal = (!mInitialized) ? 1 : (F32)next_frame / MAX_TILES;
- LLHeavenBody::setInterpVal( mInterpVal );
- updateDirections(psky);
-
- if (!mCubeMap || LLPipeline::sReflectionProbesEnabled)
- {
- mCubeMapUpdateStage = NUM_CUBEMAP_FACES;
- mForceUpdate = false;
- return true;
- }
-
- if (mCubeMapUpdateStage < 0)
- {
- calc();
-
- bool same_atmospherics = approximatelyEqual(m_lastAtmosphericsVars, m_atmosphericsVars, UPDATE_MIN_DELTA_THRESHOLD);
-
- mNeedUpdate = mNeedUpdate || !same_atmospherics;
-
- if (mNeedUpdate && (mForceUpdateThrottle.hasExpired() || mForceUpdate))
- {
- // start updating cube map sides
- updateFog(LLViewerCamera::getInstance()->getFar());
- mCubeMapUpdateStage = 0;
- mForceUpdate = false;
- }
- }
- else if (mCubeMapUpdateStage == NUM_CUBEMAP_FACES && !LLPipeline::sReflectionProbesEnabled)
- {
- LL_PROFILE_ZONE_NAMED("updateSky - forced");
- LLSkyTex::stepCurrent();
-
- bool is_alm_wl_sky = gPipeline.canUseWindLightShaders();
-
- int tex = mSkyTex[0].getWhich(true);
-
- for (int side = 0; side < NUM_CUBEMAP_FACES; side++)
- {
- LLImageRaw* raw1 = nullptr;
- LLImageRaw* raw2 = nullptr;
-
- if (!is_alm_wl_sky)
- {
- raw1 = mSkyTex[side].getImageRaw(true);
- raw2 = mSkyTex[side].getImageRaw(false);
- raw2->copy(raw1);
- mSkyTex[side].createGLImage(tex);
- }
-
- raw1 = mShinyTex[side].getImageRaw(true);
- raw2 = mShinyTex[side].getImageRaw(false);
- raw2->copy(raw1);
- mShinyTex[side].createGLImage(tex);
- }
- next_frame = 0;
-
- // update the sky texture
- if (!is_alm_wl_sky)
- {
- for (S32 i = 0; i < NUM_CUBEMAP_FACES; ++i)
- {
- mSkyTex[i].create();
- }
- }
-
- for (S32 i = 0; i < NUM_CUBEMAP_FACES; ++i)
- {
- mShinyTex[i].create();
- }
-
- // update the environment map
- initCubeMap();
-
- m_lastAtmosphericsVars = m_atmosphericsVars;
-
- mNeedUpdate = false;
- mForceUpdate = false;
-
- mForceUpdateThrottle.setTimerExpirySec(UPDATE_EXPRY);
-
- if (mDrawable.notNull() && mDrawable->getFace(0) && !mDrawable->getFace(0)->getVertexBuffer())
- {
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME);
- }
- mCubeMapUpdateStage = -1;
- }
- // run 0 to 5 faces, each face in own frame
- else if (mCubeMapUpdateStage >= 0 && mCubeMapUpdateStage < NUM_CUBEMAP_FACES && !LLPipeline::sReflectionProbesEnabled)
- {
- LL_PROFILE_ZONE_NAMED("updateSky - create");
- S32 side = mCubeMapUpdateStage;
- // CPU hungry part, createSkyTexture() is math heavy
- // Prior to EEP it was mostly per tile, but since EPP it is per face.
- // This still can be optimized further
- // (i.e. potentially can be made per tile again, can be moved to thread
- // instead of executing per face, or may be can be moved to shaders)
- for (S32 tile = 0; tile < NUM_TILES; tile++)
- {
- createSkyTexture(psky, m_atmosphericsVars, side, tile);
- }
- mCubeMapUpdateStage++;
- }
-
- return true;
-}
-
-void LLVOSky::updateTextures()
-{
- if (mSunTexturep[0])
- {
- mSunTexturep[0]->addTextureStats( (F32)MAX_IMAGE_AREA );
- }
-
- if (mSunTexturep[1])
- {
- mSunTexturep[1]->addTextureStats( (F32)MAX_IMAGE_AREA );
-}
-
- if (mMoonTexturep[0])
-{
- mMoonTexturep[0]->addTextureStats( (F32)MAX_IMAGE_AREA );
-}
-
- if (mMoonTexturep[1])
-{
- mMoonTexturep[1]->addTextureStats( (F32)MAX_IMAGE_AREA );
-}
-
- if (mBloomTexturep[0])
- {
- mBloomTexturep[0]->addTextureStats( (F32)MAX_IMAGE_AREA );
- }
-
- if (mBloomTexturep[1])
- {
- mBloomTexturep[1]->addTextureStats( (F32)MAX_IMAGE_AREA );
- }
- }
-
-LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline)
-{
- pipeline->allocDrawable(this);
- mDrawable->setLit(false);
-
- LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY);
- poolp->setSkyTex(mSkyTex);
- mDrawable->setRenderType(LLPipeline::RENDER_TYPE_SKY);
-
- for (S32 i = 0; i < NUM_CUBEMAP_FACES; ++i)
- {
- mFace[FACE_SIDE0 + i] = mDrawable->addFace(poolp, NULL);
- }
-
- mFace[FACE_SUN] = mDrawable->addFace(poolp, nullptr);
- mFace[FACE_MOON] = mDrawable->addFace(poolp, nullptr);
- mFace[FACE_BLOOM] = mDrawable->addFace(poolp, nullptr);
-
- mFace[FACE_SUN]->setMediaAllowed(false);
- mFace[FACE_MOON]->setMediaAllowed(false);
- mFace[FACE_BLOOM]->setMediaAllowed(false);
-
- return mDrawable;
-}
-
-void LLVOSky::setSunScale(F32 sun_scale)
-{
- mSunScale = sun_scale;
-}
-
-void LLVOSky::setMoonScale(F32 moon_scale)
-{
- mMoonScale = moon_scale;
-}
-
-void LLVOSky::setSunTextures(const LLUUID& sun_texture, const LLUUID& sun_texture_next)
-{
- // We test the UUIDs here because we explicitly do not want the default image returned by getFetchedTexture in that case...
- mSunTexturep[0] = sun_texture.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(sun_texture, FTT_DEFAULT, true, LLGLTexture::BOOST_UI);
- mSunTexturep[1] = sun_texture_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(sun_texture_next, FTT_DEFAULT, true, LLGLTexture::BOOST_UI);
-
- bool can_use_wl = gPipeline.canUseWindLightShaders();
-
- if (mFace[FACE_SUN])
- {
- if (mSunTexturep[0])
- {
- mSunTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
- }
-
- LLViewerTexture* current_tex0 = mFace[FACE_SUN]->getTexture(LLRender::DIFFUSE_MAP);
- LLViewerTexture* current_tex1 = mFace[FACE_SUN]->getTexture(LLRender::ALTERNATE_DIFFUSE_MAP);
-
- if (current_tex0 && (mSunTexturep[0] != current_tex0) && current_tex0->isViewerMediaTexture())
- {
- static_cast<LLViewerMediaTexture*>(current_tex0)->removeMediaFromFace(mFace[FACE_SUN]);
- }
-
- if (current_tex1 && (mSunTexturep[1] != current_tex1) && current_tex1->isViewerMediaTexture())
- {
- static_cast<LLViewerMediaTexture*>(current_tex1)->removeMediaFromFace(mFace[FACE_SUN]);
- }
-
- mFace[FACE_SUN]->setTexture(LLRender::DIFFUSE_MAP, mSunTexturep[0]);
-
- if (can_use_wl)
- {
- if (mSunTexturep[1])
- {
- mSunTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP);
- }
- mFace[FACE_SUN]->setTexture(LLRender::ALTERNATE_DIFFUSE_MAP, mSunTexturep[1]);
- }
- }
-}
-
-void LLVOSky::setMoonTextures(const LLUUID& moon_texture, const LLUUID& moon_texture_next)
-{
- LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
-
- bool can_use_wl = gPipeline.canUseWindLightShaders();
-
- mMoonTexturep[0] = moon_texture.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(moon_texture, FTT_DEFAULT, true, LLGLTexture::BOOST_UI);
- mMoonTexturep[1] = moon_texture_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(moon_texture_next, FTT_DEFAULT, true, LLGLTexture::BOOST_UI);
-
- if (mFace[FACE_MOON])
- {
- if (mMoonTexturep[0])
- {
- mMoonTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
- }
- mFace[FACE_MOON]->setTexture(LLRender::DIFFUSE_MAP, mMoonTexturep[0]);
-
- if (mMoonTexturep[1] && can_use_wl)
- {
- mMoonTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP);
- mFace[FACE_MOON]->setTexture(LLRender::ALTERNATE_DIFFUSE_MAP, mMoonTexturep[1]);
- }
- }
-}
-
-void LLVOSky::setCloudNoiseTextures(const LLUUID& cloud_noise_texture, const LLUUID& cloud_noise_texture_next)
-{
- LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
-
- mCloudNoiseTexturep[0] = cloud_noise_texture.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(cloud_noise_texture, FTT_DEFAULT, true, LLGLTexture::BOOST_UI);
- mCloudNoiseTexturep[1] = cloud_noise_texture_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(cloud_noise_texture_next, FTT_DEFAULT, true, LLGLTexture::BOOST_UI);
-
- if (mCloudNoiseTexturep[0])
- {
- mCloudNoiseTexturep[0]->setAddressMode(LLTexUnit::TAM_WRAP);
- }
-
- if (mCloudNoiseTexturep[1])
- {
- mCloudNoiseTexturep[1]->setAddressMode(LLTexUnit::TAM_WRAP);
- }
-}
-
-void LLVOSky::setBloomTextures(const LLUUID& bloom_texture, const LLUUID& bloom_texture_next)
-{
- LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
-
- LLUUID bloom_tex = bloom_texture.isNull() ? psky->GetDefaultBloomTextureId() : bloom_texture;
- LLUUID bloom_tex_next = bloom_texture_next.isNull() ? (bloom_texture.isNull() ? psky->GetDefaultBloomTextureId() : bloom_texture) : bloom_texture_next;
-
- mBloomTexturep[0] = bloom_tex.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(bloom_tex, FTT_DEFAULT, true, LLGLTexture::BOOST_UI);
- mBloomTexturep[1] = bloom_tex_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(bloom_tex_next, FTT_DEFAULT, true, LLGLTexture::BOOST_UI);
-
- if (mBloomTexturep[0])
- {
- mBloomTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
- }
-
- if (mBloomTexturep[1])
- {
- mBloomTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP);
- }
-}
-
-bool LLVOSky::updateGeometry(LLDrawable *drawable)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE;
- if (mFace[FACE_REFLECTION] == NULL)
- {
- LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
- if (gPipeline.getPool(LLDrawPool::POOL_WATER)->getShaderLevel() != 0)
- {
- mFace[FACE_REFLECTION] = drawable->addFace(poolp, NULL);
- }
- }
-
- mCameraPosAgent = drawable->getPositionAgent();
-
- mEarthCenter.mV[0] = mCameraPosAgent.mV[0];
- mEarthCenter.mV[1] = mCameraPosAgent.mV[1];
-
- LLVector3 v_agent[8];
- for (S32 i = 0; i < 8; ++i)
- {
- 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 * SKY_BOX_MULT * LLVector3(x_sgn, y_sgn, z_sgn);
- }
-
- LLStrider<LLVector3> verticesp;
- LLStrider<LLVector3> normalsp;
- LLStrider<LLVector2> texCoordsp;
- LLStrider<U16> indicesp;
- U16 index_offset;
- LLFace *face;
-
- for (S32 side = 0; side < NUM_CUBEMAP_FACES; ++side)
- {
- face = mFace[FACE_SIDE0 + side];
-
- if (!face->getVertexBuffer())
- {
- face->setSize(4, 6);
- face->setGeomIndex(0);
- face->setIndicesIndex(0);
- LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK);
- buff->allocateBuffer(4, 6);
- face->setVertexBuffer(buff);
-
- index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
-
- S32 vtx = 0;
- S32 curr_bit = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X
- S32 side_dir = side & 1; // even - 0, odd - 1
- S32 i_bit = (curr_bit + 2) % 3;
- S32 j_bit = (i_bit + 2) % 3;
-
- LLVector3 axis;
- axis.mV[curr_bit] = 1;
- face->mCenterAgent = (F32)((side_dir << 1) - 1) * axis * HORIZON_DIST;
-
- vtx = side_dir << curr_bit;
- *(verticesp++) = v_agent[vtx];
- *(verticesp++) = v_agent[vtx | 1 << j_bit];
- *(verticesp++) = v_agent[vtx | 1 << i_bit];
- *(verticesp++) = v_agent[vtx | 1 << i_bit | 1 << j_bit];
-
- *(texCoordsp++) = TEX00;
- *(texCoordsp++) = TEX01;
- *(texCoordsp++) = TEX10;
- *(texCoordsp++) = TEX11;
-
- // Triangles for each side
- *indicesp++ = index_offset + 0;
- *indicesp++ = index_offset + 1;
- *indicesp++ = index_offset + 3;
-
- *indicesp++ = index_offset + 0;
- *indicesp++ = index_offset + 3;
- *indicesp++ = index_offset + 2;
-
- buff->unmapBuffer();
- }
- }
-
- const LLVector3 &look_at = LLViewerCamera::getInstance()->getAtAxis();
- LLVector3 right = look_at % LLVector3::z_axis;
- LLVector3 up = right % look_at;
- right.normalize();
- up.normalize();
-
- bool draw_sun = updateHeavenlyBodyGeometry(drawable, mSunScale, FACE_SUN, mSun, up, right);
- bool draw_moon = updateHeavenlyBodyGeometry(drawable, mMoonScale, FACE_MOON, mMoon, up, right);
-
- draw_sun &= LLEnvironment::getInstance()->getIsSunUp();
- draw_moon &= LLEnvironment::getInstance()->getIsMoonUp();
-
- mSun.setDraw(draw_sun);
- mMoon.setDraw(draw_moon);
-
- const F32 water_height = gAgent.getRegion()->getWaterHeight() + 0.01f;
- // LLWorld::getInstance()->getWaterHeight() + 0.01f;
- const F32 camera_height = mCameraPosAgent.mV[2];
- const F32 height_above_water = camera_height - water_height;
-
- bool sun_flag = false;
- if (mSun.isVisible())
- {
- sun_flag = !mMoon.isVisible() || ((look_at * mSun.getDirection()) > 0);
- }
-
- bool above_water = (height_above_water > 0);
- bool render_ref = above_water && gPipeline.getPool(LLDrawPool::POOL_WATER)->getShaderLevel() == 0;
- setDrawRefl(above_water ? (sun_flag ? 0 : 1) : -1);
- if (render_ref)
- {
- updateReflectionGeometry(drawable, height_above_water, mSun);
- }
-
- LLPipeline::sCompiles++;
- return true;
-}
-
-bool LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, F32 scale, const S32 f, LLHeavenBody& hb, const LLVector3 &up, const LLVector3 &right)
-{
- mHeavenlyBodyUpdated = true ;
-
- LLStrider<LLVector3> verticesp;
- LLStrider<LLVector3> normalsp;
- LLStrider<LLVector2> texCoordsp;
- LLStrider<U16> indicesp;
- S32 index_offset;
- LLFace *facep;
-
-
- LLQuaternion rot = hb.getRotation();
- LLVector3 to_dir = LLVector3::x_axis * rot;
-
- LLVector3 hb_right = to_dir % LLVector3::z_axis;
- LLVector3 hb_up = hb_right % to_dir;
-
- // at zenith so math below fails spectacularly
- if ((to_dir * LLVector3::z_axis) > 0.99f)
- {
- hb_right = LLVector3::y_axis_neg * rot;
- hb_up = LLVector3::z_axis * rot;
- }
-
- LLVector3 draw_pos = to_dir * HEAVENLY_BODY_DIST;
-
- hb_right.normalize();
- hb_up.normalize();
-
- const F32 enlargm_factor = ( 1 - to_dir.mV[2] );
- F32 horiz_enlargement = 1 + enlargm_factor * 0.3f;
- F32 vert_enlargement = 1 + enlargm_factor * 0.2f;
-
- const LLVector3 scaled_right = horiz_enlargement * scale * HEAVENLY_BODY_DIST * HEAVENLY_BODY_FACTOR * hb.getDiskRadius() * hb_right;
- const LLVector3 scaled_up = vert_enlargement * scale * HEAVENLY_BODY_DIST * HEAVENLY_BODY_FACTOR * hb.getDiskRadius() * hb_up;
-
- LLVector3 v_clipped[4];
-
- v_clipped[0] = draw_pos - scaled_right + scaled_up;
- v_clipped[1] = draw_pos - scaled_right - scaled_up;
- v_clipped[2] = draw_pos + scaled_right + scaled_up;
- v_clipped[3] = draw_pos + scaled_right - scaled_up;
-
- hb.setVisible(true);
-
- facep = mFace[f];
-
- if (!facep->getVertexBuffer())
- {
- facep->setSize(4, 6);
- LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK);
- if (!buff->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount()))
- {
- LL_WARNS() << "Failed to allocate Vertex Buffer for vosky to "
- << facep->getGeomCount() << " vertices and "
- << facep->getIndicesCount() << " indices" << LL_ENDL;
- }
- facep->setGeomIndex(0);
- facep->setIndicesIndex(0);
- facep->setVertexBuffer(buff);
- }
-
- llassert(facep->getVertexBuffer()->getNumIndices() == 6);
-
- index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
-
- if (-1 == index_offset)
- {
- return true;
- }
-
- for (S32 vtx = 0; vtx < 4; ++vtx)
- {
- hb.corner(vtx) = v_clipped[vtx];
- *(verticesp++) = hb.corner(vtx) + mCameraPosAgent;
- }
-
- *(texCoordsp++) = TEX01;
- *(texCoordsp++) = TEX00;
- *(texCoordsp++) = TEX11;
- *(texCoordsp++) = TEX10;
-
- *indicesp++ = index_offset + 0;
- *indicesp++ = index_offset + 2;
- *indicesp++ = index_offset + 1;
-
- *indicesp++ = index_offset + 1;
- *indicesp++ = index_offset + 2;
- *indicesp++ = index_offset + 3;
-
- facep->getVertexBuffer()->unmapBuffer();
-
- return true;
-}
-
-F32 dtReflection(const LLVector3& p, F32 cos_dir_from_top, F32 sin_dir_from_top, F32 diff_angl_dir)
-{
- LLVector3 P = p;
- P.normalize();
-
- const F32 cos_dir_angle = -P.mV[VZ];
- const F32 sin_dir_angle = sqrt(1 - cos_dir_angle * cos_dir_angle);
-
- F32 cos_diff_angles = cos_dir_angle * cos_dir_from_top
- + sin_dir_angle * sin_dir_from_top;
-
- F32 diff_angles;
- if (cos_diff_angles > (1 - 1e-7))
- diff_angles = 0;
- else
- diff_angles = acos(cos_diff_angles);
-
- const F32 rel_diff_angles = diff_angles / diff_angl_dir;
- const F32 dt = 1 - rel_diff_angles;
-
- return (dt < 0) ? 0 : dt;
-}
-
-
-F32 dtClip(const LLVector3& v0, const LLVector3& v1, F32 far_clip2)
-{
- F32 dt_clip;
- const LLVector3 otrezok = v1 - v0;
- const F32 A = otrezok.lengthSquared();
- const F32 B = v0 * otrezok;
- const F32 C = v0.lengthSquared() - far_clip2;
- const F32 det = sqrt(B*B - A*C);
- dt_clip = (-B - det) / A;
- if ((dt_clip < 0) || (dt_clip > 1))
- dt_clip = (-B + det) / A;
- return dt_clip;
-}
-
-
-void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
- const LLHeavenBody& HB)
-{
- const LLVector3 &look_at = LLViewerCamera::getInstance()->getAtAxis();
- // const F32 water_height = gAgent.getRegion()->getWaterHeight() + 0.001f;
- // LLWorld::getInstance()->getWaterHeight() + 0.001f;
-
- LLVector3 to_dir = HB.getDirection();
- LLVector3 hb_pos = to_dir * (HORIZON_DIST - 10);
- LLVector3 to_dir_proj = to_dir;
- to_dir_proj.mV[VZ] = 0;
- to_dir_proj.normalize();
-
- LLVector3 Right = to_dir % LLVector3::z_axis;
- LLVector3 Up = Right % to_dir;
- Right.normalize();
- Up.normalize();
-
- // finding angle between look direction and sprite.
- LLVector3 look_at_right = look_at % LLVector3::z_axis;
- look_at_right.normalize();
-
- const F32 enlargm_factor = ( 1 - to_dir.mV[2] );
- F32 horiz_enlargement = 1 + enlargm_factor * 0.3f;
- F32 vert_enlargement = 1 + enlargm_factor * 0.2f;
-
- F32 vert_size = vert_enlargement * HEAVENLY_BODY_SCALE * HB.getDiskRadius();
- Right *= /*cos_lookAt_toDir */ horiz_enlargement * HEAVENLY_BODY_SCALE * HB.getDiskRadius();
- Up *= vert_size;
-
- LLVector3 v_corner[2];
- LLVector3 stretch_corner[2];
-
- LLVector3 top_hb = v_corner[0] = stretch_corner[0] = hb_pos - Right + Up;
- v_corner[1] = stretch_corner[1] = hb_pos - Right - Up;
-
- LLVector2 TEX0t = TEX00;
- LLVector2 TEX1t = TEX10;
- LLVector3 lower_corner = v_corner[1];
-
- top_hb.normalize();
- const F32 cos_angle_of_view = fabs(top_hb.mV[VZ]);
- const F32 extension = llmin (5.0f, 1.0f / cos_angle_of_view);
-
- const S32 cols = 1;
- const S32 raws = lltrunc(16 * extension);
- S32 quads = cols * raws;
-
- stretch_corner[0] = lower_corner + extension * (stretch_corner[0] - lower_corner);
- stretch_corner[1] = lower_corner + extension * (stretch_corner[1] - lower_corner);
-
- F32 cos_dir_from_top[2];
-
- LLVector3 dir = stretch_corner[0];
- dir.normalize();
- cos_dir_from_top[0] = dir.mV[VZ];
-
- dir = stretch_corner[1];
- dir.normalize();
- cos_dir_from_top[1] = dir.mV[VZ];
-
- const F32 sin_dir_from_top = sqrt(1 - cos_dir_from_top[0] * cos_dir_from_top[0]);
- const F32 sin_dir_from_top2 = sqrt(1 - cos_dir_from_top[1] * cos_dir_from_top[1]);
- const F32 cos_diff_dir = cos_dir_from_top[0] * cos_dir_from_top[1]
- + sin_dir_from_top * sin_dir_from_top2;
- const F32 diff_angl_dir = acos(cos_diff_dir);
-
- v_corner[0] = stretch_corner[0];
- v_corner[1] = lower_corner;
-
-
- LLVector2 TEX0tt = TEX01;
- LLVector2 TEX1tt = TEX11;
-
- LLVector3 v_refl_corner[4];
- LLVector3 v_sprite_corner[4];
-
- S32 vtx;
- for (vtx = 0; vtx < 2; ++vtx)
- {
- LLVector3 light_proj = v_corner[vtx];
- light_proj.normalize();
-
- const F32 z = light_proj.mV[VZ];
- const F32 sin_angle = sqrt(1 - z * z);
- light_proj *= 1.f / sin_angle;
- light_proj.mV[VZ] = 0;
- const F32 to_refl_point = H * sin_angle / fabs(z);
-
- v_refl_corner[vtx] = to_refl_point * light_proj;
- }
-
-
- for (vtx = 2; vtx < 4; ++vtx)
- {
- const LLVector3 to_dir_vec = (to_dir_proj * v_refl_corner[vtx-2]) * to_dir_proj;
- v_refl_corner[vtx] = v_refl_corner[vtx-2] + 2 * (to_dir_vec - v_refl_corner[vtx-2]);
- }
-
- for (vtx = 0; vtx < 4; ++vtx)
- v_refl_corner[vtx].mV[VZ] -= H;
-
- S32 side = 0;
- LLVector3 refl_corn_norm[2];
- refl_corn_norm[0] = v_refl_corner[1];
- refl_corn_norm[0].normalize();
- refl_corn_norm[1] = v_refl_corner[3];
- refl_corn_norm[1].normalize();
-
- F32 cos_refl_look_at[2];
- cos_refl_look_at[0] = refl_corn_norm[0] * look_at;
- cos_refl_look_at[1] = refl_corn_norm[1] * look_at;
-
- if (cos_refl_look_at[1] > cos_refl_look_at[0])
- {
- side = 2;
- }
-
- //const F32 far_clip = (LLViewerCamera::getInstance()->getFar() - 0.01) / far_clip_factor;
- const F32 far_clip = 512;
- const F32 far_clip2 = far_clip*far_clip;
-
- F32 dt_clip;
- F32 vtx_near2, vtx_far2;
-
- if ((vtx_far2 = v_refl_corner[side].lengthSquared()) > far_clip2)
- {
- // whole thing is sprite: reflection is beyond far clip plane.
- dt_clip = 1.1f;
- quads = 1;
- }
- else if ((vtx_near2 = v_refl_corner[side+1].lengthSquared()) > far_clip2)
- {
- // part is reflection, the rest is sprite.
- dt_clip = dtClip(v_refl_corner[side + 1], v_refl_corner[side], far_clip2);
- const LLVector3 P = (1 - dt_clip) * v_refl_corner[side + 1] + dt_clip * v_refl_corner[side];
-
- F32 dt_tex = dtReflection(P, cos_dir_from_top[0], sin_dir_from_top, diff_angl_dir);
-
- TEX0tt = LLVector2(0, dt_tex);
- TEX1tt = LLVector2(1, dt_tex);
- quads++;
- }
- else
- {
- // whole thing is correct reflection.
- dt_clip = -0.1f;
- }
-
- LLFace *face = mFace[FACE_REFLECTION];
-
- if (face)
- {
- if (!face->getVertexBuffer() || quads*4 != face->getGeomCount())
- {
- face->setSize(quads * 4, quads * 6);
- LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK);
- if (!buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount()))
- {
- LL_WARNS() << "Failed to allocate Vertex Buffer for vosky to "
- << face->getGeomCount() << " vertices and "
- << face->getIndicesCount() << " indices" << LL_ENDL;
- }
- face->setIndicesIndex(0);
- face->setGeomIndex(0);
- face->setVertexBuffer(buff);
- }
-
- LLStrider<LLVector3> verticesp;
- LLStrider<LLVector3> normalsp;
- LLStrider<LLVector2> texCoordsp;
- LLStrider<U16> indicesp;
- S32 index_offset;
-
- index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
- if (-1 == index_offset)
- {
- return;
- }
-
- LLColor3 hb_col3 = HB.getInterpColor();
- hb_col3.clamp();
- const LLColor4 hb_col = LLColor4(hb_col3);
-
- const F32 min_attenuation = 0.4f;
- const F32 max_attenuation = 0.7f;
- const F32 attenuation = min_attenuation
- + cos_angle_of_view * (max_attenuation - min_attenuation);
-
- LLColor4 hb_refl_col = (1 - attenuation) * hb_col + attenuation * getSkyFogColor();
- face->setFaceColor(hb_refl_col);
-
- LLVector3 v_far[2];
- v_far[0] = v_refl_corner[1];
- v_far[1] = v_refl_corner[3];
-
- if(dt_clip > 0)
- {
- if (dt_clip >= 1)
- {
- for (S32 vtx = 0; vtx < 4; ++vtx)
- {
- F32 ratio = far_clip / v_refl_corner[vtx].length();
- *(verticesp++) = v_refl_corner[vtx] = ratio * v_refl_corner[vtx] + mCameraPosAgent;
- }
- const LLVector3 draw_pos = 0.25 *
- (v_refl_corner[0] + v_refl_corner[1] + v_refl_corner[2] + v_refl_corner[3]);
- face->mCenterAgent = draw_pos;
- }
- else
- {
- F32 ratio = far_clip / v_refl_corner[1].length();
- v_sprite_corner[1] = v_refl_corner[1] * ratio;
-
- ratio = far_clip / v_refl_corner[3].length();
- v_sprite_corner[3] = v_refl_corner[3] * ratio;
-
- v_refl_corner[1] = (1 - dt_clip) * v_refl_corner[1] + dt_clip * v_refl_corner[0];
- v_refl_corner[3] = (1 - dt_clip) * v_refl_corner[3] + dt_clip * v_refl_corner[2];
- v_sprite_corner[0] = v_refl_corner[1];
- v_sprite_corner[2] = v_refl_corner[3];
-
- for (S32 vtx = 0; vtx < 4; ++vtx)
- {
- *(verticesp++) = v_sprite_corner[vtx] + mCameraPosAgent;
- }
-
- const LLVector3 draw_pos = 0.25 *
- (v_refl_corner[0] + v_sprite_corner[1] + v_refl_corner[2] + v_sprite_corner[3]);
- face->mCenterAgent = draw_pos;
- }
-
- *(texCoordsp++) = TEX0tt;
- *(texCoordsp++) = TEX0t;
- *(texCoordsp++) = TEX1tt;
- *(texCoordsp++) = TEX1t;
-
- *indicesp++ = index_offset + 0;
- *indicesp++ = index_offset + 2;
- *indicesp++ = index_offset + 1;
-
- *indicesp++ = index_offset + 1;
- *indicesp++ = index_offset + 2;
- *indicesp++ = index_offset + 3;
-
- index_offset += 4;
- }
-
- if (dt_clip < 1)
- {
- if (dt_clip <= 0)
- {
- const LLVector3 draw_pos = 0.25 *
- (v_refl_corner[0] + v_refl_corner[1] + v_refl_corner[2] + v_refl_corner[3]);
- face->mCenterAgent = draw_pos;
- }
-
- const F32 raws_inv = 1.f/raws;
- const F32 cols_inv = 1.f/cols;
- LLVector3 left = v_refl_corner[0] - v_refl_corner[1];
- LLVector3 right = v_refl_corner[2] - v_refl_corner[3];
- left *= raws_inv;
- right *= raws_inv;
-
- for (S32 raw = 0; raw < raws; ++raw)
- {
- F32 dt_v0 = raw * raws_inv;
- F32 dt_v1 = (raw + 1) * raws_inv;
- const LLVector3 BL = v_refl_corner[1] + (F32)raw * left;
- const LLVector3 BR = v_refl_corner[3] + (F32)raw * right;
- const LLVector3 EL = BL + left;
- const LLVector3 ER = BR + right;
- dt_v0 = dt_v1 = dtReflection(EL, cos_dir_from_top[0], sin_dir_from_top, diff_angl_dir);
- for (S32 col = 0; col < cols; ++col)
- {
- F32 dt_h0 = col * cols_inv;
- *(verticesp++) = (1 - dt_h0) * EL + dt_h0 * ER + mCameraPosAgent;
- *(verticesp++) = (1 - dt_h0) * BL + dt_h0 * BR + mCameraPosAgent;
- F32 dt_h1 = (col + 1) * cols_inv;
- *(verticesp++) = (1 - dt_h1) * EL + dt_h1 * ER + mCameraPosAgent;
- *(verticesp++) = (1 - dt_h1) * BL + dt_h1 * BR + mCameraPosAgent;
-
- *(texCoordsp++) = LLVector2(dt_h0, dt_v1);
- *(texCoordsp++) = LLVector2(dt_h0, dt_v0);
- *(texCoordsp++) = LLVector2(dt_h1, dt_v1);
- *(texCoordsp++) = LLVector2(dt_h1, dt_v0);
-
- *indicesp++ = index_offset + 0;
- *indicesp++ = index_offset + 2;
- *indicesp++ = index_offset + 1;
-
- *indicesp++ = index_offset + 1;
- *indicesp++ = index_offset + 2;
- *indicesp++ = index_offset + 3;
-
- index_offset += 4;
- }
- }
- }
-
- face->getVertexBuffer()->unmapBuffer();
-}
-}
-
-void LLVOSky::updateFog(const F32 distance)
-{
- LLEnvironment& environment = LLEnvironment::instance();
- if (environment.getCurrentSky() != nullptr)
- {
- LLVector3 light_dir = LLVector3(environment.getClampedLightNorm());
- m_legacyAtmospherics.updateFog(distance, light_dir);
- }
- }
-
-void LLVOSky::setSunAndMoonDirectionsCFR(const LLVector3 &sun_dir_cfr, const LLVector3 &moon_dir_cfr)
-{
- mSun.setDirection(sun_dir_cfr);
- mMoon.setDirection(moon_dir_cfr);
-
- // Push the sun "South" as it approaches directly overhead so that we can always see bump mapping
- // on the upward facing faces of cubes.
- // Same as dot product with the up direction + clamp.
- F32 sunDot = llmax(0.f, sun_dir_cfr.mV[2]);
- sunDot *= sunDot;
-
- // Create normalized vector that has the sunDir pushed south about an hour and change.
- LLVector3 adjustedDir = (sun_dir_cfr + LLVector3(0.f, -0.70711f, 0.70711f)) * 0.5f;
-
- // Blend between normal sun dir and adjusted sun dir based on how close we are
- // to having the sun overhead.
- mBumpSunDir = adjustedDir * sunDot + sun_dir_cfr * (1.0f - sunDot);
- mBumpSunDir.normalize();
-
- LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
- updateDirections(psky);
-}
-
-void LLVOSky::setSunDirectionCFR(const LLVector3 &sun_dir_cfr)
-{
- mSun.setDirection(sun_dir_cfr);
-
- // Push the sun "South" as it approaches directly overhead so that we can always see bump mapping
- // on the upward facing faces of cubes.
- // Same as dot product with the up direction + clamp.
- F32 sunDot = llmax(0.f, sun_dir_cfr.mV[2]);
- sunDot *= sunDot;
-
- // Create normalized vector that has the sunDir pushed south about an hour and change.
- LLVector3 adjustedDir = (sun_dir_cfr + LLVector3(0.f, -0.70711f, 0.70711f)) * 0.5f;
-
- // Blend between normal sun dir and adjusted sun dir based on how close we are
- // to having the sun overhead.
- mBumpSunDir = adjustedDir * sunDot + sun_dir_cfr * (1.0f - sunDot);
- mBumpSunDir.normalize();
-
- LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
- updateDirections(psky);
-}
-
-void LLVOSky::setMoonDirectionCFR(const LLVector3 &moon_dir_cfr)
-{
- mMoon.setDirection(moon_dir_cfr);
- LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
- updateDirections(psky);
-}
+/** + * @file llvosky.cpp + * @brief LLVOSky class implementation + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llvosky.h" + +#include "llfeaturemanager.h" +#include "llviewercontrol.h" +#include "llframetimer.h" + +#include "llagent.h" +#include "llagentcamera.h" +#include "lldrawable.h" +#include "llface.h" +#include "llcubemap.h" +#include "lldrawpoolsky.h" +#include "lldrawpoolwater.h" +#include "llglheaders.h" +#include "llsky.h" +#include "llviewercamera.h" +#include "llviewertexturelist.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llworld.h" +#include "pipeline.h" +#include "lldrawpoolwlsky.h" +#include "v3colorutil.h" + +#include "llsettingssky.h" +#include "llenvironment.h" + +#include "lltrace.h" +#include "llfasttimer.h" + +#undef min +#undef max + +namespace +{ + const S32 NUM_TILES_X = 8; + const S32 NUM_TILES_Y = 4; + const S32 NUM_TILES = NUM_TILES_X * NUM_TILES_Y; + const S32 NUM_CUBEMAP_FACES = 6; // See SKYTEX_RESOLUTION for face dimensions + const S32 TOTAL_TILES = NUM_CUBEMAP_FACES * NUM_TILES; + const S32 MAX_TILES = TOTAL_TILES + 1; + +// 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; + +// 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); + + F32Seconds UPDATE_EXPRY(0.25f); + + const F32 UPDATE_MIN_DELTA_THRESHOLD = 0.0005f; +} +/*************************************** + SkyTex +***************************************/ + +S32 LLSkyTex::sCurrent = 0; + + +LLSkyTex::LLSkyTex() : + mSkyData(NULL), + mSkyDirs(NULL), + mIsShiny(false) +{ +} + +void LLSkyTex::init(bool isShiny) +{ + mIsShiny = isShiny; + mSkyData = new LLColor4[(U32)(SKYTEX_RESOLUTION * SKYTEX_RESOLUTION)]; + mSkyDirs = new LLVector3[(U32)(SKYTEX_RESOLUTION * SKYTEX_RESOLUTION)]; + + for (S32 i = 0; i < 2; ++i) + { + mTexture[i] = LLViewerTextureManager::getLocalTexture(false); + mTexture[i]->setAddressMode(LLTexUnit::TAM_CLAMP); + mImageRaw[i] = new LLImageRaw(SKYTEX_RESOLUTION, SKYTEX_RESOLUTION, SKYTEX_COMPONENTS); + + initEmpty(i); + } +} + +void LLSkyTex::cleanupGL() +{ + mTexture[0] = NULL; + mTexture[1] = NULL; +} + +void LLSkyTex::restoreGL() +{ + for (S32 i = 0; i < 2; i++) + { + mTexture[i] = LLViewerTextureManager::getLocalTexture(false); + mTexture[i]->setAddressMode(LLTexUnit::TAM_CLAMP); + } +} + +LLSkyTex::~LLSkyTex() +{ + delete[] mSkyData; + mSkyData = NULL; + + delete[] mSkyDirs; + mSkyDirs = NULL; +} + +S32 LLSkyTex::getResolution() +{ + return SKYTEX_RESOLUTION; +} + +S32 LLSkyTex::getCurrent() +{ + return sCurrent; +} + +S32 LLSkyTex::stepCurrent() { + sCurrent++; + sCurrent &= 1; + return sCurrent; +} + +S32 LLSkyTex::getNext() +{ + return ((sCurrent+1) & 1); +} + +S32 LLSkyTex::getWhich(const bool curr) +{ + int tex = curr ? sCurrent : getNext(); + return tex; +} + +void LLSkyTex::initEmpty(const S32 tex) +{ + LLImageDataLock lock(mImageRaw[tex]); + U8* data = mImageRaw[tex]->getData(); + for (S32 i = 0; i < SKYTEX_RESOLUTION; ++i) + { + for (S32 j = 0; j < SKYTEX_RESOLUTION; ++j) + { + const S32 basic_offset = (i * SKYTEX_RESOLUTION + j); + S32 offset = basic_offset * SKYTEX_COMPONENTS; + data[offset] = 0; + data[offset+1] = 0; + data[offset+2] = 0; + data[offset+3] = 255; + + mSkyData[basic_offset].setToBlack(); + } + } + + createGLImage(tex); +} + +void LLSkyTex::create() +{ + LLImageDataSharedLock lock(mImageRaw[sCurrent]); + const U8* data = mImageRaw[sCurrent]->getData(); + for (S32 i = 0; i < SKYTEX_RESOLUTION; ++i) + { + for (S32 j = 0; j < SKYTEX_RESOLUTION; ++j) + { + const S32 basic_offset = (i * SKYTEX_RESOLUTION + j); + S32 offset = basic_offset * SKYTEX_COMPONENTS; + U32* pix = (U32*)(data + offset); + LLColor4U temp = LLColor4U(mSkyData[basic_offset]); + *pix = temp.asRGBA(); + } + } + createGLImage(sCurrent); +} + +void LLSkyTex::createGLImage(S32 which) +{ + mTexture[which]->setExplicitFormat(GL_RGBA8, GL_RGBA); + mTexture[which]->createGLTexture(0, mImageRaw[which], 0, true, LLGLTexture::LOCAL); + mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP); +} + +void LLSkyTex::bindTexture(bool curr) +{ + int tex = getWhich(curr); + gGL.getTexUnit(0)->bind(mTexture[tex], true); +} + +LLImageRaw* LLSkyTex::getImageRaw(bool curr) +{ + int tex = getWhich(curr); + return mImageRaw[tex]; +} + +/*************************************** + LLHeavenBody +***************************************/ + +F32 LLHeavenBody::sInterpVal = 0; + +LLHeavenBody::LLHeavenBody(const F32 rad) +: mDirectionCached(LLVector3(0,0,0)), + mDirection(LLVector3(0,0,0)), + mIntensity(0.f), + mDiskRadius(rad), + mDraw(false), + mHorizonVisibility(1.f), + mVisibility(1.f), + mVisible(false) +{ + mColor.setToBlack(); + mColorCached.setToBlack(); +} + +const LLQuaternion& LLHeavenBody::getRotation() const +{ + return mRotation; +} + +void LLHeavenBody::setRotation(const LLQuaternion& rot) +{ + mRotation = rot; +} + +const LLVector3& LLHeavenBody::getDirection() const +{ + return mDirection; +} + +void LLHeavenBody::setDirection(const LLVector3 &direction) +{ + mDirection = direction; +} + +void LLHeavenBody::setAngularVelocity(const LLVector3 &ang_vel) +{ + mAngularVelocity = ang_vel; +} + +const LLVector3& LLHeavenBody::getAngularVelocity() const +{ + return mAngularVelocity; +} + +const LLVector3& LLHeavenBody::getDirectionCached() const +{ + return mDirectionCached; +} + +void LLHeavenBody::renewDirection() +{ + mDirectionCached = mDirection; +} + +const LLColor3& LLHeavenBody::getColorCached() const +{ + return mColorCached; +} + +void LLHeavenBody::setColorCached(const LLColor3& c) +{ + mColorCached = c; +} + +const LLColor3& LLHeavenBody::getColor() const +{ + return mColor; +} + +void LLHeavenBody::setColor(const LLColor3& c) +{ + mColor = c; +} + +void LLHeavenBody::renewColor() +{ + mColorCached = mColor; +} + +F32 LLHeavenBody::interpVal() +{ + return sInterpVal; +} + +void LLHeavenBody::setInterpVal(const F32 v) +{ + sInterpVal = v; +} + +LLColor3 LLHeavenBody::getInterpColor() const +{ + return sInterpVal * mColor + (1 - sInterpVal) * mColorCached; +} + +const F32& LLHeavenBody::getVisibility() const +{ + return mVisibility; +} + +void LLHeavenBody::setVisibility(const F32 c) +{ + mVisibility = c; +} + +bool LLHeavenBody::isVisible() const +{ + return mVisible; +} + +void LLHeavenBody::setVisible(const bool v) +{ + mVisible = v; +} + +const F32& LLHeavenBody::getIntensity() const +{ + return mIntensity; +} + +void LLHeavenBody::setIntensity(const F32 c) +{ + mIntensity = c; +} + +void LLHeavenBody::setDiskRadius(const F32 radius) +{ + mDiskRadius = radius; +} + +F32 LLHeavenBody::getDiskRadius() const +{ + return mDiskRadius; +} + +void LLHeavenBody::setDraw(const bool draw) +{ + mDraw = draw; +} + +bool LLHeavenBody::getDraw() const +{ + return mDraw; +} + +const LLVector3& LLHeavenBody::corner(const S32 n) const +{ + return mQuadCorner[n]; +} + +LLVector3& LLHeavenBody::corner(const S32 n) +{ + return mQuadCorner[n]; +} + +const LLVector3* LLHeavenBody::corners() const +{ + return mQuadCorner; +} + +/*************************************** + Sky +***************************************/ + +const S32 SKYTEX_TILE_RES_X = SKYTEX_RESOLUTION / NUM_TILES_X; +const S32 SKYTEX_TILE_RES_Y = SKYTEX_RESOLUTION / NUM_TILES_Y; + +LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) +: LLStaticViewerObject(id, pcode, regionp, true), + mSun(SUN_DISK_RADIUS), mMoon(MOON_DISK_RADIUS), + mBrightnessScale(1.f), + mBrightnessScaleNew(0.f), + mBrightnessScaleGuess(1.f), + mWeatherChange(false), + mCloudDensity(0.2f), + mWind(0.f), + mForceUpdate(false), + mNeedUpdate(true), + mCubeMapUpdateStage(-1), + mWorldScale(1.f), + mBumpSunDir(0.f, 0.f, 1.f) +{ + /// WL PARAMS + + mInitialized = false; + mbCanSelect = false; + mUpdateTimer.reset(); + + mForceUpdateThrottle.setTimerExpirySec(UPDATE_EXPRY); + mForceUpdateThrottle.reset(); + + for (S32 i = 0; i < NUM_CUBEMAP_FACES; i++) + { + mSkyTex[i].init(false); + mShinyTex[i].init(true); + } + for (S32 i=0; i<FACE_COUNT; i++) + { + mFace[i] = NULL; + } + + mCameraPosAgent = gAgentCamera.getCameraPositionAgent(); + mAtmHeight = ATM_HEIGHT; + mEarthCenter = LLVector3(mCameraPosAgent.mV[0], mCameraPosAgent.mV[1], -EARTH_RADIUS); + + mSun.setIntensity(SUN_INTENSITY); + mMoon.setIntensity(0.1f * SUN_INTENSITY); + + mHeavenlyBodyUpdated = false ; + + mDrawRefl = 0; + mInterpVal = 0.f; +} + + +LLVOSky::~LLVOSky() +{ + // Don't delete images - it'll get deleted by gTextureList on shutdown + // This needs to be done for each texture + + mCubeMap = NULL; +} + +void LLVOSky::init() +{ + llassert(!mInitialized); + + // Update sky at least once to get correct initial sun/moon directions and lighting calcs performed + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + psky->update(); + + updateDirections(psky); + + cacheEnvironment(psky,m_atmosphericsVars); + + // Initialize the cached normalized direction vectors + for (S32 side = 0; side < NUM_CUBEMAP_FACES; ++side) + { + for (S32 tile = 0; tile < NUM_TILES; ++tile) + { + initSkyTextureDirs(side, tile); + createSkyTexture(psky, m_atmosphericsVars, side, tile); + } + mSkyTex[side].create(); + mShinyTex[side].create(); + } + + initCubeMap(); + + mInitialized = true; + + mHeavenlyBodyUpdated = false ; + + mRainbowMap = LLViewerTextureManager::getFetchedTexture(psky->getRainbowTextureId(), FTT_DEFAULT, true, LLGLTexture::BOOST_UI); + mHaloMap = LLViewerTextureManager::getFetchedTexture(psky->getHaloTextureId(), FTT_DEFAULT, true, LLGLTexture::BOOST_UI); +} + + +void LLVOSky::cacheEnvironment(LLSettingsSky::ptr_t psky,AtmosphericsVars& atmosphericsVars) +{ + // NOTE: Also see: LLAtmospherics::updateFog() + // invariants across whole sky tex process... + atmosphericsVars.blue_density = psky->getBlueDensity(); + atmosphericsVars.blue_horizon = psky->getBlueHorizon(); + atmosphericsVars.haze_density = psky->getHazeDensity(); + atmosphericsVars.haze_horizon = psky->getHazeHorizon(); + atmosphericsVars.density_multiplier = psky->getDensityMultiplier(); + atmosphericsVars.distance_multiplier = psky->getDistanceMultiplier(); + atmosphericsVars.max_y = psky->getMaxY(); + atmosphericsVars.sun_norm = LLEnvironment::instance().getClampedSunNorm(); + atmosphericsVars.sunlight = psky->getIsSunUp() ? psky->getSunlightColor() : psky->getMoonlightColor(); + atmosphericsVars.ambient = psky->getAmbientColor(); + atmosphericsVars.glow = psky->getGlow(); + atmosphericsVars.cloud_shadow = psky->getCloudShadow(); + atmosphericsVars.dome_radius = psky->getDomeRadius(); + atmosphericsVars.dome_offset = psky->getDomeOffset(); + atmosphericsVars.light_atten = psky->getLightAttenuation(atmosphericsVars.max_y); + atmosphericsVars.light_transmittance = psky->getLightTransmittance(atmosphericsVars.max_y); + atmosphericsVars.total_density = psky->getTotalDensity(); + atmosphericsVars.gamma = psky->getGamma(); +} + +void LLVOSky::calc() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT; + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + cacheEnvironment(psky,m_atmosphericsVars); + + mSun.setColor(psky->getSunDiffuse()); + mMoon.setColor(LLColor3(1.0f, 1.0f, 1.0f)); + + mSun.renewDirection(); + mSun.renewColor(); + mMoon.renewDirection(); + mMoon.renewColor(); +} + +void LLVOSky::initCubeMap() +{ + std::vector<LLPointer<LLImageRaw> > images; + for (S32 side = 0; side < NUM_CUBEMAP_FACES; side++) + { + images.push_back(mShinyTex[side].getImageRaw()); + } + + if (!mCubeMap && gSavedSettings.getBOOL("RenderWater") && LLCubeMap::sUseCubeMaps) + { + mCubeMap = new LLCubeMap(false); + } + + if (mCubeMap) + { + mCubeMap->init(images); + } + + gGL.getTexUnit(0)->disable(); +} + + +void LLVOSky::cleanupGL() +{ + S32 i; + for (i = 0; i < NUM_CUBEMAP_FACES; i++) + { + mSkyTex[i].cleanupGL(); + } + if (getCubeMap()) + { + getCubeMap()->destroyGL(); + } +} + +void LLVOSky::restoreGL() +{ + S32 i; + for (i = 0; i < NUM_CUBEMAP_FACES; i++) + { + mSkyTex[i].restoreGL(); + } + + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + + if (psky) + { + setSunTextures(psky->getSunTextureId(), psky->getNextSunTextureId()); + setMoonTextures(psky->getMoonTextureId(), psky->getNextMoonTextureId()); + } + + updateDirections(psky); + + if (gSavedSettings.getBOOL("RenderWater") && LLCubeMap::sUseCubeMaps) + { + initCubeMap(); + } + + forceSkyUpdate(); + + if (mDrawable) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME); + } + +} + +void LLVOSky::initSkyTextureDirs(const S32 side, const S32 tile) +{ + S32 tile_x = tile % NUM_TILES_X; + S32 tile_y = tile / NUM_TILES_X; + + S32 tile_x_pos = tile_x * SKYTEX_TILE_RES_X; + S32 tile_y_pos = tile_y * SKYTEX_TILE_RES_Y; + + F32 coeff[3] = {0, 0, 0}; + const S32 curr_coef = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X + const S32 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1 + const S32 x_coef = (curr_coef + 1) % 3; + const S32 y_coef = (x_coef + 1) % 3; + + coeff[curr_coef] = (F32)side_dir; + + F32 inv_res = 1.f/SKYTEX_RESOLUTION; + S32 x, y; + for (y = tile_y_pos; y < (tile_y_pos + SKYTEX_TILE_RES_Y); ++y) + { + for (x = tile_x_pos; x < (tile_x_pos + SKYTEX_TILE_RES_X); ++x) + { + coeff[x_coef] = F32((x<<1) + 1) * inv_res - 1.f; + coeff[y_coef] = F32((y<<1) + 1) * inv_res - 1.f; + LLVector3 dir(coeff[0], coeff[1], coeff[2]); + dir.normalize(); + mSkyTex[side].setDir(dir, x, y); + mShinyTex[side].setDir(dir, x, y); + } + } +} + +void LLVOSky::createSkyTexture(const LLSettingsSky::ptr_t &psky, AtmosphericsVars& vars, const S32 side, const S32 tile) +{ + const bool low_end = !gPipeline.canUseWindLightShaders(); + + S32 tile_x = tile % NUM_TILES_X; + S32 tile_y = tile / NUM_TILES_X; + + S32 tile_x_pos = tile_x * SKYTEX_TILE_RES_X; + S32 tile_y_pos = tile_y * SKYTEX_TILE_RES_Y; + + S32 x, y; + for (y = tile_y_pos; y < (tile_y_pos + SKYTEX_TILE_RES_Y); ++y) + { + for (x = tile_x_pos; x < (tile_x_pos + SKYTEX_TILE_RES_X); ++x) + { + mSkyTex [side].setPixel(m_legacyAtmospherics.calcSkyColorInDir(psky, vars, mSkyTex [side].getDir(x, y), false, low_end), x, y); + mShinyTex[side].setPixel(m_legacyAtmospherics.calcSkyColorInDir(psky, vars, mShinyTex[side].getDir(x, y), true , low_end), x, y); + } + } +} + +void LLVOSky::updateDirections(LLSettingsSky::ptr_t psky) +{ + mSun.setDirection(psky->getSunDirection()); + mMoon.setDirection(psky->getMoonDirection()); + mSun.setRotation(psky->getSunRotation()); + mMoon.setRotation(psky->getMoonRotation()); + mSun.renewDirection(); + mMoon.renewDirection(); +} + +void LLVOSky::idleUpdate(LLAgent &agent, const F64 &time) +{ +} + +void LLVOSky::forceSkyUpdate() +{ + mForceUpdate = true; + m_lastAtmosphericsVars = {}; + mCubeMapUpdateStage = -1; +} + +bool LLVOSky::updateSky() +{ + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + + if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))) + { + // It's dead. Don't update it. + return true; + } + + if (gGLManager.mIsDisabled) + { + return true; + } + + LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT; + + static S32 next_frame = 0; + + mNeedUpdate = mForceUpdate; + + ++next_frame; + next_frame = next_frame % MAX_TILES; + + mInterpVal = (!mInitialized) ? 1 : (F32)next_frame / MAX_TILES; + LLHeavenBody::setInterpVal( mInterpVal ); + updateDirections(psky); + + if (!mCubeMap || LLPipeline::sReflectionProbesEnabled) + { + mCubeMapUpdateStage = NUM_CUBEMAP_FACES; + mForceUpdate = false; + return true; + } + + if (mCubeMapUpdateStage < 0) + { + calc(); + + bool same_atmospherics = approximatelyEqual(m_lastAtmosphericsVars, m_atmosphericsVars, UPDATE_MIN_DELTA_THRESHOLD); + + mNeedUpdate = mNeedUpdate || !same_atmospherics; + + if (mNeedUpdate && (mForceUpdateThrottle.hasExpired() || mForceUpdate)) + { + // start updating cube map sides + updateFog(LLViewerCamera::getInstance()->getFar()); + mCubeMapUpdateStage = 0; + mForceUpdate = false; + } + } + else if (mCubeMapUpdateStage == NUM_CUBEMAP_FACES && !LLPipeline::sReflectionProbesEnabled) + { + LL_PROFILE_ZONE_NAMED("updateSky - forced"); + LLSkyTex::stepCurrent(); + + bool is_alm_wl_sky = gPipeline.canUseWindLightShaders(); + + int tex = mSkyTex[0].getWhich(true); + + for (int side = 0; side < NUM_CUBEMAP_FACES; side++) + { + LLImageRaw* raw1 = nullptr; + LLImageRaw* raw2 = nullptr; + + if (!is_alm_wl_sky) + { + raw1 = mSkyTex[side].getImageRaw(true); + raw2 = mSkyTex[side].getImageRaw(false); + raw2->copy(raw1); + mSkyTex[side].createGLImage(tex); + } + + raw1 = mShinyTex[side].getImageRaw(true); + raw2 = mShinyTex[side].getImageRaw(false); + raw2->copy(raw1); + mShinyTex[side].createGLImage(tex); + } + next_frame = 0; + + // update the sky texture + if (!is_alm_wl_sky) + { + for (S32 i = 0; i < NUM_CUBEMAP_FACES; ++i) + { + mSkyTex[i].create(); + } + } + + for (S32 i = 0; i < NUM_CUBEMAP_FACES; ++i) + { + mShinyTex[i].create(); + } + + // update the environment map + initCubeMap(); + + m_lastAtmosphericsVars = m_atmosphericsVars; + + mNeedUpdate = false; + mForceUpdate = false; + + mForceUpdateThrottle.setTimerExpirySec(UPDATE_EXPRY); + + if (mDrawable.notNull() && mDrawable->getFace(0) && !mDrawable->getFace(0)->getVertexBuffer()) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME); + } + mCubeMapUpdateStage = -1; + } + // run 0 to 5 faces, each face in own frame + else if (mCubeMapUpdateStage >= 0 && mCubeMapUpdateStage < NUM_CUBEMAP_FACES && !LLPipeline::sReflectionProbesEnabled) + { + LL_PROFILE_ZONE_NAMED("updateSky - create"); + S32 side = mCubeMapUpdateStage; + // CPU hungry part, createSkyTexture() is math heavy + // Prior to EEP it was mostly per tile, but since EPP it is per face. + // This still can be optimized further + // (i.e. potentially can be made per tile again, can be moved to thread + // instead of executing per face, or may be can be moved to shaders) + for (S32 tile = 0; tile < NUM_TILES; tile++) + { + createSkyTexture(psky, m_atmosphericsVars, side, tile); + } + mCubeMapUpdateStage++; + } + + return true; +} + +void LLVOSky::updateTextures() +{ + if (mSunTexturep[0]) + { + mSunTexturep[0]->addTextureStats( (F32)MAX_IMAGE_AREA ); + } + + if (mSunTexturep[1]) + { + mSunTexturep[1]->addTextureStats( (F32)MAX_IMAGE_AREA ); +} + + if (mMoonTexturep[0]) +{ + mMoonTexturep[0]->addTextureStats( (F32)MAX_IMAGE_AREA ); +} + + if (mMoonTexturep[1]) +{ + mMoonTexturep[1]->addTextureStats( (F32)MAX_IMAGE_AREA ); +} + + if (mBloomTexturep[0]) + { + mBloomTexturep[0]->addTextureStats( (F32)MAX_IMAGE_AREA ); + } + + if (mBloomTexturep[1]) + { + mBloomTexturep[1]->addTextureStats( (F32)MAX_IMAGE_AREA ); + } + } + +LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline) +{ + pipeline->allocDrawable(this); + mDrawable->setLit(false); + + LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY); + poolp->setSkyTex(mSkyTex); + mDrawable->setRenderType(LLPipeline::RENDER_TYPE_SKY); + + for (S32 i = 0; i < NUM_CUBEMAP_FACES; ++i) + { + mFace[FACE_SIDE0 + i] = mDrawable->addFace(poolp, NULL); + } + + mFace[FACE_SUN] = mDrawable->addFace(poolp, nullptr); + mFace[FACE_MOON] = mDrawable->addFace(poolp, nullptr); + mFace[FACE_BLOOM] = mDrawable->addFace(poolp, nullptr); + + mFace[FACE_SUN]->setMediaAllowed(false); + mFace[FACE_MOON]->setMediaAllowed(false); + mFace[FACE_BLOOM]->setMediaAllowed(false); + + return mDrawable; +} + +void LLVOSky::setSunScale(F32 sun_scale) +{ + mSunScale = sun_scale; +} + +void LLVOSky::setMoonScale(F32 moon_scale) +{ + mMoonScale = moon_scale; +} + +void LLVOSky::setSunTextures(const LLUUID& sun_texture, const LLUUID& sun_texture_next) +{ + // We test the UUIDs here because we explicitly do not want the default image returned by getFetchedTexture in that case... + mSunTexturep[0] = sun_texture.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(sun_texture, FTT_DEFAULT, true, LLGLTexture::BOOST_UI); + mSunTexturep[1] = sun_texture_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(sun_texture_next, FTT_DEFAULT, true, LLGLTexture::BOOST_UI); + + bool can_use_wl = gPipeline.canUseWindLightShaders(); + + if (mFace[FACE_SUN]) + { + if (mSunTexturep[0]) + { + mSunTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP); + } + + LLViewerTexture* current_tex0 = mFace[FACE_SUN]->getTexture(LLRender::DIFFUSE_MAP); + LLViewerTexture* current_tex1 = mFace[FACE_SUN]->getTexture(LLRender::ALTERNATE_DIFFUSE_MAP); + + if (current_tex0 && (mSunTexturep[0] != current_tex0) && current_tex0->isViewerMediaTexture()) + { + static_cast<LLViewerMediaTexture*>(current_tex0)->removeMediaFromFace(mFace[FACE_SUN]); + } + + if (current_tex1 && (mSunTexturep[1] != current_tex1) && current_tex1->isViewerMediaTexture()) + { + static_cast<LLViewerMediaTexture*>(current_tex1)->removeMediaFromFace(mFace[FACE_SUN]); + } + + mFace[FACE_SUN]->setTexture(LLRender::DIFFUSE_MAP, mSunTexturep[0]); + + if (can_use_wl) + { + if (mSunTexturep[1]) + { + mSunTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP); + } + mFace[FACE_SUN]->setTexture(LLRender::ALTERNATE_DIFFUSE_MAP, mSunTexturep[1]); + } + } +} + +void LLVOSky::setMoonTextures(const LLUUID& moon_texture, const LLUUID& moon_texture_next) +{ + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + + bool can_use_wl = gPipeline.canUseWindLightShaders(); + + mMoonTexturep[0] = moon_texture.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(moon_texture, FTT_DEFAULT, true, LLGLTexture::BOOST_UI); + mMoonTexturep[1] = moon_texture_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(moon_texture_next, FTT_DEFAULT, true, LLGLTexture::BOOST_UI); + + if (mFace[FACE_MOON]) + { + if (mMoonTexturep[0]) + { + mMoonTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP); + } + mFace[FACE_MOON]->setTexture(LLRender::DIFFUSE_MAP, mMoonTexturep[0]); + + if (mMoonTexturep[1] && can_use_wl) + { + mMoonTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP); + mFace[FACE_MOON]->setTexture(LLRender::ALTERNATE_DIFFUSE_MAP, mMoonTexturep[1]); + } + } +} + +void LLVOSky::setCloudNoiseTextures(const LLUUID& cloud_noise_texture, const LLUUID& cloud_noise_texture_next) +{ + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + + mCloudNoiseTexturep[0] = cloud_noise_texture.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(cloud_noise_texture, FTT_DEFAULT, true, LLGLTexture::BOOST_UI); + mCloudNoiseTexturep[1] = cloud_noise_texture_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(cloud_noise_texture_next, FTT_DEFAULT, true, LLGLTexture::BOOST_UI); + + if (mCloudNoiseTexturep[0]) + { + mCloudNoiseTexturep[0]->setAddressMode(LLTexUnit::TAM_WRAP); + } + + if (mCloudNoiseTexturep[1]) + { + mCloudNoiseTexturep[1]->setAddressMode(LLTexUnit::TAM_WRAP); + } +} + +void LLVOSky::setBloomTextures(const LLUUID& bloom_texture, const LLUUID& bloom_texture_next) +{ + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + + LLUUID bloom_tex = bloom_texture.isNull() ? psky->GetDefaultBloomTextureId() : bloom_texture; + LLUUID bloom_tex_next = bloom_texture_next.isNull() ? (bloom_texture.isNull() ? psky->GetDefaultBloomTextureId() : bloom_texture) : bloom_texture_next; + + mBloomTexturep[0] = bloom_tex.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(bloom_tex, FTT_DEFAULT, true, LLGLTexture::BOOST_UI); + mBloomTexturep[1] = bloom_tex_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(bloom_tex_next, FTT_DEFAULT, true, LLGLTexture::BOOST_UI); + + if (mBloomTexturep[0]) + { + mBloomTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP); + } + + if (mBloomTexturep[1]) + { + mBloomTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP); + } +} + +bool LLVOSky::updateGeometry(LLDrawable *drawable) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE; + if (mFace[FACE_REFLECTION] == NULL) + { + LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER); + if (gPipeline.getPool(LLDrawPool::POOL_WATER)->getShaderLevel() != 0) + { + mFace[FACE_REFLECTION] = drawable->addFace(poolp, NULL); + } + } + + mCameraPosAgent = drawable->getPositionAgent(); + + mEarthCenter.mV[0] = mCameraPosAgent.mV[0]; + mEarthCenter.mV[1] = mCameraPosAgent.mV[1]; + + LLVector3 v_agent[8]; + for (S32 i = 0; i < 8; ++i) + { + 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 * SKY_BOX_MULT * LLVector3(x_sgn, y_sgn, z_sgn); + } + + LLStrider<LLVector3> verticesp; + LLStrider<LLVector3> normalsp; + LLStrider<LLVector2> texCoordsp; + LLStrider<U16> indicesp; + U16 index_offset; + LLFace *face; + + for (S32 side = 0; side < NUM_CUBEMAP_FACES; ++side) + { + face = mFace[FACE_SIDE0 + side]; + + if (!face->getVertexBuffer()) + { + face->setSize(4, 6); + face->setGeomIndex(0); + face->setIndicesIndex(0); + LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK); + buff->allocateBuffer(4, 6); + face->setVertexBuffer(buff); + + index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); + + S32 vtx = 0; + S32 curr_bit = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X + S32 side_dir = side & 1; // even - 0, odd - 1 + S32 i_bit = (curr_bit + 2) % 3; + S32 j_bit = (i_bit + 2) % 3; + + LLVector3 axis; + axis.mV[curr_bit] = 1; + face->mCenterAgent = (F32)((side_dir << 1) - 1) * axis * HORIZON_DIST; + + vtx = side_dir << curr_bit; + *(verticesp++) = v_agent[vtx]; + *(verticesp++) = v_agent[vtx | 1 << j_bit]; + *(verticesp++) = v_agent[vtx | 1 << i_bit]; + *(verticesp++) = v_agent[vtx | 1 << i_bit | 1 << j_bit]; + + *(texCoordsp++) = TEX00; + *(texCoordsp++) = TEX01; + *(texCoordsp++) = TEX10; + *(texCoordsp++) = TEX11; + + // Triangles for each side + *indicesp++ = index_offset + 0; + *indicesp++ = index_offset + 1; + *indicesp++ = index_offset + 3; + + *indicesp++ = index_offset + 0; + *indicesp++ = index_offset + 3; + *indicesp++ = index_offset + 2; + + buff->unmapBuffer(); + } + } + + const LLVector3 &look_at = LLViewerCamera::getInstance()->getAtAxis(); + LLVector3 right = look_at % LLVector3::z_axis; + LLVector3 up = right % look_at; + right.normalize(); + up.normalize(); + + bool draw_sun = updateHeavenlyBodyGeometry(drawable, mSunScale, FACE_SUN, mSun, up, right); + bool draw_moon = updateHeavenlyBodyGeometry(drawable, mMoonScale, FACE_MOON, mMoon, up, right); + + draw_sun &= LLEnvironment::getInstance()->getIsSunUp(); + draw_moon &= LLEnvironment::getInstance()->getIsMoonUp(); + + mSun.setDraw(draw_sun); + mMoon.setDraw(draw_moon); + + const F32 water_height = gAgent.getRegion()->getWaterHeight() + 0.01f; + // LLWorld::getInstance()->getWaterHeight() + 0.01f; + const F32 camera_height = mCameraPosAgent.mV[2]; + const F32 height_above_water = camera_height - water_height; + + bool sun_flag = false; + if (mSun.isVisible()) + { + sun_flag = !mMoon.isVisible() || ((look_at * mSun.getDirection()) > 0); + } + + bool above_water = (height_above_water > 0); + bool render_ref = above_water && gPipeline.getPool(LLDrawPool::POOL_WATER)->getShaderLevel() == 0; + setDrawRefl(above_water ? (sun_flag ? 0 : 1) : -1); + if (render_ref) + { + updateReflectionGeometry(drawable, height_above_water, mSun); + } + + LLPipeline::sCompiles++; + return true; +} + +bool LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, F32 scale, const S32 f, LLHeavenBody& hb, const LLVector3 &up, const LLVector3 &right) +{ + mHeavenlyBodyUpdated = true ; + + LLStrider<LLVector3> verticesp; + LLStrider<LLVector3> normalsp; + LLStrider<LLVector2> texCoordsp; + LLStrider<U16> indicesp; + S32 index_offset; + LLFace *facep; + + + LLQuaternion rot = hb.getRotation(); + LLVector3 to_dir = LLVector3::x_axis * rot; + + LLVector3 hb_right = to_dir % LLVector3::z_axis; + LLVector3 hb_up = hb_right % to_dir; + + // at zenith so math below fails spectacularly + if ((to_dir * LLVector3::z_axis) > 0.99f) + { + hb_right = LLVector3::y_axis_neg * rot; + hb_up = LLVector3::z_axis * rot; + } + + LLVector3 draw_pos = to_dir * HEAVENLY_BODY_DIST; + + hb_right.normalize(); + hb_up.normalize(); + + const F32 enlargm_factor = ( 1 - to_dir.mV[2] ); + F32 horiz_enlargement = 1 + enlargm_factor * 0.3f; + F32 vert_enlargement = 1 + enlargm_factor * 0.2f; + + const LLVector3 scaled_right = horiz_enlargement * scale * HEAVENLY_BODY_DIST * HEAVENLY_BODY_FACTOR * hb.getDiskRadius() * hb_right; + const LLVector3 scaled_up = vert_enlargement * scale * HEAVENLY_BODY_DIST * HEAVENLY_BODY_FACTOR * hb.getDiskRadius() * hb_up; + + LLVector3 v_clipped[4]; + + v_clipped[0] = draw_pos - scaled_right + scaled_up; + v_clipped[1] = draw_pos - scaled_right - scaled_up; + v_clipped[2] = draw_pos + scaled_right + scaled_up; + v_clipped[3] = draw_pos + scaled_right - scaled_up; + + hb.setVisible(true); + + facep = mFace[f]; + + if (!facep->getVertexBuffer()) + { + facep->setSize(4, 6); + LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK); + if (!buff->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount())) + { + LL_WARNS() << "Failed to allocate Vertex Buffer for vosky to " + << facep->getGeomCount() << " vertices and " + << facep->getIndicesCount() << " indices" << LL_ENDL; + } + facep->setGeomIndex(0); + facep->setIndicesIndex(0); + facep->setVertexBuffer(buff); + } + + llassert(facep->getVertexBuffer()->getNumIndices() == 6); + + index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp); + + if (-1 == index_offset) + { + return true; + } + + for (S32 vtx = 0; vtx < 4; ++vtx) + { + hb.corner(vtx) = v_clipped[vtx]; + *(verticesp++) = hb.corner(vtx) + mCameraPosAgent; + } + + *(texCoordsp++) = TEX01; + *(texCoordsp++) = TEX00; + *(texCoordsp++) = TEX11; + *(texCoordsp++) = TEX10; + + *indicesp++ = index_offset + 0; + *indicesp++ = index_offset + 2; + *indicesp++ = index_offset + 1; + + *indicesp++ = index_offset + 1; + *indicesp++ = index_offset + 2; + *indicesp++ = index_offset + 3; + + facep->getVertexBuffer()->unmapBuffer(); + + return true; +} + +F32 dtReflection(const LLVector3& p, F32 cos_dir_from_top, F32 sin_dir_from_top, F32 diff_angl_dir) +{ + LLVector3 P = p; + P.normalize(); + + const F32 cos_dir_angle = -P.mV[VZ]; + const F32 sin_dir_angle = sqrt(1 - cos_dir_angle * cos_dir_angle); + + F32 cos_diff_angles = cos_dir_angle * cos_dir_from_top + + sin_dir_angle * sin_dir_from_top; + + F32 diff_angles; + if (cos_diff_angles > (1 - 1e-7)) + diff_angles = 0; + else + diff_angles = acos(cos_diff_angles); + + const F32 rel_diff_angles = diff_angles / diff_angl_dir; + const F32 dt = 1 - rel_diff_angles; + + return (dt < 0) ? 0 : dt; +} + + +F32 dtClip(const LLVector3& v0, const LLVector3& v1, F32 far_clip2) +{ + F32 dt_clip; + const LLVector3 otrezok = v1 - v0; + const F32 A = otrezok.lengthSquared(); + const F32 B = v0 * otrezok; + const F32 C = v0.lengthSquared() - far_clip2; + const F32 det = sqrt(B*B - A*C); + dt_clip = (-B - det) / A; + if ((dt_clip < 0) || (dt_clip > 1)) + dt_clip = (-B + det) / A; + return dt_clip; +} + + +void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H, + const LLHeavenBody& HB) +{ + const LLVector3 &look_at = LLViewerCamera::getInstance()->getAtAxis(); + // const F32 water_height = gAgent.getRegion()->getWaterHeight() + 0.001f; + // LLWorld::getInstance()->getWaterHeight() + 0.001f; + + LLVector3 to_dir = HB.getDirection(); + LLVector3 hb_pos = to_dir * (HORIZON_DIST - 10); + LLVector3 to_dir_proj = to_dir; + to_dir_proj.mV[VZ] = 0; + to_dir_proj.normalize(); + + LLVector3 Right = to_dir % LLVector3::z_axis; + LLVector3 Up = Right % to_dir; + Right.normalize(); + Up.normalize(); + + // finding angle between look direction and sprite. + LLVector3 look_at_right = look_at % LLVector3::z_axis; + look_at_right.normalize(); + + const F32 enlargm_factor = ( 1 - to_dir.mV[2] ); + F32 horiz_enlargement = 1 + enlargm_factor * 0.3f; + F32 vert_enlargement = 1 + enlargm_factor * 0.2f; + + F32 vert_size = vert_enlargement * HEAVENLY_BODY_SCALE * HB.getDiskRadius(); + Right *= /*cos_lookAt_toDir */ horiz_enlargement * HEAVENLY_BODY_SCALE * HB.getDiskRadius(); + Up *= vert_size; + + LLVector3 v_corner[2]; + LLVector3 stretch_corner[2]; + + LLVector3 top_hb = v_corner[0] = stretch_corner[0] = hb_pos - Right + Up; + v_corner[1] = stretch_corner[1] = hb_pos - Right - Up; + + LLVector2 TEX0t = TEX00; + LLVector2 TEX1t = TEX10; + LLVector3 lower_corner = v_corner[1]; + + top_hb.normalize(); + const F32 cos_angle_of_view = fabs(top_hb.mV[VZ]); + const F32 extension = llmin (5.0f, 1.0f / cos_angle_of_view); + + const S32 cols = 1; + const S32 raws = lltrunc(16 * extension); + S32 quads = cols * raws; + + stretch_corner[0] = lower_corner + extension * (stretch_corner[0] - lower_corner); + stretch_corner[1] = lower_corner + extension * (stretch_corner[1] - lower_corner); + + F32 cos_dir_from_top[2]; + + LLVector3 dir = stretch_corner[0]; + dir.normalize(); + cos_dir_from_top[0] = dir.mV[VZ]; + + dir = stretch_corner[1]; + dir.normalize(); + cos_dir_from_top[1] = dir.mV[VZ]; + + const F32 sin_dir_from_top = sqrt(1 - cos_dir_from_top[0] * cos_dir_from_top[0]); + const F32 sin_dir_from_top2 = sqrt(1 - cos_dir_from_top[1] * cos_dir_from_top[1]); + const F32 cos_diff_dir = cos_dir_from_top[0] * cos_dir_from_top[1] + + sin_dir_from_top * sin_dir_from_top2; + const F32 diff_angl_dir = acos(cos_diff_dir); + + v_corner[0] = stretch_corner[0]; + v_corner[1] = lower_corner; + + + LLVector2 TEX0tt = TEX01; + LLVector2 TEX1tt = TEX11; + + LLVector3 v_refl_corner[4]; + LLVector3 v_sprite_corner[4]; + + S32 vtx; + for (vtx = 0; vtx < 2; ++vtx) + { + LLVector3 light_proj = v_corner[vtx]; + light_proj.normalize(); + + const F32 z = light_proj.mV[VZ]; + const F32 sin_angle = sqrt(1 - z * z); + light_proj *= 1.f / sin_angle; + light_proj.mV[VZ] = 0; + const F32 to_refl_point = H * sin_angle / fabs(z); + + v_refl_corner[vtx] = to_refl_point * light_proj; + } + + + for (vtx = 2; vtx < 4; ++vtx) + { + const LLVector3 to_dir_vec = (to_dir_proj * v_refl_corner[vtx-2]) * to_dir_proj; + v_refl_corner[vtx] = v_refl_corner[vtx-2] + 2 * (to_dir_vec - v_refl_corner[vtx-2]); + } + + for (vtx = 0; vtx < 4; ++vtx) + v_refl_corner[vtx].mV[VZ] -= H; + + S32 side = 0; + LLVector3 refl_corn_norm[2]; + refl_corn_norm[0] = v_refl_corner[1]; + refl_corn_norm[0].normalize(); + refl_corn_norm[1] = v_refl_corner[3]; + refl_corn_norm[1].normalize(); + + F32 cos_refl_look_at[2]; + cos_refl_look_at[0] = refl_corn_norm[0] * look_at; + cos_refl_look_at[1] = refl_corn_norm[1] * look_at; + + if (cos_refl_look_at[1] > cos_refl_look_at[0]) + { + side = 2; + } + + //const F32 far_clip = (LLViewerCamera::getInstance()->getFar() - 0.01) / far_clip_factor; + const F32 far_clip = 512; + const F32 far_clip2 = far_clip*far_clip; + + F32 dt_clip; + F32 vtx_near2, vtx_far2; + + if ((vtx_far2 = v_refl_corner[side].lengthSquared()) > far_clip2) + { + // whole thing is sprite: reflection is beyond far clip plane. + dt_clip = 1.1f; + quads = 1; + } + else if ((vtx_near2 = v_refl_corner[side+1].lengthSquared()) > far_clip2) + { + // part is reflection, the rest is sprite. + dt_clip = dtClip(v_refl_corner[side + 1], v_refl_corner[side], far_clip2); + const LLVector3 P = (1 - dt_clip) * v_refl_corner[side + 1] + dt_clip * v_refl_corner[side]; + + F32 dt_tex = dtReflection(P, cos_dir_from_top[0], sin_dir_from_top, diff_angl_dir); + + TEX0tt = LLVector2(0, dt_tex); + TEX1tt = LLVector2(1, dt_tex); + quads++; + } + else + { + // whole thing is correct reflection. + dt_clip = -0.1f; + } + + LLFace *face = mFace[FACE_REFLECTION]; + + if (face) + { + if (!face->getVertexBuffer() || quads*4 != face->getGeomCount()) + { + face->setSize(quads * 4, quads * 6); + LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK); + if (!buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount())) + { + LL_WARNS() << "Failed to allocate Vertex Buffer for vosky to " + << face->getGeomCount() << " vertices and " + << face->getIndicesCount() << " indices" << LL_ENDL; + } + face->setIndicesIndex(0); + face->setGeomIndex(0); + face->setVertexBuffer(buff); + } + + LLStrider<LLVector3> verticesp; + LLStrider<LLVector3> normalsp; + LLStrider<LLVector2> texCoordsp; + LLStrider<U16> indicesp; + S32 index_offset; + + index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); + if (-1 == index_offset) + { + return; + } + + LLColor3 hb_col3 = HB.getInterpColor(); + hb_col3.clamp(); + const LLColor4 hb_col = LLColor4(hb_col3); + + const F32 min_attenuation = 0.4f; + const F32 max_attenuation = 0.7f; + const F32 attenuation = min_attenuation + + cos_angle_of_view * (max_attenuation - min_attenuation); + + LLColor4 hb_refl_col = (1 - attenuation) * hb_col + attenuation * getSkyFogColor(); + face->setFaceColor(hb_refl_col); + + LLVector3 v_far[2]; + v_far[0] = v_refl_corner[1]; + v_far[1] = v_refl_corner[3]; + + if(dt_clip > 0) + { + if (dt_clip >= 1) + { + for (S32 vtx = 0; vtx < 4; ++vtx) + { + F32 ratio = far_clip / v_refl_corner[vtx].length(); + *(verticesp++) = v_refl_corner[vtx] = ratio * v_refl_corner[vtx] + mCameraPosAgent; + } + const LLVector3 draw_pos = 0.25 * + (v_refl_corner[0] + v_refl_corner[1] + v_refl_corner[2] + v_refl_corner[3]); + face->mCenterAgent = draw_pos; + } + else + { + F32 ratio = far_clip / v_refl_corner[1].length(); + v_sprite_corner[1] = v_refl_corner[1] * ratio; + + ratio = far_clip / v_refl_corner[3].length(); + v_sprite_corner[3] = v_refl_corner[3] * ratio; + + v_refl_corner[1] = (1 - dt_clip) * v_refl_corner[1] + dt_clip * v_refl_corner[0]; + v_refl_corner[3] = (1 - dt_clip) * v_refl_corner[3] + dt_clip * v_refl_corner[2]; + v_sprite_corner[0] = v_refl_corner[1]; + v_sprite_corner[2] = v_refl_corner[3]; + + for (S32 vtx = 0; vtx < 4; ++vtx) + { + *(verticesp++) = v_sprite_corner[vtx] + mCameraPosAgent; + } + + const LLVector3 draw_pos = 0.25 * + (v_refl_corner[0] + v_sprite_corner[1] + v_refl_corner[2] + v_sprite_corner[3]); + face->mCenterAgent = draw_pos; + } + + *(texCoordsp++) = TEX0tt; + *(texCoordsp++) = TEX0t; + *(texCoordsp++) = TEX1tt; + *(texCoordsp++) = TEX1t; + + *indicesp++ = index_offset + 0; + *indicesp++ = index_offset + 2; + *indicesp++ = index_offset + 1; + + *indicesp++ = index_offset + 1; + *indicesp++ = index_offset + 2; + *indicesp++ = index_offset + 3; + + index_offset += 4; + } + + if (dt_clip < 1) + { + if (dt_clip <= 0) + { + const LLVector3 draw_pos = 0.25 * + (v_refl_corner[0] + v_refl_corner[1] + v_refl_corner[2] + v_refl_corner[3]); + face->mCenterAgent = draw_pos; + } + + const F32 raws_inv = 1.f/raws; + const F32 cols_inv = 1.f/cols; + LLVector3 left = v_refl_corner[0] - v_refl_corner[1]; + LLVector3 right = v_refl_corner[2] - v_refl_corner[3]; + left *= raws_inv; + right *= raws_inv; + + for (S32 raw = 0; raw < raws; ++raw) + { + F32 dt_v0 = raw * raws_inv; + F32 dt_v1 = (raw + 1) * raws_inv; + const LLVector3 BL = v_refl_corner[1] + (F32)raw * left; + const LLVector3 BR = v_refl_corner[3] + (F32)raw * right; + const LLVector3 EL = BL + left; + const LLVector3 ER = BR + right; + dt_v0 = dt_v1 = dtReflection(EL, cos_dir_from_top[0], sin_dir_from_top, diff_angl_dir); + for (S32 col = 0; col < cols; ++col) + { + F32 dt_h0 = col * cols_inv; + *(verticesp++) = (1 - dt_h0) * EL + dt_h0 * ER + mCameraPosAgent; + *(verticesp++) = (1 - dt_h0) * BL + dt_h0 * BR + mCameraPosAgent; + F32 dt_h1 = (col + 1) * cols_inv; + *(verticesp++) = (1 - dt_h1) * EL + dt_h1 * ER + mCameraPosAgent; + *(verticesp++) = (1 - dt_h1) * BL + dt_h1 * BR + mCameraPosAgent; + + *(texCoordsp++) = LLVector2(dt_h0, dt_v1); + *(texCoordsp++) = LLVector2(dt_h0, dt_v0); + *(texCoordsp++) = LLVector2(dt_h1, dt_v1); + *(texCoordsp++) = LLVector2(dt_h1, dt_v0); + + *indicesp++ = index_offset + 0; + *indicesp++ = index_offset + 2; + *indicesp++ = index_offset + 1; + + *indicesp++ = index_offset + 1; + *indicesp++ = index_offset + 2; + *indicesp++ = index_offset + 3; + + index_offset += 4; + } + } + } + + face->getVertexBuffer()->unmapBuffer(); +} +} + +void LLVOSky::updateFog(const F32 distance) +{ + LLEnvironment& environment = LLEnvironment::instance(); + if (environment.getCurrentSky() != nullptr) + { + LLVector3 light_dir = LLVector3(environment.getClampedLightNorm()); + m_legacyAtmospherics.updateFog(distance, light_dir); + } + } + +void LLVOSky::setSunAndMoonDirectionsCFR(const LLVector3 &sun_dir_cfr, const LLVector3 &moon_dir_cfr) +{ + mSun.setDirection(sun_dir_cfr); + mMoon.setDirection(moon_dir_cfr); + + // Push the sun "South" as it approaches directly overhead so that we can always see bump mapping + // on the upward facing faces of cubes. + // Same as dot product with the up direction + clamp. + F32 sunDot = llmax(0.f, sun_dir_cfr.mV[2]); + sunDot *= sunDot; + + // Create normalized vector that has the sunDir pushed south about an hour and change. + LLVector3 adjustedDir = (sun_dir_cfr + LLVector3(0.f, -0.70711f, 0.70711f)) * 0.5f; + + // Blend between normal sun dir and adjusted sun dir based on how close we are + // to having the sun overhead. + mBumpSunDir = adjustedDir * sunDot + sun_dir_cfr * (1.0f - sunDot); + mBumpSunDir.normalize(); + + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + updateDirections(psky); +} + +void LLVOSky::setSunDirectionCFR(const LLVector3 &sun_dir_cfr) +{ + mSun.setDirection(sun_dir_cfr); + + // Push the sun "South" as it approaches directly overhead so that we can always see bump mapping + // on the upward facing faces of cubes. + // Same as dot product with the up direction + clamp. + F32 sunDot = llmax(0.f, sun_dir_cfr.mV[2]); + sunDot *= sunDot; + + // Create normalized vector that has the sunDir pushed south about an hour and change. + LLVector3 adjustedDir = (sun_dir_cfr + LLVector3(0.f, -0.70711f, 0.70711f)) * 0.5f; + + // Blend between normal sun dir and adjusted sun dir based on how close we are + // to having the sun overhead. + mBumpSunDir = adjustedDir * sunDot + sun_dir_cfr * (1.0f - sunDot); + mBumpSunDir.normalize(); + + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + updateDirections(psky); +} + +void LLVOSky::setMoonDirectionCFR(const LLVector3 &moon_dir_cfr) +{ + mMoon.setDirection(moon_dir_cfr); + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + updateDirections(psky); +} |