diff options
Diffstat (limited to 'indra')
-rw-r--r-- | indra/newview/lldrawpoolwater.cpp | 314 | ||||
-rw-r--r-- | indra/newview/llvosky.cpp | 2248 |
2 files changed, 1581 insertions, 981 deletions
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index ee37f36cbd..9316890156 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -46,9 +46,14 @@ #include "llworld.h" #include "pipeline.h" #include "llviewershadermgr.h" -#include "llenvironment.h" -#include "llsettingssky.h" -#include "llsettingswater.h" +#include "llwaterparammanager.h" + +#if LL_WINDOWS +#pragma optimize("", off) +#endif + +const LLUUID TRANSPARENT_WATER_TEXTURE("2bfd3884-7e27-69b9-ba3a-3e673f680004"); +const LLUUID OPAQUE_WATER_TEXTURE("43c32285-d658-1793-c123-bf86315de055"); static float sTime; @@ -57,51 +62,42 @@ BOOL deferred_render = FALSE; BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE; BOOL LLDrawPoolWater::sNeedsReflectionUpdate = TRUE; BOOL LLDrawPoolWater::sNeedsDistortionUpdate = TRUE; +LLColor4 LLDrawPoolWater::sWaterFogColor = LLColor4(0.2f, 0.5f, 0.5f, 0.f); F32 LLDrawPoolWater::sWaterFogEnd = 0.f; -LLDrawPoolWater::LLDrawPoolWater() : LLFacePool(POOL_WATER) -{ -} +LLVector3 LLDrawPoolWater::sLightDir; -LLDrawPoolWater::~LLDrawPoolWater() +LLDrawPoolWater::LLDrawPoolWater() : + LLFacePool(POOL_WATER) { -} + mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); + gGL.getTexUnit(0)->bind(mHBTex[0]) ; + mHBTex[0]->setAddressMode(LLTexUnit::TAM_CLAMP); -void LLDrawPoolWater::setTransparentTextures(const LLUUID& transparentTextureId, const LLUUID& nextTransparentTextureId) -{ - LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater(); - mWaterImagep[0] = LLViewerTextureManager::getFetchedTexture(!transparentTextureId.isNull() ? transparentTextureId : pwater->GetDefaultTransparentTextureAssetId()); - mWaterImagep[1] = LLViewerTextureManager::getFetchedTexture(!nextTransparentTextureId.isNull() ? nextTransparentTextureId : (!transparentTextureId.isNull() ? transparentTextureId : pwater->GetDefaultTransparentTextureAssetId())); - mWaterImagep[0]->addTextureStats(1024.f*1024.f); - mWaterImagep[1]->addTextureStats(1024.f*1024.f); -} + mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); + gGL.getTexUnit(0)->bind(mHBTex[1]); + mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP); -void LLDrawPoolWater::setOpaqueTexture(const LLUUID& opaqueTextureId) -{ - LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater(); - mOpaqueWaterImagep = LLViewerTextureManager::getFetchedTexture(opaqueTextureId); - mOpaqueWaterImagep->addTextureStats(1024.f*1024.f); + + mWaterImagep = LLViewerTextureManager::getFetchedTexture(TRANSPARENT_WATER_TEXTURE); + llassert(mWaterImagep); + mWaterImagep->setNoDelete(); + mOpaqueWaterImagep = LLViewerTextureManager::getFetchedTexture(OPAQUE_WATER_TEXTURE); + llassert(mOpaqueWaterImagep); + mWaterNormp = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL); + mWaterNormp->setNoDelete(); + + restoreGL(); } -void LLDrawPoolWater::setNormalMaps(const LLUUID& normalMapId, const LLUUID& nextNormalMapId) +LLDrawPoolWater::~LLDrawPoolWater() { - LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater(); - mWaterNormp[0] = LLViewerTextureManager::getFetchedTexture(!normalMapId.isNull() ? normalMapId : pwater->GetDefaultWaterNormalAssetId()); - mWaterNormp[1] = LLViewerTextureManager::getFetchedTexture(!nextNormalMapId.isNull() ? nextNormalMapId : (!normalMapId.isNull() ? normalMapId : pwater->GetDefaultWaterNormalAssetId())); - mWaterNormp[0]->addTextureStats(1024.f*1024.f); - mWaterNormp[1]->addTextureStats(1024.f*1024.f); } //static void LLDrawPoolWater::restoreGL() { - /*LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater(); - if (pwater) - { - setTransparentTextures(pwater->getTransparentTextureID(), pwater->getNextTransparentTextureID()); - setOpaqueTexture(pwater->GetDefaultOpaqueTextureAssetId()); - setNormalMaps(pwater->getNormalMapID(), pwater->getNextNormalMapID()); - }*/ + } LLDrawPool *LLDrawPoolWater::instancePool() @@ -113,7 +109,14 @@ LLDrawPool *LLDrawPoolWater::instancePool() void LLDrawPoolWater::prerender() { - mShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ? LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0; + mVertexShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ? + LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0; + + // got rid of modulation by light color since it got a little too + // green at sunset and sl-57047 (underwater turns black at 8:00) + sWaterFogColor = LLWaterParamManager::instance().getFogColor(); + sWaterFogColor.mV[3] = 0; + } S32 LLDrawPoolWater::getNumPasses() @@ -179,7 +182,7 @@ void LLDrawPoolWater::render(S32 pass) LLGLEnable blend(GL_BLEND); - if ((mShaderLevel > 0) && !sSkipScreenCopy) + if ((mVertexShaderLevel > 0) && !sSkipScreenCopy) { shade(); return; @@ -204,13 +207,10 @@ void LLDrawPoolWater::render(S32 pass) LLGLDisable cullFace(GL_CULL_FACE); // Set up second pass first + mWaterImagep->addTextureStats(1024.f*1024.f); gGL.getTexUnit(1)->activate(); gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(1)->bind(mWaterImagep[0]) ; - - gGL.getTexUnit(2)->activate(); - gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(2)->bind(mWaterImagep[1]) ; + gGL.getTexUnit(1)->bind(mWaterImagep) ; LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis(); F32 up_dot = camera_up * LLVector3::z_axis; @@ -267,14 +267,6 @@ void LLDrawPoolWater::render(S32 pass) gGL.getTexUnit(1)->activate(); gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->disable(); - - glDisable(GL_TEXTURE_GEN_S); //texture unit 1 - glDisable(GL_TEXTURE_GEN_T); //texture unit 1 - - gGL.getTexUnit(1)->activate(); - gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(1)->disable(); - glDisable(GL_TEXTURE_GEN_S); //texture unit 1 glDisable(GL_TEXTURE_GEN_T); //texture unit 1 @@ -374,6 +366,8 @@ void LLDrawPoolWater::renderOpaqueLegacyWater() gPipeline.disableLights(); + mOpaqueWaterImagep->addTextureStats(1024.f*1024.f); + // Activate the texture binding and bind one // texture since all images will have the same texture gGL.getTexUnit(0)->activate(); @@ -471,7 +465,7 @@ void LLDrawPoolWater::renderReflection(LLFace* face) LLGLSNoFog noFog; - gGL.getTexUnit(0)->bind((dr == 0) ? voskyp->getSunTex() : voskyp->getMoonTex()); + gGL.getTexUnit(0)->bind(mHBTex[dr]); LLOverrideFaceColor override(this, LLColor4(face->getFaceColor().mV)); face->renderIndexed(); @@ -496,33 +490,31 @@ void LLDrawPoolWater::shade() LLColor3 light_diffuse(0,0,0); F32 light_exp = 0.0f; LLVector3 light_dir; - - LLEnvironment& environment = LLEnvironment::instance(); - LLSettingsWater::ptr_t pwater = environment.getCurrentWater(); - LLSettingsSky::ptr_t psky = environment.getCurrentSky(); - - light_dir = environment.getLightDirection(); - light_dir.normalize(); - - bool sun_up = environment.getIsSunUp(); - bool moon_up = environment.getIsMoonUp(); - - if (sun_up) - { - light_diffuse += voskyp->getSun().getColorCached(); - } - // moonlight is several orders of magnitude less bright than sunlight, - // so only use this color when the moon alone is showing - else if (moon_up) - { - light_diffuse += psky->getMoonDiffuse(); + LLColor3 light_color; + + if (gSky.getSunDirection().mV[2] > LLSky::NIGHTTIME_ELEVATION_COS) + { + light_dir = gSky.getSunDirection(); + light_dir.normVec(); + light_color = gSky.getSunDiffuseColor(); + if(gSky.mVOSkyp) { + light_diffuse = gSky.mVOSkyp->getSun().getColorCached(); + light_diffuse.normVec(); + } + light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0); + light_diffuse *= light_exp + 0.25f; + } + else + { + light_dir = gSky.getMoonDirection(); + light_dir.normVec(); + light_color = gSky.getMoonDiffuseColor(); + light_diffuse = gSky.mVOSkyp->getMoon().getColorCached(); + light_diffuse.normVec(); + light_diffuse *= 0.5f; + light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0); } - light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0.f); - - light_diffuse.normalize(); - light_diffuse *= (light_exp + 0.25f); - light_exp *= light_exp; light_exp *= light_exp; light_exp *= light_exp; @@ -530,22 +522,20 @@ void LLDrawPoolWater::shade() light_exp *= 256.f; light_exp = light_exp > 32.f ? light_exp : 32.f; - light_diffuse *= 6.f; - LLGLSLShader* shader; - F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - LLEnvironment::instance().getWaterHeight(); + F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - gAgent.getRegion()->getWaterHeight(); if (eyedepth < 0.f && LLPipeline::sWaterReflections) { - if (deferred_render) - { - shader = &gDeferredUnderWaterProgram; - } + if (deferred_render) + { + shader = &gDeferredUnderWaterProgram; + } else - { - shader = &gUnderWaterProgram; - } + { + shader = &gUnderWaterProgram; + } } else if (deferred_render) { @@ -556,18 +546,16 @@ void LLDrawPoolWater::shade() shader = &gWaterProgram; } - shader->bind(); - if (deferred_render) { - if (shader->getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0) - { - glh::matrix4f norm_mat = get_current_modelview().inverse().transpose(); - shader->uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m); - } + gPipeline.bindDeferredShader(*shader); + } + else + { + shader->bind(); } - sTime = (F32)LLFrameTimer::getElapsedSeconds() * 0.5f; + sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f; S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX); @@ -581,48 +569,43 @@ void LLDrawPoolWater::shade() //bind normal map S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP); - if (mWaterNormp[0]) - { - gGL.getTexUnit(bumpTex)->bind(mWaterNormp[0]) ; + LLWaterParamManager * param_mgr = &LLWaterParamManager::instance(); - if (gSavedSettings.getBOOL("RenderWaterMipNormal")) - { - mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); - } - else - { - mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_POINT); - } + // change mWaterNormp if needed + if (mWaterNormp->getID() != param_mgr->getNormalMapID()) + { + mWaterNormp = LLViewerTextureManager::getFetchedTexture(param_mgr->getNormalMapID()); } - if (mWaterNormp[1]) - { - bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP2); - - gGL.getTexUnit(bumpTex)->bind(mWaterNormp[1]) ; - - if (gSavedSettings.getBOOL("RenderWaterMipNormal")) - { - mWaterNormp[1]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); - } - else - { - mWaterNormp[1]->setFilteringOption(LLTexUnit::TFO_POINT); - } + mWaterNormp->addTextureStats(1024.f*1024.f); + gGL.getTexUnit(bumpTex)->bind(mWaterNormp) ; + if (gSavedSettings.getBOOL("RenderWaterMipNormal")) + { + mWaterNormp->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); } - - shader->uniform3fv(LLShaderMgr::WATER_FOGCOLOR, 1, pwater->getWaterFogColor().mV); - shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, pwater->getWaterFogDensity()); + else + { + mWaterNormp->setFilteringOption(LLTexUnit::TFO_POINT); + } + + S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX); + + if (screentex > -1) + { + shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV); + shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, + param_mgr->getFogDensity()); + gPipeline.mWaterDis.bindTexture(0, screentex); + } + + stop_glerror(); - // bind reflection texture from RenderTarget - S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX); gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis); - if (mShaderLevel == 1) + if (mVertexShaderLevel == 1) { - LLColor4 fog_color(pwater->getWaterFogColor(), 0.f); - fog_color[3] = pwater->getWaterFogDensity(); - shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV); + sWaterFogColor.mV[3] = param_mgr->mDensitySliderValue; + shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV); } F32 screenRes[] = @@ -636,30 +619,25 @@ void LLDrawPoolWater::shade() S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP); stop_glerror(); + light_dir.normVec(); + sLightDir = light_dir; + + light_diffuse *= 6.f; + //shader->uniformMatrix4fv("inverse_ref", 1, GL_FALSE, (GLfloat*) gGLObliqueProjectionInverse.mMatrix); shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, eyedepth); shader->uniform1f(LLShaderMgr::WATER_TIME, sTime); shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV); shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV); shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp); - if (LLEnvironment::instance().isCloudScrollPaused()) - { - static const std::array<F32, 2> zerowave{ {0.0f, 0.0f} }; - - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, zerowave.data()); - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, zerowave.data()); - } - else - { - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV); - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV); - } + shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, param_mgr->getWave1Dir().mV); + shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, param_mgr->getWave2Dir().mV); shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV); - shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV); - shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale()); - shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset()); - shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, pwater->getBlurMultiplier()); + shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, param_mgr->getNormalScale().mV); + shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, param_mgr->getFresnelScale()); + shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, param_mgr->getFresnelOffset()); + shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, param_mgr->getBlurMultiplier()); F32 sunAngle = llmax(0.f, light_dir.mV[2]); F32 scaledAngle = 1.f - sunAngle; @@ -674,12 +652,12 @@ void LLDrawPoolWater::shade() if (LLViewerCamera::getInstance()->cameraUnderWater()) { water_color.setVec(1.f, 1.f, 1.f, 0.4f); - shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow()); + shader->uniform1f(LLShaderMgr::WATER_REFSCALE, param_mgr->getScaleBelow()); } else { water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot)); - shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove()); + shader->uniform1f(LLShaderMgr::WATER_REFSCALE, param_mgr->getScaleAbove()); } if (water_color.mV[3] > 0.9f) @@ -687,19 +665,40 @@ void LLDrawPoolWater::shade() water_color.mV[3] = 0.9f; } - { + { + LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0); LLGLDisable cullface(GL_CULL_FACE); - - sNeedsReflectionUpdate = TRUE; - sNeedsDistortionUpdate = TRUE; - - for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) + for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) { LLFace *face = *iter; + + if (voskyp->isReflFace(face)) + { + continue; + } + + LLVOWater* water = (LLVOWater*) face->getViewerObject(); gGL.getTexUnit(diffTex)->bind(face->getTexture()); - face->renderIndexed(); + + sNeedsReflectionUpdate = TRUE; + + if (water->getUseTexture() || !water->getIsEdgePatch()) + { + sNeedsDistortionUpdate = TRUE; + face->renderIndexed(); + } + else if (gGLManager.mHasDepthClamp || deferred_render) + { + face->renderIndexed(); + } + else + { + LLGLSquashToFarClip far_clip(glh_get_current_projection()); + face->renderIndexed(); + } } - } + } shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); shader->disableTexture(LLShaderMgr::WATER_SCREENTEX); @@ -708,7 +707,14 @@ void LLDrawPoolWater::shade() shader->disableTexture(LLShaderMgr::WATER_REFTEX); shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH); - shader->unbind(); + if (deferred_render) + { + gPipeline.unbindDeferredShader(*shader); + } + else + { + shader->unbind(); + } gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index af078251b3..54ec238fde 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -48,42 +48,156 @@ #include "llworld.h" #include "pipeline.h" #include "lldrawpoolwlsky.h" -#include "v3colorutil.h" - -#include "llsettingssky.h" -#include "llenvironment.h" - -#include "lltrace.h" -#include "llfasttimer.h" +#include "llwlparammanager.h" +#include "llwaterparammanager.h" #undef min #undef max -namespace +#if LL_WINDOWS +#pragma optimize("", off) +#endif + +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 +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; + +// Texture coordinates: +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; +LLUUID gMoonTextureID = IMG_MOON; + +class LLFastLn { - const S32 NUM_TILES_X = 8; - const S32 NUM_TILES_Y = 4; - const S32 NUM_TILES = NUM_TILES_X * NUM_TILES_Y; +public: + LLFastLn() + { + mTable[0] = 0; + for( S32 i = 1; i < 257; i++ ) + { + mTable[i] = log((F32)i); + } + } + + F32 ln( F32 x ) + { + const F32 OO_255 = 0.003921568627450980392156862745098f; + const F32 LN_255 = 5.5412635451584261462455391880218f; + + if( x < OO_255 ) + { + return log(x); + } + else + if( x < 1 ) + { + x *= 255.f; + S32 index = llfloor(x); + F32 t = x - index; + F32 low = mTable[index]; + F32 high = mTable[index + 1]; + return low + t * (high - low) - LN_255; + } + else + if( x <= 255 ) + { + S32 index = llfloor(x); + F32 t = x - index; + F32 low = mTable[index]; + F32 high = mTable[index + 1]; + return low + t * (high - low); + } + else + { + return log( x ); + } + } + + F32 pow( F32 x, F32 y ) + { + return (F32)LL_FAST_EXP(y * ln(x)); + } + + +private: + F32 mTable[257]; // index 0 is unused +}; + +static LLFastLn gFastLn; - // 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); +// Functions used a lot. - const F32 LIGHT_DIRECTION_THRESHOLD = (F32) cosf(DEG_TO_RAD * 1.f); - const F32 COLOR_CHANGE_THRESHOLD = 0.01f; +inline F32 LLHaze::calcPhase(const F32 cos_theta) const +{ + const F32 g2 = mG * mG; + const F32 den = 1 + g2 - 2 * mG * cos_theta; + return (1 - g2) * gFastLn.pow(den, -1.5); +} + +inline void color_pow(LLColor3 &col, const F32 e) +{ + col.mV[0] = gFastLn.pow(col.mV[0], e); + col.mV[1] = gFastLn.pow(col.mV[1], e); + col.mV[2] = gFastLn.pow(col.mV[2], e); +} - LLTrace::BlockTimerStatHandle FTM_VOSKY_UPDATETIMER("VOSky Update Timer Tick"); - LLTrace::BlockTimerStatHandle FTM_VOSKY_UPDATEFORCED("VOSky Update Forced"); +inline LLColor3 color_norm(const LLColor3 &col) +{ + const F32 m = color_max(col); + if (m > 1.f) + { + return 1.f/m * col; + } + else return col; +} + +inline void color_gamma_correct(LLColor3 &col) +{ + const F32 gamma_inv = 1.f/1.2f; + if (col.mV[0] != 0.f) + { + col.mV[0] = gFastLn.pow(col.mV[0], gamma_inv); + } + if (col.mV[1] != 0.f) + { + col.mV[1] = gFastLn.pow(col.mV[1], gamma_inv); + } + if (col.mV[2] != 0.f) + { + col.mV[2] = gFastLn.pow(col.mV[2], gamma_inv); + } +} - F32Seconds UPDATE_EXPRY(2.0f); +static LLColor3 calc_air_sca_sea_level() +{ + static LLColor3 WAVE_LEN(675, 520, 445); + static LLColor3 refr_ind = refr_ind_calc(WAVE_LEN); + static LLColor3 n21 = refr_ind * refr_ind - LLColor3(1, 1, 1); + static LLColor3 n4 = n21 * n21; + static LLColor3 wl2 = WAVE_LEN * WAVE_LEN * 1e-6f; + static LLColor3 wl4 = wl2 * wl2; + static LLColor3 mult_const = fsigma * 2.0f/ 3.0f * 1e24f * (F_PI * F_PI) * n4; + static F32 dens_div_N = F32( ATM_SEA_LEVEL_NDENS / Ndens2); + return dens_div_N * color_div ( mult_const, wl4 ); } + +// static constants. +LLColor3 const LLHaze::sAirScaSeaLevel = calc_air_sca_sea_level(); +F32 const LLHaze::sAirScaIntense = color_intens(LLHaze::sAirScaSeaLevel); +F32 const LLHaze::sAirScaAvg = LLHaze::sAirScaIntense / 3.f; + + /*************************************** SkyTex ***************************************/ @@ -139,32 +253,6 @@ LLSkyTex::~LLSkyTex() mSkyDirs = NULL; } -S32 LLSkyTex::getResolution() -{ - return sResolution; -} - -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) { @@ -205,6 +293,9 @@ void LLSkyTex::create(const F32 brightness) createGLImage(sCurrent); } + + + void LLSkyTex::createGLImage(S32 which) { mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLGLTexture::LOCAL); @@ -213,175 +304,14 @@ void LLSkyTex::createGLImage(S32 which) 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 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; + gGL.getTexUnit(0)->bind(mTexture[getWhich(curr)], true); } /*************************************** Sky ***************************************/ +F32 LLHeavenBody::sInterpVal = 0; S32 LLVOSky::sResolution = LLSkyTex::getResolution(); S32 LLVOSky::sTileResX = sResolution/NUM_TILES_X; @@ -400,15 +330,32 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) 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 = 1.f; + 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(); - mForceUpdateThrottle.setTimerExpirySec(UPDATE_EXPRY); - mForceUpdateThrottle.reset(); - for (S32 i = 0; i < 6; i++) { mSkyTex[i].init(); @@ -423,13 +370,33 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) mAtmHeight = ATM_HEIGHT; mEarthCenter = LLVector3(mCameraPosAgent.mV[0], mCameraPosAgent.mV[1], -EARTH_RADIUS); + mSunDefaultPosition = LLVector3(LLWLParamManager::getInstance()->mCurParams.getVector("lightnorm", error)); + if (gSavedSettings.getBOOL("SkyOverrideSimSunPosition")) + { + initSunDirection(mSunDefaultPosition, LLVector3(0, 0, 0)); + } + mAmbientScale = gSavedSettings.getF32("SkyAmbientScale"); + mNightColorShift = gSavedSettings.getColor3("SkyNightColorShift"); + mFogColor.mV[VRED] = mFogColor.mV[VGREEN] = mFogColor.mV[VBLUE] = 0.5f; + mFogColor.mV[VALPHA] = 0.0f; + mFogRatio = 1.2f; + mSun.setIntensity(SUN_INTENSITY); mMoon.setIntensity(0.1f * SUN_INTENSITY); + mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); + mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); + mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); + mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); + mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1); + mBloomTexturep->setNoDelete() ; + mBloomTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); + mHeavenlyBodyUpdated = FALSE ; mDrawRefl = 0; - mInterpVal = 0.f; + mHazeConcentration = 0.f; + mInterpVal = 0.f; } @@ -443,32 +410,11 @@ LLVOSky::~LLVOSky() void LLVOSky::init() { - llassert(!mInitialized); - - // Update sky at least once to get correct initial sun/moon directions and lighting calcs performed - LLEnvironment::instance().getCurrentSky()->update(); - - updateDirections(); - - LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - - // invariants across whole sky tex process... - m_atmosphericsVars.blue_density = psky->getBlueDensity(); - m_atmosphericsVars.blue_horizon = psky->getBlueHorizon(); - m_atmosphericsVars.haze_density = psky->getHazeDensity(); - m_atmosphericsVars.haze_horizon = psky->getHazeHorizon(); - m_atmosphericsVars.density_multiplier = psky->getDensityMultiplier(); - m_atmosphericsVars.max_y = psky->getMaxY(); - m_atmosphericsVars.sun_norm = LLEnvironment::instance().getClampedSunNorm(); - m_atmosphericsVars.sunlight = psky->getSunlightColor(); - m_atmosphericsVars.ambient = psky->getAmbientColor(); - m_atmosphericsVars.glow = psky->getGlow(); - m_atmosphericsVars.cloud_shadow = psky->getCloudShadow(); - m_atmosphericsVars.dome_radius = psky->getDomeRadius(); - m_atmosphericsVars.dome_offset = psky->getDomeOffset(); - m_atmosphericsVars.light_atten = psky->getLightAttenuation(m_atmosphericsVars.max_y); - m_atmosphericsVars.light_transmittance = psky->getLightTransmittance(); - m_atmosphericsVars.gamma = psky->getGamma(); + const F32 haze_int = color_intens(mHaze.calcSigSca(0)); + mHazeConcentration = haze_int / + (color_intens(LLHaze::calcAirSca(0)) + haze_int); + + calcAtmospherics(); // Initialize the cached normalized direction vectors for (S32 side = 0; side < 6; ++side) @@ -476,7 +422,7 @@ void LLVOSky::init() for (S32 tile = 0; tile < NUM_TILES; ++tile) { initSkyTextureDirs(side, tile); - createSkyTexture(m_atmosphericsVars, side, tile, false); + createSkyTexture(side, tile); } } @@ -487,107 +433,9 @@ void LLVOSky::init() } 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::calc() -{ - LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - - // invariants across whole sky tex process... - m_atmosphericsVars.blue_density = psky->getBlueDensity(); - m_atmosphericsVars.blue_horizon = psky->getBlueHorizon(); - m_atmosphericsVars.haze_density = psky->getHazeDensity(); - m_atmosphericsVars.haze_horizon = psky->getHazeHorizon(); - m_atmosphericsVars.density_multiplier = psky->getDensityMultiplier(); - m_atmosphericsVars.max_y = psky->getMaxY(); - m_atmosphericsVars.sun_norm = LLEnvironment::instance().getClampedSunNorm(); - m_atmosphericsVars.sunlight = psky->getSunlightColor(); - m_atmosphericsVars.ambient = psky->getAmbientColor(); - m_atmosphericsVars.glow = psky->getGlow(); - m_atmosphericsVars.cloud_shadow = psky->getCloudShadow(); - m_atmosphericsVars.dome_radius = psky->getDomeRadius(); - m_atmosphericsVars.dome_offset = psky->getDomeOffset(); - m_atmosphericsVars.light_atten = psky->getLightAttenuation(m_atmosphericsVars.max_y); - m_atmosphericsVars.light_transmittance = psky->getLightTransmittance(); - m_atmosphericsVars.gamma = psky->getGamma(); - - LLColor3 vary_HazeColor; - LLColor3 vary_SunlightColor; - LLColor3 vary_AmbientColor; - { - // Initialize temp variables - LLColor3 sunlight = m_atmosphericsVars.sunlight; - - // Sunlight attenuation effect (hue and brightness) due to atmosphere - // this is used later for sunlight modulation at various altitudes - LLColor3 light_atten = - (m_atmosphericsVars.blue_density * 1.0 + smear(m_atmosphericsVars.haze_density * 0.25f)) * (m_atmosphericsVars.density_multiplier * m_atmosphericsVars.max_y); - - // Calculate relative weights - LLColor3 temp2(0.f, 0.f, 0.f); - LLColor3 temp1 = m_atmosphericsVars.blue_density + smear(m_atmosphericsVars.haze_density); - LLColor3 blue_weight = componentDiv(m_atmosphericsVars.blue_density, temp1); - LLColor3 haze_weight = componentDiv(smear(m_atmosphericsVars.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] ); - F32 lighty = getSun().getDirection().mV[2]; - temp2.mV[1] = llmax(0.f, lighty); - if(temp2.mV[1] > 0.f) - { - temp2.mV[1] = 1.f / temp2.mV[1]; - } - componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1])); - - // Distance - temp2.mV[2] = m_atmosphericsVars.density_multiplier; - - // Transparency (-> temp1) - temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]); - - // vary_AtmosAttenuation = temp1; - - //increase ambient when there are more clouds - LLColor3 tmpAmbient = m_atmosphericsVars.ambient + (smear(1.f) - m_atmosphericsVars.ambient) * m_atmosphericsVars.cloud_shadow * 0.5f; - - //haze color - vary_HazeColor = - (m_atmosphericsVars.blue_horizon * blue_weight * (sunlight * (1.f - m_atmosphericsVars.cloud_shadow) + tmpAmbient) - + componentMult(m_atmosphericsVars.haze_horizon * haze_weight, sunlight * (1.f - m_atmosphericsVars.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, m_atmosphericsVars.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, m_atmosphericsVars.gamma); - vary_AmbientColor = smear(1.0f) - vary_AmbientColor; - - componentMultBy(vary_HazeColor, LLColor3(1.f, 1.f, 1.f) - temp1); - - } - - mSun.setColor(vary_SunlightColor); - mMoon.setColor(LLColor3(1.0f, 1.0f, 1.0f)); - - mSun.renewDirection(); - mSun.renewColor(); - mMoon.renewDirection(); - mMoon.renewColor(); } void LLVOSky::initCubeMap() @@ -630,16 +478,15 @@ void LLVOSky::restoreGL() { mSkyTex[i].restoreGL(); } + mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); + mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); + mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); + mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); + mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1); + mBloomTexturep->setNoDelete() ; + mBloomTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - - if (psky) - { - setSunTextures(psky->getSunTextureId(), psky->getNextSunTextureId()); - setMoonTextures(psky->getMoonTextureId(), psky->getNextMoonTextureId()); - } - - updateDirections(); + calcAtmospherics(); if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) @@ -655,11 +502,10 @@ void LLVOSky::restoreGL() if(cube_map) { cube_map->init(images); + mForceUpdate = TRUE; } } - mForceUpdate = TRUE; - if (mDrawable) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); @@ -699,7 +545,7 @@ void LLVOSky::initSkyTextureDirs(const S32 side, const S32 tile) } } -void LLVOSky::createSkyTexture(AtmosphericsVars& vars, const S32 side, const S32 tile, bool skip_sky_tex) +void LLVOSky::createSkyTexture(const S32 side, const S32 tile) { S32 tile_x = tile % NUM_TILES_X; S32 tile_y = tile / NUM_TILES_X; @@ -708,55 +554,495 @@ void LLVOSky::createSkyTexture(AtmosphericsVars& vars, const S32 side, const S32 S32 tile_y_pos = tile_y * sTileResY; S32 x, y; - if (!skip_sky_tex) - { - for (y = tile_y_pos; y < (tile_y_pos + sTileResY); ++y) - { - for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x) - { - mSkyTex[side].setPixel(m_legacyAtmospherics.calcSkyColorInDir(vars, mSkyTex[side].getDir(x, y)), x, y); - } - } - } - for (y = tile_y_pos; y < (tile_y_pos + sTileResY); ++y) { for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x) { - mShinyTex[side].setPixel(m_legacyAtmospherics.calcSkyColorInDir(vars, mSkyTex[side].getDir(x, y), true), x, y); + mSkyTex[side].setPixel(calcSkyColorInDir(mSkyTex[side].getDir(x, y)), x, y); + mShinyTex[side].setPixel(calcSkyColorInDir(mSkyTex[side].getDir(x, y), true), x, y); } } } -void LLVOSky::updateDirections(void) +static inline LLColor3 componentDiv(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]); +} + + +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]); +} + + +static inline LLColor3 componentExp(LLColor3 const &v) +{ + 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)); +} + +static inline LLColor3 componentSaturate(LLColor3 const &v) +{ + 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) { - LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + left.mV[0] *= right.mV[0]; + left.mV[1] *= right.mV[1]; + left.mV[2] *= right.mV[2]; +} - mLastSunLightingDirection = mSun.getDirection(); - mLastMoonLightingDirection = mMoon.getDirection(); +static inline LLColor3 colorMix(LLColor3 const & left, LLColor3 const & right, F32 amount) +{ + return (left + ((right - left) * amount)); +} - mSun.setDirection(psky->getSunDirection()); - mMoon.setDirection(psky->getMoonDirection()); +static inline LLColor3 smear(F32 val) +{ + return LLColor3(val, val, val); +} - mSun.setColor(psky->getSunlightColor()); - mMoon.setColor(psky->getMoonDiffuse()); +void LLVOSky::initAtmospherics(void) +{ + bool error; + + // uniform parameters for convenience + dome_radius = LLWLParamManager::getInstance()->getDomeRadius(); + dome_offset_ratio = LLWLParamManager::getInstance()->getDomeOffset(); + sunlight_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("sunlight_color", error)); + ambient = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("ambient", error)); + //lightnorm = LLWLParamManager::getInstance()->mCurParams.getVector("lightnorm", error); + gamma = LLWLParamManager::getInstance()->mCurParams.getFloat("gamma", error); + blue_density = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_density", error)); + blue_horizon = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_horizon", error)); + haze_density = LLWLParamManager::getInstance()->mCurParams.getFloat("haze_density", error); + haze_horizon = LLWLParamManager::getInstance()->mCurParams.getFloat("haze_horizon", error); + density_multiplier = LLWLParamManager::getInstance()->mCurParams.getFloat("density_multiplier", error); + max_y = LLWLParamManager::getInstance()->mCurParams.getFloat("max_y", error); + glow = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("glow", error)); + cloud_shadow = LLWLParamManager::getInstance()->mCurParams.getFloat("cloud_shadow", error); + cloud_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_color", error)); + cloud_scale = LLWLParamManager::getInstance()->mCurParams.getFloat("cloud_scale", error); + cloud_pos_density1 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density1", error)); + cloud_pos_density2 = LLColor3(LLWLParamManager::getInstance()->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; + } + +} + +LLColor4 LLVOSky::calcSkyColorInDir(const LLVector3 &dir, bool isShiny) +{ + F32 saturation = 0.3f; + if (dir.mV[VZ] < -0.02f) + { + 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; + } + + // undo OGL_TO_CFR_ROTATION and negate vertical direction. + LLVector3 Pn = LLVector3(-dir[1] , -dir[2], -dir[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) + { + 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); + } + 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); + if (fabsf(sinA) < 0.01f) + { //avoid division by zero + sinA = 0.01f; + } + + 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; + + // Set altitude + if (Pn[1] > 0.f) + { + Pn *= (max_y / Pn[1]); + } + else + { + Pn *= (-32000.f / Pn[1]); + } + + Plen = Pn.length(); + Pn /= Plen; + + // Initialize temp variables + LLColor3 sunlight = sunlight_color; + + // 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); + + // 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])); + + // Distance + temp2.mV[2] = Plen * density_multiplier; + + // Transparency (-> temp1) + temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]); + + + // Compute haze glow + temp2.mV[0] = Pn * LLVector3(lightnorm); + + 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 + + // Add "minimum anti-solar illumination" + temp2.mV[0] += .25f; + + + // Haze color above cloud + vary_HazeColor = (blue_horizon * blue_weight * (sunlight + ambient) + + componentMult(haze_horizon * haze_weight, sunlight * temp2.mV[0] + ambient) + ); + + // Increase ambient when there are more clouds + LLColor3 tmpAmbient = ambient + (LLColor3::white - ambient) * cloud_shadow * 0.5f; + + // Dim sunlight by cloud shadow percentage + sunlight *= (1.f - cloud_shadow); + + // Haze color below cloud + LLColor3 additiveColorBelowCloud = (blue_horizon * blue_weight * (sunlight + tmpAmbient) + + componentMult(haze_horizon * haze_weight, sunlight * temp2.mV[0] + tmpAmbient) + ); + + // 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) + { + // 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(); + + 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 + +LLColor3 LLVOSky::calcSkyColorWLFrag(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLColor3 & vary_CloudColorSun, + LLColor3 & vary_CloudColorAmbient, F32 & vary_CloudDensity, + LLVector2 vary_HorizontalProjection[2]) +{ + LLColor3 res; + + LLColor3 color0 = vary_HazeColor; + + 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; +} + +LLColor3 LLVOSky::createDiffuseFromWL(LLColor3 diffuse, LLColor3 ambient, LLColor3 sundiffuse, LLColor3 sunambient) +{ + return componentMult(diffuse, sundiffuse) * 4.0f + + componentMult(ambient, sundiffuse) * 2.0f + sunambient; +} + +LLColor3 LLVOSky::createAmbientFromWL(LLColor3 ambient, LLColor3 sundiffuse, LLColor3 sunambient) +{ + return (componentMult(ambient, sundiffuse) + sunambient) * 0.8f; +} + + +void LLVOSky::calcAtmospherics(void) +{ + initAtmospherics(); + + LLColor3 vary_HazeColor; + LLColor3 vary_SunlightColor; + LLColor3 vary_AmbientColor; + { + // Initialize temp variables + LLColor3 sunlight = sunlight_color; + + // 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); + + // 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 < LLSky::NIGHTTIME_ELEVATION_COS) + { + lighty = -lighty; + } + + temp2.mV[1] = llmax(0.f, lighty); + if(temp2.mV[1] > 0.f) + { + temp2.mV[1] = 1.f / temp2.mV[1]; + } + componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1])); + + // Distance + temp2.mV[2] = density_multiplier; + + // Transparency (-> temp1) + temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]); + + // 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 * 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); + + } + + mSun.setColor(vary_SunlightColor); + mMoon.setColor(LLColor3(1.0f, 1.0f, 1.0f)); mSun.renewDirection(); mSun.renewColor(); mMoon.renewDirection(); mMoon.renewColor(); + + float dp = getToSunLast() * LLVector3(0,0,1.f); + if (dp < 0) + { + dp = 0; + } + + // 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::getInstance()->mSceneLightStrength = 2.0f * (1.0f + sun_dynamic_range * dp); + + mSunDiffuse = vary_SunlightColor; + mSunAmbient = vary_AmbientColor; + mMoonDiffuse = vary_SunlightColor; + mMoonAmbient = vary_AmbientColor; + + mTotalAmbient = vary_AmbientColor; + mTotalAmbient.setAlpha(1); + + mFadeColor = mTotalAmbient + (mSunDiffuse + mMoonDiffuse) * 0.5f; + mFadeColor.setAlpha(0); } void LLVOSky::idleUpdate(LLAgent &agent, const F64 &time) { } -bool LLVOSky::updateSky() -{ - LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - - LLColor4 total_ambient = psky->getTotalAmbient(); - +BOOL LLVOSky::updateSky() +{ if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))) { return TRUE; @@ -776,13 +1062,11 @@ bool LLVOSky::updateSky() const S32 total_no_tiles = 6 * NUM_TILES; const S32 cycle_frame_no = total_no_tiles + 1; - if (mUpdateTimer.getElapsedTimeF32() > 0.025f) + if (mUpdateTimer.getElapsedTimeF32() > 0.001f) { - mUpdateTimer.reset(); + mUpdateTimer.reset(); const S32 frame = next_frame; - mForceUpdate = mForceUpdate || (total_no_tiles == frame); - ++next_frame; next_frame = next_frame % cycle_frame_no; @@ -790,150 +1074,117 @@ bool LLVOSky::updateSky() // sInterpVal = (F32)next_frame / cycle_frame_no; LLSkyTex::setInterpVal( mInterpVal ); LLHeavenBody::setInterpVal( mInterpVal ); - updateDirections(); - - LLVector3 direction = mSun.getDirection(); - direction.normalize(); - const F32 dot_sun = direction * mLastSunLightingDirection; - const F32 dot_moon = direction * mLastMoonLightingDirection; + calcAtmospherics(); - LLColor3 delta_color; - delta_color.setVec(mLastTotalAmbient.mV[0] - total_ambient.mV[0], - mLastTotalAmbient.mV[1] - total_ambient.mV[1], - mLastTotalAmbient.mV[2] - total_ambient.mV[2]); - - bool sun_direction_changed = (dot_sun < LIGHT_DIRECTION_THRESHOLD); - bool moon_direction_changed = (dot_moon < LIGHT_DIRECTION_THRESHOLD); - bool color_changed = (delta_color.length() >= COLOR_CHANGE_THRESHOLD); - - mForceUpdate = mForceUpdate || sun_direction_changed; - mForceUpdate = mForceUpdate || moon_direction_changed; - mForceUpdate = mForceUpdate || color_changed; - mForceUpdate = mForceUpdate || !mInitialized; - - bool is_alm_wl_sky = gPipeline.canUseWindLightShaders(); - - calc(); - - if (mForceUpdate && mForceUpdateThrottle.hasExpired()) + if (mForceUpdate || total_no_tiles == frame) { - LL_RECORD_BLOCK_TIME(FTM_VOSKY_UPDATEFORCED); - - mForceUpdateThrottle.setTimerExpirySec(UPDATE_EXPRY); - LLSkyTex::stepCurrent(); - - if (!direction.isExactlyZero()) + + const static F32 LIGHT_DIRECTION_THRESHOLD = (F32) cos(DEG_TO_RAD * 1.f); + const static F32 COLOR_CHANGE_THRESHOLD = 0.01f; + + LLVector3 direction = mSun.getDirection(); + direction.normalize(); + const F32 dot_lighting = direction * mLastLightingDirection; + + LLColor3 delta_color; + delta_color.setVec(mLastTotalAmbient.mV[0] - mTotalAmbient.mV[0], + mLastTotalAmbient.mV[1] - mTotalAmbient.mV[1], + mLastTotalAmbient.mV[2] - mTotalAmbient.mV[2]); + + if ( mForceUpdate + || (((dot_lighting < LIGHT_DIRECTION_THRESHOLD) + || (delta_color.length() > COLOR_CHANGE_THRESHOLD) + || !mInitialized) + && !direction.isExactlyZero())) { - mLastTotalAmbient = total_ambient; + mLastLightingDirection = direction; + mLastTotalAmbient = mTotalAmbient; mInitialized = TRUE; if (mCubeMap) { - updateFog(LLViewerCamera::getInstance()->getFar()); - - for (int side = 0; side < 6; side++) + if (mForceUpdate) { - for (int tile = 0; tile < NUM_TILES; tile++) + updateFog(LLViewerCamera::getInstance()->getFar()); + for (int side = 0; side < 6; side++) { - createSkyTexture(m_atmosphericsVars, side, tile, is_alm_wl_sky); + for (int tile = 0; tile < NUM_TILES; tile++) + { + createSkyTexture(side, tile); + } } - } - int tex = mSkyTex[0].getWhich(TRUE); + calcAtmospherics(); - for (int side = 0; side < 6; 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); + for (int side = 0; side < 6; side++) + { + LLImageRaw* raw1 = mSkyTex[side].getImageRaw(TRUE); + 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; } - next_frame = 0; - - // update the sky texture - if (!is_alm_wl_sky) - { - for (S32 i = 0; i < 6; ++i) - { - mSkyTex[i].create(1.0f); - } - } - - for (S32 i = 0; i < 6; ++i) - { - 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); - gGL.getTexUnit(0)->disable(); - } } - } + } + + /// *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); + gGL.getTexUnit(0)->disable(); + } gPipeline.markRebuild(gSky.mVOGroundp->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; } + else + { + const S32 side = frame / NUM_TILES; + const S32 tile = frame % NUM_TILES; + createSkyTexture(side, tile); + } } if (mDrawable.notNull() && mDrawable->getFace(0) && !mDrawable->getFace(0)->getVertexBuffer()) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); } - return TRUE; } void LLVOSky::updateTextures() { - if (mSunTexturep[0]) + if (mSunTexturep) { - 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 ); + mSunTexturep->addTextureStats( (F32)MAX_IMAGE_AREA ); + mMoonTexturep->addTextureStats( (F32)MAX_IMAGE_AREA ); + mBloomTexturep->addTextureStats( (F32)MAX_IMAGE_AREA ); } } @@ -951,121 +1202,60 @@ LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline) 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] = mDrawable->addFace(poolp, mSunTexturep); + mFace[FACE_MOON] = mDrawable->addFace(poolp, mMoonTexturep); + mFace[FACE_BLOOM] = mDrawable->addFace(poolp, mBloomTexturep); return mDrawable; } -void LLVOSky::setSunScale(F32 sun_scale) -{ - mSunScale = sun_scale; -} - -void LLVOSky::setMoonScale(F32 moon_scale) +//by bao +//fake vertex buffer updating +//to guarantee at least updating one VBO buffer every frame +//to walk around the bug caused by ATI card --> DEV-3855 +// +void LLVOSky::createDummyVertexBuffer() { - 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); - - 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 (mSunTexturep[1]) - { - mSunTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP); - } - mFace[FACE_SUN]->setTexture(LLRender::ALTERNATE_DIFFUSE_MAP, mSunTexturep[1]); - } -} + if(!mFace[FACE_DUMMY]) + { + LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY); + mFace[FACE_DUMMY] = mDrawable->addFace(poolp, NULL); + } -void LLVOSky::setMoonTextures(const LLUUID& moon_texture, const LLUUID& moon_texture_next) -{ - LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - - 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]) - { - mMoonTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP); - mFace[FACE_MOON]->setTexture(LLRender::ALTERNATE_DIFFUSE_MAP, mMoonTexturep[1]); - } - } + if(!mFace[FACE_DUMMY]->getVertexBuffer()) + { + LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB); + buff->allocateBuffer(1, 1, TRUE); + mFace[FACE_DUMMY]->setVertexBuffer(buff); + } } -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); - } +static LLTrace::BlockTimerStatHandle FTM_RENDER_FAKE_VBO_UPDATE("Fake VBO Update"); - 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(); +void LLVOSky::updateDummyVertexBuffer() +{ + if(!LLVertexBuffer::sEnableVBOs) + return ; - 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; + if(mHeavenlyBodyUpdated) + { + mHeavenlyBodyUpdated = FALSE ; + return ; + } - 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); + LL_RECORD_BLOCK_TIME(FTM_RENDER_FAKE_VBO_UPDATE) ; - if (mBloomTexturep[0]) - { - mBloomTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP); - } + if(!mFace[FACE_DUMMY] || !mFace[FACE_DUMMY]->getVertexBuffer()) + createDummyVertexBuffer() ; - if (mBloomTexturep[1]) - { - mBloomTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP); - } + LLStrider<LLVector3> vertices ; + mFace[FACE_DUMMY]->getVertexBuffer()->getVertexStrider(vertices, 0); + *vertices = mCameraPosAgent ; + mFace[FACE_DUMMY]->getVertexBuffer()->flush(); } - +//---------------------------------- +//end of fake vertex buffer updating +//---------------------------------- static LLTrace::BlockTimerStatHandle FTM_GEO_SKY("Sky Geometry"); BOOL LLVOSky::updateGeometry(LLDrawable *drawable) @@ -1074,14 +1264,13 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) if (mFace[FACE_REFLECTION] == NULL) { LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER); - if (gPipeline.getPool(LLDrawPool::POOL_WATER)->getShaderLevel() != 0) + if (gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() != 0) { mFace[FACE_REFLECTION] = drawable->addFace(poolp, NULL); } } mCameraPosAgent = drawable->getPositionAgent(); - mEarthCenter.mV[0] = mCameraPosAgent.mV[0]; mEarthCenter.mV[1] = mCameraPosAgent.mV[1]; @@ -1155,40 +1344,64 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) 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 static F32 elevation_factor = 0.0f/sResolution; + const F32 cos_max_angle = cosHorizon(elevation_factor); + mSun.setDraw(updateHeavenlyBodyGeometry(drawable, FACE_SUN, TRUE, mSun, cos_max_angle, up, right)); + mMoon.setDraw(updateHeavenlyBodyGeometry(drawable, FACE_MOON, FALSE, mMoon, cos_max_angle, up, right)); 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; + BOOL sun_flag = FALSE; + if (mSun.isVisible()) - { - sun_flag = !mMoon.isVisible() || ((look_at * mSun.getDirection()) > 0); + { + if (mMoon.isVisible()) + { + sun_flag = look_at * mSun.getDirection() > 0; + } + else + { + sun_flag = TRUE; + } } - 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); - } + if (height_above_water > 0) + { + BOOL render_ref = gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() == 0; + + if (sun_flag) + { + setDrawRefl(0); + if (render_ref) + { + updateReflectionGeometry(drawable, height_above_water, mSun); + } + } + else + { + setDrawRefl(1); + if (render_ref) + { + updateReflectionGeometry(drawable, height_above_water, mMoon); + } + } + } + else + { + setDrawRefl(-1); + } LLPipeline::sCompiles++; return TRUE; } -bool LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, F32 scale, const S32 f, LLHeavenBody& hb, const LLVector3 &up, const LLVector3 &right) +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 ; @@ -1199,28 +1412,52 @@ bool LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, F32 scale, const S32 index_offset; LLFace *facep; - LLVector3 to_dir = hb.getDirection(); + 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; + LLVector3 hb_right = to_dir % LLVector3::z_axis; LLVector3 hb_up = hb_right % to_dir; hb_right.normalize(); hb_up.normalize(); - const F32 enlargm_factor = ( 1 - to_dir.mV[2] ); + //const static F32 cos_max_turn = sqrt(3.f) / 2; // 30 degrees + //const F32 cos_turn_right = 1. / (llmax(cos_max_turn, hb_right * right)); + //const F32 cos_turn_up = 1. / llmax(cos_max_turn, hb_up * up); + + 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; + // Parameters for the water reflection + hb.setU(HEAVENLY_BODY_FACTOR * horiz_enlargement * hb.getDiskRadius() * hb_right); + hb.setV(HEAVENLY_BODY_FACTOR * vert_enlargement * hb.getDiskRadius() * hb_up); + // End of parameters for the water reflection + + const LLVector3 scaled_right = HEAVENLY_BODY_DIST * hb.getU(); + const LLVector3 scaled_up = HEAVENLY_BODY_DIST * hb.getV(); + //const LLVector3 scaled_right = horiz_enlargement * HEAVENLY_BODY_SCALE * hb.getDiskRadius() * hb_right;//right; + //const LLVector3 scaled_up = vert_enlargement * HEAVENLY_BODY_SCALE * hb.getDiskRadius() * hb_up;//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.corner(0) = draw_pos - scaled_right + scaled_up; + hb.corner(1) = draw_pos - scaled_right - scaled_up; + hb.corner(2) = draw_pos + scaled_right + scaled_up; + hb.corner(3) = draw_pos + scaled_right - scaled_up; + + F32 t_left, t_right; + if (!clip_quad_to_horizon(t_left, t_right, v_clipped, hb.corners(), cos_max_angle)) + { + hb.setVisible(FALSE); + return FALSE; + } hb.setVisible(TRUE); facep = mFace[f]; @@ -1270,9 +1507,164 @@ bool LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, F32 scale, const facep->getVertexBuffer()->flush(); + if (is_sun) + { + if ((t_left > 0) && (t_right > 0)) + { + F32 t = (t_left + t_right) * 0.5f; + mSun.setHorizonVisibility(0.5f * (1 + cos(t * F_PI))); + } + else + { + mSun.setHorizonVisibility(); + } + updateSunHaloGeometry(drawable); + } + return TRUE; } + + + +// Clips quads with top and bottom sides parallel to horizon. + +BOOL clip_quad_to_horizon(F32& t_left, F32& t_right, LLVector3 v_clipped[4], + const LLVector3 v_corner[4], const F32 cos_max_angle) +{ + t_left = clip_side_to_horizon(v_corner[1], v_corner[0], cos_max_angle); + t_right = clip_side_to_horizon(v_corner[3], v_corner[2], cos_max_angle); + + if ((t_left >= 1) || (t_right >= 1)) + { + return FALSE; + } + + //const BOOL left_clip = (t_left > 0); + //const BOOL right_clip = (t_right > 0); + + //if (!left_clip && !right_clip) + { + for (S32 vtx = 0; vtx < 4; ++vtx) + { + v_clipped[vtx] = v_corner[vtx]; + } + } +/* else + { + v_clipped[0] = v_corner[0]; + v_clipped[1] = left_clip ? ((1 - t_left) * v_corner[1] + t_left * v_corner[0]) + : v_corner[1]; + v_clipped[2] = v_corner[2]; + v_clipped[3] = right_clip ? ((1 - t_right) * v_corner[3] + t_right * v_corner[2]) + : v_corner[3]; + }*/ + + return TRUE; +} + + +F32 clip_side_to_horizon(const LLVector3& V0, const LLVector3& V1, const F32 cos_max_angle) +{ + const LLVector3 V = V1 - V0; + const F32 k2 = 1.f/(cos_max_angle * cos_max_angle) - 1; + const F32 A = V.mV[0] * V.mV[0] + V.mV[1] * V.mV[1] - k2 * V.mV[2] * V.mV[2]; + const F32 B = V0.mV[0] * V.mV[0] + V0.mV[1] * V.mV[1] - k2 * V0.mV[2] * V.mV[2]; + const F32 C = V0.mV[0] * V0.mV[0] + V0.mV[1] * V0.mV[1] - k2 * V0.mV[2] * V0.mV[2]; + + if (fabs(A) < 1e-7) + { + return -0.1f; // v0 is cone origin and v1 is on the surface of the cone. + } + + const F32 det = sqrt(B*B - A*C); + const F32 t1 = (-B - det) / A; + const F32 t2 = (-B + det) / A; + const F32 z1 = V0.mV[2] + t1 * V.mV[2]; + const F32 z2 = V0.mV[2] + t2 * V.mV[2]; + if (z1 * cos_max_angle < 0) + { + return t2; + } + else if (z2 * cos_max_angle < 0) + { + return t1; + } + else if ((t1 < 0) || (t1 > 1)) + { + return t2; + } + else + { + return t1; + } +} + + +void LLVOSky::updateSunHaloGeometry(LLDrawable *drawable ) +{ +#if 0 + const LLVector3* v_corner = mSun.corners(); + + LLStrider<LLVector3> verticesp; + LLStrider<LLVector3> normalsp; + LLStrider<LLVector2> texCoordsp; + LLStrider<U16> indicesp; + S32 index_offset; + LLFace *face; + + const LLVector3 right = 2 * (v_corner[2] - v_corner[0]); + LLVector3 up = 2 * (v_corner[2] - v_corner[3]); + up.normalize(); + F32 size = right.length(); + up = size * up; + const LLVector3 draw_pos = 0.25 * (v_corner[0] + v_corner[1] + v_corner[2] + v_corner[3]); + + LLVector3 v_glow_corner[4]; + + v_glow_corner[0] = draw_pos - right + up; + v_glow_corner[1] = draw_pos - right - up; + v_glow_corner[2] = draw_pos + right + up; + v_glow_corner[3] = draw_pos + right - up; + + face = mFace[FACE_BLOOM]; + + if (face->mVertexBuffer.isNull()) + { + face->setSize(4, 6); + face->setGeomIndex(0); + face->setIndicesIndex(0); + face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + face->mVertexBuffer->allocateBuffer(4, 6, TRUE); + } + + index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); + if (-1 == index_offset) + { + return; + } + + for (S32 vtx = 0; vtx < 4; ++vtx) + { + *(verticesp++) = v_glow_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; +#endif +} + + F32 dtReflection(const LLVector3& p, F32 cos_dir_from_top, F32 sin_dir_from_top, F32 diff_angl_dir) { LLVector3 P = p; @@ -1334,6 +1726,9 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H, LLVector3 look_at_right = look_at % LLVector3::z_axis; look_at_right.normalize(); + const static F32 cos_horizon_angle = cosHorizon(0.0f/sResolution); + //const static F32 horizon_angle = acos(cos_horizon_angle); + 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; @@ -1348,10 +1743,22 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H, LLVector3 top_hb = v_corner[0] = stretch_corner[0] = hb_pos - Right + Up; v_corner[1] = stretch_corner[1] = hb_pos - Right - Up; + F32 dt_hor, dt; + dt_hor = clip_side_to_horizon(v_corner[1], v_corner[0], cos_horizon_angle); + LLVector2 TEX0t = TEX00; LLVector2 TEX1t = TEX10; LLVector3 lower_corner = v_corner[1]; + if ((dt_hor > 0) && (dt_hor < 1)) + { + TEX0t = LLVector2(0, dt_hor); + TEX1t = LLVector2(1, dt_hor); + lower_corner = (1 - dt_hor) * v_corner[1] + dt_hor * v_corner[0]; + } + else + dt_hor = llmax(0.0f, llmin(1.0f, dt_hor)); + 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); @@ -1363,6 +1770,9 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H, stretch_corner[0] = lower_corner + extension * (stretch_corner[0] - lower_corner); stretch_corner[1] = lower_corner + extension * (stretch_corner[1] - lower_corner); + dt = dt_hor; + + F32 cos_dir_from_top[2]; LLVector3 dir = stretch_corner[0]; @@ -1451,8 +1861,9 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H, 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); + dt = dt_tex; + TEX0tt = LLVector2(0, dt); + TEX1tt = LLVector2(1, dt); quads++; } else @@ -1463,225 +1874,408 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H, 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, GL_STREAM_DRAW_ARB); - if (!buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE)) + if (!face->getVertexBuffer() || quads*4 != face->getGeomCount()) + { + face->setSize(quads * 4, quads * 6); + LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + if (!buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE)) + { + 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 * mFogColor; + 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) { - LL_WARNS() << "Failed to allocate Vertex Buffer for vosky to " - << face->getGeomCount() << " vertices and " - << face->getIndicesCount() << " indices" << LL_ENDL; + *(verticesp++) = v_sprite_corner[vtx] + mCameraPosAgent; } - 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()->flush(); - } + + 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; + + F32 dt_raw = dt; + + 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_raw; + dt_raw = 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()->flush(); } + + + 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); - } -} + if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG)) + { + if (!LLGLSLShader::sNoFixedFunction) + { + glFogf(GL_FOG_DENSITY, 0); + glFogfv(GL_FOG_COLOR, (F32 *) &LLColor4::white.mV); + glFogf(GL_FOG_END, 1000000.f); + } + return; + } -void LLVOSky::setSunAndMoonDirectionsCFR(const LLVector3 &sun_dir_cfr, const LLVector3 &moon_dir_cfr) -{ - mSun.setDirection(sun_dir_cfr); - mMoon.setDirection(moon_dir_cfr); + const BOOL hide_clip_plane = TRUE; + LLColor4 target_fog(0.f, 0.2f, 0.5f, 0.f); - // 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; + const F32 water_height = gAgent.getRegion() ? gAgent.getRegion()->getWaterHeight() : 0.f; + // LLWorld::getInstance()->getWaterHeight(); + F32 camera_height = gAgentCamera.getCameraPositionAgent().mV[2]; + + F32 near_clip_height = LLViewerCamera::getInstance()->getAtAxis().mV[VZ] * LLViewerCamera::getInstance()->getNear(); + camera_height += near_clip_height; + + F32 fog_distance = 0.f; + LLColor3 res_color[3]; + + LLColor3 sky_fog_color = LLColor3::white; + LLColor3 render_fog_color = LLColor3::white; - // 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; + LLVector3 tosun = getToSunLast(); + const F32 tosun_z = tosun.mV[VZ]; + tosun.mV[VZ] = 0.f; + tosun.normalize(); + LLVector3 perp_tosun; + perp_tosun.mV[VX] = -tosun.mV[VY]; + perp_tosun.mV[VY] = tosun.mV[VX]; + LLVector3 tosun_45 = tosun + perp_tosun; + tosun_45.normalize(); - // 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(); - } + F32 delta = 0.06f; + tosun.mV[VZ] = delta; + perp_tosun.mV[VZ] = delta; + tosun_45.mV[VZ] = delta; + tosun.normalize(); + perp_tosun.normalize(); + tosun_45.normalize(); - updateDirections(); + // 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. + initAtmospherics(); + res_color[0] = calcSkyColorInDir(tosun); + res_color[1] = calcSkyColorInDir(perp_tosun); + res_color[2] = calcSkyColorInDir(tosun_45); - mForceUpdate = true; + sky_fog_color = color_norm(res_color[0] + res_color[1] + res_color[2]); + + F32 full_off = -0.25f; + F32 full_on = 0.00f; + F32 on = (tosun_z - full_off) / (full_on - full_off); + on = llclamp(on, 0.01f, 1.f); + sky_fog_color *= 0.5f * on; + + + // We need to clamp these to non-zero, in order for the gamma correction to work. 0^y = ??? + S32 i; + for (i = 0; i < 3; i++) + { + sky_fog_color.mV[i] = llmax(0.0001f, sky_fog_color.mV[i]); + } + + 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) + { + LLColor4 fog(render_fog_color); + if (!LLGLSLShader::sNoFixedFunction) + { + 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; + if (!LLGLSLShader::sNoFixedFunction) + { + glFogi(GL_FOG_MODE, GL_EXP2); + } + } + else + { + const F32 f_log = 4.6051701859880913680359829093687f; // fabs(log(0.01f)) + fog_density = (f_log)/fog_distance; + if (!LLGLSLShader::sNoFixedFunction) + { + glFogi(GL_FOG_MODE, GL_EXP); + } + } + } + else + { + F32 depth = water_height - camera_height; + + // get the water param manager variables + float water_fog_density = LLWaterParamManager::getInstance()->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 + mGLFogCol = fogCol; + + // set the density based on what the shaders use + fog_density = water_fog_density * gSavedSettings.getF32("WaterGLFogDensityScale"); + + if (!LLGLSLShader::sNoFixedFunction) + { + glFogfv(GL_FOG_COLOR, (F32 *) &fogCol.mV); + glFogi(GL_FOG_MODE, GL_EXP2); + } + } + + mFogColor = sky_fog_color; + mFogColor.setAlpha(1); + LLDrawPoolWater::sWaterFogEnd = fog_distance*2.2f; + + if (!LLGLSLShader::sNoFixedFunction) + { + LLGLSFog gls_fog; + glFogf(GL_FOG_END, fog_distance*2.2f); + glFogf(GL_FOG_DENSITY, fog_density); + glHint(GL_FOG_HINT, GL_NICEST); + } + stop_glerror(); } -void LLVOSky::setSunDirectionCFR(const LLVector3 &sun_dir_cfr) + +// Functions used a lot. +F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply) { - mSun.setDirection(sun_dir_cfr); + F32 mv = color_max(col); + if (0 == mv) + { + return 0; + } - // 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; + col *= 1.f / mv; + color_pow(col, e); + if (postmultiply) + { + col *= mv; + } + return mv; +} - // 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; +// Returns angle (RADIANs) between the horizontal projection of "v" and the x_axis. +// Range of output is 0.0f to 2pi //359.99999...f +// Returns 0.0f when "v" = +/- z_axis. +F32 azimuth(const LLVector3 &v) +{ + F32 azimuth = 0.0f; + if (v.mV[VX] == 0.0f) + { + if (v.mV[VY] > 0.0f) + { + azimuth = F_PI * 0.5f; + } + else if (v.mV[VY] < 0.0f) + { + azimuth = F_PI * 1.5f;// 270.f; + } + } + else + { + azimuth = (F32) atan(v.mV[VY] / v.mV[VX]); + if (v.mV[VX] < 0.0f) + { + azimuth += F_PI; + } + else if (v.mV[VY] < 0.0f) + { + azimuth += F_PI * 2; + } + } + return azimuth; +} - // 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(); - } +void LLVOSky::initSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity) +{ + LLVector3 sun_direction = (sun_dir.length() == 0) ? LLVector3::x_axis : sun_dir; + sun_direction.normalize(); + mSun.setDirection(sun_direction); + mSun.renewDirection(); + mSun.setAngularVelocity(sun_ang_velocity); + mMoon.setDirection(-mSun.getDirection()); + mMoon.renewDirection(); + mLastLightingDirection = mSun.getDirection(); - updateDirections(); + calcAtmospherics(); - mForceUpdate = true; + if ( !mInitialized ) + { + init(); + LLSkyTex::stepCurrent(); + } } -void LLVOSky::setMoonDirectionCFR(const LLVector3 &moon_dir_cfr) +void LLVOSky::setSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity) { - mMoon.setDirection(moon_dir_cfr); - - updateDirections(); + LLVector3 sun_direction = (sun_dir.length() == 0) ? LLVector3::x_axis : sun_dir; + sun_direction.normalize(); - mForceUpdate = true; + // 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; + + // Same as dot product with the up direction + clamp. + F32 sunDot = llmax(0.f, newDir.mV[2]); + sunDot *= sunDot; + + // 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; + + // 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.normalize(); + + 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; + } } |