From a0598b12656cdcf22ba95cacd01b5ff36f8f1b26 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Mon, 11 Jun 2018 17:46:16 +0100 Subject: Fix water fog consolidation in underwater shaders. Add plumbing facilities to allow current and next moon textures to be passed to moon shader. Modify moon shader to blend between current and next moon textures by blend factor. --- indra/newview/llvovolume.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 7d6881f8a8..d4c8d4f923 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -2152,7 +2152,7 @@ bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture) switch(range_it->second.map) { - case LLRender::DIFFUSE_MAP: + case LLRender::DIFFUSE_MAP: { if(LLMaterial::DIFFUSE_ALPHA_MODE_NONE != cur_material->getDiffuseAlphaMode()) { //missing texture + !LLMaterial::DIFFUSE_ALPHA_MODE_NONE => LLMaterial::DIFFUSE_ALPHA_MODE_NONE @@ -2194,9 +2194,8 @@ bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture) mat->setSpecularID(LLUUID::null); } break; - case LLRender::NUM_TEXTURE_CHANNELS: - //nothing to do, make compiler happy - break; + default: + break; } //switch } //for -- cgit v1.3 From e5a8fb042af9429ff0d6a578ce181dbe8ef11b77 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Mon, 24 Sep 2018 19:14:41 +0100 Subject: SL-9708 Fix knock-on from fix for SL1505 reflection matrix bug by putting back old code for setting up underwater culling planes. Fix some diffs from viewer-release. --- indra/newview/lldrawpoolwater.cpp | 1522 ++++++++++++++++++------------------- indra/newview/llviewerregion.h | 488 ++++++------ indra/newview/llvovolume.cpp | 5 +- indra/newview/pipeline.cpp | 11 +- 4 files changed, 1017 insertions(+), 1009 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 56f3b75792..a91246b5a1 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -1,762 +1,762 @@ -/** - * @file lldrawpoolwater.cpp - * @brief LLDrawPoolWater class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llfeaturemanager.h" -#include "lldrawpoolwater.h" - -#include "llviewercontrol.h" -#include "lldir.h" -#include "llerror.h" -#include "m3math.h" -#include "llrender.h" - -#include "llagent.h" // for gAgent for getRegion for getWaterHeight -#include "llcubemap.h" -#include "lldrawable.h" -#include "llface.h" -#include "llsky.h" -#include "llviewertexturelist.h" -#include "llviewerregion.h" -#include "llvosky.h" -#include "llvowater.h" -#include "llworld.h" -#include "pipeline.h" -#include "llviewershadermgr.h" -#include "llenvironment.h" -#include "llsettingssky.h" -#include "llsettingswater.h" - -static float sTime; - -BOOL deferred_render = FALSE; - -BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE; -BOOL LLDrawPoolWater::sNeedsReflectionUpdate = TRUE; -BOOL LLDrawPoolWater::sNeedsDistortionUpdate = TRUE; -F32 LLDrawPoolWater::sWaterFogEnd = 0.f; - -LLDrawPoolWater::LLDrawPoolWater() : LLFacePool(POOL_WATER) -{ -} - -LLDrawPoolWater::~LLDrawPoolWater() -{ -} - -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); -} - -void LLDrawPoolWater::setOpaqueTexture(const LLUUID& opaqueTextureId) -{ - LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater(); - mOpaqueWaterImagep = LLViewerTextureManager::getFetchedTexture(opaqueTextureId); - mOpaqueWaterImagep->addTextureStats(1024.f*1024.f); -} - -void LLDrawPoolWater::setNormalMaps(const LLUUID& normalMapId, const LLUUID& nextNormalMapId) -{ - 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() -{ - LL_ERRS() << "Should never be calling instancePool on a water pool!" << LL_ENDL; - return NULL; -} - - -void LLDrawPoolWater::prerender() -{ - mVertexShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ? LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0; -} - -S32 LLDrawPoolWater::getNumPasses() -{ - if (LLViewerCamera::getInstance()->getOrigin().mV[2] < 1024.f) - { - return 1; - } - - return 0; -} - -void LLDrawPoolWater::beginPostDeferredPass(S32 pass) -{ - beginRenderPass(pass); - deferred_render = TRUE; -} - -void LLDrawPoolWater::endPostDeferredPass(S32 pass) -{ - endRenderPass(pass); - deferred_render = FALSE; -} - -//=============================== -//DEFERRED IMPLEMENTATION -//=============================== -void LLDrawPoolWater::renderDeferred(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_WATER); - deferred_render = TRUE; - shade(); - deferred_render = FALSE; -} - -//========================================= - -void LLDrawPoolWater::render(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_WATER); - if (mDrawFace.empty() || LLDrawable::getCurrentFrame() <= 1) - { - return; - } - - //do a quick 'n dirty depth sort - for (std::vector::iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) - { - LLFace* facep = *iter; - facep->mDistance = -facep->mCenterLocal.mV[2]; - } - - std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater()); - - // See if we are rendering water as opaque or not - if (!gSavedSettings.getBOOL("RenderTransparentWater")) - { - // render water for low end hardware - renderOpaqueLegacyWater(); - return; - } - - LLGLEnable blend(GL_BLEND); - - if ((mVertexShaderLevel > 0) && !sSkipScreenCopy) - { - shade(); - return; - } - - LLVOSky *voskyp = gSky.mVOSkyp; - - stop_glerror(); - - if (!gGLManager.mHasMultitexture) - { - // Ack! No multitexture! Bail! - return; - } - - LLFace* refl_face = voskyp->getReflFace(); - - gPipeline.disableLights(); - - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - - LLGLDisable cullFace(GL_CULL_FACE); - - // Set up second pass first - 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]) ; - - LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis(); - F32 up_dot = camera_up * LLVector3::z_axis; - - LLColor4 water_color; - if (LLViewerCamera::getInstance()->cameraUnderWater()) - { - water_color.setVec(1.f, 1.f, 1.f, 0.4f); - } - else - { - water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot)); - } - - gGL.diffuseColor4fv(water_color.mV); - - // Automatically generate texture coords for detail map - glEnable(GL_TEXTURE_GEN_S); //texture unit 1 - glEnable(GL_TEXTURE_GEN_T); //texture unit 1 - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - - // Slowly move over time. - F32 offset = fmod(gFrameTimeSeconds*2.f, 100.f); - F32 tp0[4] = {16.f/256.f, 0.0f, 0.0f, offset*0.01f}; - F32 tp1[4] = {0.0f, 16.f/256.f, 0.0f, offset*0.01f}; - glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0); - glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1); - - gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_ALPHA); - - gGL.getTexUnit(0)->activate(); - - glClearStencil(1); - glClear(GL_STENCIL_BUFFER_BIT); - LLGLEnable gls_stencil(GL_STENCIL_TEST); - glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); - glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF); - - for (std::vector::iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) - { - LLFace *face = *iter; - if (voskyp->isReflFace(face)) - { - continue; - } - gGL.getTexUnit(0)->bind(face->getTexture()); - face->renderIndexed(); - } - - // Now, disable texture coord generation on texture state 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 - - 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 - - // Disable texture coordinate and color arrays - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - stop_glerror(); - - if (gSky.mVOSkyp->getCubeMap()) - { - gSky.mVOSkyp->getCubeMap()->enable(0); - gSky.mVOSkyp->getCubeMap()->bind(); - - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview(); - LLMatrix4 camera_rot(camera_mat.getMat3()); - camera_rot.invert(); - - gGL.loadMatrix((F32 *)camera_rot.mMatrix); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - LLOverrideFaceColor overrid(this, 1.f, 1.f, 1.f, 0.5f*up_dot); - - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - - for (std::vector::iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) - { - LLFace *face = *iter; - if (voskyp->isReflFace(face)) - { - //refl_face = face; - continue; - } - - if (face->getGeomCount() > 0) - { - face->renderIndexed(); - } - } - - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - - gSky.mVOSkyp->getCubeMap()->disable(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - - } - - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - - if (refl_face) - { - glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF); - renderReflection(refl_face); - } - - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); -} - -// for low end hardware -void LLDrawPoolWater::renderOpaqueLegacyWater() -{ - LLVOSky *voskyp = gSky.mVOSkyp; - - LLGLSLShader* shader = NULL; - if (LLGLSLShader::sNoFixedFunction) - { - if (LLPipeline::sUnderWaterRender) - { - shader = &gObjectSimpleNonIndexedTexGenWaterProgram; - } - else - { - shader = &gObjectSimpleNonIndexedTexGenProgram; - } - - shader->bind(); - } - - stop_glerror(); - - // Depth sorting and write to depth buffer - // since this is opaque, we should see nothing - // behind the water. No blending because - // of no transparency. And no face culling so - // that the underside of the water is also opaque. - LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); - LLGLDisable no_cull(GL_CULL_FACE); - LLGLDisable no_blend(GL_BLEND); - - gPipeline.disableLights(); - - // Activate the texture binding and bind one - // texture since all images will have the same texture - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->bind(mOpaqueWaterImagep); - - // Automatically generate texture coords for water texture - if (!shader) - { - glEnable(GL_TEXTURE_GEN_S); //texture unit 0 - glEnable(GL_TEXTURE_GEN_T); //texture unit 0 - glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - } - - // Use the fact that we know all water faces are the same size - // to save some computation - - // Slowly move texture coordinates over time so the watter appears - // to be moving. - F32 movement_period_secs = 50.f; - - F32 offset = fmod(gFrameTimeSeconds, movement_period_secs); - - if (movement_period_secs != 0) - { - offset /= movement_period_secs; - } - else - { - offset = 0; - } - - F32 tp0[4] = { 16.f / 256.f, 0.0f, 0.0f, offset }; - F32 tp1[4] = { 0.0f, 16.f / 256.f, 0.0f, offset }; - - if (!shader) - { - glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0); - glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1); - } - else - { - shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0); - shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1); - } - - gGL.diffuseColor3f(1.f, 1.f, 1.f); - - for (std::vector::iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) - { - LLFace *face = *iter; - if (voskyp->isReflFace(face)) - { - continue; - } - - face->renderIndexed(); - } - - stop_glerror(); - - if (!shader) - { - // Reset the settings back to expected values - glDisable(GL_TEXTURE_GEN_S); //texture unit 0 - glDisable(GL_TEXTURE_GEN_T); //texture unit 0 - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); -} - - -void LLDrawPoolWater::renderReflection(LLFace* face) -{ - LLVOSky *voskyp = gSky.mVOSkyp; - - if (!voskyp) - { - return; - } - - if (!face->getGeomCount()) - { - return; - } - - S8 dr = voskyp->getDrawRefl(); - if (dr < 0) - { - return; - } - - LLGLSNoFog noFog; - - gGL.getTexUnit(0)->bind((dr == 0) ? voskyp->getSunTex() : voskyp->getMoonTex()); - - LLOverrideFaceColor override(this, LLColor4(face->getFaceColor().mV)); - face->renderIndexed(); -} - -void LLDrawPoolWater::shade() -{ - if (!deferred_render) - { - gGL.setColorMask(true, true); - } - - LLVOSky *voskyp = gSky.mVOSkyp; - - if(voskyp == NULL) - { - return; - } - - LLGLDisable blend(GL_BLEND); - - LLColor3 light_diffuse(0,0,0); - F32 light_exp = 0.0f; - LLVector3 light_dir; - LLColor3 light_color; - - 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_color = light_color + psky->getSunAmbient(); - light_diffuse += psky->getSunDiffuse(); - } - - light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0.f); - - if (moon_up) - { - LLColor3 moon_diffuse_color = psky->getMoonDiffuse(); - light_color += moon_diffuse_color; - light_diffuse += moon_diffuse_color * 0.5f; - - if (!sun_up) - { - 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; - light_exp *= light_exp; - 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(); - - if (eyedepth < 0.f && LLPipeline::sWaterReflections) - { - if (deferred_render) - { - shader = &gDeferredUnderWaterProgram; - } - else - { - shader = &gUnderWaterProgram; - } - } - else if (deferred_render) - { - shader = &gDeferredWaterProgram; - } - else - { - 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); - } - } - - sTime = (F32)LLFrameTimer::getElapsedSeconds() * 0.5f; - - S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX); - - if (reftex > -1) - { - gGL.getTexUnit(reftex)->activate(); - gGL.getTexUnit(reftex)->bind(&gPipeline.mWaterRef); - gGL.getTexUnit(0)->activate(); - } - - //bind normal map - S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP); - - if (mWaterNormp[0]) - { - gGL.getTexUnit(bumpTex)->bind(mWaterNormp[0]) ; - - if (gSavedSettings.getBOOL("RenderWaterMipNormal")) - { - mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); - } - else - { - mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_POINT); - } - } - - 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); - } - } - - shader->uniform3fv(LLShaderMgr::WATER_FOGCOLOR, 1, pwater->getWaterFogColor().mV); - shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, pwater->getWaterFogDensity()); - - // bind reflection texture from RenderTarget - S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX); - gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis); - - if (mVertexShaderLevel == 1) - { - LLColor4 fog_color(pwater->getWaterFogColor(), 0.f); - fog_color[3] = pwater->getWaterFogDensity(); - shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV); - } - - F32 screenRes[] = - { - 1.f/gGLViewport[2], - 1.f/gGLViewport[3] - }; - shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes); - stop_glerror(); - - S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP); - stop_glerror(); - - //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 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->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()); - - F32 sunAngle = llmax(0.f, light_dir.mV[2]); - F32 scaledAngle = 1.f - sunAngle; - - shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle); - shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle); - shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f*sunAngle); - - LLColor4 water_color; - LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis(); - F32 up_dot = camera_up * LLVector3::z_axis; - if (LLViewerCamera::getInstance()->cameraUnderWater()) - { - water_color.setVec(1.f, 1.f, 1.f, 0.4f); - shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow()); - } - else - { - water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot)); - shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove()); - } - - if (water_color.mV[3] > 0.9f) - { - water_color.mV[3] = 0.9f; - } - - { - LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0); - LLGLDisable cullface(GL_CULL_FACE); - for (std::vector::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()); - - sNeedsReflectionUpdate = TRUE; - - if (water->getUseTexture() || !water->getIsEdgePatch()) - { - sNeedsDistortionUpdate = TRUE; - face->renderIndexed(); - } - // using squash clip for deferred rendering makes the horizon lines match - // between ALM and non-ALM rendering (SL-1655), but introduces an ugly seem between - // near and far water(SL-9696)...we're going to live with the former and not cause the latter +/** + * @file lldrawpoolwater.cpp + * @brief LLDrawPoolWater class implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfeaturemanager.h" +#include "lldrawpoolwater.h" + +#include "llviewercontrol.h" +#include "lldir.h" +#include "llerror.h" +#include "m3math.h" +#include "llrender.h" + +#include "llagent.h" // for gAgent for getRegion for getWaterHeight +#include "llcubemap.h" +#include "lldrawable.h" +#include "llface.h" +#include "llsky.h" +#include "llviewertexturelist.h" +#include "llviewerregion.h" +#include "llvosky.h" +#include "llvowater.h" +#include "llworld.h" +#include "pipeline.h" +#include "llviewershadermgr.h" +#include "llenvironment.h" +#include "llsettingssky.h" +#include "llsettingswater.h" + +static float sTime; + +BOOL deferred_render = FALSE; + +BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE; +BOOL LLDrawPoolWater::sNeedsReflectionUpdate = TRUE; +BOOL LLDrawPoolWater::sNeedsDistortionUpdate = TRUE; +F32 LLDrawPoolWater::sWaterFogEnd = 0.f; + +LLDrawPoolWater::LLDrawPoolWater() : LLFacePool(POOL_WATER) +{ +} + +LLDrawPoolWater::~LLDrawPoolWater() +{ +} + +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); +} + +void LLDrawPoolWater::setOpaqueTexture(const LLUUID& opaqueTextureId) +{ + LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater(); + mOpaqueWaterImagep = LLViewerTextureManager::getFetchedTexture(opaqueTextureId); + mOpaqueWaterImagep->addTextureStats(1024.f*1024.f); +} + +void LLDrawPoolWater::setNormalMaps(const LLUUID& normalMapId, const LLUUID& nextNormalMapId) +{ + 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() +{ + LL_ERRS() << "Should never be calling instancePool on a water pool!" << LL_ENDL; + return NULL; +} + + +void LLDrawPoolWater::prerender() +{ + mVertexShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ? LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0; +} + +S32 LLDrawPoolWater::getNumPasses() +{ + if (LLViewerCamera::getInstance()->getOrigin().mV[2] < 1024.f) + { + return 1; + } + + return 0; +} + +void LLDrawPoolWater::beginPostDeferredPass(S32 pass) +{ + beginRenderPass(pass); + deferred_render = TRUE; +} + +void LLDrawPoolWater::endPostDeferredPass(S32 pass) +{ + endRenderPass(pass); + deferred_render = FALSE; +} + +//=============================== +//DEFERRED IMPLEMENTATION +//=============================== +void LLDrawPoolWater::renderDeferred(S32 pass) +{ + LL_RECORD_BLOCK_TIME(FTM_RENDER_WATER); + deferred_render = TRUE; + shade(); + deferred_render = FALSE; +} + +//========================================= + +void LLDrawPoolWater::render(S32 pass) +{ + LL_RECORD_BLOCK_TIME(FTM_RENDER_WATER); + if (mDrawFace.empty() || LLDrawable::getCurrentFrame() <= 1) + { + return; + } + + //do a quick 'n dirty depth sort + for (std::vector::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace* facep = *iter; + facep->mDistance = -facep->mCenterLocal.mV[2]; + } + + std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater()); + + // See if we are rendering water as opaque or not + if (!gSavedSettings.getBOOL("RenderTransparentWater")) + { + // render water for low end hardware + renderOpaqueLegacyWater(); + return; + } + + LLGLEnable blend(GL_BLEND); + + if ((mVertexShaderLevel > 0) && !sSkipScreenCopy) + { + shade(); + return; + } + + LLVOSky *voskyp = gSky.mVOSkyp; + + stop_glerror(); + + if (!gGLManager.mHasMultitexture) + { + // Ack! No multitexture! Bail! + return; + } + + LLFace* refl_face = voskyp->getReflFace(); + + gPipeline.disableLights(); + + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + + LLGLDisable cullFace(GL_CULL_FACE); + + // Set up second pass first + 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]) ; + + LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis(); + F32 up_dot = camera_up * LLVector3::z_axis; + + LLColor4 water_color; + if (LLViewerCamera::getInstance()->cameraUnderWater()) + { + water_color.setVec(1.f, 1.f, 1.f, 0.4f); + } + else + { + water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot)); + } + + gGL.diffuseColor4fv(water_color.mV); + + // Automatically generate texture coords for detail map + glEnable(GL_TEXTURE_GEN_S); //texture unit 1 + glEnable(GL_TEXTURE_GEN_T); //texture unit 1 + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + + // Slowly move over time. + F32 offset = fmod(gFrameTimeSeconds*2.f, 100.f); + F32 tp0[4] = {16.f/256.f, 0.0f, 0.0f, offset*0.01f}; + F32 tp1[4] = {0.0f, 16.f/256.f, 0.0f, offset*0.01f}; + glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0); + glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1); + + gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); + gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_ALPHA); + + gGL.getTexUnit(0)->activate(); + + glClearStencil(1); + glClear(GL_STENCIL_BUFFER_BIT); + LLGLEnable gls_stencil(GL_STENCIL_TEST); + glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); + glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF); + + for (std::vector::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace *face = *iter; + if (voskyp->isReflFace(face)) + { + continue; + } + gGL.getTexUnit(0)->bind(face->getTexture()); + face->renderIndexed(); + } + + // Now, disable texture coord generation on texture state 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 + + 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 + + // Disable texture coordinate and color arrays + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + stop_glerror(); + + if (gSky.mVOSkyp->getCubeMap()) + { + gSky.mVOSkyp->getCubeMap()->enable(0); + gSky.mVOSkyp->getCubeMap()->bind(); + + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadIdentity(); + LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview(); + LLMatrix4 camera_rot(camera_mat.getMat3()); + camera_rot.invert(); + + gGL.loadMatrix((F32 *)camera_rot.mMatrix); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + LLOverrideFaceColor overrid(this, 1.f, 1.f, 1.f, 0.5f*up_dot); + + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + + for (std::vector::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace *face = *iter; + if (voskyp->isReflFace(face)) + { + //refl_face = face; + continue; + } + + if (face->getGeomCount() > 0) + { + face->renderIndexed(); + } + } + + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + + gSky.mVOSkyp->getCubeMap()->disable(); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + + } + + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + if (refl_face) + { + glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF); + renderReflection(refl_face); + } + + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); +} + +// for low end hardware +void LLDrawPoolWater::renderOpaqueLegacyWater() +{ + LLVOSky *voskyp = gSky.mVOSkyp; + + LLGLSLShader* shader = NULL; + if (LLGLSLShader::sNoFixedFunction) + { + if (LLPipeline::sUnderWaterRender) + { + shader = &gObjectSimpleNonIndexedTexGenWaterProgram; + } + else + { + shader = &gObjectSimpleNonIndexedTexGenProgram; + } + + shader->bind(); + } + + stop_glerror(); + + // Depth sorting and write to depth buffer + // since this is opaque, we should see nothing + // behind the water. No blending because + // of no transparency. And no face culling so + // that the underside of the water is also opaque. + LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); + LLGLDisable no_cull(GL_CULL_FACE); + LLGLDisable no_blend(GL_BLEND); + + gPipeline.disableLights(); + + // Activate the texture binding and bind one + // texture since all images will have the same texture + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->bind(mOpaqueWaterImagep); + + // Automatically generate texture coords for water texture + if (!shader) + { + glEnable(GL_TEXTURE_GEN_S); //texture unit 0 + glEnable(GL_TEXTURE_GEN_T); //texture unit 0 + glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + } + + // Use the fact that we know all water faces are the same size + // to save some computation + + // Slowly move texture coordinates over time so the watter appears + // to be moving. + F32 movement_period_secs = 50.f; + + F32 offset = fmod(gFrameTimeSeconds, movement_period_secs); + + if (movement_period_secs != 0) + { + offset /= movement_period_secs; + } + else + { + offset = 0; + } + + F32 tp0[4] = { 16.f / 256.f, 0.0f, 0.0f, offset }; + F32 tp1[4] = { 0.0f, 16.f / 256.f, 0.0f, offset }; + + if (!shader) + { + glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0); + glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1); + } + else + { + shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0); + shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1); + } + + gGL.diffuseColor3f(1.f, 1.f, 1.f); + + for (std::vector::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace *face = *iter; + if (voskyp->isReflFace(face)) + { + continue; + } + + face->renderIndexed(); + } + + stop_glerror(); + + if (!shader) + { + // Reset the settings back to expected values + glDisable(GL_TEXTURE_GEN_S); //texture unit 0 + glDisable(GL_TEXTURE_GEN_T); //texture unit 0 + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); +} + + +void LLDrawPoolWater::renderReflection(LLFace* face) +{ + LLVOSky *voskyp = gSky.mVOSkyp; + + if (!voskyp) + { + return; + } + + if (!face->getGeomCount()) + { + return; + } + + S8 dr = voskyp->getDrawRefl(); + if (dr < 0) + { + return; + } + + LLGLSNoFog noFog; + + gGL.getTexUnit(0)->bind((dr == 0) ? voskyp->getSunTex() : voskyp->getMoonTex()); + + LLOverrideFaceColor override(this, LLColor4(face->getFaceColor().mV)); + face->renderIndexed(); +} + +void LLDrawPoolWater::shade() +{ + if (!deferred_render) + { + gGL.setColorMask(true, true); + } + + LLVOSky *voskyp = gSky.mVOSkyp; + + if(voskyp == NULL) + { + return; + } + + LLGLDisable blend(GL_BLEND); + + LLColor3 light_diffuse(0,0,0); + F32 light_exp = 0.0f; + LLVector3 light_dir; + LLColor3 light_color; + + 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_color = light_color + psky->getSunAmbient(); + light_diffuse += psky->getSunDiffuse(); + } + + light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0.f); + + if (moon_up) + { + LLColor3 moon_diffuse_color = psky->getMoonDiffuse(); + light_color += moon_diffuse_color; + light_diffuse += moon_diffuse_color * 0.5f; + + if (!sun_up) + { + 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; + light_exp *= light_exp; + 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(); + + if (eyedepth < 0.f && LLPipeline::sWaterReflections) + { + if (deferred_render) + { + shader = &gDeferredUnderWaterProgram; + } + else + { + shader = &gUnderWaterProgram; + } + } + else if (deferred_render) + { + shader = &gDeferredWaterProgram; + } + else + { + 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); + } + } + + sTime = (F32)LLFrameTimer::getElapsedSeconds() * 0.5f; + + S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX); + + if (reftex > -1) + { + gGL.getTexUnit(reftex)->activate(); + gGL.getTexUnit(reftex)->bind(&gPipeline.mWaterRef); + gGL.getTexUnit(0)->activate(); + } + + //bind normal map + S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP); + + if (mWaterNormp[0]) + { + gGL.getTexUnit(bumpTex)->bind(mWaterNormp[0]) ; + + if (gSavedSettings.getBOOL("RenderWaterMipNormal")) + { + mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); + } + else + { + mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_POINT); + } + } + + 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); + } + } + + shader->uniform3fv(LLShaderMgr::WATER_FOGCOLOR, 1, pwater->getWaterFogColor().mV); + shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, pwater->getWaterFogDensity()); + + // bind reflection texture from RenderTarget + S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX); + gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis); + + if (mVertexShaderLevel == 1) + { + LLColor4 fog_color(pwater->getWaterFogColor(), 0.f); + fog_color[3] = pwater->getWaterFogDensity(); + shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV); + } + + F32 screenRes[] = + { + 1.f/gGLViewport[2], + 1.f/gGLViewport[3] + }; + shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes); + stop_glerror(); + + S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP); + stop_glerror(); + + //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 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->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()); + + F32 sunAngle = llmax(0.f, light_dir.mV[2]); + F32 scaledAngle = 1.f - sunAngle; + + shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle); + shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle); + shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f*sunAngle); + + LLColor4 water_color; + LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis(); + F32 up_dot = camera_up * LLVector3::z_axis; + if (LLViewerCamera::getInstance()->cameraUnderWater()) + { + water_color.setVec(1.f, 1.f, 1.f, 0.4f); + shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow()); + } + else + { + water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot)); + shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove()); + } + + if (water_color.mV[3] > 0.9f) + { + water_color.mV[3] = 0.9f; + } + + { + LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0); + LLGLDisable cullface(GL_CULL_FACE); + for (std::vector::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()); + + sNeedsReflectionUpdate = TRUE; + + if (water->getUseTexture() || !water->getIsEdgePatch()) + { + sNeedsDistortionUpdate = TRUE; + face->renderIndexed(); + } + // using squash clip for deferred rendering makes the horizon lines match + // between ALM and non-ALM rendering (SL-1655), but introduces an ugly seem between + // near and far water(SL-9696)...we're going to live with the former and not cause the latter else if (gGLManager.mHasDepthClamp || deferred_render) - { - face->renderIndexed(); - } - else - { - LLGLSquashToFarClip far_clip(get_current_projection()); - face->renderIndexed(); - } - } - } - - shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); - shader->disableTexture(LLShaderMgr::WATER_SCREENTEX); - shader->disableTexture(LLShaderMgr::BUMP_MAP); - shader->disableTexture(LLShaderMgr::DIFFUSE_MAP); - shader->disableTexture(LLShaderMgr::WATER_REFTEX); - shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH); - - shader->unbind(); - - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - if (!deferred_render) - { - gGL.setColorMask(true, false); - } - -} - -LLViewerTexture *LLDrawPoolWater::getDebugTexture() -{ - return LLViewerFetchedTexture::sSmokeImagep; -} - -LLColor3 LLDrawPoolWater::getDebugColor() const -{ - return LLColor3(0.f, 1.f, 1.f); -} + { + face->renderIndexed(); + } + else + { + LLGLSquashToFarClip far_clip(get_current_projection()); + face->renderIndexed(); + } + } + } + + shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); + shader->disableTexture(LLShaderMgr::WATER_SCREENTEX); + shader->disableTexture(LLShaderMgr::BUMP_MAP); + shader->disableTexture(LLShaderMgr::DIFFUSE_MAP); + shader->disableTexture(LLShaderMgr::WATER_REFTEX); + shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH); + + shader->unbind(); + + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + if (!deferred_render) + { + gGL.setColorMask(true, false); + } + +} + +LLViewerTexture *LLDrawPoolWater::getDebugTexture() +{ + return LLViewerFetchedTexture::sSmokeImagep; +} + +LLColor3 LLDrawPoolWater::getDebugColor() const +{ + return LLColor3(0.f, 1.f, 1.f); +} diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index d74b77c880..302647215f 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -74,311 +74,311 @@ class LLVOCachePartition; class LLViewerRegion: public LLCapabilityProvider // implements this interface { public: - //MUST MATCH THE ORDER OF DECLARATION IN CONSTRUCTOR + //MUST MATCH THE ORDER OF DECLARATION IN CONSTRUCTOR typedef enum - { + { PARTITION_HUD=0, - PARTITION_TERRAIN, - PARTITION_VOIDWATER, - PARTITION_WATER, - PARTITION_TREE, - PARTITION_PARTICLE, - PARTITION_GRASS, - PARTITION_VOLUME, - PARTITION_BRIDGE, - PARTITION_HUD_PARTICLE, - PARTITION_VO_CACHE, - PARTITION_NONE, - NUM_PARTITIONS - } eObjectPartitions; - - typedef boost::signals2::signal caps_received_signal_t; - - LLViewerRegion(const U64 &handle, - const LLHost &host, - const U32 surface_grid_width, - const U32 patch_grid_width, - const F32 region_width_meters); - ~LLViewerRegion(); - - // Call this after you have the region name and handle. - void loadObjectCache(); - void saveObjectCache(); - - void sendMessage(); // Send the current message to this region's simulator - void sendReliableMessage(); // Send the current message to this region's simulator - - void setOriginGlobal(const LLVector3d &origin); - //void setAgentOffset(const LLVector3d &offset); - void updateRenderMatrix(); - - void setAllowDamage(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_DAMAGE, b); } - void setAllowLandmark(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_LANDMARK, b); } - void setAllowSetHome(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_SET_HOME, b); } - void setResetHomeOnTeleport(BOOL b) { setRegionFlag(REGION_FLAGS_RESET_HOME_ON_TELEPORT, b); } - void setSunFixed(BOOL b) { setRegionFlag(REGION_FLAGS_SUN_FIXED, b); } - //void setBlockFly(BOOL b) { setRegionFlag(REGION_FLAGS_BLOCK_FLY, b); } Never used - void setAllowDirectTeleport(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_DIRECT_TELEPORT, b); } - - - inline BOOL getAllowDamage() const; - inline BOOL getAllowLandmark() const; - inline BOOL getAllowSetHome() const; - inline BOOL getResetHomeOnTeleport() const; - inline BOOL getSunFixed() const; - inline BOOL getBlockFly() const; - inline BOOL getAllowDirectTeleport() const; - inline BOOL isPrelude() const; - inline BOOL getAllowTerraform() const; - inline BOOL getRestrictPushObject() const; - inline BOOL getReleaseNotesRequested() const; - - bool isAlive(); // can become false if circuit disconnects - - void setWaterHeight(F32 water_level); - F32 getWaterHeight() const; - - BOOL isVoiceEnabled() const; - - void setBillableFactor(F32 billable_factor) { mBillableFactor = billable_factor; } - F32 getBillableFactor() const { return mBillableFactor; } - - // Maximum number of primitives allowed, regardless of object - // bonus factor. - U32 getMaxTasks() const { return mMaxTasks; } - void setMaxTasks(U32 max_tasks) { mMaxTasks = max_tasks; } - - // Draw lines in the dirt showing ownership. Return number of - // vertices drawn. - S32 renderPropertyLines(); - - // Call this whenever you change the height data in the region. - // (Automatically called by LLSurfacePatch's update routine) - void dirtyHeights(); - - LLViewerParcelOverlay *getParcelOverlay() const + PARTITION_TERRAIN, + PARTITION_VOIDWATER, + PARTITION_WATER, + PARTITION_TREE, + PARTITION_PARTICLE, + PARTITION_GRASS, + PARTITION_VOLUME, + PARTITION_BRIDGE, + PARTITION_HUD_PARTICLE, + PARTITION_VO_CACHE, + PARTITION_NONE, + NUM_PARTITIONS + } eObjectPartitions; + + typedef boost::signals2::signal caps_received_signal_t; + + LLViewerRegion(const U64 &handle, + const LLHost &host, + const U32 surface_grid_width, + const U32 patch_grid_width, + const F32 region_width_meters); + ~LLViewerRegion(); + + // Call this after you have the region name and handle. + void loadObjectCache(); + void saveObjectCache(); + + void sendMessage(); // Send the current message to this region's simulator + void sendReliableMessage(); // Send the current message to this region's simulator + + void setOriginGlobal(const LLVector3d &origin); + //void setAgentOffset(const LLVector3d &offset); + void updateRenderMatrix(); + + void setAllowDamage(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_DAMAGE, b); } + void setAllowLandmark(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_LANDMARK, b); } + void setAllowSetHome(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_SET_HOME, b); } + void setResetHomeOnTeleport(BOOL b) { setRegionFlag(REGION_FLAGS_RESET_HOME_ON_TELEPORT, b); } + void setSunFixed(BOOL b) { setRegionFlag(REGION_FLAGS_SUN_FIXED, b); } + //void setBlockFly(BOOL b) { setRegionFlag(REGION_FLAGS_BLOCK_FLY, b); } Never used + void setAllowDirectTeleport(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_DIRECT_TELEPORT, b); } + + + inline BOOL getAllowDamage() const; + inline BOOL getAllowLandmark() const; + inline BOOL getAllowSetHome() const; + inline BOOL getResetHomeOnTeleport() const; + inline BOOL getSunFixed() const; + inline BOOL getBlockFly() const; + inline BOOL getAllowDirectTeleport() const; + inline BOOL isPrelude() const; + inline BOOL getAllowTerraform() const; + inline BOOL getRestrictPushObject() const; + inline BOOL getReleaseNotesRequested() const; + + bool isAlive(); // can become false if circuit disconnects + + void setWaterHeight(F32 water_level); + F32 getWaterHeight() const; + + BOOL isVoiceEnabled() const; + + void setBillableFactor(F32 billable_factor) { mBillableFactor = billable_factor; } + F32 getBillableFactor() const { return mBillableFactor; } + + // Maximum number of primitives allowed, regardless of object + // bonus factor. + U32 getMaxTasks() const { return mMaxTasks; } + void setMaxTasks(U32 max_tasks) { mMaxTasks = max_tasks; } + + // Draw lines in the dirt showing ownership. Return number of + // vertices drawn. + S32 renderPropertyLines(); + + // Call this whenever you change the height data in the region. + // (Automatically called by LLSurfacePatch's update routine) + void dirtyHeights(); + + LLViewerParcelOverlay *getParcelOverlay() const { return mParcelOverlay; } - inline void setRegionFlag(U64 flag, BOOL on); - inline BOOL getRegionFlag(U64 flag) const; - void setRegionFlags(U64 flags); - U64 getRegionFlags() const { return mRegionFlags; } + inline void setRegionFlag(U64 flag, BOOL on); + inline BOOL getRegionFlag(U64 flag) const; + void setRegionFlags(U64 flags); + U64 getRegionFlags() const { return mRegionFlags; } - inline void setRegionProtocol(U64 protocol, BOOL on); - BOOL getRegionProtocol(U64 protocol) const; - void setRegionProtocols(U64 protocols) { mRegionProtocols = protocols; } - U64 getRegionProtocols() const { return mRegionProtocols; } + inline void setRegionProtocol(U64 protocol, BOOL on); + BOOL getRegionProtocol(U64 protocol) const; + void setRegionProtocols(U64 protocols) { mRegionProtocols = protocols; } + U64 getRegionProtocols() const { return mRegionProtocols; } - void setTimeDilation(F32 time_dilation); - F32 getTimeDilation() const { return mTimeDilation; } + void setTimeDilation(F32 time_dilation); + F32 getTimeDilation() const { return mTimeDilation; } - // Origin height is at zero. - const LLVector3d &getOriginGlobal() const; - LLVector3 getOriginAgent() const; + // Origin height is at zero. + const LLVector3d &getOriginGlobal() const; + LLVector3 getOriginAgent() const; - // Center is at the height of the water table. - const LLVector3d &getCenterGlobal() const; - LLVector3 getCenterAgent() const; + // Center is at the height of the water table. + const LLVector3d &getCenterGlobal() const; + LLVector3 getCenterAgent() const; - void setRegionNameAndZone(const std::string& name_and_zone); - const std::string& getName() const { return mName; } - const std::string& getZoning() const { return mZoning; } + void setRegionNameAndZone(const std::string& name_and_zone); + const std::string& getName() const { return mName; } + const std::string& getZoning() const { return mZoning; } - void setOwner(const LLUUID& owner_id); - const LLUUID& getOwner() const; + void setOwner(const LLUUID& owner_id); + const LLUUID& getOwner() const; - // Is the current agent on the estate manager list for this region? - void setIsEstateManager(BOOL b) { mIsEstateManager = b; } - BOOL isEstateManager() const { return mIsEstateManager; } - BOOL canManageEstate() const; + // Is the current agent on the estate manager list for this region? + void setIsEstateManager(BOOL b) { mIsEstateManager = b; } + BOOL isEstateManager() const { return mIsEstateManager; } + BOOL canManageEstate() const; - void setSimAccess(U8 sim_access) { mSimAccess = sim_access; } - U8 getSimAccess() const { return mSimAccess; } - const std::string getSimAccessString() const; + void setSimAccess(U8 sim_access) { mSimAccess = sim_access; } + U8 getSimAccess() const { return mSimAccess; } + const std::string getSimAccessString() const; - // Homestead-related getters; there are no setters as nobody should be - // setting them other than the individual message handler which is a member - S32 getSimClassID() const { return mClassID; } - S32 getSimCPURatio() const { return mCPURatio; } - const std::string& getSimColoName() const { return mColoName; } - const std::string& getSimProductSKU() const { return mProductSKU; } - std::string getLocalizedSimProductName() const; - - // Returns "Sandbox", "Expensive", etc. - static std::string regionFlagsToString(U64 flags); - - // Returns translated version of "Mature", "PG", "Adult", etc. - static std::string accessToString(U8 sim_access); - - // Returns "M", "PG", "A" etc. - static std::string accessToShortString(U8 sim_access); - static U8 shortStringToAccess(const std::string &sim_access); - - // Return access icon name - static std::string getAccessIcon(U8 sim_access); + // Homestead-related getters; there are no setters as nobody should be + // setting them other than the individual message handler which is a member + S32 getSimClassID() const { return mClassID; } + S32 getSimCPURatio() const { return mCPURatio; } + const std::string& getSimColoName() const { return mColoName; } + const std::string& getSimProductSKU() const { return mProductSKU; } + std::string getLocalizedSimProductName() const; + + // Returns "Sandbox", "Expensive", etc. + static std::string regionFlagsToString(U64 flags); + + // Returns translated version of "Mature", "PG", "Adult", etc. + static std::string accessToString(U8 sim_access); + + // Returns "M", "PG", "A" etc. + static std::string accessToShortString(U8 sim_access); + static U8 shortStringToAccess(const std::string &sim_access); + + // Return access icon name + static std::string getAccessIcon(U8 sim_access); - // helper function which just makes sure all interested parties - // can process the message. - static void processRegionInfo(LLMessageSystem* msg, void**); + // helper function which just makes sure all interested parties + // can process the message. + static void processRegionInfo(LLMessageSystem* msg, void**); - //check if the viewer camera is static - static BOOL isViewerCameraStatic(); - static void calcNewObjectCreationThrottle(); + //check if the viewer camera is static + static BOOL isViewerCameraStatic(); + static void calcNewObjectCreationThrottle(); - void setCacheID(const LLUUID& id); + void setCacheID(const LLUUID& id); - F32 getWidth() const { return mWidth; } + F32 getWidth() const { return mWidth; } - void idleUpdate(F32 max_update_time); - void lightIdleUpdate(); - bool addVisibleGroup(LLViewerOctreeGroup* group); - void addVisibleChildCacheEntry(LLVOCacheEntry* parent, LLVOCacheEntry* child); - void addActiveCacheEntry(LLVOCacheEntry* entry); + void idleUpdate(F32 max_update_time); + void lightIdleUpdate(); + bool addVisibleGroup(LLViewerOctreeGroup* group); + void addVisibleChildCacheEntry(LLVOCacheEntry* parent, LLVOCacheEntry* child); + void addActiveCacheEntry(LLVOCacheEntry* entry); void removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep); - void killCacheEntry(U32 local_id); //physically delete the cache entry + void killCacheEntry(U32 local_id); //physically delete the cache entry - // Like idleUpdate, but forces everything to complete regardless of - // how long it takes. - void forceUpdate(); + // Like idleUpdate, but forces everything to complete regardless of + // how long it takes. + void forceUpdate(); - void connectNeighbor(LLViewerRegion *neighborp, U32 direction); + void connectNeighbor(LLViewerRegion *neighborp, U32 direction); - void updateNetStats(); + void updateNetStats(); - U32 getPacketsLost() const; + U32 getPacketsLost() const; - S32 getHttpResponderID() const; + S32 getHttpResponderID() const; - // Get/set named capability URLs for this region. - void setSeedCapability(const std::string& url); - S32 getNumSeedCapRetries(); - void setCapability(const std::string& name, const std::string& url); - void setCapabilityDebug(const std::string& name, const std::string& url); - bool isCapabilityAvailable(const std::string& name) const; - // implements LLCapabilityProvider + // Get/set named capability URLs for this region. + void setSeedCapability(const std::string& url); + S32 getNumSeedCapRetries(); + void setCapability(const std::string& name, const std::string& url); + void setCapabilityDebug(const std::string& name, const std::string& url); + bool isCapabilityAvailable(const std::string& name) const; + // implements LLCapabilityProvider virtual std::string getCapability(const std::string& name) const; std::string getCapabilityDebug(const std::string& name) const; - // has region received its final (not seed) capability list? - bool capabilitiesReceived() const; - void setCapabilitiesReceived(bool received); - boost::signals2::connection setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb); + // has region received its final (not seed) capability list? + bool capabilitiesReceived() const; + void setCapabilitiesReceived(bool received); + boost::signals2::connection setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb); - static bool isSpecialCapabilityName(const std::string &name); - void logActiveCapabilities() const; + static bool isSpecialCapabilityName(const std::string &name); + void logActiveCapabilities() const; /// implements LLCapabilityProvider - /*virtual*/ const LLHost& getHost() const; - const U64 &getHandle() const { return mHandle; } + /*virtual*/ const LLHost& getHost() const; + const U64 &getHandle() const { return mHandle; } - LLSurface &getLand() const; + LLSurface &getLand() const; - // set and get the region id - const LLUUID& getRegionID() const; - void setRegionID(const LLUUID& region_id); + // set and get the region id + const LLUUID& getRegionID() const; + void setRegionID(const LLUUID& region_id); - BOOL pointInRegionGlobal(const LLVector3d &point_global) const; - LLVector3 getPosRegionFromGlobal(const LLVector3d &point_global) const; - LLVector3 getPosRegionFromAgent(const LLVector3 &agent_pos) const; - LLVector3 getPosAgentFromRegion(const LLVector3 ®ion_pos) const; - LLVector3d getPosGlobalFromRegion(const LLVector3 &offset) const; + BOOL pointInRegionGlobal(const LLVector3d &point_global) const; + LLVector3 getPosRegionFromGlobal(const LLVector3d &point_global) const; + LLVector3 getPosRegionFromAgent(const LLVector3 &agent_pos) const; + LLVector3 getPosAgentFromRegion(const LLVector3 ®ion_pos) const; + LLVector3d getPosGlobalFromRegion(const LLVector3 &offset) const; - LLVLComposition *getComposition() const; - F32 getCompositionXY(const S32 x, const S32 y) const; + LLVLComposition *getComposition() const; + F32 getCompositionXY(const S32 x, const S32 y) const; - BOOL isOwnedSelf(const LLVector3& pos); + BOOL isOwnedSelf(const LLVector3& pos); - // Owned by a group you belong to? (officer OR member) - BOOL isOwnedGroup(const LLVector3& pos); + // Owned by a group you belong to? (officer OR member) + BOOL isOwnedGroup(const LLVector3& pos); - // deal with map object updates in the world. - void updateCoarseLocations(LLMessageSystem* msg); + // deal with map object updates in the world. + void updateCoarseLocations(LLMessageSystem* msg); - F32 getLandHeightRegion(const LLVector3& region_pos); + F32 getLandHeightRegion(const LLVector3& region_pos); - U8 getCentralBakeVersion() { return mCentralBakeVersion; } + U8 getCentralBakeVersion() { return mCentralBakeVersion; } - void getInfo(LLSD& info); + void getInfo(LLSD& info); - bool meshRezEnabled() const; - bool meshUploadEnabled() const; + bool meshRezEnabled() const; + bool meshUploadEnabled() const; - // has region received its simulator features list? Requires an additional query after caps received. - void setSimulatorFeaturesReceived(bool); - bool simulatorFeaturesReceived() const; - boost::signals2::connection setSimulatorFeaturesReceivedCallback(const caps_received_signal_t::slot_type& cb); + // has region received its simulator features list? Requires an additional query after caps received. + void setSimulatorFeaturesReceived(bool); + bool simulatorFeaturesReceived() const; + boost::signals2::connection setSimulatorFeaturesReceivedCallback(const caps_received_signal_t::slot_type& cb); void getSimulatorFeatures(LLSD& info) const; - void setSimulatorFeatures(const LLSD& info); + void setSimulatorFeatures(const LLSD& info); - bool dynamicPathfindingEnabled() const; - - bool avatarHoverHeightEnabled() const; - - typedef enum - { - CACHE_MISS_TYPE_FULL = 0, - CACHE_MISS_TYPE_CRC, - CACHE_MISS_TYPE_NONE - } eCacheMissType; - - typedef enum - { - CACHE_UPDATE_DUPE = 0, - CACHE_UPDATE_CHANGED, - CACHE_UPDATE_ADDED, - CACHE_UPDATE_REPLACED - } eCacheUpdateResult; - - // handle a full update message - eCacheUpdateResult cacheFullUpdate(LLDataPackerBinaryBuffer &dp, U32 flags); + bool dynamicPathfindingEnabled() const; + + bool avatarHoverHeightEnabled() const; + + typedef enum + { + CACHE_MISS_TYPE_FULL = 0, + CACHE_MISS_TYPE_CRC, + CACHE_MISS_TYPE_NONE + } eCacheMissType; + + typedef enum + { + CACHE_UPDATE_DUPE = 0, + CACHE_UPDATE_CHANGED, + CACHE_UPDATE_ADDED, + CACHE_UPDATE_REPLACED + } eCacheUpdateResult; + + // handle a full update message + eCacheUpdateResult cacheFullUpdate(LLDataPackerBinaryBuffer &dp, U32 flags); eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp, U32 flags); - LLVOCacheEntry* getCacheEntryForOctree(U32 local_id); - LLVOCacheEntry* getCacheEntry(U32 local_id, bool valid = true); - bool probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss_type); - U64 getRegionCacheHitCount() { return mRegionCacheHitCount; } - U64 getRegionCacheMissCount() { return mRegionCacheMissCount; } - void requestCacheMisses(); - void addCacheMissFull(const U32 local_id); - //update object cache if the object receives a full-update or terse update - LLViewerObject* updateCacheEntry(U32 local_id, LLViewerObject* objectp, U32 update_type); - void findOrphans(U32 parent_id); - void clearCachedVisibleObjects(); - void dumpCache(); - - void unpackRegionHandshake(); - - void calculateCenterGlobal(); - void calculateCameraDistance(); - - friend std::ostream& operator<<(std::ostream &s, const LLViewerRegion ®ion); + LLVOCacheEntry* getCacheEntryForOctree(U32 local_id); + LLVOCacheEntry* getCacheEntry(U32 local_id, bool valid = true); + bool probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss_type); + U64 getRegionCacheHitCount() { return mRegionCacheHitCount; } + U64 getRegionCacheMissCount() { return mRegionCacheMissCount; } + void requestCacheMisses(); + void addCacheMissFull(const U32 local_id); + //update object cache if the object receives a full-update or terse update + LLViewerObject* updateCacheEntry(U32 local_id, LLViewerObject* objectp, U32 update_type); + void findOrphans(U32 parent_id); + void clearCachedVisibleObjects(); + void dumpCache(); + + void unpackRegionHandshake(); + + void calculateCenterGlobal(); + void calculateCameraDistance(); + + friend std::ostream& operator<<(std::ostream &s, const LLViewerRegion ®ion); /// implements LLCapabilityProvider virtual std::string getDescription() const; std::string getViewerAssetUrl() const { return mViewerAssetUrl; } - U32 getNumOfVisibleGroups() const; - U32 getNumOfActiveCachedObjects() const; - LLSpatialPartition* getSpatialPartition(U32 type); - LLVOCachePartition* getVOCachePartition(); + U32 getNumOfVisibleGroups() const; + U32 getNumOfActiveCachedObjects() const; + LLSpatialPartition* getSpatialPartition(U32 type); + LLVOCachePartition* getVOCachePartition(); - bool objectIsReturnable(const LLVector3& pos, const std::vector& boxes) const; + bool objectIsReturnable(const LLVector3& pos, const std::vector& boxes) const; bool childrenObjectReturnable( const std::vector& boxes ) const; - bool objectsCrossParcel(const std::vector& boxes) const; + bool objectsCrossParcel(const std::vector& boxes) const; void getNeighboringRegions( std::vector& uniqueRegions ); void getNeighboringRegionsStatus( std::vector& regions ); - const LLViewerRegionImpl * getRegionImpl() const { return mImpl; } - LLViewerRegionImpl * getRegionImplNC() { return mImpl; } + const LLViewerRegionImpl * getRegionImpl() const { return mImpl; } + LLViewerRegionImpl * getRegionImplNC() { return mImpl; } - // implements the materials capability throttle - bool materialsCapThrottled() const { return !mMaterialsCapThrottleTimer.hasExpired(); } - void resetMaterialsCapThrottle(); + // implements the materials capability throttle + bool materialsCapThrottled() const { return !mMaterialsCapThrottleTimer.hasExpired(); } + void resetMaterialsCapThrottle(); - U32 getMaxMaterialsPerTransaction() const; + U32 getMaxMaterialsPerTransaction() const; - void removeFromCreatedList(U32 local_id); + void removeFromCreatedList(U32 local_id); void addToCreatedList(U32 local_id); BOOL isPaused() const {return mPaused;} diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index d4c8d4f923..f046a903ed 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -2194,8 +2194,9 @@ bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture) mat->setSpecularID(LLUUID::null); } break; - default: - break; + case LLRender::NUM_TEXTURE_CHANNELS: + //nothing to do, make compiler happy + break; } //switch } //for diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9531e0a349..cafa49a229 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -9818,18 +9818,25 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) camera.setOriginAndLookAt(reflect_origin, LLVector3::z_axis, reflect_interest_point); + F32 to_clip = fabsf(camera_height-water_height); + F32 pad = -to_clip*0.05f; //amount to "pad" clip plane by + //plane params LLVector3 pnorm; + F32 pd; + S32 water_clip = 0; if (!LLViewerCamera::getInstance()->cameraUnderWater()) { //camera is above water, clip plane points up pnorm.setVec(0,0,1); + pd = -water_height; plane.setVec(pnorm, -distance_to_water); water_clip = -1; } else { //camera is below water, clip plane points down pnorm = LLVector3(0,0,-1); + pd = water_height; plane.setVec(pnorm, distance_to_water); water_clip = 1; } @@ -10024,7 +10031,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) { //clip out geometry on the same side of water as the camera mat = get_current_modelview(); - LLPlane plane(-pnorm, -distance_to_water); + LLPlane plane(-pnorm, -(pd+pad)); LLGLUserClipPlane clip_plane(plane, mat, projection); static LLCullResult result; @@ -10089,7 +10096,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) gPipeline.popRenderTypeMask(); LLDrawPoolWater::sNeedsReflectionUpdate = FALSE; LLDrawPoolWater::sNeedsDistortionUpdate = FALSE; - LLPlane npnorm(-pnorm, -distance_to_water); + LLPlane npnorm(-pnorm, -pd); LLViewerCamera::getInstance()->setUserClipPlane(npnorm); LLGLState::checkStates(); -- cgit v1.3 From 7e9033821a96a9d6e80b58fafb4c7da63807b9d4 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Thu, 6 Dec 2018 10:59:11 -0800 Subject: De-duplicate deferred gbuffer access for getPosition/getNorm. De-duplicate ambient occlusion shader code and move to new aoUtil.glsl Split shared shadow tap funcs into shadowUtil.glsl --- indra/llrender/llglslshader.cpp | 1 + indra/llrender/llglslshader.h | 1 + indra/llrender/llshadermgr.cpp | 21 +- .../shaders/class1/deferred/alphaF.glsl | 319 +++++----- .../shaders/class1/deferred/aoUtil.glsl | 93 +++ .../shaders/class1/deferred/blurLightF.glsl | 125 ++-- .../shaders/class1/deferred/deferredUtil.glsl | 222 ------- .../shaders/class1/deferred/materialF.glsl | 487 +++++++------- .../shaders/class1/deferred/multiPointLightF.glsl | 13 +- .../shaders/class1/deferred/multiSpotLightF.glsl | 14 +- .../shaders/class1/deferred/pointLightF.glsl | 13 +- .../shaders/class1/deferred/shadowUtil.glsl | 191 ++++++ .../shaders/class1/deferred/softenLightF.glsl | 36 +- .../shaders/class1/deferred/spotLightF.glsl | 14 +- .../shaders/class1/deferred/sunLightSSAOF.glsl | 87 +-- .../shaders/class2/deferred/multiSpotLightF.glsl | 14 +- .../shaders/class2/deferred/softenLightF.glsl | 40 +- .../shaders/class2/deferred/spotLightF.glsl | 14 +- .../shaders/class2/deferred/sunLightF.glsl | 39 +- .../shaders/class2/deferred/sunLightSSAOF.glsl | 117 +--- indra/newview/lldrawpool.cpp | 4 +- indra/newview/lldrawpool.h | 4 +- indra/newview/lldrawpoolalpha.cpp | 12 +- indra/newview/lldrawpoolavatar.cpp | 29 +- indra/newview/lldrawpoolavatar.h | 2 +- indra/newview/lldrawpoolbump.cpp | 30 +- indra/newview/lldrawpoolground.cpp | 2 +- indra/newview/lldrawpoolmaterials.cpp | 4 +- indra/newview/lldrawpoolsimple.cpp | 40 +- indra/newview/lldrawpoolsky.cpp | 8 +- indra/newview/lldrawpoolterrain.cpp | 10 +- indra/newview/lldrawpooltree.cpp | 4 +- indra/newview/lldrawpoolwater.cpp | 6 +- indra/newview/lldrawpoolwlsky.h | 2 +- indra/newview/llpanelvolume.cpp | 2 +- indra/newview/llviewerdisplay.cpp | 2 +- indra/newview/llviewerjointmesh.cpp | 12 +- indra/newview/llviewermenu.cpp | 8 +- indra/newview/llviewershadermgr.cpp | 707 ++++++++++++--------- indra/newview/llviewershadermgr.h | 4 +- indra/newview/llvoavatar.cpp | 4 +- indra/newview/llvosky.cpp | 4 +- indra/newview/llvovolume.cpp | 2 +- indra/newview/pipeline.cpp | 16 +- 44 files changed, 1366 insertions(+), 1413 deletions(-) create mode 100644 indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl create mode 100644 indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 15a018a0bb..4dae61e185 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -84,6 +84,7 @@ LLShaderFeatures::LLShaderFeatures() , isDeferred(false) , hasIndirect(false) , hasShadows(false) + , hasAmbientOcclusion(false) , mIndexedTextureChannels(0) , disableTextureIndex(false) , hasAlphaMask(false) diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index ed13106bfd..56d322fe6c 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -49,6 +49,7 @@ public: bool hasAtmospherics; bool hasGamma; bool hasShadows; + bool hasAmbientOcclusion; bool hasSrgb; bool encodesNormal; bool decodesNormal; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 3a80ff0144..29d120a135 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -196,8 +196,8 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) } } -#if USE_DEFERRED_SHADER_API - if (features->isDeferred || features->hasShadows) + // we want this BEFORE shadows and AO because those facilities use pos/norm access + if (features->isDeferred || features->hasShadows || features->hasAmbientOcclusion) { if (!shader->attachObject("deferred/deferredUtil.glsl")) { @@ -205,6 +205,22 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) } } + if (features->hasShadows) + { + if (!shader->attachObject("deferred/shadowUtil.glsl")) + { + return FALSE; + } + } + + if (features->hasAmbientOcclusion) + { + if (!shader->attachObject("deferred/aoUtil.glsl")) + { + return FALSE; + } + } + if (features->hasIndirect) { if (!shader->attachObject("deferred/indirect.glsl")) @@ -212,7 +228,6 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) return FALSE; } } -#endif if (features->hasGamma) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index 5e3c767460..33e61f2062 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -94,46 +94,46 @@ void calcFragAtmospherics(vec3 inPositionEye, float ambFactor, out vec3 sunlit, vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) { - //get light vector - vec3 lv = lp.xyz-v; - - //get distance - float d = length(lv); - - float da = 1.0; - - vec3 col = vec3(0); - - if (d > 0.0 && la > 0.0 && fa > 0.0) - { - //normalize light vector - lv = normalize(lv); - - //distance attenuation - float dist = d/la; - float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); - dist_atten *= dist_atten; - dist_atten *= 2.0; - - // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); - da *= spot*spot; // GL_SPOT_EXPONENT=2 - - //angular attenuation - da *= max(dot(n, lv), 0.0); - - float lit = max(da * dist_atten,0.0); - - col = light_col * lit * diffuse; - - // no spec for alpha shader... - } - - return max(col, vec3(0.0,0.0,0.0)); + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + float da = 1.0; + + vec3 col = vec3(0); + + if (d > 0.0 && la > 0.0 && fa > 0.0) + { + //normalize light vector + lv = normalize(lv); + + //distance attenuation + float dist = d/la; + float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); + dist_atten *= dist_atten; + dist_atten *= 2.0; + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= max(dot(n, lv), 0.0); + + float lit = max(da * dist_atten,0.0); + + col = light_col * lit * diffuse; + + // no spec for alpha shader... + } + + return max(col, vec3(0.0,0.0,0.0)); } #if HAS_SHADOW -float pcfShadow(sampler2DShadow shadowMap, vec4 stc) +float pcfShadowLegacy(sampler2DShadow shadowMap, vec4 stc) { stc.xyz /= stc.w; stc.z += shadow_bias; @@ -152,174 +152,175 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc) } #endif +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 pos_screen); void main() { - vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; - frag *= screen_res; - - vec4 pos = vec4(vary_position, 1.0); - vec3 norm = vary_norm; + vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; + frag *= screen_res; + + vec4 pos = vec4(vary_position, 1.0); + vec3 norm = vary_norm; - float shadow = 1.0; + float shadow = 1.0; #if HAS_SHADOW - vec4 spos = pos; - - if (spos.z > -shadow_clip.w) - { - shadow = 0.0; - - vec4 lpos; - - vec4 near_split = shadow_clip*-0.75; - vec4 far_split = shadow_clip*-1.25; - vec4 transition_domain = near_split-far_split; - float weight = 0.0; - - if (spos.z < near_split.z) - { - lpos = shadow_matrix[3]*spos; - - float w = 1.0; - w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap3, lpos)*w; - weight += w; - shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); - } - - if (spos.z < near_split.y && spos.z > far_split.z) - { - lpos = shadow_matrix[2]*spos; - - float w = 1.0; - w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; - w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap2, lpos)*w; - weight += w; - } - - if (spos.z < near_split.x && spos.z > far_split.y) - { - lpos = shadow_matrix[1]*spos; - - float w = 1.0; - w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; - w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; - shadow += pcfShadow(shadowMap1, lpos)*w; - weight += w; - } - - if (spos.z > far_split.x) - { - lpos = shadow_matrix[0]*spos; - - float w = 1.0; - w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; - - shadow += pcfShadow(shadowMap0, lpos)*w; - weight += w; - } - - - shadow /= weight; - } - else - { - shadow = 1.0; - } + vec4 spos = pos; + + if (spos.z > -shadow_clip.w) + { + shadow = 0.0; + + vec4 lpos; + + vec4 near_split = shadow_clip*-0.75; + vec4 far_split = shadow_clip*-1.25; + vec4 transition_domain = near_split-far_split; + float weight = 0.0; + + if (spos.z < near_split.z) + { + lpos = shadow_matrix[3]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; + shadow += pcfShadowLegacy(shadowMap3, lpos)*w; + weight += w; + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + + if (spos.z < near_split.y && spos.z > far_split.z) + { + lpos = shadow_matrix[2]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; + w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; + shadow += pcfShadowLegacy(shadowMap2, lpos)*w; + weight += w; + } + + if (spos.z < near_split.x && spos.z > far_split.y) + { + lpos = shadow_matrix[1]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; + w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; + shadow += pcfShadowLegacy(shadowMap1, lpos)*w; + weight += w; + } + + if (spos.z > far_split.x) + { + lpos = shadow_matrix[0]*spos; + + float w = 1.0; + w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; + + shadow += pcfShadowLegacy(shadowMap0, lpos)*w; + weight += w; + } + + + shadow /= weight; + } + else + { + shadow = 1.0; + } #endif #ifdef USE_INDEXED_TEX - vec4 diff = diffuseLookup(vary_texcoord0.xy); + vec4 diff = diffuseLookup(vary_texcoord0.xy); #else - vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy); + vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy); #endif #ifdef FOR_IMPOSTOR - vec4 color; - color.rgb = diff.rgb; - color.a = 1.0; + vec4 color; + color.rgb = diff.rgb; + color.a = 1.0; #ifdef USE_VERTEX_COLOR - float final_alpha = diff.a * vertex_color.a; - diff.rgb *= vertex_color.rgb; + float final_alpha = diff.a * vertex_color.a; + diff.rgb *= vertex_color.rgb; #else - float final_alpha = diff.a; + float final_alpha = diff.a; #endif - - // Insure we don't pollute depth with invis pixels in impostor rendering - // - if (final_alpha < 0.01) - { - discard; - } + + // Insure we don't pollute depth with invis pixels in impostor rendering + // + if (final_alpha < 0.01) + { + discard; + } #else - + #ifdef USE_VERTEX_COLOR - float final_alpha = diff.a * vertex_color.a; - diff.rgb *= vertex_color.rgb; + float final_alpha = diff.a * vertex_color.a; + diff.rgb *= vertex_color.rgb; #else - float final_alpha = diff.a; + float final_alpha = diff.a; #endif vec3 sunlit; vec3 amblit; vec3 additive; vec3 atten; - calcFragAtmospherics(pos.xyz, 1.0, sunlit, amblit, additive, atten); + calcFragAtmospherics(pos.xyz, 1.0, sunlit, amblit, additive, atten); - vec2 abnormal = encode_normal(norm.xyz); - norm.xyz = decode_normal(abnormal.xy); + vec2 abnormal = encode_normal(norm.xyz); + norm.xyz = decode_normal(abnormal.xy); - float sun_da = dot(norm.xyz, sun_dir.xyz); - float moon_da = dot(norm.xyz, moon_dir.xyz); + float sun_da = dot(norm.xyz, sun_dir.xyz); + float moon_da = dot(norm.xyz, moon_dir.xyz); float final_da = max(sun_da, moon_da); final_da = min(final_da, shadow); final_da = clamp(final_da, 0.0f, 1.0f); - final_da = pow(final_da, display_gamma); + final_da = pow(final_da, display_gamma); - vec4 color = vec4(0,0,0,0); + vec4 color = vec4(0,0,0,0); - color.rgb = atmosFragAmbient(color.rgb, amblit); - color.a = final_alpha; + color.rgb = atmosFragAmbient(color.rgb, amblit); + color.a = final_alpha; - float ambient = abs(final_da); - ambient *= 0.5; - ambient *= ambient; - ambient = (1.0-ambient); + float ambient = abs(final_da); + ambient *= 0.5; + ambient *= ambient; + ambient = (1.0-ambient); - color.rgb *= ambient; - color.rgb += (final_da * sunlit); - color.rgb *= diff.rgb; + color.rgb *= ambient; + color.rgb += (final_da * sunlit); + color.rgb *= diff.rgb; - //color.rgb = mix(diff.rgb, color.rgb, final_alpha); - - color.rgb = atmosFragLighting(color.rgb, additive, atten); - color.rgb = scaleSoftClip(color.rgb); + //color.rgb = mix(diff.rgb, color.rgb, final_alpha); + + color.rgb = atmosFragLighting(color.rgb, additive, atten); + color.rgb = scaleSoftClip(color.rgb); - vec4 light = vec4(0,0,0,0); + vec4 light = vec4(0,0,0,0); #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, diff.rgb, pos.xyz, norm, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z); - LIGHT_LOOP(1) - LIGHT_LOOP(2) - LIGHT_LOOP(3) - LIGHT_LOOP(4) - LIGHT_LOOP(5) - LIGHT_LOOP(6) - LIGHT_LOOP(7) + LIGHT_LOOP(1) + LIGHT_LOOP(2) + LIGHT_LOOP(3) + LIGHT_LOOP(4) + LIGHT_LOOP(5) + LIGHT_LOOP(6) + LIGHT_LOOP(7) - // keep it linear - // - color.rgb += light.rgb; + // keep it linear + // + color.rgb += light.rgb; #ifdef WATER_FOG - color = applyWaterFogView(pos.xyz, color); + color = applyWaterFogView(pos.xyz, color); #endif #endif - frag_color = color; + frag_color = color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl new file mode 100644 index 0000000000..3bb59dd7f9 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl @@ -0,0 +1,93 @@ +/** + * @file class1/deferred/aoUtil.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform sampler2D noiseMap; + +uniform float ssao_radius; +uniform float ssao_max_radius; +uniform float ssao_factor; +uniform float ssao_factor_inv; + +vec4 getPosition(vec2 pos_screen); + +vec2 getKern(int i) +{ + vec2 kern[8]; + // exponentially (^2) distant occlusion samples spread around origin + kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; + kern[1] = vec2(1.0, 0.0) * 0.250*0.250; + kern[2] = vec2(0.0, 1.0) * 0.375*0.375; + kern[3] = vec2(0.0, -1.0) * 0.500*0.500; + kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; + kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; + kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; + kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; + + return kern[i]; +} + +//calculate decreases in ambient lighting when crowded out (SSAO) +float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen) +{ + float ret = 1.0; + vec3 pos_world = pos.xyz; + vec2 noise_reflect = texture2D(noiseMap, pos_screen.xy/128.0).xy; + + float angle_hidden = 0.0; + float points = 0; + + float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); + + // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) + for (int i = 0; i < 8; i++) + { + vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect); + vec3 samppos_world = getPosition(samppos_screen).xyz; + + vec3 diff = pos_world - samppos_world; + float dist2 = dot(diff, diff); + + // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area + // --> solid angle shrinking by the square of distance + //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 + //(k should vary inversely with # of samples, but this is taken care of later) + + float funky_val = (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) ? 1.0 : 0.0; + angle_hidden = angle_hidden + funky_val * min(1.0/dist2, ssao_factor_inv); + + // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" + float diffz_val = (diff.z > -1.0) ? 1.0 : 0.0; + points = points + diffz_val; + } + + angle_hidden = min(ssao_factor*angle_hidden/points, 1.0); + + float points_val = (points > 0.0) ? 1.0 : 0.0; + ret = (1.0 - (points_val * angle_hidden)); + + ret = max(ret, 0.0); + return min(ret, 1.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index b56abb66d1..868eec3926 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -48,82 +48,69 @@ VARYING vec2 vary_fragcoord; uniform mat4 inv_proj; uniform vec2 screen_res; -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - +vec4 getPosition(vec2 pos_screen); +vec3 getNorm(vec2 pos_screen); vec3 decode_normal (vec2 enc); void main() { vec2 tc = vary_fragcoord.xy; - vec3 norm = texture2DRect(normalMap, tc).xyz; - norm = decode_normal(norm.xy); // unpack norm - - vec3 pos = getPosition(tc).xyz; - vec4 ccol = texture2DRect(lightMap, tc).rgba; - - vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy); - dlt /= max(-pos.z*dist_factor, 1.0); - - vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' - vec4 col = defined_weight.xyxx * ccol; - - // relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances - float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005; - - // perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large - float tc_mod = 0.5*(tc.x + tc.y); // mod(tc.x+tc.y,2) - tc_mod -= floor(tc_mod); - tc_mod *= 2.0; - tc += ( (tc_mod - 0.5) * kern[1].z * dlt * 0.5 ); - - for (int i = 1; i < 4; i++) - { - vec2 samptc = tc + kern[i].z*dlt; - vec3 samppos = getPosition(samptc).xyz; - - float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane - - if (d*d <= pointplanedist_tolerance_pow2) - { - col += texture2DRect(lightMap, samptc)*kern[i].xyxx; - defined_weight += kern[i].xy; - } - } - - for (int i = 1; i < 4; i++) - { - vec2 samptc = tc - kern[i].z*dlt; - vec3 samppos = getPosition(samptc).xyz; - - float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane - - if (d*d <= pointplanedist_tolerance_pow2) - { - col += texture2DRect(lightMap, samptc)*kern[i].xyxx; - defined_weight += kern[i].xy; - } - } - - col /= defined_weight.xyxx; - col.y *= col.y; - - frag_color = col; + vec3 norm = getNorm(tc); + vec3 pos = getPosition(tc).xyz; + vec4 ccol = texture2DRect(lightMap, tc).rgba; + + vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy); + dlt /= max(-pos.z*dist_factor, 1.0); + + vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' + vec4 col = defined_weight.xyxx * ccol; + + // relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances + float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005; + + // perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large + float tc_mod = 0.5*(tc.x + tc.y); // mod(tc.x+tc.y,2) + tc_mod -= floor(tc_mod); + tc_mod *= 2.0; + tc += ( (tc_mod - 0.5) * kern[1].z * dlt * 0.5 ); + + for (int i = 1; i < 4; i++) + { + vec2 samptc = tc + kern[i].z*dlt; + vec3 samppos = getPosition(samptc).xyz; + + float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane + + if (d*d <= pointplanedist_tolerance_pow2) + { + col += texture2DRect(lightMap, samptc)*kern[i].xyxx; + defined_weight += kern[i].xy; + } + } + + for (int i = 1; i < 4; i++) + { + vec2 samptc = tc - kern[i].z*dlt; + vec3 samppos = getPosition(samptc).xyz; + + float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane + + if (d*d <= pointplanedist_tolerance_pow2) + { + col += texture2DRect(lightMap, samptc)*kern[i].xyxx; + defined_weight += kern[i].xy; + } + } + + col /= defined_weight.xyxx; + col.y *= col.y; + + frag_color = col; #ifdef IS_AMD_CARD - // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts. - vec3 dummy1 = kern[0]; - vec3 dummy2 = kern[3]; + // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts. + vec3 dummy1 = kern[0]; + vec3 dummy2 = kern[3]; #endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl index ec05dab57f..9d7a7f6556 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl @@ -25,29 +25,6 @@ uniform sampler2DRect normalMap; uniform sampler2DRect depthMap; -uniform sampler2D noiseMap; -uniform sampler2DShadow shadowMap0; -uniform sampler2DShadow shadowMap1; -uniform sampler2DShadow shadowMap2; -uniform sampler2DShadow shadowMap3; -uniform sampler2DShadow shadowMap4; -uniform sampler2DShadow shadowMap5; - -uniform float ssao_radius; -uniform float ssao_max_radius; -uniform float ssao_factor; -uniform float ssao_factor_inv; - -uniform vec3 sun_dir; -uniform vec3 moon_dir; -uniform vec2 shadow_res; -uniform vec2 proj_shadow_res; -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; -uniform float shadow_bias; - -uniform float spot_shadow_bias; -uniform float spot_shadow_offset; uniform mat4 inv_proj; uniform vec2 screen_res; @@ -87,8 +64,6 @@ vec4 getPosition(vec2 pos_screen) return pos; } -#if USE_DEFERRED_SHADER_API - vec4 getPositionWithDepth(vec2 pos_screen, float depth) { vec2 sc = getScreenCoordinate(pos_screen); @@ -98,200 +73,3 @@ vec4 getPositionWithDepth(vec2 pos_screen, float depth) pos.w = 1.0; return pos; } - -float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 pos_screen) -{ - stc.xyz /= stc.w; - stc.z += shadow_bias * bias_scale; - - stc.x = floor(stc.x*pos_screen.x + fract(stc.y*shadow_res.y*12345))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here - - float cs = shadow2D(shadowMap, stc.xyz).x; - float shadow = cs; - shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; - return shadow*0.2; -} - -float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 pos_screen) -{ - stc.xyz /= stc.w; - stc.z += spot_shadow_bias * bias_scale; - stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap - - float cs = shadow2D(shadowMap, stc.xyz).x; - float shadow = cs; - - vec2 off = 1.0/proj_shadow_res; - off.y *= 1.5; - - shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x; - shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x; - return shadow*0.2; -} - -float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen) -{ - float dp_sun = max(0.0, dot(sun_dir.xyz, norm)); - float dp_moon = max(0.0, dot(moon_dir.xyz, norm)); - float dp_directional_light = max(dp_sun,dp_moon); - dp_directional_light = clamp(dp_directional_light, 0.0, 1.0); - - vec3 light_dir = (dp_moon > dp_sun) ? moon_dir : sun_dir; - vec3 offset = light_dir * (1.0-dp_directional_light); - vec3 shadow_pos = pos.xyz + (offset * shadow_bias); - - float shadow = 0.0f; - vec4 spos = vec4(shadow_pos,1.0); - if (spos.z > -shadow_clip.w) - { - vec4 lpos; - vec4 near_split = shadow_clip*-0.75; - vec4 far_split = shadow_clip*-1.25; - vec4 transition_domain = near_split-far_split; - float weight = 0.0; - - if (spos.z < near_split.z) - { - lpos = shadow_matrix[3]*spos; - - float w = 1.0; - w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap3, lpos, 0.5, pos_screen)*w; - weight += w; - shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); - } - - if (spos.z < near_split.y && spos.z > far_split.z) - { - lpos = shadow_matrix[2]*spos; - - float w = 1.0; - w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; - w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap2, lpos, 0.75, pos_screen)*w; - weight += w; - } - - if (spos.z < near_split.x && spos.z > far_split.y) - { - lpos = shadow_matrix[1]*spos; - - float w = 1.0; - w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; - w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; - shadow += pcfShadow(shadowMap1, lpos, 0.88, pos_screen)*w; - weight += w; - } - - if (spos.z > far_split.x) - { - lpos = shadow_matrix[0]*spos; - - float w = 1.0; - w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; - - shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w; - weight += w; - } - - shadow /= weight; - } - return shadow; -} - -float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen) -{ - float shadow = 0.0f; - pos += norm * spot_shadow_offset; - - vec4 spos = vec4(pos,1.0); - if (spos.z > -shadow_clip.w) - { - vec4 lpos; - - vec4 near_split = shadow_clip*-0.75; - vec4 far_split = shadow_clip*-1.25; - vec4 transition_domain = near_split-far_split; - float weight = 0.0; - - { - lpos = shadow_matrix[4 + index]*spos; - float w = 1.0; - w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; - - shadow += pcfSpotShadow((index == 0) ? shadowMap4 : shadowMap5, lpos, 0.8, spos.xy)*w; - weight += w; - shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); - } - - shadow /= weight; - } - return shadow; -} - -vec2 getKern(int i) -{ - vec2 kern[8]; - // exponentially (^2) distant occlusion samples spread around origin - kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; - kern[1] = vec2(1.0, 0.0) * 0.250*0.250; - kern[2] = vec2(0.0, 1.0) * 0.375*0.375; - kern[3] = vec2(0.0, -1.0) * 0.500*0.500; - kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; - kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; - kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; - kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; - - return kern[i]; -} - -//calculate decreases in ambient lighting when crowded out (SSAO) -float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen) -{ - float ret = 1.0; - vec3 pos_world = pos.xyz; - vec2 noise_reflect = texture2D(noiseMap, pos_screen.xy/128.0).xy; - - float angle_hidden = 0.0; - float points = 0; - - float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); - - // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) - for (int i = 0; i < 8; i++) - { - vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect); - vec3 samppos_world = getPosition(samppos_screen).xyz; - - vec3 diff = pos_world - samppos_world; - float dist2 = dot(diff, diff); - - // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area - // --> solid angle shrinking by the square of distance - //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 - //(k should vary inversely with # of samples, but this is taken care of later) - - float funky_val = (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) ? 1.0 : 0.0; - angle_hidden = angle_hidden + funky_val * min(1.0/dist2, ssao_factor_inv); - - // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" - float diffz_val = (diff.z > -1.0) ? 1.0 : 0.0; - points = points + diffz_val; - } - - angle_hidden = min(ssao_factor*angle_hidden/points, 1.0); - - float points_val = (points > 0.0) ? 1.0 : 0.0; - ret = (1.0 - (points_val * angle_hidden)); - - ret = max(ret, 0.0); - return min(ret, 1.0); -} - -#endif - diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl index 211bedee59..a0da8563a2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl @@ -25,9 +25,9 @@ /*[EXTRA_CODE_HERE]*/ -#define DIFFUSE_ALPHA_MODE_IGNORE 0 -#define DIFFUSE_ALPHA_MODE_BLEND 1 -#define DIFFUSE_ALPHA_MODE_MASK 2 +#define DIFFUSE_ALPHA_MODE_IGNORE 0 +#define DIFFUSE_ALPHA_MODE_BLEND 1 +#define DIFFUSE_ALPHA_MODE_MASK 2 #define DIFFUSE_ALPHA_MODE_EMISSIVE 3 uniform float emissive_brightness; @@ -62,7 +62,7 @@ uniform vec4 shadow_clip; uniform vec2 shadow_res; uniform float shadow_bias; -float pcfShadow(sampler2DShadow shadowMap, vec4 stc) +float pcfShadowLegacy(sampler2DShadow shadowMap, vec4 stc) { stc.xyz /= stc.w; stc.z += shadow_bias; @@ -80,10 +80,11 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc) return shadow*0.2; } +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 pos_screen); #endif uniform samplerCube environmentMap; -uniform sampler2D lightFunc; +uniform sampler2D lightFunc; // Inputs uniform vec4 morphFactor; @@ -109,80 +110,80 @@ uniform vec3 light_diffuse[8]; vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare) { - //get light vector - vec3 lv = lp.xyz-v; - - //get distance - float d = length(lv); - - float da = 1.0; - - vec3 col = vec3(0,0,0); - - if (d > 0.0 && la > 0.0 && fa > 0.0) - { - //normalize light vector - lv = normalize(lv); - - //distance attenuation - float dist = d/la; - float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); - dist_atten *= dist_atten; - dist_atten *= 2.0; - - // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); - da *= spot*spot; // GL_SPOT_EXPONENT=2 - - //angular attenuation - da *= max(dot(n, lv), 0.0); - - float lit = max(da * dist_atten, 0.0); - - col = light_col*lit*diffuse; - - if (spec.a > 0.0) - { - //vec3 ref = dot(pos+lv, norm); - vec3 h = normalize(lv+npos); - float nh = dot(n, h); - float nv = dot(n, npos); - float vh = dot(npos, h); - float sa = nh; - float fres = pow(1 - dot(h, npos), 5)*0.4+0.5; - - float gtdenom = 2 * nh; - float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); - - if (nh > 0.0) - { - float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da); - vec3 speccol = lit*scol*light_col.rgb*spec.rgb; - col += speccol; - - float cur_glare = max(speccol.r, speccol.g); - cur_glare = max(cur_glare, speccol.b); - glare = max(glare, speccol.r); - glare += max(cur_glare, 0.0); - //col += spec.rgb; - } - } - } - - return max(col, vec3(0.0,0.0,0.0)); + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + float da = 1.0; + + vec3 col = vec3(0,0,0); + + if (d > 0.0 && la > 0.0 && fa > 0.0) + { + //normalize light vector + lv = normalize(lv); + + //distance attenuation + float dist = d/la; + float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); + dist_atten *= dist_atten; + dist_atten *= 2.0; + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= max(dot(n, lv), 0.0); + + float lit = max(da * dist_atten, 0.0); + + col = light_col*lit*diffuse; + + if (spec.a > 0.0) + { + //vec3 ref = dot(pos+lv, norm); + vec3 h = normalize(lv+npos); + float nh = dot(n, h); + float nv = dot(n, npos); + float vh = dot(npos, h); + float sa = nh; + float fres = pow(1 - dot(h, npos), 5)*0.4+0.5; + + float gtdenom = 2 * nh; + float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); + + if (nh > 0.0) + { + float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da); + vec3 speccol = lit*scol*light_col.rgb*spec.rgb; + col += speccol; + + float cur_glare = max(speccol.r, speccol.g); + cur_glare = max(cur_glare, speccol.b); + glare = max(glare, speccol.r); + glare += max(cur_glare, 0.0); + //col += spec.rgb; + } + } + } + + return max(col, vec3(0.0,0.0,0.0)); } vec4 getPosition_d(vec2 pos_screen, float depth) { - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; } @@ -232,253 +233,253 @@ void main() { vec2 pos_screen = vary_texcoord0.xy; - vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy); - diffcol.rgb *= vertex_color.rgb; + vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy); + diffcol.rgb *= vertex_color.rgb; #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK) - if (diffcol.a < minimum_alpha) - { - discard; - } + if (diffcol.a < minimum_alpha) + { + discard; + } #endif #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) - vec3 gamma_diff = diffcol.rgb; + vec3 gamma_diff = diffcol.rgb; #endif #if HAS_SPECULAR_MAP - vec4 spec = texture2D(specularMap, vary_texcoord2.xy); - spec.rgb *= specular_color.rgb; + vec4 spec = texture2D(specularMap, vary_texcoord2.xy); + spec.rgb *= specular_color.rgb; #else - vec4 spec = vec4(specular_color.rgb, 1.0); + vec4 spec = vec4(specular_color.rgb, 1.0); #endif #if HAS_NORMAL_MAP - vec4 norm = texture2D(bumpMap, vary_texcoord1.xy); + vec4 norm = texture2D(bumpMap, vary_texcoord1.xy); - norm.xyz = norm.xyz * 2 - 1; + norm.xyz = norm.xyz * 2 - 1; - vec3 tnorm = vec3(dot(norm.xyz,vary_mat0), - dot(norm.xyz,vary_mat1), - dot(norm.xyz,vary_mat2)); + vec3 tnorm = vec3(dot(norm.xyz,vary_mat0), + dot(norm.xyz,vary_mat1), + dot(norm.xyz,vary_mat2)); #else - vec4 norm = vec4(0,0,0,1.0); - vec3 tnorm = vary_normal; + vec4 norm = vec4(0,0,0,1.0); + vec3 tnorm = vary_normal; #endif norm.xyz = tnorm; norm.xyz = normalize(norm.xyz); - vec2 abnormal = encode_normal(norm.xyz); - norm.xyz = decode_normal(abnormal.xy); + vec2 abnormal = encode_normal(norm.xyz); + norm.xyz = decode_normal(abnormal.xy); - vec4 final_color = diffcol; - + vec4 final_color = diffcol; + #if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE) - final_color.a = emissive_brightness; + final_color.a = emissive_brightness; #else - final_color.a = max(final_color.a, emissive_brightness); + final_color.a = max(final_color.a, emissive_brightness); #endif - vec4 final_specular = spec; + vec4 final_specular = spec; #if HAS_SPECULAR_MAP - vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, 0.0); - final_specular.a = specular_color.a * norm.a; + vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, 0.0); + final_specular.a = specular_color.a * norm.a; #else - vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, 0.0); - final_specular.a = specular_color.a; + vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, 0.0); + final_specular.a = specular_color.a; #endif - + #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) - //forward rendering, output just lit RGBA - vec3 pos = vary_position; + //forward rendering, output just lit RGBA + vec3 pos = vary_position; #if HAS_SUN_SHADOW - float shadow = 0.0; - - vec4 spos = vec4(pos,1.0); - - if (spos.z > -shadow_clip.w) - { - vec4 lpos; - - vec4 near_split = shadow_clip*-0.75; - vec4 far_split = shadow_clip*-1.25; - vec4 transition_domain = near_split-far_split; - float weight = 0.0; - - if (spos.z < near_split.z) - { - lpos = shadow_matrix[3]*spos; - - float w = 1.0; - w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap3, lpos)*w; - weight += w; - shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); - } - - if (spos.z < near_split.y && spos.z > far_split.z) - { - lpos = shadow_matrix[2]*spos; - - float w = 1.0; - w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; - w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap2, lpos)*w; - weight += w; - } - - if (spos.z < near_split.x && spos.z > far_split.y) - { - lpos = shadow_matrix[1]*spos; - - float w = 1.0; - w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; - w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; - shadow += pcfShadow(shadowMap1, lpos)*w; - weight += w; - } - - if (spos.z > far_split.x) - { - lpos = shadow_matrix[0]*spos; - - float w = 1.0; - w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; - - shadow += pcfShadow(shadowMap0, lpos)*w; - weight += w; - } - - - shadow /= weight; - } - else - { - shadow = 1.0; - } + float shadow = 0.0; + + vec4 spos = vec4(pos,1.0); + + if (spos.z > -shadow_clip.w) + { + vec4 lpos; + + vec4 near_split = shadow_clip*-0.75; + vec4 far_split = shadow_clip*-1.25; + vec4 transition_domain = near_split-far_split; + float weight = 0.0; + + if (spos.z < near_split.z) + { + lpos = shadow_matrix[3]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; + shadow += pcfShadowLegacy(shadowMap3, lpos)*w; + weight += w; + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + + if (spos.z < near_split.y && spos.z > far_split.z) + { + lpos = shadow_matrix[2]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; + w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; + shadow += pcfShadowLegacy(shadowMap2, lpos)*w; + weight += w; + } + + if (spos.z < near_split.x && spos.z > far_split.y) + { + lpos = shadow_matrix[1]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; + w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; + shadow += pcfShadowLegacy(shadowMap1, lpos)*w; + weight += w; + } + + if (spos.z > far_split.x) + { + lpos = shadow_matrix[0]*spos; + + float w = 1.0; + w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; + + shadow += pcfShadowLegacy(shadowMap0, lpos)*w; + weight += w; + } + + + shadow /= weight; + } + else + { + shadow = 1.0; + } #else - float shadow = 1.0; + float shadow = 1.0; #endif - spec = final_specular; - vec4 diffuse = final_color; - float envIntensity = final_normal.z; + spec = final_specular; + vec4 diffuse = final_color; + float envIntensity = final_normal.z; vec3 col = vec3(0.0f,0.0f,0.0f); - float bloom = 0.0; + float bloom = 0.0; vec3 sunlit; vec3 amblit; vec3 additive; vec3 atten; - calcFragAtmospherics(pos.xyz, 1.0, sunlit, amblit, additive, atten); - - vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + calcFragAtmospherics(pos.xyz, 1.0, sunlit, amblit, additive, atten); + + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); - float sun_da = dot(norm.xyz, sun_dir.xyz); - float moon_da = dot(norm.xyz, moon_dir.xyz); + float sun_da = dot(norm.xyz, sun_dir.xyz); + float moon_da = dot(norm.xyz, moon_dir.xyz); float final_da = max(sun_da,moon_da); final_da = min(final_da, shadow); //final_da = max(final_da, diffuse.a); final_da = max(final_da, 0.0f); - final_da = min(final_da, 1.0f); - final_da = pow(final_da, display_gamma); + final_da = min(final_da, 1.0f); + final_da = pow(final_da, display_gamma); - col.rgb = (col * 0.5) + amblit; - - float ambient = min(abs(final_da), 1.0); - ambient *= 0.5; - ambient *= ambient; - ambient = (1.0-ambient); + col.rgb = (col * 0.5) + amblit; + + float ambient = min(abs(final_da), 1.0); + ambient *= 0.5; + ambient *= ambient; + ambient = (1.0-ambient); - col.rgb *= ambient; + col.rgb *= ambient; - col.rgb = col.rgb + (final_da * sunlit); + col.rgb = col.rgb + (final_da * sunlit); - col.rgb *= gamma_diff.rgb; - + col.rgb *= gamma_diff.rgb; + - float glare = 0.0; + float glare = 0.0; - if (spec.a > 0.0) // specular reflection - { - // the old infinite-sky shiny reflection - // - + if (spec.a > 0.0) // specular reflection + { + // the old infinite-sky shiny reflection + // + float sa = dot(refnormpersp, sun_dir.xyz); - vec3 dumbshiny = sunlit*shadow*(texture2D(lightFunc, vec2(sa, spec.a)).r); - - // add the two types of shiny together - vec3 spec_contrib = dumbshiny * spec.rgb; - bloom = dot(spec_contrib, spec_contrib) / 6; + vec3 dumbshiny = sunlit*shadow*(texture2D(lightFunc, vec2(sa, spec.a)).r); + + // add the two types of shiny together + vec3 spec_contrib = dumbshiny * spec.rgb; + bloom = dot(spec_contrib, spec_contrib) / 6; - glare = max(spec_contrib.r, spec_contrib.g); - glare = max(glare, spec_contrib.b); + glare = max(spec_contrib.r, spec_contrib.g); + glare = max(glare, spec_contrib.b); - col += spec_contrib; - } + col += spec_contrib; + } - col = mix(col.rgb, diffcol.rgb, diffuse.a); + col = mix(col.rgb, diffcol.rgb, diffuse.a); - if (envIntensity > 0.0) - { - //add environmentmap - vec3 env_vec = env_mat * refnormpersp; - - vec3 refcol = textureCube(environmentMap, env_vec).rgb; + if (envIntensity > 0.0) + { + //add environmentmap + vec3 env_vec = env_mat * refnormpersp; + + vec3 refcol = textureCube(environmentMap, env_vec).rgb; - col = mix(col.rgb, refcol, - envIntensity); + col = mix(col.rgb, refcol, + envIntensity); - float cur_glare = max(refcol.r, refcol.g); - cur_glare = max(cur_glare, refcol.b); - cur_glare *= envIntensity*4.0; - glare += cur_glare; - } + float cur_glare = max(refcol.r, refcol.g); + cur_glare = max(cur_glare, refcol.b); + cur_glare *= envIntensity*4.0; + glare += cur_glare; + } - col = atmosFragLighting(col, additive, atten); + col = atmosFragLighting(col, additive, atten); - vec3 npos = normalize(-pos.xyz); - - vec3 light = vec3(0,0,0); + vec3 npos = normalize(-pos.xyz); + + vec3 light = vec3(0,0,0); #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare); - LIGHT_LOOP(1) - LIGHT_LOOP(2) - LIGHT_LOOP(3) - LIGHT_LOOP(4) - LIGHT_LOOP(5) - LIGHT_LOOP(6) - LIGHT_LOOP(7) + LIGHT_LOOP(1) + LIGHT_LOOP(2) + LIGHT_LOOP(3) + LIGHT_LOOP(4) + LIGHT_LOOP(5) + LIGHT_LOOP(6) + LIGHT_LOOP(7) - col.rgb += light.rgb; + col.rgb += light.rgb; - glare = min(glare, 1.0); - float al = max(diffcol.a,glare)*vertex_color.a; + glare = min(glare, 1.0); + float al = max(diffcol.a,glare)*vertex_color.a; - col = scaleSoftClipFrag(col); + col = scaleSoftClipFrag(col); #ifdef WATER_FOG - vec4 temp = applyWaterFogView(pos, vec4(col.rgb, al)); - col.rgb = temp.rgb; - al = temp.a; + vec4 temp = applyWaterFogView(pos, vec4(col.rgb, al)); + col.rgb = temp.rgb; + al = temp.a; #endif - frag_color.rgb = col.rgb; - frag_color.a = al; + frag_color.rgb = col.rgb; + frag_color.a = al; #else - frag_data[0] = final_color; - frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent. - frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity. + frag_data[0] = final_color; + frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent. + frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity. #endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index d1ac19270d..e8eef9b94b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -59,18 +59,7 @@ uniform mat4 inv_proj; vec3 decode_normal (vec2 enc); -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} +vec4 getPosition(vec2 pos_screen); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index b3dcd90d98..7438fac8fc 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -123,19 +123,7 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) return ret; } - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} +vec4 getPosition(vec2 pos_screen); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 13b803e03e..8e756c37bf 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -58,18 +58,7 @@ uniform vec4 viewport; vec3 decode_normal (vec2 enc); -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = (pos_screen.xy-viewport.xy)*2.0; - sc /= viewport.zw; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} +vec4 getPosition(vec2 pos_screen); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl new file mode 100644 index 0000000000..ae5cb7cbc1 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl @@ -0,0 +1,191 @@ +/** + * @file class1/deferred/shadowUtil.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform sampler2DRect normalMap; +uniform sampler2DRect depthMap; +uniform sampler2D noiseMap; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; +uniform sampler2DShadow shadowMap4; +uniform sampler2DShadow shadowMap5; + +uniform float ssao_radius; +uniform float ssao_max_radius; +uniform float ssao_factor; +uniform float ssao_factor_inv; + +uniform vec3 sun_dir; +uniform vec3 moon_dir; +uniform vec2 shadow_res; +uniform vec2 proj_shadow_res; +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; +uniform float shadow_bias; + +uniform float spot_shadow_bias; +uniform float spot_shadow_offset; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +vec3 decode_normal(vec2 enc); + +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 pos_screen) +{ + stc.xyz /= stc.w; + stc.z += shadow_bias; + + stc.x = floor(stc.x*pos_screen.x + fract(stc.y*shadow_res.y*12345))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here + + float cs = shadow2D(shadowMap, stc.xyz).x; + float shadow = cs; + shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x; + return shadow*0.2; +} + +float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 pos_screen) +{ + stc.xyz /= stc.w; + stc.z += spot_shadow_bias * bias_scale; + stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap + + float cs = shadow2D(shadowMap, stc.xyz).x; + float shadow = cs; + + vec2 off = 1.0/proj_shadow_res; + off.y *= 1.5; + + shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x; + shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x; + return shadow*0.2; +} + +float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen) +{ + float dp_sun = max(0.0, dot(sun_dir.xyz, norm)); + float dp_moon = max(0.0, dot(moon_dir.xyz, norm)); + float dp_directional_light = max(dp_sun,dp_moon); + dp_directional_light = clamp(dp_directional_light, 0.0, 1.0); + + vec3 light_dir = (dp_moon > dp_sun) ? moon_dir : sun_dir; + vec3 offset = light_dir * (1.0-dp_directional_light); + vec3 shadow_pos = pos.xyz + (offset * shadow_bias); + + float shadow = 0.0f; + vec4 spos = vec4(shadow_pos,1.0); + if (spos.z > -shadow_clip.w) + { + vec4 lpos; + vec4 near_split = shadow_clip*-0.75; + vec4 far_split = shadow_clip*-1.25; + vec4 transition_domain = near_split-far_split; + float weight = 0.0; + + if (spos.z < near_split.z) + { + lpos = shadow_matrix[3]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap3, lpos, 0.5, pos_screen)*w; + weight += w; + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + + if (spos.z < near_split.y && spos.z > far_split.z) + { + lpos = shadow_matrix[2]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; + w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; + shadow += pcfShadow(shadowMap2, lpos, 0.75, pos_screen)*w; + weight += w; + } + + if (spos.z < near_split.x && spos.z > far_split.y) + { + lpos = shadow_matrix[1]*spos; + + float w = 1.0; + w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; + w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; + shadow += pcfShadow(shadowMap1, lpos, 0.88, pos_screen)*w; + weight += w; + } + + if (spos.z > far_split.x) + { + lpos = shadow_matrix[0]*spos; + + float w = 1.0; + w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; + + shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w; + weight += w; + } + + shadow /= weight; + } + return shadow; +} + +float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen) +{ + float shadow = 0.0f; + pos += norm * spot_shadow_offset; + + vec4 spos = vec4(pos,1.0); + if (spos.z > -shadow_clip.w) + { + vec4 lpos; + + vec4 near_split = shadow_clip*-0.75; + vec4 far_split = shadow_clip*-1.25; + vec4 transition_domain = near_split-far_split; + float weight = 0.0; + + { + lpos = shadow_matrix[4 + index]*spos; + float w = 1.0; + w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; + + shadow += pcfSpotShadow((index == 0) ? shadowMap4 : shadowMap5, lpos, 0.8, spos.xy)*w; + weight += w; + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + + shadow /= weight; + } + return shadow; +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 2ba766a0c4..0de38a3d62 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -86,18 +86,14 @@ vec4 getPosition_d(vec2 pos_screen, float depth) return pos; } -vec4 getPosition(vec2 pos_screen) -{ //get position in screen space (world units) given window coordinate and depth map - float depth = texture2DRect(depthMap, pos_screen.xy).a; - return getPosition_d(pos_screen, depth); -} - +vec4 getPositionWithDepth(vec2 pos_screen, float depth); +vec4 getPosition(vec2 pos_screen); void main() { vec2 tc = vary_fragcoord.xy; float depth = texture2DRect(depthMap, tc.xy).r; - vec3 pos = getPosition_d(tc, depth).xyz; + vec3 pos = getPositionWithDepth(tc, depth).xyz; vec4 norm = texture2DRect(normalMap, tc); float envIntensity = norm.z; norm.xyz = decode_normal(norm.xy); // unpack norm @@ -107,14 +103,14 @@ void main() float da = max(da_sun, da_moon); float final_da = clamp(da, 0.0, 1.0); - final_da = pow(final_da, global_gamma); + final_da = pow(final_da, global_gamma + 0.3); vec4 diffuse = texture2DRect(diffuseRect, tc); - vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); - vec3 col; - float bloom = 0.0; - { + vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); + vec3 col; + float bloom = 0.0; + { vec3 sunlit; vec3 amblit; vec3 additive; @@ -162,14 +158,14 @@ void main() col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col), diffuse.a); } - #ifdef WATER_FOG - vec4 fogged = applyWaterFogView(pos.xyz,vec4(col, bloom)); - col = fogged.rgb; - bloom = fogged.a; - #endif - } + #ifdef WATER_FOG + vec4 fogged = applyWaterFogView(pos.xyz,vec4(col, bloom)); + col = fogged.rgb; + bloom = fogged.a; + #endif + } - frag_color.rgb = col.rgb; - frag_color.a = bloom; + frag_color.rgb = col.rgb; + frag_color.a = bloom; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index 1abdd4af33..22488944cd 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -121,19 +121,7 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) return ret; } - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} +vec4 getPosition(vec2 pos_screen); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl index 403df87853..6d65ee2add 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl @@ -41,82 +41,15 @@ uniform sampler2D noiseMap; // Inputs -uniform float ssao_radius; -uniform float ssao_max_radius; -uniform float ssao_factor; -uniform float ssao_factor_inv; - VARYING vec2 vary_fragcoord; uniform mat4 inv_proj; uniform vec2 screen_res; vec3 decode_normal (vec2 enc); - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -//calculate decreases in ambient lighting when crowded out (SSAO) -float calcAmbientOcclusion(vec4 pos, vec3 norm) -{ - float ret = 1.0; - - vec2 kern[8]; - // exponentially (^2) distant occlusion samples spread around origin - kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; - kern[1] = vec2(1.0, 0.0) * 0.250*0.250; - kern[2] = vec2(0.0, 1.0) * 0.375*0.375; - kern[3] = vec2(0.0, -1.0) * 0.500*0.500; - kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; - kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; - kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; - kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; - - vec2 pos_screen = vary_fragcoord.xy; - vec3 pos_world = pos.xyz; - vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; - - float angle_hidden = 0.0; - int points = 0; - - float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); - - // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations unrolling?) - for (int i = 0; i < 8; i++) - { - vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); - vec3 samppos_world = getPosition(samppos_screen).xyz; - - vec3 diff = pos_world - samppos_world; - float dist2 = dot(diff, diff); - - // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area - // --> solid angle shrinking by the square of distance - //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 - //(k should vary inversely with # of samples, but this is taken care of later) - - angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv); - - // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" - points = points + int(diff.z > -1.0); - } - - angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); - - ret = (1.0 - (float(points != 0) * angle_hidden)); - - return min(ret, 1.0); -} +vec4 getPosition(vec2 pos_screen); +vec3 getNorm(vec2 pos_screen); +float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen); void main() { @@ -124,13 +57,11 @@ void main() //try doing an unproject here - vec4 pos = getPosition(pos_screen); - - vec3 norm = texture2DRect(normalMap, pos_screen).xyz; - norm = decode_normal(norm.xy); + vec4 pos = getPosition(pos_screen); + vec3 norm = getNorm(pos_screen); - frag_color[0] = 1.0; - frag_color[1] = calcAmbientOcclusion(pos, norm); - frag_color[2] = 1.0; - frag_color[3] = 1.0; + frag_color.r = 1.0; + frag_color.g = calcAmbientOcclusion(pos, norm, pos_screen); + frag_color.b = 1.0; + frag_color.a = 1.0; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index 0a8981a102..1c5d3901f5 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -122,19 +122,7 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) return ret; } - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} +vec4 getPosition(vec2 pos_screen); void main() { diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 9de2741725..1b0a1b5d84 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -85,24 +85,8 @@ vec3 atmosTransportFrag(vec3 light, vec3 additive, vec3 atten); vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten); vec3 fullbrightShinyAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten); -vec4 getPosition_d(vec2 pos_screen, float depth) -{ - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -vec4 getPosition(vec2 pos_screen) -{ //get position in screen space (world units) given window coordinate and depth map - float depth = texture2DRect(depthMap, pos_screen.xy).r; - return getPosition_d(pos_screen, depth); -} - +vec4 getPositionWithDepth(vec2 pos_screen, float depth); +vec4 getPosition(vec2 pos_screen); #ifdef WATER_FOG vec4 applyWaterFogView(vec3 pos, vec4 color); @@ -110,19 +94,19 @@ vec4 applyWaterFogView(vec3 pos, vec4 color); void main() { - vec2 tc = vary_fragcoord.xy; - float depth = texture2DRect(depthMap, tc.xy).r; - vec3 pos = getPosition_d(tc, depth).xyz; - vec4 norm = texture2DRect(normalMap, tc); - float envIntensity = norm.z; - norm.xyz = decode_normal(norm.xy); // unpack norm - - float da_sun = dot(norm.xyz, normalize(sun_dir.xyz)); + vec2 tc = vary_fragcoord.xy; + float depth = texture2DRect(depthMap, tc.xy).r; + vec4 pos = getPositionWithDepth(tc, depth); + vec4 norm = texture2DRect(normalMap, tc); + float envIntensity = norm.z; + norm.xyz = decode_normal(norm.xy); // unpack norm + + float da_sun = dot(norm.xyz, normalize(sun_dir.xyz)); float da_moon = dot(norm.xyz, normalize(moon_dir.xyz)); float da = max(da_sun, da_moon); da = clamp(da, 0.0, 1.0); - da = pow(da, global_gamma); + da = pow(da, global_gamma + 0.3); vec4 diffuse = texture2DRect(diffuseRect, tc); @@ -132,7 +116,7 @@ void main() vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; - scol_ambocc = pow(scol_ambocc, vec2(global_gamma)); + scol_ambocc = pow(scol_ambocc, vec2(global_gamma + 0.3)); float scol = max(scol_ambocc.r, diffuse.a); float ambocc = scol_ambocc.g; diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index d97bd936d9..36854b0e66 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -122,19 +122,7 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) return ret; } - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} +vec4 getPosition(vec2 pos_screen); void main() { diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index f2d04c95fe..5f8f3114a1 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -68,22 +68,13 @@ uniform float shadow_offset; uniform float spot_shadow_bias; uniform float spot_shadow_offset; -vec3 decode_normal (vec2 enc); +vec3 getNorm(vec2 pos_screen); +vec4 getPosition(vec2 pos_screen); -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen); +float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen); -float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) +float pcfShadowLegacy(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += shadow_bias; @@ -102,7 +93,7 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) return shadow*0.2; } -float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) +float pcfSpotShadowLegacy(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += spot_shadow_bias*scl; @@ -128,10 +119,8 @@ void main() //try doing an unproject here - vec4 pos = getPosition(pos_screen); - - vec3 norm = texture2DRect(normalMap, pos_screen).xyz; - norm = decode_normal(norm.xy); // unpack norm + vec4 pos = getPosition(pos_screen); + vec3 norm = getNorm(pos_screen); /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL { @@ -174,7 +163,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w; + shadow += pcfShadowLegacy(shadowMap3, lpos, 0.25, pos_screen)*w; weight += w; shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); } @@ -186,7 +175,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap2, lpos, 0.5, pos_screen)*w; + shadow += pcfShadowLegacy(shadowMap2, lpos, 0.5, pos_screen)*w; weight += w; } @@ -197,7 +186,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; - shadow += pcfShadow(shadowMap1, lpos, 0.75, pos_screen)*w; + shadow += pcfShadowLegacy(shadowMap1, lpos, 0.75, pos_screen)*w; weight += w; } @@ -208,7 +197,7 @@ void main() float w = 1.0; w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; - shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w; + shadow += pcfShadowLegacy(shadowMap0, lpos, 1.0, pos_screen)*w; weight += w; } @@ -242,11 +231,11 @@ void main() //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - frag_color[2] = pcfSpotShadow(shadowMap4, lpos, 0.8, pos_screen); + frag_color[2] = pcfSpotShadowLegacy(shadowMap4, lpos, 0.8, pos_screen); //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - frag_color[3] = pcfSpotShadow(shadowMap5, lpos, 0.8, pos_screen); + frag_color[3] = pcfSpotShadowLegacy(shadowMap5, lpos, 0.8, pos_screen); //frag_color.rgb = pos.xyz; //frag_color.b = shadow; diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index fd3256e9c8..10ef1785da 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -1,5 +1,5 @@ /** - * @file sunLightSSAOF.glsl + * @file class2/deferred/sunLightSSAOF.glsl * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, Linden Research, Inc. @@ -42,110 +42,33 @@ uniform sampler2DShadow shadowMap2; uniform sampler2DShadow shadowMap3; uniform sampler2DShadow shadowMap4; uniform sampler2DShadow shadowMap5; -uniform sampler2D noiseMap; - - -// Inputs -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; -uniform float ssao_radius; -uniform float ssao_max_radius; -uniform float ssao_factor; -uniform float ssao_factor_inv; VARYING vec2 vary_fragcoord; uniform mat4 inv_proj; uniform vec2 screen_res; uniform vec2 proj_shadow_res; -uniform vec3 sun_dir; -uniform vec3 moon_dir; +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; uniform vec2 shadow_res; - uniform float shadow_bias; uniform float shadow_offset; - uniform float spot_shadow_bias; uniform float spot_shadow_offset; -vec3 decode_normal (vec2 enc); - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).r; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -vec2 getKern(int i) -{ - vec2 kern[8]; - // exponentially (^2) distant occlusion samples spread around origin - kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; - kern[1] = vec2(1.0, 0.0) * 0.250*0.250; - kern[2] = vec2(0.0, 1.0) * 0.375*0.375; - kern[3] = vec2(0.0, -1.0) * 0.500*0.500; - kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; - kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; - kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; - kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; - - return kern[i]; -} +uniform vec3 sun_dir; +uniform vec3 moon_dir; -//calculate decreases in ambient lighting when crowded out (SSAO) -float calcAmbientOcclusion(vec4 pos, vec3 norm) -{ - float ret = 1.0; +vec4 getPosition(vec2 pos_screen); +vec3 getNorm(vec2 pos_screen); - vec2 pos_screen = vary_fragcoord.xy; - vec3 pos_world = pos.xyz; - vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; - - float angle_hidden = 0.0; - float points = 0; - - float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); - - // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) - for (int i = 0; i < 8; i++) - { - vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect); - vec3 samppos_world = getPosition(samppos_screen).xyz; - - vec3 diff = pos_world - samppos_world; - float dist2 = dot(diff, diff); - - // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area - // --> solid angle shrinking by the square of distance - //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 - //(k should vary inversely with # of samples, but this is taken care of later) - - float funky_val = (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) ? 1.0 : 0.0; - angle_hidden = angle_hidden + funky_val * min(1.0/dist2, ssao_factor_inv); - - // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" - float diffz_val = (diff.z > -1.0) ? 1.0 : 0.0; - points = points + diffz_val; - } - - angle_hidden = min(ssao_factor*angle_hidden/points, 1.0); - - float points_val = (points > 0.0) ? 1.0 : 0.0; - ret = (1.0 - (points_val * angle_hidden)); +float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen); +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen); +float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen); - ret = max(ret, 0.0); - return min(ret, 1.0); -} -float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) +float pcfShadowLegacy(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += shadow_bias; @@ -163,7 +86,7 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) return shadow*0.2; } -float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) +float pcfSpotShadowLegacy(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) { stc.xyz /= stc.w; stc.z += spot_shadow_bias*scl; @@ -189,10 +112,8 @@ void main() //try doing an unproject here - vec4 pos = getPosition(pos_screen); - - vec3 norm = texture2DRect(normalMap, pos_screen).xyz; - norm = decode_normal(norm.xy); // unpack norm + vec4 pos = getPosition(pos_screen); + vec3 norm = getNorm(pos_screen); /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL { @@ -235,7 +156,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w; + shadow += pcfShadowLegacy(shadowMap3, lpos, 0.25, pos_screen)*w; weight += w; shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); } @@ -247,7 +168,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; - shadow += pcfShadow(shadowMap2, lpos, 0.5, pos_screen)*w; + shadow += pcfShadowLegacy(shadowMap2, lpos, 0.5, pos_screen)*w; weight += w; } @@ -258,7 +179,7 @@ void main() float w = 1.0; w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; - shadow += pcfShadow(shadowMap1, lpos, 0.75, pos_screen)*w; + shadow += pcfShadowLegacy(shadowMap1, lpos, 0.75, pos_screen)*w; weight += w; } @@ -269,7 +190,7 @@ void main() float w = 1.0; w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; - shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w; + shadow += pcfShadowLegacy(shadowMap0, lpos, 1.0, pos_screen)*w; weight += w; } @@ -297,7 +218,7 @@ void main() } frag_color[0] = shadow; - frag_color[1] = calcAmbientOcclusion(pos, norm); + frag_color[1] = calcAmbientOcclusion(pos, norm, pos_screen); spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0); diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 82888b2df6..00493c83df 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -127,7 +127,7 @@ LLDrawPool::LLDrawPool(const U32 type) mType = type; sNumDrawPools++; mId = sNumDrawPools; - mVertexShaderLevel = 0; + mShaderLevel = 0; mSkipRender = false; } @@ -141,7 +141,7 @@ LLViewerTexture *LLDrawPool::getDebugTexture() return NULL; } -//virtuals +//virtual void LLDrawPool::beginRenderPass( S32 pass ) { } diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index bc299cc89f..df86d78a89 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -107,7 +107,7 @@ public: virtual void prerender() = 0; virtual U32 getVertexDataMask() = 0; virtual BOOL verify() const { return TRUE; } // Verify that all data in the draw pool is correct! - virtual S32 getVertexShaderLevel() const { return mVertexShaderLevel; } + virtual S32 getShaderLevel() const { return mShaderLevel; } static LLDrawPool* createPool(const U32 type, LLViewerTexture *tex0 = NULL); virtual LLDrawPool *instancePool() = 0; // Create an empty new instance of the pool. @@ -116,7 +116,7 @@ public: virtual void resetDrawOrders() = 0; protected: - S32 mVertexShaderLevel; + S32 mShaderLevel; S32 mId; U32 mType; // Type of draw pool BOOL mSkipRender; diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 7679d44826..73582e2345 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -69,7 +69,7 @@ LLDrawPoolAlpha::~LLDrawPoolAlpha() void LLDrawPoolAlpha::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } S32 LLDrawPoolAlpha::getNumPostDeferredPasses() @@ -160,7 +160,7 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) } deferred_render = TRUE; - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { // Start out with no shaders. current_shader = target_shader = NULL; @@ -209,7 +209,7 @@ void LLDrawPoolAlpha::beginRenderPass(S32 pass) emissive_shader = &gObjectEmissiveProgram; } - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { // Start out with no shaders. current_shader = target_shader = NULL; @@ -264,7 +264,7 @@ void LLDrawPoolAlpha::render(S32 pass) mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { if (LLPipeline::sImpostorRender) { @@ -326,7 +326,7 @@ void LLDrawPoolAlpha::render(S32 pass) } } - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, pass); } @@ -432,7 +432,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) bool is_particle_or_hud_particle = group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_PARTICLE || group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE; - bool draw_glow_for_this_partition = mVertexShaderLevel > 0; // no shaders = no glow. + bool draw_glow_for_this_partition = mShaderLevel > 0; // no shaders = no glow. LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_GROUP_LOOP); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index d4dc6f3558..996c7eed4b 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -144,16 +144,16 @@ LLDrawPool *LLDrawPoolAvatar::instancePool() } -S32 LLDrawPoolAvatar::getVertexShaderLevel() const +S32 LLDrawPoolAvatar::getShaderLevel() const { - return (S32) LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR); + return (S32) LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR); } void LLDrawPoolAvatar::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR); - sShaderLevel = mVertexShaderLevel; + sShaderLevel = mShaderLevel; if (sShaderLevel > 0) { @@ -304,7 +304,7 @@ void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) void LLDrawPoolAvatar::beginPostDeferredAlpha() { sSkipOpaque = TRUE; - sShaderLevel = mVertexShaderLevel; + sShaderLevel = mShaderLevel; sVertexProgram = &gDeferredAvatarAlphaProgram; sRenderingSkinned = TRUE; @@ -395,7 +395,7 @@ void LLDrawPoolAvatar::endPostDeferredAlpha() gPipeline.unbindDeferredShader(*sVertexProgram); sDiffuseChannel = 0; - sShaderLevel = mVertexShaderLevel; + sShaderLevel = mShaderLevel; } void LLDrawPoolAvatar::renderPostDeferred(S32 pass) @@ -493,7 +493,7 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) } LLVOAvatar *avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); - if (avatarp->isDead() || avatarp->isUIAvatar() || avatarp->mDrawable.isNull()) + if (avatarp->isDead() || avatarp->mIsDummy || avatarp->mDrawable.isNull()) { return; } @@ -714,7 +714,7 @@ void LLDrawPoolAvatar::beginRigid() void LLDrawPoolAvatar::endRigid() { - sShaderLevel = mVertexShaderLevel; + sShaderLevel = mShaderLevel; if (sVertexProgram != NULL) { sVertexProgram->unbind(); @@ -739,7 +739,7 @@ void LLDrawPoolAvatar::beginDeferredImpostor() void LLDrawPoolAvatar::endDeferredImpostor() { - sShaderLevel = mVertexShaderLevel; + sShaderLevel = mShaderLevel; sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP); sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); @@ -766,7 +766,7 @@ void LLDrawPoolAvatar::beginDeferredRigid() void LLDrawPoolAvatar::endDeferredRigid() { - sShaderLevel = mVertexShaderLevel; + sShaderLevel = mShaderLevel; sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->unbind(); gGL.getTexUnit(0)->activate(); @@ -848,7 +848,7 @@ void LLDrawPoolAvatar::endSkinned() sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP); gGL.getTexUnit(0)->activate(); sVertexProgram->unbind(); - sShaderLevel = mVertexShaderLevel; + sShaderLevel = mShaderLevel; } else { @@ -1281,7 +1281,7 @@ void LLDrawPoolAvatar::endDeferredRiggedMaterial(S32 pass) void LLDrawPoolAvatar::beginDeferredSkinned() { - sShaderLevel = mVertexShaderLevel; + sShaderLevel = mShaderLevel; sVertexProgram = &gDeferredAvatarProgram; sRenderingSkinned = TRUE; @@ -1308,7 +1308,7 @@ void LLDrawPoolAvatar::endDeferredSkinned() sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - sShaderLevel = mVertexShaderLevel; + sShaderLevel = mShaderLevel; gGL.getTexUnit(0)->activate(); } @@ -1820,7 +1820,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { - if (!avatar->shouldRenderRigged()) + if (avatar->isSelf() && !gAgent.needsRenderAvatar()) { return; } @@ -2196,6 +2196,7 @@ void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type) { LL_ERRS() << "Invalid rigged face type." << LL_ENDL; } + if (facep->getRiggedIndex(type) != -1) { LL_ERRS() << "Tried to add a rigged face that's referenced elsewhere." << LL_ENDL; diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 45b6d71110..8292279042 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -57,7 +57,7 @@ public: virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } - virtual S32 getVertexShaderLevel() const; + virtual S32 getShaderLevel() const; LLDrawPoolAvatar(); ~LLDrawPoolAvatar(); diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index e27b6867b9..14069fa6c2 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -193,7 +193,7 @@ LLDrawPoolBump::LLDrawPoolBump() void LLDrawPoolBump::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } // static @@ -201,7 +201,7 @@ S32 LLDrawPoolBump::numBumpPasses() { if (gSavedSettings.getBOOL("RenderObjectBump")) { - if (mVertexShaderLevel > 1) + if (mShaderLevel > 1) { if (LLPipeline::sImpostorRender) { @@ -241,7 +241,7 @@ void LLDrawPoolBump::beginRenderPass(S32 pass) beginShiny(); break; case 1: - if (mVertexShaderLevel > 1) + if (mShaderLevel > 1) { beginFullbrightShiny(); } @@ -274,7 +274,7 @@ void LLDrawPoolBump::render(S32 pass) renderShiny(); break; case 1: - if (mVertexShaderLevel > 1) + if (mShaderLevel > 1) { renderFullbrightShiny(); } @@ -301,7 +301,7 @@ void LLDrawPoolBump::endRenderPass(S32 pass) endShiny(); break; case 1: - if (mVertexShaderLevel > 1) + if (mShaderLevel > 1) { endFullbrightShiny(); } @@ -335,12 +335,12 @@ void LLDrawPoolBump::beginShiny(bool invisible) mShiny = TRUE; sVertexMask = VERTEX_MASK_SHINY; // Second pass: environment map - if (!invisible && mVertexShaderLevel > 1) + if (!invisible && mShaderLevel > 1) { sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0; } - if (getVertexShaderLevel() > 0) + if (getShaderLevel() > 0) { if (LLPipeline::sUnderWaterRender) { @@ -365,9 +365,9 @@ void LLDrawPoolBump::beginShiny(bool invisible) shader = NULL; } - bindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible); + bindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel, invisible); - if (mVertexShaderLevel > 1) + if (mShaderLevel > 1) { //indexed texture rendering, channel 0 is always diffuse diffuse_channel = 0; } @@ -436,7 +436,7 @@ void LLDrawPoolBump::renderShiny(bool invisible) if( gSky.mVOSkyp->getCubeMap() ) { LLGLEnable blend_enable(GL_BLEND); - if (!invisible && mVertexShaderLevel > 1) + if (!invisible && mShaderLevel > 1) { LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); } @@ -461,7 +461,7 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& { shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); - if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0) + if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0) { if (diffuse_channel != 0) { @@ -494,7 +494,7 @@ void LLDrawPoolBump::endShiny(bool invisible) return; } - unbindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible); + unbindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel, invisible); if (shader) { shader->unbind(); @@ -568,7 +568,7 @@ void LLDrawPoolBump::beginFullbrightShiny() gGL.getTexUnit(0)->activate(); } - if (mVertexShaderLevel > 1) + if (mShaderLevel > 1) { //indexed texture rendering, channel 0 is always diffuse diffuse_channel = 0; } @@ -588,7 +588,7 @@ void LLDrawPoolBump::renderFullbrightShiny() { LLGLEnable blend_enable(GL_BLEND); - if (mVertexShaderLevel > 1) + if (mShaderLevel > 1) { LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); } @@ -1541,7 +1541,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL tex_setup = true; } - if (mShiny && mVertexShaderLevel > 1 && texture) + if (mShiny && mShaderLevel > 1 && texture) { if (params.mTexture.notNull()) { diff --git a/indra/newview/lldrawpoolground.cpp b/indra/newview/lldrawpoolground.cpp index bae07a171b..6bd2631d3b 100644 --- a/indra/newview/lldrawpoolground.cpp +++ b/indra/newview/lldrawpoolground.cpp @@ -53,7 +53,7 @@ LLDrawPool *LLDrawPoolGround::instancePool() void LLDrawPoolGround::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); } void LLDrawPoolGround::render(S32 pass) diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index 113c198a9a..05b0c1f1a9 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -42,7 +42,7 @@ LLDrawPoolMaterials::LLDrawPoolMaterials() void LLDrawPoolMaterials::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } S32 LLDrawPoolMaterials::getNumDeferredPasses() @@ -203,7 +203,7 @@ void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, tex_setup = true; } - if (mVertexShaderLevel > 1 && texture) + if (mShaderLevel > 1 && texture) { if (params.mTexture.notNull()) { diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index bb50ad8e3e..f653920662 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -90,7 +90,7 @@ void LLDrawPoolGlow::endPostDeferredPass(S32 pass) S32 LLDrawPoolGlow::getNumPasses() { - if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0) + if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0) { return 1; } @@ -111,7 +111,7 @@ void LLDrawPoolGlow::render(S32 pass) glPolygonOffset(-1.0f, -1.0f); gGL.setSceneBlendType(LLRender::BT_ADD); - U32 shader_level = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + U32 shader_level = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); //should never get here without basic shaders enabled llassert(shader_level > 0); @@ -164,7 +164,7 @@ LLDrawPoolSimple::LLDrawPoolSimple() : void LLDrawPoolSimple::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } void LLDrawPoolSimple::beginRenderPass(S32 pass) @@ -184,7 +184,7 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass) simple_shader = &gObjectSimpleProgram; } - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { simple_shader->bind(); @@ -213,7 +213,7 @@ void LLDrawPoolSimple::endRenderPass(S32 pass) stop_glerror(); LLRenderPass::endRenderPass(pass); stop_glerror(); - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { simple_shader->unbind(); } @@ -227,7 +227,7 @@ void LLDrawPoolSimple::render(S32 pass) LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE); gPipeline.enableLightsDynamic(); - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { U32 mask = getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX; @@ -270,7 +270,7 @@ LLDrawPoolAlphaMask::LLDrawPoolAlphaMask() : void LLDrawPoolAlphaMask::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } void LLDrawPoolAlphaMask::beginRenderPass(S32 pass) @@ -286,7 +286,7 @@ void LLDrawPoolAlphaMask::beginRenderPass(S32 pass) simple_shader = &gObjectSimpleAlphaMaskProgram; } - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { simple_shader->bind(); @@ -315,7 +315,7 @@ void LLDrawPoolAlphaMask::endRenderPass(S32 pass) stop_glerror(); LLRenderPass::endRenderPass(pass); stop_glerror(); - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { simple_shader->unbind(); } @@ -326,7 +326,7 @@ void LLDrawPoolAlphaMask::render(S32 pass) LLGLDisable blend(GL_BLEND); LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK); - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { simple_shader->bind(); simple_shader->setMinimumAlpha(0.33f); @@ -361,7 +361,7 @@ LLDrawPoolFullbrightAlphaMask::LLDrawPoolFullbrightAlphaMask() : void LLDrawPoolFullbrightAlphaMask::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } void LLDrawPoolFullbrightAlphaMask::beginRenderPass(S32 pass) @@ -377,7 +377,7 @@ void LLDrawPoolFullbrightAlphaMask::beginRenderPass(S32 pass) simple_shader = &gObjectFullbrightAlphaMaskProgram; } - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { simple_shader->bind(); @@ -406,7 +406,7 @@ void LLDrawPoolFullbrightAlphaMask::endRenderPass(S32 pass) stop_glerror(); LLRenderPass::endRenderPass(pass); stop_glerror(); - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { simple_shader->unbind(); } @@ -416,7 +416,7 @@ void LLDrawPoolFullbrightAlphaMask::render(S32 pass) { LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK); - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { if (simple_shader) { @@ -533,7 +533,7 @@ LLDrawPoolGrass::LLDrawPoolGrass() : void LLDrawPoolGrass::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } @@ -551,7 +551,7 @@ void LLDrawPoolGrass::beginRenderPass(S32 pass) simple_shader = &gObjectAlphaMaskNonIndexedProgram; } - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { simple_shader->bind(); simple_shader->setMinimumAlpha(0.5f); @@ -580,7 +580,7 @@ void LLDrawPoolGrass::endRenderPass(S32 pass) LL_RECORD_BLOCK_TIME(FTM_RENDER_GRASS); LLRenderPass::endRenderPass(pass); - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { simple_shader->unbind(); } @@ -643,7 +643,7 @@ LLDrawPoolFullbright::LLDrawPoolFullbright() : void LLDrawPoolFullbright::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } void LLDrawPoolFullbright::beginPostDeferredPass(S32 pass) @@ -711,7 +711,7 @@ void LLDrawPoolFullbright::endRenderPass(S32 pass) stop_glerror(); - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { fullbright_shader->unbind(); } @@ -726,7 +726,7 @@ void LLDrawPoolFullbright::render(S32 pass) stop_glerror(); - if (mVertexShaderLevel > 0) + if (mShaderLevel > 0) { fullbright_shader->bind(); fullbright_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f); diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp index 4d4711d7c9..516302676d 100644 --- a/indra/newview/lldrawpoolsky.cpp +++ b/indra/newview/lldrawpoolsky.cpp @@ -55,7 +55,7 @@ LLDrawPool *LLDrawPoolSky::instancePool() void LLDrawPoolSky::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable); } @@ -75,7 +75,7 @@ void LLDrawPoolSky::render(S32 pass) } // don't render sky under water (background just gets cleared to fog color) - if(mVertexShaderLevel > 0 && LLPipeline::sUnderWaterRender) + if(mShaderLevel > 0 && LLPipeline::sUnderWaterRender) { return; } @@ -100,8 +100,8 @@ void LLDrawPoolSky::render(S32 pass) LLGLSPipelineDepthTestSkyBox gls_skybox(true, false); - LLGLEnable fog_enable( (mVertexShaderLevel < 1 && LLViewerCamera::getInstance()->cameraUnderWater()) ? GL_FOG : 0); - + LLGLEnable fog_enable( (mShaderLevel < 1 && LLViewerCamera::getInstance()->cameraUnderWater()) ? GL_FOG : 0); + gGL.pushMatrix(); LLVector3 origin = LLViewerCamera::getInstance()->getOrigin(); gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]); diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index b716a76543..593636b14a 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -110,7 +110,7 @@ U32 LLDrawPoolTerrain::getVertexDataMask() void LLDrawPoolTerrain::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); sDetailMode = gSavedSettings.getS32("RenderTerrainDetail"); } @@ -123,7 +123,7 @@ void LLDrawPoolTerrain::beginRenderPass( S32 pass ) &gTerrainWaterProgram : &gTerrainProgram; - if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0) + if (mShaderLevel > 1 && sShader->mShaderLevel > 0) { sShader->bind(); } @@ -134,7 +134,7 @@ void LLDrawPoolTerrain::endRenderPass( S32 pass ) LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN); //LLFacePool::endRenderPass(pass); - if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0) { + if (mShaderLevel > 1 && sShader->mShaderLevel > 0) { sShader->unbind(); } } @@ -180,7 +180,7 @@ void LLDrawPoolTerrain::render(S32 pass) LLGLSPipeline gls; - if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0) + if (mShaderLevel > 1 && sShader->mShaderLevel > 0) { gPipeline.enableLightsDynamic(); @@ -434,7 +434,7 @@ void LLDrawPoolTerrain::renderFullShader() void LLDrawPoolTerrain::hilightParcelOwners() { - if (mVertexShaderLevel > 1) + if (mShaderLevel > 1) { //use fullbright shader for highlighting LLGLSLShader* old_shader = sShader; sShader->unbind(); diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index b1f40781f7..81b0c8b1bb 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -57,7 +57,7 @@ LLDrawPool *LLDrawPoolTree::instancePool() void LLDrawPoolTree::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } void LLDrawPoolTree::beginRenderPass(S32 pass) @@ -138,7 +138,7 @@ void LLDrawPoolTree::endRenderPass(S32 pass) shader->unbind(); } - if (mVertexShaderLevel <= 0) + if (mShaderLevel <= 0) { gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index d217f95cf3..ee37f36cbd 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -113,7 +113,7 @@ LLDrawPool *LLDrawPoolWater::instancePool() void LLDrawPoolWater::prerender() { - mVertexShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ? LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0; + mShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ? LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0; } S32 LLDrawPoolWater::getNumPasses() @@ -179,7 +179,7 @@ void LLDrawPoolWater::render(S32 pass) LLGLEnable blend(GL_BLEND); - if ((mVertexShaderLevel > 0) && !sSkipScreenCopy) + if ((mShaderLevel > 0) && !sSkipScreenCopy) { shade(); return; @@ -618,7 +618,7 @@ void LLDrawPoolWater::shade() S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX); gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis); - if (mVertexShaderLevel == 1) + if (mShaderLevel == 1) { LLColor4 fog_color(pwater->getWaterFogColor(), 0.f); fog_color[3] = pwater->getWaterFogDensity(); diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h index e7b4726321..1980ba6878 100644 --- a/indra/newview/lldrawpoolwlsky.h +++ b/indra/newview/lldrawpoolwlsky.h @@ -66,7 +66,7 @@ public: /*virtual*/ void prerender(); /*virtual*/ U32 getVertexDataMask() { return SKY_VERTEX_DATA_MASK; } /*virtual*/ BOOL verify() const { return TRUE; } // Verify that all data in the draw pool is correct! - /*virtual*/ S32 getVertexShaderLevel() const { return mVertexShaderLevel; } + /*virtual*/ S32 getShaderLevel() const { return mShaderLevel; } //static LLDrawPool* createPool(const U32 type, LLViewerTexture *tex0 = NULL); diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 96dd309fa4..4993441508 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -560,7 +560,7 @@ void LLPanelVolume::refresh() mRootObject = NULL; } - BOOL visible = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 0 ? TRUE : FALSE; + BOOL visible = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 0 ? TRUE : FALSE; getChildView("Light FOV")->setVisible( visible); getChildView("Light Focus")->setVisible( visible); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 82120db53e..29b4ab0a24 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -653,7 +653,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) stop_glerror(); S32 water_clip = 0; - if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) && + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) && (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) || gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER))) { diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 43a81ada49..6990f56a08 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -112,7 +112,7 @@ void LLViewerJointMesh::uploadJointMatrices() S32 joint_num; LLPolyMesh *reference_mesh = mMesh->getReferenceMesh(); LLDrawPool *poolp = mFace ? mFace->getPool() : NULL; - BOOL hardware_skinning = (poolp && poolp->getVertexShaderLevel() > 0) ? TRUE : FALSE; + BOOL hardware_skinning = (poolp && poolp->getShaderLevel() > 0) ? TRUE : FALSE; //calculate joint matrices for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.size(); joint_num++) @@ -246,7 +246,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) stop_glerror(); - LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), (mFace->getPool()->getVertexShaderLevel() > 0 || LLGLSLShader::sNoFixedFunction) ? 0.f : mShiny); + LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), (mFace->getPool()->getShaderLevel() > 0 || LLGLSLShader::sNoFixedFunction) ? 0.f : mShiny); //---------------------------------------------------------------- // setup current texture @@ -307,14 +307,14 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) if (mMesh->hasWeights()) { - if ((mFace->getPool()->getVertexShaderLevel() > 0)) + if ((mFace->getPool()->getShaderLevel() > 0)) { if (first_pass) { uploadJointMatrices(); } mask = mask | LLVertexBuffer::MAP_WEIGHT; - if (mFace->getPool()->getVertexShaderLevel() > 1) + if (mFace->getPool()->getShaderLevel() > 1) { mask = mask | LLVertexBuffer::MAP_CLOTHWEIGHT; } @@ -390,7 +390,7 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w } LLDrawPool *poolp = mFace->getPool(); - BOOL hardware_skinning = (poolp && poolp->getVertexShaderLevel() > 0) ? TRUE : FALSE; + BOOL hardware_skinning = (poolp && poolp->getShaderLevel() > 0) ? TRUE : FALSE; if (!hardware_skinning && terse_update) { //no need to do terse updates if we're doing software vertex skinning @@ -538,7 +538,7 @@ void LLViewerJointMesh::updateJointGeometry() && mFace && mMesh->hasWeights() && mFace->getVertexBuffer() - && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) == 0)) + && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) == 0)) { return; } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 00189f0b11..7033fd4d9f 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -2274,8 +2274,8 @@ class LLAdvancedEnableRenderDeferred: public view_listener_t { bool handleEvent(const LLSD& userdata) { - bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 && - LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0; + bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 && + LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0; return new_value; } }; @@ -2287,8 +2287,8 @@ class LLAdvancedEnableRenderDeferredOptions: public view_listener_t { bool handleEvent(const LLSD& userdata) { - bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 && - LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 && gSavedSettings.getBOOL("RenderDeferred"); + bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 && + LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 && gSavedSettings.getBOOL("RenderDeferred"); return new_value; } }; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index f4f9a3a0c2..bb3ad4bea6 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -247,7 +247,7 @@ LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2]; LLGLSLShader gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2]; LLViewerShaderMgr::LLViewerShaderMgr() : - mVertexShaderLevel(SHADER_COUNT, 0), + mShaderLevel(SHADER_COUNT, 0), mMaxAvatarShaderLevel(0) { /// Make sure WL Sky is the first program @@ -354,7 +354,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() : LLViewerShaderMgr::~LLViewerShaderMgr() { - mVertexShaderLevel.clear(); + mShaderLevel.clear(); mShaderList.clear(); } @@ -391,9 +391,9 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void) //============================================================================ // Set Levels -S32 LLViewerShaderMgr::getVertexShaderLevel(S32 type) +S32 LLViewerShaderMgr::getShaderLevel(S32 type) { - return LLPipeline::sDisableShaders ? 0 : mVertexShaderLevel[type]; + return LLPipeline::sDisableShaders ? 0 : mShaderLevel[type]; } //============================================================================ @@ -468,7 +468,7 @@ void LLViewerShaderMgr::setShaders() for (S32 i = 0; i < SHADER_COUNT; i++) { - mVertexShaderLevel[i] = 0; + mShaderLevel[i] = 0; } mMaxAvatarShaderLevel = 0; @@ -526,22 +526,22 @@ void LLViewerShaderMgr::setShaders() } // Trigger a full rebuild of the fallback skybox / cubemap if we've toggled windlight shaders - if (mVertexShaderLevel[SHADER_WINDLIGHT] != wl_class && gSky.mVOSkyp.notNull()) + if (mShaderLevel[SHADER_WINDLIGHT] != wl_class && gSky.mVOSkyp.notNull()) { gSky.mVOSkyp->forceSkyUpdate(); } // Load lighting shaders - mVertexShaderLevel[SHADER_LIGHTING] = light_class; - mVertexShaderLevel[SHADER_INTERFACE] = light_class; - mVertexShaderLevel[SHADER_ENVIRONMENT] = env_class; - mVertexShaderLevel[SHADER_WATER] = water_class; - mVertexShaderLevel[SHADER_OBJECT] = obj_class; - mVertexShaderLevel[SHADER_EFFECT] = effect_class; - mVertexShaderLevel[SHADER_WINDLIGHT] = wl_class; - mVertexShaderLevel[SHADER_DEFERRED] = deferred_class; - mVertexShaderLevel[SHADER_TRANSFORM] = transform_class; + mShaderLevel[SHADER_LIGHTING] = light_class; + mShaderLevel[SHADER_INTERFACE] = light_class; + mShaderLevel[SHADER_ENVIRONMENT] = env_class; + mShaderLevel[SHADER_WATER] = water_class; + mShaderLevel[SHADER_OBJECT] = obj_class; + mShaderLevel[SHADER_EFFECT] = effect_class; + mShaderLevel[SHADER_WINDLIGHT] = wl_class; + mShaderLevel[SHADER_DEFERRED] = deferred_class; + mShaderLevel[SHADER_TRANSFORM] = transform_class; BOOL loaded = loadBasicShaders(); if (loaded) @@ -646,7 +646,7 @@ void LLViewerShaderMgr::setShaders() if (loaded) { // Load max avatar shaders to set the max level - mVertexShaderLevel[SHADER_AVATAR] = 3; + mShaderLevel[SHADER_AVATAR] = 3; mMaxAvatarShaderLevel = 3; if (gSavedSettings.getBOOL("RenderAvatarVP") && loadShadersObject()) @@ -657,17 +657,18 @@ void LLViewerShaderMgr::setShaders() S32 avatar_class = avatar_cloth ? 3 : 1; // Set the actual level - mVertexShaderLevel[SHADER_AVATAR] = avatar_class; + mShaderLevel[SHADER_AVATAR] = avatar_class; + loaded = loadShadersAvatar(); llassert(loaded); - if (mVertexShaderLevel[SHADER_AVATAR] != avatar_class) + if (mShaderLevel[SHADER_AVATAR] != avatar_class) { - if (mVertexShaderLevel[SHADER_AVATAR] == 0) + if (mShaderLevel[SHADER_AVATAR] == 0) { gSavedSettings.setBOOL("RenderAvatarVP", FALSE); } - if(llmax(mVertexShaderLevel[SHADER_AVATAR]-1,0) >= 3) + if(llmax(mShaderLevel[SHADER_AVATAR]-1,0) >= 3) { avatar_cloth = true; } @@ -680,8 +681,8 @@ void LLViewerShaderMgr::setShaders() } else { //hardware skinning not possible, neither is deferred rendering - mVertexShaderLevel[SHADER_AVATAR] = 0; - mVertexShaderLevel[SHADER_DEFERRED] = 0; + mShaderLevel[SHADER_AVATAR] = 0; + mShaderLevel[SHADER_DEFERRED] = 0; if (gSavedSettings.getBOOL("RenderAvatarVP")) { @@ -734,14 +735,14 @@ void LLViewerShaderMgr::setShaders() LLGLSLShader::sNoFixedFunction = false; gPipeline.mVertexShadersEnabled = FALSE; gPipeline.mVertexShadersLoaded = 0; - mVertexShaderLevel[SHADER_LIGHTING] = 0; - mVertexShaderLevel[SHADER_INTERFACE] = 0; - mVertexShaderLevel[SHADER_ENVIRONMENT] = 0; - mVertexShaderLevel[SHADER_WATER] = 0; - mVertexShaderLevel[SHADER_OBJECT] = 0; - mVertexShaderLevel[SHADER_EFFECT] = 0; - mVertexShaderLevel[SHADER_WINDLIGHT] = 0; - mVertexShaderLevel[SHADER_AVATAR] = 0; + mShaderLevel[SHADER_LIGHTING] = 0; + mShaderLevel[SHADER_INTERFACE] = 0; + mShaderLevel[SHADER_ENVIRONMENT] = 0; + mShaderLevel[SHADER_WATER] = 0; + mShaderLevel[SHADER_OBJECT] = 0; + mShaderLevel[SHADER_EFFECT] = 0; + mShaderLevel[SHADER_WINDLIGHT] = 0; + mShaderLevel[SHADER_AVATAR] = 0; } } else @@ -749,14 +750,14 @@ void LLViewerShaderMgr::setShaders() LLGLSLShader::sNoFixedFunction = false; gPipeline.mVertexShadersEnabled = FALSE; gPipeline.mVertexShadersLoaded = 0; - mVertexShaderLevel[SHADER_LIGHTING] = 0; - mVertexShaderLevel[SHADER_INTERFACE] = 0; - mVertexShaderLevel[SHADER_ENVIRONMENT] = 0; - mVertexShaderLevel[SHADER_WATER] = 0; - mVertexShaderLevel[SHADER_OBJECT] = 0; - mVertexShaderLevel[SHADER_EFFECT] = 0; - mVertexShaderLevel[SHADER_WINDLIGHT] = 0; - mVertexShaderLevel[SHADER_AVATAR] = 0; + mShaderLevel[SHADER_LIGHTING] = 0; + mShaderLevel[SHADER_INTERFACE] = 0; + mShaderLevel[SHADER_ENVIRONMENT] = 0; + mShaderLevel[SHADER_WATER] = 0; + mShaderLevel[SHADER_OBJECT] = 0; + mShaderLevel[SHADER_EFFECT] = 0; + mShaderLevel[SHADER_WINDLIGHT] = 0; + mShaderLevel[SHADER_AVATAR] = 0; } if (gViewerWindow) @@ -885,15 +886,15 @@ void LLViewerShaderMgr::unloadShaders() gTransformColorProgram.unload(); gTransformTangentProgram.unload(); - mVertexShaderLevel[SHADER_LIGHTING] = 0; - mVertexShaderLevel[SHADER_OBJECT] = 0; - mVertexShaderLevel[SHADER_AVATAR] = 0; - mVertexShaderLevel[SHADER_ENVIRONMENT] = 0; - mVertexShaderLevel[SHADER_WATER] = 0; - mVertexShaderLevel[SHADER_INTERFACE] = 0; - mVertexShaderLevel[SHADER_EFFECT] = 0; - mVertexShaderLevel[SHADER_WINDLIGHT] = 0; - mVertexShaderLevel[SHADER_TRANSFORM] = 0; + mShaderLevel[SHADER_LIGHTING] = 0; + mShaderLevel[SHADER_OBJECT] = 0; + mShaderLevel[SHADER_AVATAR] = 0; + mShaderLevel[SHADER_ENVIRONMENT] = 0; + mShaderLevel[SHADER_WATER] = 0; + mShaderLevel[SHADER_INTERFACE] = 0; + mShaderLevel[SHADER_EFFECT] = 0; + mShaderLevel[SHADER_WINDLIGHT] = 0; + mShaderLevel[SHADER_TRANSFORM] = 0; gPipeline.mVertexShadersLoaded = 0; } @@ -936,16 +937,16 @@ BOOL LLViewerShaderMgr::loadBasicShaders() // (in order of shader function call depth for reference purposes, deepest level first) vector< pair > shaders; - shaders.push_back( make_pair( "windlight/atmosphericsVarsV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); - shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); - shaders.push_back( make_pair( "windlight/atmosphericsHelpersV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); - shaders.push_back( make_pair( "lighting/lightFuncV.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + shaders.push_back( make_pair( "windlight/atmosphericsVarsV.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); + shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterV.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); + shaders.push_back( make_pair( "windlight/atmosphericsHelpersV.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); + shaders.push_back( make_pair( "lighting/lightFuncV.glsl", mShaderLevel[SHADER_LIGHTING] ) ); shaders.push_back( make_pair( "lighting/sumLightsV.glsl", sum_lights_class ) ); - shaders.push_back( make_pair( "lighting/lightV.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - shaders.push_back( make_pair( "lighting/lightFuncSpecularV.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + shaders.push_back( make_pair( "lighting/lightV.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + shaders.push_back( make_pair( "lighting/lightFuncSpecularV.glsl", mShaderLevel[SHADER_LIGHTING] ) ); shaders.push_back( make_pair( "lighting/sumLightsSpecularV.glsl", sum_lights_class ) ); - shaders.push_back( make_pair( "lighting/lightSpecularV.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - shaders.push_back( make_pair( "windlight/atmosphericsV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); + shaders.push_back( make_pair( "lighting/lightSpecularV.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + shaders.push_back( make_pair( "windlight/atmosphericsV.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); shaders.push_back( make_pair( "avatar/avatarSkinV.glsl", 1 ) ); shaders.push_back( make_pair( "avatar/objectSkinV.glsl", 1 ) ); if (gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30) @@ -981,44 +982,44 @@ BOOL LLViewerShaderMgr::loadBasicShaders() } std::vector index_channels; - index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsHelpersF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/transportF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/gammaF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT]) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "environment/waterFogF.glsl", mVertexShaderLevel[SHADER_WATER] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "environment/encodeNormF.glsl", mVertexShaderLevel[SHADER_ENVIRONMENT] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "environment/decodeNormF.glsl", mVertexShaderLevel[SHADER_ENVIRONMENT] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "environment/srgbF.glsl", mVertexShaderLevel[SHADER_ENVIRONMENT] ) ); -#if USE_DEFERRED_SHADER_API - index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/deferredUtil.glsl", mVertexShaderLevel[SHADER_DEFERRED] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/indirect.glsl", mVertexShaderLevel[SHADER_DEFERRED] ) ); -#endif - index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightAlphaMaskNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightShinyNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightShinyNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightShinyWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightWaterAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsHelpersF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/gammaF.glsl", mShaderLevel[SHADER_WINDLIGHT]) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/transportF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "environment/waterFogF.glsl", mShaderLevel[SHADER_WATER] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "environment/encodeNormF.glsl", mShaderLevel[SHADER_ENVIRONMENT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "environment/decodeNormF.glsl", mShaderLevel[SHADER_ENVIRONMENT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "environment/srgbF.glsl", mShaderLevel[SHADER_ENVIRONMENT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/deferredUtil.glsl", mShaderLevel[SHADER_DEFERRED] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/shadowUtil.glsl", mShaderLevel[SHADER_DEFERRED] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/aoUtil.glsl", mShaderLevel[SHADER_DEFERRED] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/indirect.glsl", mShaderLevel[SHADER_DEFERRED] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightAlphaMaskNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedAlphaMaskF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightWaterNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightShinyNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightShinyNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightShinyWaterNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightAlphaMaskF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightAlphaMaskF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightWaterF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightWaterF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightWaterAlphaMaskF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightShinyF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); for (U32 i = 0; i < shaders.size(); i++) { @@ -1037,7 +1038,7 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment() { BOOL success = TRUE; - if (mVertexShaderLevel[SHADER_ENVIRONMENT] == 0) + if (mShaderLevel[SHADER_ENVIRONMENT] == 0) { gTerrainProgram.unload(); return TRUE; @@ -1048,21 +1049,24 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment() gTerrainProgram.mName = "Terrain Shader"; gTerrainProgram.mFeatures.calculatesLighting = true; gTerrainProgram.mFeatures.calculatesAtmospherics = true; - gTerrainProgram.mFeatures.hasAtmospherics = true; + gTerrainProgram.mFeatures.hasAtmospherics = true; + gTerrainProgram.mFeatures.hasTransport = true; + gTerrainProgram.mFeatures.hasGamma = true; + gTerrainProgram.mFeatures.hasSrgb = true; gTerrainProgram.mFeatures.mIndexedTextureChannels = 0; gTerrainProgram.mFeatures.disableTextureIndex = true; gTerrainProgram.mFeatures.hasGamma = true; gTerrainProgram.mShaderFiles.clear(); gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainV.glsl", GL_VERTEX_SHADER_ARB)); gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainF.glsl", GL_FRAGMENT_SHADER_ARB)); - gTerrainProgram.mShaderLevel = mVertexShaderLevel[SHADER_ENVIRONMENT]; + gTerrainProgram.mShaderLevel = mShaderLevel[SHADER_ENVIRONMENT]; success = gTerrainProgram.createShader(NULL, NULL); llassert(success); } if (!success) { - mVertexShaderLevel[SHADER_ENVIRONMENT] = 0; + mShaderLevel[SHADER_ENVIRONMENT] = 0; return FALSE; } @@ -1076,7 +1080,7 @@ BOOL LLViewerShaderMgr::loadShadersWater() BOOL success = TRUE; BOOL terrainWaterSuccess = TRUE; - if (mVertexShaderLevel[SHADER_WATER] == 0) + if (mShaderLevel[SHADER_WATER] == 0) { gWaterProgram.unload(); gUnderWaterProgram.unload(); @@ -1095,7 +1099,7 @@ BOOL LLViewerShaderMgr::loadShadersWater() gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB)); gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER_ARB)); gWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_WATER]; + gWaterProgram.mShaderLevel = mShaderLevel[SHADER_WATER]; success = gWaterProgram.createShader(NULL, NULL); llassert(success); } @@ -1109,7 +1113,7 @@ BOOL LLViewerShaderMgr::loadShadersWater() gUnderWaterProgram.mShaderFiles.clear(); gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB)); gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/underWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gUnderWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_WATER]; + gUnderWaterProgram.mShaderLevel = mShaderLevel[SHADER_WATER]; gUnderWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gUnderWaterProgram.createShader(NULL, NULL); llassert(success); @@ -1128,30 +1132,30 @@ BOOL LLViewerShaderMgr::loadShadersWater() gTerrainWaterProgram.mShaderFiles.clear(); gTerrainWaterProgram.mShaderFiles.push_back(make_pair("environment/terrainV.glsl", GL_VERTEX_SHADER_ARB)); gTerrainWaterProgram.mShaderFiles.push_back(make_pair("environment/terrainWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gTerrainWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_ENVIRONMENT]; + gTerrainWaterProgram.mShaderLevel = mShaderLevel[SHADER_ENVIRONMENT]; gTerrainWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; terrainWaterSuccess = gTerrainWaterProgram.createShader(NULL, NULL); llassert(terrainWaterSuccess); } /// Keep track of water shader levels - if (gWaterProgram.mShaderLevel != mVertexShaderLevel[SHADER_WATER] - || gUnderWaterProgram.mShaderLevel != mVertexShaderLevel[SHADER_WATER]) + if (gWaterProgram.mShaderLevel != mShaderLevel[SHADER_WATER] + || gUnderWaterProgram.mShaderLevel != mShaderLevel[SHADER_WATER]) { - mVertexShaderLevel[SHADER_WATER] = llmin(gWaterProgram.mShaderLevel, gUnderWaterProgram.mShaderLevel); + mShaderLevel[SHADER_WATER] = llmin(gWaterProgram.mShaderLevel, gUnderWaterProgram.mShaderLevel); } if (!success) { - mVertexShaderLevel[SHADER_WATER] = 0; + mShaderLevel[SHADER_WATER] = 0; return FALSE; } // if we failed to load the terrain water shaders and we need them (using class2 water), // then drop down to class1 water. - if (mVertexShaderLevel[SHADER_WATER] > 1 && !terrainWaterSuccess) + if (mShaderLevel[SHADER_WATER] > 1 && !terrainWaterSuccess) { - mVertexShaderLevel[SHADER_WATER]--; + mShaderLevel[SHADER_WATER]--; return loadShadersWater(); } @@ -1164,7 +1168,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects() { BOOL success = TRUE; - if (mVertexShaderLevel[SHADER_EFFECT] == 0) + if (mShaderLevel[SHADER_EFFECT] == 0) { gGlowProgram.unload(); gGlowExtractProgram.unload(); @@ -1179,7 +1183,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects() gGlowProgram.mShaderFiles.clear(); gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowV.glsl", GL_VERTEX_SHADER_ARB)); gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowF.glsl", GL_FRAGMENT_SHADER_ARB)); - gGlowProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT]; + gGlowProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT]; success = gGlowProgram.createShader(NULL, NULL); if (!success) { @@ -1193,7 +1197,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects() gGlowExtractProgram.mShaderFiles.clear(); gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractV.glsl", GL_VERTEX_SHADER_ARB)); gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractF.glsl", GL_FRAGMENT_SHADER_ARB)); - gGlowExtractProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT]; + gGlowExtractProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT]; success = gGlowExtractProgram.createShader(NULL, NULL); if (!success) { @@ -1207,7 +1211,9 @@ BOOL LLViewerShaderMgr::loadShadersEffects() BOOL LLViewerShaderMgr::loadShadersDeferred() { - if (mVertexShaderLevel[SHADER_DEFERRED] == 0) + bool use_sun_shadow = mShaderLevel[SHADER_DEFERRED] > 1; + + if (mShaderLevel[SHADER_DEFERRED] == 0) { gDeferredTreeProgram.unload(); gDeferredTreeShadowProgram.unload(); @@ -1279,11 +1285,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader"; gDeferredDiffuseProgram.mFeatures.encodesNormal = true; + gDeferredDiffuseProgram.mFeatures.isDeferred = true; gDeferredDiffuseProgram.mShaderFiles.clear(); gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredDiffuseProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - gDeferredDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredDiffuseProgram.createShader(NULL, NULL); llassert(success); } @@ -1292,11 +1299,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Alpha Mask Shader"; gDeferredDiffuseAlphaMaskProgram.mFeatures.encodesNormal = true; + gDeferredDiffuseAlphaMaskProgram.mFeatures.isDeferred = true; gDeferredDiffuseAlphaMaskProgram.mShaderFiles.clear(); gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredDiffuseAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredDiffuseAlphaMaskProgram.createShader(NULL, NULL); llassert(success); } @@ -1305,10 +1313,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredNonIndexedDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader"; gDeferredNonIndexedDiffuseAlphaMaskProgram.mFeatures.encodesNormal = true; + gDeferredNonIndexedDiffuseAlphaMaskProgram.mFeatures.isDeferred = true; gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.clear(); gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredNonIndexedDiffuseAlphaMaskProgram.createShader(NULL, NULL); llassert(success); } @@ -1317,10 +1326,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader"; gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mFeatures.encodesNormal = true; + gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mFeatures.isDeferred = true; gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.clear(); gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseNoColorV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskNoColorF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.createShader(NULL, NULL); llassert(success); } @@ -1329,10 +1339,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredNonIndexedDiffuseProgram.mName = "Non Indexed Deferred Diffuse Shader"; gDeferredNonIndexedDiffuseProgram.mFeatures.encodesNormal = true; + gDeferredNonIndexedDiffuseProgram.mFeatures.isDeferred = true; gDeferredNonIndexedDiffuseProgram.mShaderFiles.clear(); gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredNonIndexedDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredNonIndexedDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredNonIndexedDiffuseProgram.createShader(NULL, NULL); llassert(success); } @@ -1342,10 +1353,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSkinnedDiffuseProgram.mName = "Deferred Skinned Diffuse Shader"; gDeferredSkinnedDiffuseProgram.mFeatures.hasObjectSkinning = true; gDeferredSkinnedDiffuseProgram.mFeatures.encodesNormal = true; + gDeferredSkinnedDiffuseProgram.mFeatures.isDeferred = true; gDeferredSkinnedDiffuseProgram.mShaderFiles.clear(); gDeferredSkinnedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredSkinnedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSkinnedDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredSkinnedDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredSkinnedDiffuseProgram.createShader(NULL, NULL); llassert(success); } @@ -1355,10 +1367,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSkinnedBumpProgram.mName = "Deferred Skinned Bump Shader"; gDeferredSkinnedBumpProgram.mFeatures.hasObjectSkinning = true; gDeferredSkinnedBumpProgram.mFeatures.encodesNormal = true; + gDeferredSkinnedBumpProgram.mFeatures.isDeferred = true; gDeferredSkinnedBumpProgram.mShaderFiles.clear(); gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSkinnedBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredSkinnedBumpProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredSkinnedBumpProgram.createShader(NULL, NULL); llassert(success); } @@ -1378,15 +1391,18 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true; gDeferredSkinnedAlphaProgram.mFeatures.hasTransport = true; gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true; + gDeferredSkinnedAlphaProgram.mFeatures.hasShadows = true; + gDeferredSkinnedAlphaProgram.mFeatures.hasIndirect = true; + gDeferredSkinnedAlphaProgram.mFeatures.isDeferred = true; gDeferredSkinnedAlphaProgram.mShaderFiles.clear(); gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredSkinnedAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredSkinnedAlphaProgram.addPermutation("USE_DIFFUSE_TEX", "1"); gDeferredSkinnedAlphaProgram.addPermutation("HAS_SKIN", "1"); gDeferredSkinnedAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1"); - gDeferredSkinnedAlphaProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0"); + gDeferredSkinnedAlphaProgram.addPermutation("HAS_SHADOW", use_sun_shadow ? "1" : "0"); success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL); llassert(success); @@ -1399,10 +1415,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredBumpProgram.mName = "Deferred Bump Shader"; gDeferredBumpProgram.mFeatures.encodesNormal = true; + gDeferredBumpProgram.mFeatures.isDeferred = true; gDeferredBumpProgram.mShaderFiles.clear(); gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredBumpProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredBumpProgram.createShader(NULL, NULL); llassert(success); } @@ -1436,21 +1453,24 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredMaterialProgram[i].mShaderFiles.clear(); gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredMaterialProgram[i].mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredMaterialProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredMaterialProgram[i].addPermutation("HAS_NORMAL_MAP", i & 0x8? "1" : "0"); gDeferredMaterialProgram[i].addPermutation("HAS_SPECULAR_MAP", i & 0x4 ? "1" : "0"); gDeferredMaterialProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode)); - gDeferredMaterialProgram[i].addPermutation("HAS_SUN_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0"); + gDeferredMaterialProgram[i].addPermutation("HAS_SUN_SHADOW", use_sun_shadow ? "1" : "0"); bool has_skin = i & 0x10; gDeferredMaterialProgram[i].addPermutation("HAS_SKIN",has_skin ? "1" : "0"); gDeferredMaterialProgram[i].mFeatures.hasSrgb = true; - gDeferredMaterialProgram[i].mFeatures.hasGamma = true; gDeferredMaterialProgram[i].mFeatures.hasTransport = true; gDeferredMaterialProgram[i].mFeatures.decodesNormal = true; gDeferredMaterialProgram[i].mFeatures.encodesNormal = true; gDeferredMaterialProgram[i].mFeatures.calculatesAtmospherics = true; gDeferredMaterialProgram[i].mFeatures.hasAtmospherics = true; + gDeferredMaterialProgram[i].mFeatures.hasGamma = true; + gDeferredMaterialProgram[i].mFeatures.hasShadows = true; + gDeferredMaterialProgram[i].mFeatures.hasIndirect = true; + gDeferredMaterialProgram[i].mFeatures.isDeferred = true; if (has_skin) { @@ -1470,25 +1490,29 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredMaterialWaterProgram[i].mShaderFiles.clear(); gDeferredMaterialWaterProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredMaterialWaterProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredMaterialWaterProgram[i].mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredMaterialWaterProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredMaterialWaterProgram[i].mShaderGroup = LLGLSLShader::SG_WATER; gDeferredMaterialWaterProgram[i].addPermutation("HAS_NORMAL_MAP", i & 0x8? "1" : "0"); gDeferredMaterialWaterProgram[i].addPermutation("HAS_SPECULAR_MAP", i & 0x4 ? "1" : "0"); gDeferredMaterialWaterProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode)); - gDeferredMaterialWaterProgram[i].addPermutation("HAS_SUN_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0"); + gDeferredMaterialWaterProgram[i].addPermutation("HAS_SUN_SHADOW", use_sun_shadow ? "1" : "0"); bool has_skin = i & 0x10; gDeferredMaterialWaterProgram[i].addPermutation("HAS_SKIN",has_skin ? "1" : "0"); gDeferredMaterialWaterProgram[i].addPermutation("WATER_FOG","1"); gDeferredMaterialWaterProgram[i].mFeatures.hasWaterFog = true; gDeferredMaterialWaterProgram[i].mFeatures.hasSrgb = true; - gDeferredMaterialWaterProgram[i].mFeatures.hasGamma = true; - gDeferredMaterialWaterProgram[i].mFeatures.hasTransport = true; gDeferredMaterialWaterProgram[i].mFeatures.decodesNormal = true; gDeferredMaterialWaterProgram[i].mFeatures.encodesNormal = true; gDeferredMaterialWaterProgram[i].mFeatures.calculatesAtmospherics = true; gDeferredMaterialWaterProgram[i].mFeatures.hasAtmospherics = true; + gDeferredMaterialWaterProgram[i].mFeatures.hasGamma = true; + + gDeferredMaterialWaterProgram[i].mFeatures.hasTransport = true; + gDeferredMaterialWaterProgram[i].mFeatures.hasShadows = true; + gDeferredMaterialWaterProgram[i].mFeatures.hasIndirect = true; + gDeferredMaterialWaterProgram[i].mFeatures.isDeferred = true; if (has_skin) { @@ -1524,9 +1548,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredTreeProgram.mName = "Deferred Tree Shader"; gDeferredTreeProgram.mShaderFiles.clear(); gDeferredTreeProgram.mFeatures.encodesNormal = true; + gDeferredTreeProgram.mFeatures.isDeferred = true; gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredTreeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredTreeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredTreeProgram.createShader(NULL, NULL); llassert(success); } @@ -1535,9 +1560,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredTreeShadowProgram.mName = "Deferred Tree Shadow Shader"; gDeferredTreeShadowProgram.mShaderFiles.clear(); + gDeferredTreeShadowProgram.mFeatures.isDeferred = true; gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredTreeShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredTreeShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredTreeShadowProgram.createShader(NULL, NULL); llassert(success); } @@ -1548,10 +1574,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredImpostorProgram.mFeatures.hasSrgb = true; gDeferredImpostorProgram.mFeatures.decodesNormal = true; gDeferredImpostorProgram.mFeatures.encodesNormal = true; + //gDeferredImpostorProgram.mFeatures.isDeferred = true; gDeferredImpostorProgram.mShaderFiles.clear(); gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredImpostorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredImpostorProgram.createShader(NULL, NULL); llassert(success); } @@ -1560,10 +1587,13 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredLightProgram.mName = "Deferred Light Shader"; gDeferredLightProgram.mFeatures.decodesNormal = true; + gDeferredLightProgram.mFeatures.isDeferred = true; + gDeferredLightProgram.mFeatures.hasShadows = true; + gDeferredLightProgram.mShaderFiles.clear(); gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredLightProgram.createShader(NULL, NULL); llassert(success); @@ -1575,10 +1605,13 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredMultiLightProgram[i].mName = llformat("Deferred MultiLight Shader %d", i); gDeferredMultiLightProgram[i].mFeatures.decodesNormal = true; + gDeferredMultiLightProgram[i].mFeatures.isDeferred = true; + gDeferredMultiLightProgram[i].mFeatures.hasShadows = true; + gDeferredMultiLightProgram[i].mShaderFiles.clear(); gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredMultiLightProgram[i].mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredMultiLightProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredMultiLightProgram[i].addPermutation("LIGHT_COUNT", llformat("%d", i+1)); success = gDeferredMultiLightProgram[i].createShader(NULL, NULL); llassert(success); @@ -1591,9 +1624,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSpotLightProgram.mShaderFiles.clear(); gDeferredSpotLightProgram.mFeatures.hasSrgb = true; gDeferredSpotLightProgram.mFeatures.decodesNormal = true; + gDeferredSpotLightProgram.mFeatures.isDeferred = true; + gDeferredSpotLightProgram.mFeatures.hasShadows = true; + gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/spotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredSpotLightProgram.createShader(NULL, NULL); llassert(success); @@ -1604,10 +1640,13 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader"; gDeferredMultiSpotLightProgram.mFeatures.hasSrgb = true; gDeferredMultiSpotLightProgram.mFeatures.decodesNormal = true; + gDeferredMultiSpotLightProgram.mFeatures.isDeferred = true; + gDeferredMultiSpotLightProgram.mFeatures.hasShadows = true; + gDeferredMultiSpotLightProgram.mShaderFiles.clear(); gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredMultiSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredMultiSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL); llassert(success); @@ -1618,14 +1657,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() std::string fragment; std::string vertex = "deferred/sunLightV.glsl"; - if (gSavedSettings.getBOOL("RenderDeferredSSAO")) + bool use_ao = gSavedSettings.getBOOL("RenderDeferredSSAO"); + + if (use_ao) { fragment = "deferred/sunLightSSAOF.glsl"; } else { fragment = "deferred/sunLightF.glsl"; - if (mVertexShaderLevel[SHADER_DEFERRED] == 1) + if (mShaderLevel[SHADER_DEFERRED] == 1) { //no shadows, no SSAO, no frag coord vertex = "deferred/sunLightNoFragCoordV.glsl"; } @@ -1633,10 +1674,15 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSunProgram.mName = "Deferred Sun Shader"; gDeferredSunProgram.mFeatures.decodesNormal = true; + gDeferredSunProgram.mFeatures.isDeferred = true; + gDeferredSunProgram.mFeatures.hasShadows = true; + gDeferredSunProgram.mFeatures.hasIndirect = true; + gDeferredSunProgram.mFeatures.hasAmbientOcclusion = use_ao; + gDeferredSunProgram.mShaderFiles.clear(); gDeferredSunProgram.mShaderFiles.push_back(make_pair(vertex, GL_VERTEX_SHADER_ARB)); gDeferredSunProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB)); - gDeferredSunProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredSunProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredSunProgram.createShader(NULL, NULL); llassert(success); @@ -1646,10 +1692,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader"; gDeferredBlurLightProgram.mFeatures.decodesNormal = true; + gDeferredBlurLightProgram.mFeatures.isDeferred = true; + gDeferredBlurLightProgram.mShaderFiles.clear(); gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredBlurLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredBlurLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredBlurLightProgram.createShader(NULL, NULL); llassert(success); @@ -1664,13 +1712,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAlphaProgram.mFeatures.isAlphaLighting = true; gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels gDeferredAlphaProgram.mFeatures.hasSrgb = true; - gDeferredAlphaProgram.mFeatures.hasGamma = true; gDeferredAlphaProgram.mFeatures.decodesNormal = true; gDeferredAlphaProgram.mFeatures.encodesNormal = true; gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true; gDeferredAlphaProgram.mFeatures.hasAtmospherics = true; + gDeferredAlphaProgram.mFeatures.hasGamma = true; + gDeferredAlphaProgram.mFeatures.hasTransport = true; + gDeferredAlphaProgram.mFeatures.isDeferred = true; + gDeferredAlphaProgram.mFeatures.hasShadows = true; + gDeferredAlphaProgram.mFeatures.hasIndirect = true; - if (mVertexShaderLevel[SHADER_DEFERRED] < 1) + if (mShaderLevel[SHADER_DEFERRED] < 1) { gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; } @@ -1683,9 +1735,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredAlphaProgram.addPermutation("USE_INDEXED_TEX", "1"); - gDeferredAlphaProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0"); + gDeferredAlphaProgram.addPermutation("HAS_SHADOW", use_sun_shadow ? "1" : "0"); gDeferredAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1"); - gDeferredAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredAlphaProgram.createShader(NULL, NULL); llassert(success); @@ -1705,8 +1757,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAlphaImpostorProgram.mFeatures.hasSrgb = true; gDeferredAlphaImpostorProgram.mFeatures.decodesNormal = true; gDeferredAlphaImpostorProgram.mFeatures.encodesNormal = true; + gDeferredAlphaImpostorProgram.mFeatures.isDeferred = true; + gDeferredAlphaImpostorProgram.mFeatures.hasShadows = true; + gDeferredAlphaImpostorProgram.mFeatures.hasIndirect = true; + gDeferredAlphaImpostorProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels - if (mVertexShaderLevel[SHADER_DEFERRED] < 1) + if (mShaderLevel[SHADER_DEFERRED] < 1) { gDeferredAlphaImpostorProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; } @@ -1719,11 +1775,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAlphaImpostorProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredAlphaImpostorProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredAlphaImpostorProgram.addPermutation("USE_INDEXED_TEX", "1"); - gDeferredAlphaImpostorProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0"); + gDeferredAlphaImpostorProgram.addPermutation("HAS_SHADOW", use_sun_shadow ? "1" : "0"); gDeferredAlphaImpostorProgram.addPermutation("USE_VERTEX_COLOR", "1"); gDeferredAlphaImpostorProgram.addPermutation("FOR_IMPOSTOR", "1"); - gDeferredAlphaImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredAlphaImpostorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredAlphaImpostorProgram.createShader(NULL, NULL); llassert(success); @@ -1742,13 +1798,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAlphaWaterProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels gDeferredAlphaWaterProgram.mFeatures.hasWaterFog = true; gDeferredAlphaWaterProgram.mFeatures.hasSrgb = true; - gDeferredAlphaWaterProgram.mFeatures.hasGamma = true; gDeferredAlphaWaterProgram.mFeatures.decodesNormal = true; gDeferredAlphaWaterProgram.mFeatures.encodesNormal = true; gDeferredAlphaWaterProgram.mFeatures.calculatesAtmospherics = true; gDeferredAlphaWaterProgram.mFeatures.hasAtmospherics = true; + gDeferredAlphaWaterProgram.mFeatures.hasGamma = true; + gDeferredAlphaWaterProgram.mFeatures.hasTransport = true; + gDeferredAlphaWaterProgram.mFeatures.isDeferred = true; + gDeferredAlphaWaterProgram.mFeatures.hasShadows = true; + gDeferredAlphaWaterProgram.mFeatures.hasIndirect = true; - if (mVertexShaderLevel[SHADER_DEFERRED] < 1) + if (mShaderLevel[SHADER_DEFERRED] < 1) { gDeferredAlphaWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; } @@ -1763,8 +1823,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAlphaWaterProgram.addPermutation("USE_INDEXED_TEX", "1"); gDeferredAlphaWaterProgram.addPermutation("WATER_FOG", "1"); gDeferredAlphaWaterProgram.addPermutation("USE_VERTEX_COLOR", "1"); - gDeferredAlphaWaterProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0"); - gDeferredAlphaWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredAlphaWaterProgram.addPermutation("HAS_SHADOW", use_sun_shadow ? "1" : "0"); + gDeferredAlphaWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredAlphaWaterProgram.createShader(NULL, NULL); llassert(success); @@ -1783,11 +1843,13 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAvatarEyesProgram.mFeatures.disableTextureIndex = true; gDeferredAvatarEyesProgram.mFeatures.hasSrgb = true; gDeferredAvatarEyesProgram.mFeatures.encodesNormal = true; - gDeferredAvatarEyesProgram.mFeatures.hasGamma = true; + gDeferredAvatarEyesProgram.mFeatures.isDeferred = true; + gDeferredAvatarEyesProgram.mFeatures.hasShadows = true; + gDeferredAvatarEyesProgram.mShaderFiles.clear(); gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/avatarEyesV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredAvatarEyesProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredAvatarEyesProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredAvatarEyesProgram.createShader(NULL, NULL); llassert(success); } @@ -1799,12 +1861,13 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredFullbrightProgram.mFeatures.hasGamma = true; gDeferredFullbrightProgram.mFeatures.hasTransport = true; gDeferredFullbrightProgram.mFeatures.hasSrgb = true; - gDeferredFullbrightProgram.mFeatures.hasGamma = true; + gDeferredFullbrightProgram.mFeatures.isDeferred = true; + gDeferredFullbrightProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; gDeferredFullbrightProgram.mShaderFiles.clear(); gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredFullbrightProgram.createShader(NULL, NULL); llassert(success); } @@ -1816,13 +1879,14 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredFullbrightAlphaMaskProgram.mFeatures.hasGamma = true; gDeferredFullbrightAlphaMaskProgram.mFeatures.hasTransport = true; gDeferredFullbrightAlphaMaskProgram.mFeatures.hasSrgb = true; - gDeferredFullbrightAlphaMaskProgram.mFeatures.hasGamma = true; + gDeferredFullbrightAlphaMaskProgram.mFeatures.isDeferred = true; + gDeferredFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; gDeferredFullbrightAlphaMaskProgram.mShaderFiles.clear(); gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredFullbrightAlphaMaskProgram.addPermutation("HAS_ALPHA_MASK","1"); - gDeferredFullbrightAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredFullbrightAlphaMaskProgram.createShader(NULL, NULL); llassert(success); } @@ -1835,12 +1899,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredFullbrightWaterProgram.mFeatures.hasTransport = true; gDeferredFullbrightWaterProgram.mFeatures.hasWaterFog = true; gDeferredFullbrightWaterProgram.mFeatures.hasSrgb = true; - gDeferredFullbrightWaterProgram.mFeatures.hasGamma = true; + gDeferredFullbrightWaterProgram.mFeatures.isDeferred = true; gDeferredFullbrightWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; gDeferredFullbrightWaterProgram.mShaderFiles.clear(); gDeferredFullbrightWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredFullbrightWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredFullbrightWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; gDeferredFullbrightWaterProgram.addPermutation("WATER_FOG","1"); success = gDeferredFullbrightWaterProgram.createShader(NULL, NULL); @@ -1855,12 +1919,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasTransport = true; gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasWaterFog = true; gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasSrgb = true; - gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasGamma = true; + gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.isDeferred = true; gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.clear(); gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredFullbrightAlphaMaskWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredFullbrightAlphaMaskWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredFullbrightAlphaMaskWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; gDeferredFullbrightAlphaMaskWaterProgram.addPermutation("HAS_ALPHA_MASK","1"); gDeferredFullbrightAlphaMaskWaterProgram.addPermutation("WATER_FOG","1"); @@ -1874,11 +1938,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true; gDeferredFullbrightShinyProgram.mFeatures.hasGamma = true; gDeferredFullbrightShinyProgram.mFeatures.hasTransport = true; + gDeferredFullbrightShinyProgram.mFeatures.isDeferred = true; gDeferredFullbrightShinyProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels-1; gDeferredFullbrightShinyProgram.mShaderFiles.clear(); gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredFullbrightShinyProgram.createShader(NULL, NULL); llassert(success); } @@ -1892,10 +1957,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSkinnedFullbrightProgram.mFeatures.hasObjectSkinning = true; gDeferredSkinnedFullbrightProgram.mFeatures.disableTextureIndex = true; gDeferredSkinnedFullbrightProgram.mFeatures.hasSrgb = true; + gDeferredSkinnedFullbrightProgram.mFeatures.isDeferred = true; gDeferredSkinnedFullbrightProgram.mShaderFiles.clear(); gDeferredSkinnedFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredSkinnedFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSkinnedFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gDeferredSkinnedFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gDeferredSkinnedFullbrightProgram.createShader(NULL, NULL); llassert(success); } @@ -1908,10 +1974,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasTransport = true; gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasObjectSkinning = true; gDeferredSkinnedFullbrightShinyProgram.mFeatures.disableTextureIndex = true; + gDeferredSkinnedFullbrightShinyProgram.mFeatures.isDeferred = true; gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.clear(); gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSkinnedFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gDeferredSkinnedFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gDeferredSkinnedFullbrightShinyProgram.createShader(NULL, NULL); llassert(success); } @@ -1922,11 +1989,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredEmissiveProgram.mFeatures.calculatesAtmospherics = true; gDeferredEmissiveProgram.mFeatures.hasGamma = true; gDeferredEmissiveProgram.mFeatures.hasTransport = true; + gDeferredEmissiveProgram.mFeatures.isDeferred = true; gDeferredEmissiveProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; gDeferredEmissiveProgram.mShaderFiles.clear(); gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredEmissiveProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredEmissiveProgram.createShader(NULL, NULL); llassert(success); } @@ -1939,10 +2007,14 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredWaterProgram.mFeatures.hasGamma = true; gDeferredWaterProgram.mFeatures.hasTransport = true; gDeferredWaterProgram.mFeatures.encodesNormal = true; + gDeferredWaterProgram.mFeatures.isDeferred = true; + gDeferredWaterProgram.mFeatures.hasShadows = true; + gDeferredWaterProgram.mFeatures.hasIndirect = true; + gDeferredWaterProgram.mShaderFiles.clear(); gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gDeferredWaterProgram.createShader(NULL, NULL); llassert(success); @@ -1958,10 +2030,14 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredUnderWaterProgram.mFeatures.hasTransport = true; gDeferredUnderWaterProgram.mFeatures.hasSrgb = true; gDeferredUnderWaterProgram.mFeatures.encodesNormal = true; + gDeferredUnderWaterProgram.mFeatures.isDeferred = true; + gDeferredUnderWaterProgram.mFeatures.hasShadows = true; + gDeferredUnderWaterProgram.mFeatures.hasIndirect = true; + gDeferredUnderWaterProgram.mShaderFiles.clear(); gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/underWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredUnderWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredUnderWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredUnderWaterProgram.createShader(NULL, NULL); llassert(success); } @@ -1974,18 +2050,29 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSoftenProgram.mFeatures.decodesNormal = true; gDeferredSoftenProgram.mFeatures.calculatesAtmospherics = true; gDeferredSoftenProgram.mFeatures.hasAtmospherics = true; - gDeferredSoftenProgram.mFeatures.hasGamma = true; gDeferredSoftenProgram.mFeatures.hasTransport = true; + gDeferredSoftenProgram.mFeatures.hasGamma = true; + gDeferredSoftenProgram.mFeatures.isDeferred = true; + gDeferredSoftenProgram.mFeatures.hasShadows = true; + gDeferredSoftenProgram.mFeatures.hasIndirect = true; gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSoftenProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredSoftenProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - if (gSavedSettings.getBOOL("RenderDeferredSSAO")) + if (gSavedSettings.getBOOL("RenderDeferredSSAO")) { //if using SSAO, take screen space light map into account as if shadows are enabled gDeferredSoftenProgram.mShaderLevel = llmax(gDeferredSoftenProgram.mShaderLevel, 2); } + + // insure we use class3/deferred version of softenLight for advanced atmo.. + gDeferredSoftenProgram.mShaderLevel = gSavedSettings.getBOOL("RenderUseAdvancedAtmospherics") ? 3 : gDeferredSoftenProgram.mShaderLevel; + + if (gAtmosphere && gDeferredSoftenProgram.mShaderLevel > 2) + { + gDeferredSoftenProgram.mExtraLinkObject = gAtmosphere->getAtmosphericShaderForLink(); + } success = gDeferredSoftenProgram.createShader(NULL, NULL); llassert(success); @@ -1998,7 +2085,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSoftenWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredSoftenWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredSoftenWaterProgram.addPermutation("WATER_FOG", "1"); gDeferredSoftenWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; gDeferredSoftenWaterProgram.mFeatures.hasWaterFog = true; @@ -2006,8 +2094,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSoftenWaterProgram.mFeatures.decodesNormal = true; gDeferredSoftenWaterProgram.mFeatures.calculatesAtmospherics = true; gDeferredSoftenWaterProgram.mFeatures.hasAtmospherics = true; - gDeferredSoftenWaterProgram.mFeatures.hasGamma = true; gDeferredSoftenWaterProgram.mFeatures.hasTransport = true; + gDeferredSoftenWaterProgram.mFeatures.hasGamma = true; + gDeferredSoftenWaterProgram.mFeatures.isDeferred = true; + gDeferredSoftenWaterProgram.mFeatures.hasShadows = true; + gDeferredSoftenWaterProgram.mFeatures.hasIndirect = true; + + if (gAtmosphere && gDeferredSoftenWaterProgram.mShaderLevel > 2) + { + gDeferredSoftenWaterProgram.mExtraLinkObject = gAtmosphere->getAtmosphericShaderForLink(); + } if (gSavedSettings.getBOOL("RenderDeferredSSAO")) { //if using SSAO, take screen space light map into account as if shadows are enabled @@ -2021,10 +2117,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredShadowProgram.mName = "Deferred Shadow Shader"; + gDeferredShadowProgram.mFeatures.isDeferred = true; gDeferredShadowProgram.mShaderFiles.clear(); gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0"); success = gDeferredShadowProgram.createShader(NULL, NULL); llassert(success); @@ -2033,11 +2130,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredShadowCubeProgram.mName = "Deferred Shadow Cube Shader"; + gDeferredShadowCubeProgram.mFeatures.isDeferred = true; gDeferredShadowCubeProgram.mShaderFiles.clear(); gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowCubeV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredShadowCubeProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0"); - gDeferredShadowCubeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredShadowCubeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredShadowCubeProgram.createShader(NULL, NULL); llassert(success); } @@ -2046,11 +2144,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredShadowAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader"; gDeferredShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + gDeferredShadowAlphaMaskProgram.mFeatures.isDeferred = true; gDeferredShadowAlphaMaskProgram.mShaderFiles.clear(); gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredShadowAlphaMaskProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0"); - gDeferredShadowAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredShadowAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredShadowAlphaMaskProgram.createShader(NULL, NULL); llassert(success); } @@ -2059,11 +2158,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredAvatarShadowProgram.mName = "Deferred Avatar Shadow Shader"; gDeferredAvatarShadowProgram.mFeatures.hasSkinning = true; + gDeferredAvatarShadowProgram.mFeatures.isDeferred = true; gDeferredAvatarShadowProgram.mShaderFiles.clear(); gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredAvatarShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0"); - gDeferredAvatarShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredAvatarShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredAvatarShadowProgram.createShader(NULL, NULL); llassert(success); } @@ -2072,11 +2172,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredAttachmentShadowProgram.mName = "Deferred Attachment Shadow Shader"; gDeferredAttachmentShadowProgram.mFeatures.hasObjectSkinning = true; + gDeferredAttachmentShadowProgram.mFeatures.isDeferred = true; gDeferredAttachmentShadowProgram.mShaderFiles.clear(); gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredAttachmentShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0"); - gDeferredAttachmentShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredAttachmentShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredAttachmentShadowProgram.createShader(NULL, NULL); llassert(success); } @@ -2085,10 +2186,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gTerrainProgram.mName = "Deferred Terrain Shader"; gDeferredTerrainProgram.mFeatures.encodesNormal = true; + gDeferredTerrainProgram.mFeatures.isDeferred = true; gDeferredTerrainProgram.mShaderFiles.clear(); gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredTerrainProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredTerrainProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredTerrainProgram.createShader(NULL, NULL); llassert(success); } @@ -2098,10 +2200,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAvatarProgram.mName = "Avatar Shader"; gDeferredAvatarProgram.mFeatures.hasSkinning = true; gDeferredAvatarProgram.mFeatures.encodesNormal = true; + gDeferredAvatarProgram.mFeatures.isDeferred = true; gDeferredAvatarProgram.mShaderFiles.clear(); gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredAvatarProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredAvatarProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredAvatarProgram.createShader(NULL, NULL); llassert(success); } @@ -2121,14 +2224,20 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true; gDeferredAvatarAlphaProgram.mFeatures.hasTransport = true; gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true; + gDeferredAvatarAlphaProgram.mFeatures.isDeferred = true; + gDeferredAvatarAlphaProgram.mFeatures.hasShadows = true; + gDeferredAvatarAlphaProgram.mFeatures.hasIndirect = true; gDeferredAvatarAlphaProgram.mShaderFiles.clear(); gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredAvatarAlphaProgram.addPermutation("USE_DIFFUSE_TEX", "1"); gDeferredAvatarAlphaProgram.addPermutation("IS_AVATAR_SKIN", "1"); - gDeferredAvatarAlphaProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0"); - gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + if (use_sun_shadow) + { + gDeferredAvatarAlphaProgram.addPermutation("HAS_SHADOW", "1"); + } + gDeferredAvatarAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredAvatarAlphaProgram.createShader(NULL, NULL); llassert(success); @@ -2141,10 +2250,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredPostGammaCorrectProgram.mName = "Deferred Gamma Correction Post Process"; gDeferredPostGammaCorrectProgram.mFeatures.hasSrgb = true; + gDeferredPostGammaCorrectProgram.mFeatures.isDeferred = true; gDeferredPostGammaCorrectProgram.mShaderFiles.clear(); gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredPostGammaCorrectProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredPostGammaCorrectProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredPostGammaCorrectProgram.createShader(NULL, NULL); llassert(success); } @@ -2152,10 +2262,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gFXAAProgram.mName = "FXAA Shader"; + gFXAAProgram.mFeatures.isDeferred = true; gFXAAProgram.mShaderFiles.clear(); gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB)); gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/fxaaF.glsl", GL_FRAGMENT_SHADER_ARB)); - gFXAAProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gFXAAProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gFXAAProgram.createShader(NULL, NULL); llassert(success); } @@ -2163,10 +2274,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredPostProgram.mName = "Deferred Post Shader"; + gFXAAProgram.mFeatures.isDeferred = true; gDeferredPostProgram.mShaderFiles.clear(); gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredPostProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredPostProgram.createShader(NULL, NULL); llassert(success); } @@ -2177,7 +2289,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredCoFProgram.mShaderFiles.clear(); gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/cofF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredCoFProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredCoFProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredCoFProgram.createShader(NULL, NULL); llassert(success); } @@ -2185,10 +2297,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredDoFCombineProgram.mName = "Deferred DoFCombine Shader"; + gDeferredDoFCombineProgram.mFeatures.isDeferred = true; gDeferredDoFCombineProgram.mShaderFiles.clear(); gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/dofCombineF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredDoFCombineProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredDoFCombineProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredDoFCombineProgram.createShader(NULL, NULL); llassert(success); } @@ -2196,10 +2309,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredPostNoDoFProgram.mName = "Deferred Post Shader"; + gDeferredPostNoDoFProgram.mFeatures.isDeferred = true; gDeferredPostNoDoFProgram.mShaderFiles.clear(); gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoDoFF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredPostNoDoFProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredPostNoDoFProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredPostNoDoFProgram.createShader(NULL, NULL); llassert(success); } @@ -2212,10 +2326,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredWLSkyProgram.mFeatures.calculatesAtmospherics = true; gDeferredWLSkyProgram.mFeatures.hasTransport = true; gDeferredWLSkyProgram.mFeatures.hasGamma = true; + gDeferredWLSkyProgram.mFeatures.hasSrgb = true; + gDeferredWLSkyProgram.mFeatures.isDeferred = true; + gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredWLSkyProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT]; + gDeferredWLSkyProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT]; gDeferredWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY; + if (gAtmosphere && gDeferredWLSkyProgram.mShaderLevel > 2) + { + gDeferredWLSkyProgram.mExtraLinkObject = gAtmosphere->getAtmosphericShaderForLink(); + } success = gDeferredWLSkyProgram.createShader(NULL, NULL); llassert(success); } @@ -2227,10 +2348,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredWLCloudProgram.mFeatures.calculatesAtmospherics = true; gDeferredWLCloudProgram.mFeatures.hasTransport = true; gDeferredWLCloudProgram.mFeatures.hasGamma = true; + gDeferredWLCloudProgram.mFeatures.hasSrgb = true; + gDeferredWLCloudProgram.mFeatures.isDeferred = true; + gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredWLCloudProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT]; + gDeferredWLCloudProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT]; gDeferredWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY; + if (gAtmosphere && gDeferredWLCloudProgram.mShaderLevel > 2) + { + gDeferredWLCloudProgram.mExtraLinkObject = gAtmosphere->getAtmosphericShaderForLink(); + } success = gDeferredWLCloudProgram.createShader(NULL, NULL); llassert(success); } @@ -2244,10 +2372,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredWLSunProgram.mFeatures.hasAtmospherics = true; gDeferredWLSunProgram.mFeatures.isFullbright = true; gDeferredWLSunProgram.mFeatures.disableTextureIndex = true; + gDeferredWLSunProgram.mFeatures.isDeferred = true; gDeferredWLSunProgram.mShaderFiles.clear(); gDeferredWLSunProgram.mShaderFiles.push_back(make_pair("deferred/sunDiscV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredWLSunProgram.mShaderFiles.push_back(make_pair("deferred/sunDiscF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredWLSunProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredWLSunProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredWLSunProgram.mShaderGroup = LLGLSLShader::SG_SKY; success = gDeferredWLSunProgram.createShader(NULL, NULL); llassert(success); @@ -2262,10 +2391,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredWLMoonProgram.mFeatures.hasAtmospherics = true; gDeferredWLMoonProgram.mFeatures.isFullbright = true; gDeferredWLMoonProgram.mFeatures.disableTextureIndex = true; + gDeferredWLMoonProgram.mFeatures.isDeferred = true; + gDeferredWLMoonProgram.mShaderFiles.clear(); gDeferredWLMoonProgram.mShaderFiles.push_back(make_pair("deferred/moonV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredWLMoonProgram.mShaderFiles.push_back(make_pair("deferred/moonF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredWLMoonProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredWLMoonProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredWLMoonProgram.mShaderGroup = LLGLSLShader::SG_SKY; success = gDeferredWLMoonProgram.createShader(NULL, NULL); llassert(success); @@ -2274,10 +2405,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredStarProgram.mName = "Deferred Star Program"; + gDeferredStarProgram.mFeatures.isDeferred = true; gDeferredStarProgram.mShaderFiles.clear(); gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredStarProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredStarProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredStarProgram.mShaderGroup = LLGLSLShader::SG_SKY; success = gDeferredStarProgram.createShader(NULL, NULL); llassert(success); @@ -2286,10 +2418,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gNormalMapGenProgram.mName = "Normal Map Generation Program"; + gNormalMapGenProgram.mFeatures.isDeferred = true; gNormalMapGenProgram.mShaderFiles.clear(); gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenV.glsl", GL_VERTEX_SHADER_ARB)); gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenF.glsl", GL_FRAGMENT_SHADER_ARB)); - gNormalMapGenProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gNormalMapGenProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gNormalMapGenProgram.mShaderGroup = LLGLSLShader::SG_SKY; success = gNormalMapGenProgram.createShader(NULL, NULL); } @@ -2301,7 +2434,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() { BOOL success = TRUE; - if (mVertexShaderLevel[SHADER_OBJECT] == 0) + if (mShaderLevel[SHADER_OBJECT] == 0) { gObjectShinyProgram.unload(); gObjectFullbrightShinyProgram.unload(); @@ -2366,7 +2499,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleNonIndexedProgram.mShaderFiles.clear(); gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectSimpleNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectSimpleNonIndexedProgram.createShader(NULL, NULL); } @@ -2382,7 +2515,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.clear(); gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.push_back(make_pair("objects/simpleTexGenV.glsl", GL_VERTEX_SHADER_ARB)); gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleNonIndexedTexGenProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectSimpleNonIndexedTexGenProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectSimpleNonIndexedTexGenProgram.createShader(NULL, NULL); } @@ -2399,7 +2532,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleNonIndexedWaterProgram.mShaderFiles.clear(); gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectSimpleNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectSimpleNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectSimpleNonIndexedWaterProgram.createShader(NULL, NULL); } @@ -2416,7 +2549,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.clear(); gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleTexGenV.glsl", GL_VERTEX_SHADER_ARB)); gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleNonIndexedTexGenWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectSimpleNonIndexedTexGenWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectSimpleNonIndexedTexGenWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectSimpleNonIndexedTexGenWaterProgram.createShader(NULL, NULL); } @@ -2434,7 +2567,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectAlphaMaskNonIndexedProgram.mShaderFiles.clear(); gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleNonIndexedV.glsl", GL_VERTEX_SHADER_ARB)); gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectAlphaMaskNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectAlphaMaskNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectAlphaMaskNonIndexedProgram.createShader(NULL, NULL); } @@ -2451,7 +2584,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.clear(); gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleNonIndexedV.glsl", GL_VERTEX_SHADER_ARB)); gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectAlphaMaskNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectAlphaMaskNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectAlphaMaskNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectAlphaMaskNonIndexedWaterProgram.createShader(NULL, NULL); } @@ -2469,7 +2602,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectAlphaMaskNoColorProgram.mShaderFiles.clear(); gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER_ARB)); gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectAlphaMaskNoColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectAlphaMaskNoColorProgram.createShader(NULL, NULL); } @@ -2486,7 +2619,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.clear(); gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER_ARB)); gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectAlphaMaskNoColorWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectAlphaMaskNoColorWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectAlphaMaskNoColorWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectAlphaMaskNoColorWaterProgram.createShader(NULL, NULL); } @@ -2504,7 +2637,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gTreeProgram.mShaderFiles.clear(); gTreeProgram.mShaderFiles.push_back(make_pair("objects/treeV.glsl", GL_VERTEX_SHADER_ARB)); gTreeProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gTreeProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gTreeProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gTreeProgram.createShader(NULL, NULL); } @@ -2521,7 +2654,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gTreeWaterProgram.mShaderFiles.clear(); gTreeWaterProgram.mShaderFiles.push_back(make_pair("objects/treeV.glsl", GL_VERTEX_SHADER_ARB)); gTreeWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gTreeWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gTreeWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gTreeWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gTreeWaterProgram.createShader(NULL, NULL); } @@ -2538,7 +2671,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightNonIndexedProgram.mShaderFiles.clear(); gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectFullbrightNonIndexedProgram.createShader(NULL, NULL); } @@ -2554,7 +2687,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.clear(); gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectFullbrightNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectFullbrightNonIndexedWaterProgram.createShader(NULL, NULL); } @@ -2571,7 +2704,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectEmissiveNonIndexedProgram.mShaderFiles.clear(); gObjectEmissiveNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); gObjectEmissiveNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectEmissiveNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectEmissiveNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectEmissiveNonIndexedProgram.createShader(NULL, NULL); } @@ -2586,7 +2719,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.clear(); gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectEmissiveNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectEmissiveNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectEmissiveNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectEmissiveNonIndexedWaterProgram.createShader(NULL, NULL); } @@ -2603,7 +2736,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightNoColorProgram.mShaderFiles.clear(); gObjectFullbrightNoColorProgram.mShaderFiles.push_back(make_pair("objects/fullbrightNoColorV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightNoColorProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightNoColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightNoColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectFullbrightNoColorProgram.createShader(NULL, NULL); } @@ -2618,7 +2751,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightNoColorWaterProgram.mShaderFiles.clear(); gObjectFullbrightNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightNoColorV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightNoColorWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightNoColorWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectFullbrightNoColorWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectFullbrightNoColorWaterProgram.createShader(NULL, NULL); } @@ -2635,7 +2768,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectShinyNonIndexedProgram.mShaderFiles.clear(); gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectShinyNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectShinyNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectShinyNonIndexedProgram.createShader(NULL, NULL); } @@ -2651,7 +2784,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectShinyNonIndexedWaterProgram.mShaderFiles.clear(); gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectShinyNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectShinyNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectShinyNonIndexedWaterProgram.createShader(NULL, NULL); } @@ -2668,7 +2801,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.clear(); gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightShinyNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightShinyNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectFullbrightShinyNonIndexedProgram.createShader(NULL, NULL); } @@ -2685,7 +2818,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.clear(); gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightShinyNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightShinyNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectFullbrightShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectFullbrightShinyNonIndexedWaterProgram.createShader(NULL, NULL); } @@ -2698,7 +2831,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gImpostorProgram.mShaderFiles.clear(); gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorV.glsl", GL_VERTEX_SHADER_ARB)); gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorF.glsl", GL_FRAGMENT_SHADER_ARB)); - gImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gImpostorProgram.createShader(NULL, NULL); } @@ -2715,7 +2848,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectPreviewProgram.mShaderFiles.clear(); gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewV.glsl", GL_VERTEX_SHADER_ARB)); gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectPreviewProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectPreviewProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectPreviewProgram.createShader(NULL, NULL); gObjectPreviewProgram.mFeatures.hasLighting = true; } @@ -2732,7 +2865,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleProgram.mShaderFiles.clear(); gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectSimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectSimpleProgram.createShader(NULL, NULL); } @@ -2752,7 +2885,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleImpostorProgram.mShaderFiles.clear(); gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectSimpleImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectSimpleImpostorProgram.createShader(NULL, NULL); } @@ -2769,7 +2902,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleWaterProgram.mShaderFiles.clear(); gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectSimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectSimpleWaterProgram.createShader(NULL, NULL); } @@ -2787,7 +2920,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectBumpProgram.mShaderFiles.clear(); gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpV.glsl", GL_VERTEX_SHADER_ARB)); gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectBumpProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectBumpProgram.createShader(NULL, NULL); if (success) { //lldrawpoolbump assumes "texture0" has channel 0 and "texture1" has channel 1 @@ -2812,7 +2945,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleAlphaMaskProgram.mShaderFiles.clear(); gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectSimpleAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectSimpleAlphaMaskProgram.createShader(NULL, NULL); } @@ -2829,7 +2962,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.clear(); gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleWaterAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectSimpleWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectSimpleWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectSimpleWaterAlphaMaskProgram.createShader(NULL, NULL); } @@ -2846,7 +2979,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightProgram.mShaderFiles.clear(); gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectFullbrightProgram.createShader(NULL, NULL); } @@ -2861,7 +2994,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightWaterProgram.mShaderFiles.clear(); gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectFullbrightWaterProgram.createShader(NULL, NULL); } @@ -2878,7 +3011,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectEmissiveProgram.mShaderFiles.clear(); gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectEmissiveProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectEmissiveProgram.createShader(NULL, NULL); } @@ -2893,7 +3026,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectEmissiveWaterProgram.mShaderFiles.clear(); gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectEmissiveWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectEmissiveWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectEmissiveWaterProgram.createShader(NULL, NULL); } @@ -2911,7 +3044,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightAlphaMaskProgram.mShaderFiles.clear(); gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectFullbrightAlphaMaskProgram.createShader(NULL, NULL); } @@ -2927,7 +3060,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.clear(); gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightWaterAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectFullbrightWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectFullbrightWaterAlphaMaskProgram.createShader(NULL, NULL); } @@ -2944,7 +3077,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectShinyProgram.mShaderFiles.clear(); gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectShinyProgram.createShader(NULL, NULL); } @@ -2960,7 +3093,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectShinyWaterProgram.mShaderFiles.clear(); gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectShinyWaterProgram.createShader(NULL, NULL); } @@ -2977,7 +3110,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightShinyProgram.mShaderFiles.clear(); gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gObjectFullbrightShinyProgram.createShader(NULL, NULL); } @@ -2994,12 +3127,12 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightShinyWaterProgram.mShaderFiles.clear(); gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gObjectFullbrightShinyWaterProgram.createShader(NULL, NULL); } - if (mVertexShaderLevel[SHADER_AVATAR] > 0) + if (mShaderLevel[SHADER_AVATAR] > 0) { //load hardware skinned attachment shaders if (success) { @@ -3015,7 +3148,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gSkinnedObjectSimpleProgram.mShaderFiles.clear(); gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectSimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gSkinnedObjectSimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gSkinnedObjectSimpleProgram.createShader(NULL, NULL); } @@ -3033,7 +3166,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gSkinnedObjectFullbrightProgram.mShaderFiles.clear(); gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gSkinnedObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gSkinnedObjectFullbrightProgram.createShader(NULL, NULL); } @@ -3050,7 +3183,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gSkinnedObjectEmissiveProgram.mShaderFiles.clear(); gSkinnedObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gSkinnedObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectEmissiveProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gSkinnedObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gSkinnedObjectEmissiveProgram.createShader(NULL, NULL); } @@ -3067,7 +3200,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gSkinnedObjectEmissiveWaterProgram.mShaderFiles.clear(); gSkinnedObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gSkinnedObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectEmissiveWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gSkinnedObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gSkinnedObjectEmissiveWaterProgram.createShader(NULL, NULL); } @@ -3085,7 +3218,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gSkinnedObjectFullbrightShinyProgram.mShaderFiles.clear(); gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gSkinnedObjectFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gSkinnedObjectFullbrightShinyProgram.createShader(NULL, NULL); } @@ -3103,7 +3236,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gSkinnedObjectShinySimpleProgram.mShaderFiles.clear(); gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectShinySimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gSkinnedObjectShinySimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gSkinnedObjectShinySimpleProgram.createShader(NULL, NULL); } @@ -3124,7 +3257,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear(); gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectSimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gSkinnedObjectSimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gSkinnedObjectSimpleWaterProgram.createShader(NULL, NULL); } @@ -3143,7 +3276,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gSkinnedObjectFullbrightWaterProgram.mShaderFiles.clear(); gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectFullbrightWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gSkinnedObjectFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gSkinnedObjectFullbrightWaterProgram.createShader(NULL, NULL); } @@ -3163,7 +3296,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.clear(); gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectFullbrightShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gSkinnedObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gSkinnedObjectFullbrightShinyWaterProgram.createShader(NULL, NULL); } @@ -3183,14 +3316,14 @@ BOOL LLViewerShaderMgr::loadShadersObject() gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.clear(); gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectShinySimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gSkinnedObjectShinySimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = gSkinnedObjectShinySimpleWaterProgram.createShader(NULL, NULL); } } if( !success ) { - mVertexShaderLevel[SHADER_OBJECT] = 0; + mShaderLevel[SHADER_OBJECT] = 0; return FALSE; } @@ -3201,7 +3334,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() { BOOL success = TRUE; - if (mVertexShaderLevel[SHADER_AVATAR] == 0) + if (mShaderLevel[SHADER_AVATAR] == 0) { gAvatarProgram.unload(); gAvatarWaterProgram.unload(); @@ -3224,7 +3357,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() gAvatarProgram.mShaderFiles.clear(); gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB)); gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarF.glsl", GL_FRAGMENT_SHADER_ARB)); - gAvatarProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR]; + gAvatarProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR]; success = gAvatarProgram.createShader(NULL, NULL); if (success) @@ -3242,15 +3375,15 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() gAvatarWaterProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB)); gAvatarWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); // Note: no cloth under water: - gAvatarWaterProgram.mShaderLevel = llmin(mVertexShaderLevel[SHADER_AVATAR], 1); + gAvatarWaterProgram.mShaderLevel = llmin(mShaderLevel[SHADER_AVATAR], 1); gAvatarWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; success = gAvatarWaterProgram.createShader(NULL, NULL); } /// Keep track of avatar levels - if (gAvatarProgram.mShaderLevel != mVertexShaderLevel[SHADER_AVATAR]) + if (gAvatarProgram.mShaderLevel != mShaderLevel[SHADER_AVATAR]) { - mMaxAvatarShaderLevel = mVertexShaderLevel[SHADER_AVATAR] = gAvatarProgram.mShaderLevel; + mMaxAvatarShaderLevel = mShaderLevel[SHADER_AVATAR] = gAvatarProgram.mShaderLevel; } } @@ -3262,7 +3395,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() gAvatarPickProgram.mShaderFiles.clear(); gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarV.glsl", GL_VERTEX_SHADER_ARB)); gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarF.glsl", GL_FRAGMENT_SHADER_ARB)); - gAvatarPickProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR]; + gAvatarPickProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR]; success = gAvatarPickProgram.createShader(NULL, NULL); } @@ -3280,13 +3413,13 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() gAvatarEyeballProgram.mShaderFiles.clear(); gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER_ARB)); gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballF.glsl", GL_FRAGMENT_SHADER_ARB)); - gAvatarEyeballProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR]; + gAvatarEyeballProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR]; success = gAvatarEyeballProgram.createShader(NULL, NULL); } if( !success ) { - mVertexShaderLevel[SHADER_AVATAR] = 0; + mShaderLevel[SHADER_AVATAR] = 0; mMaxAvatarShaderLevel = 0; return FALSE; } @@ -3298,7 +3431,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() { BOOL success = TRUE; - if (mVertexShaderLevel[SHADER_INTERFACE] == 0) + if (mShaderLevel[SHADER_INTERFACE] == 0) { gHighlightProgram.unload(); return TRUE; @@ -3310,7 +3443,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gHighlightProgram.mShaderFiles.clear(); gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER_ARB)); gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gHighlightProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gHighlightProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gHighlightProgram.createShader(NULL, NULL); } @@ -3320,7 +3453,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gHighlightNormalProgram.mShaderFiles.clear(); gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightNormV.glsl", GL_VERTEX_SHADER_ARB)); gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gHighlightNormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gHighlightNormalProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gHighlightNormalProgram.createShader(NULL, NULL); } @@ -3330,7 +3463,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gHighlightSpecularProgram.mShaderFiles.clear(); gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightSpecV.glsl", GL_VERTEX_SHADER_ARB)); gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gHighlightSpecularProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gHighlightSpecularProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gHighlightSpecularProgram.createShader(NULL, NULL); } @@ -3340,7 +3473,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gUIProgram.mShaderFiles.clear(); gUIProgram.mShaderFiles.push_back(make_pair("interface/uiV.glsl", GL_VERTEX_SHADER_ARB)); gUIProgram.mShaderFiles.push_back(make_pair("interface/uiF.glsl", GL_FRAGMENT_SHADER_ARB)); - gUIProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gUIProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gUIProgram.createShader(NULL, NULL); } @@ -3350,7 +3483,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gPathfindingProgram.mShaderFiles.clear(); gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingV.glsl", GL_VERTEX_SHADER_ARB)); gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER_ARB)); - gPathfindingProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gPathfindingProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gPathfindingProgram.createShader(NULL, NULL); } @@ -3360,7 +3493,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gPathfindingNoNormalsProgram.mShaderFiles.clear(); gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingNoNormalV.glsl", GL_VERTEX_SHADER_ARB)); gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER_ARB)); - gPathfindingNoNormalsProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gPathfindingNoNormalsProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gPathfindingNoNormalsProgram.createShader(NULL, NULL); } @@ -3370,7 +3503,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gCustomAlphaProgram.mShaderFiles.clear(); gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaV.glsl", GL_VERTEX_SHADER_ARB)); gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaF.glsl", GL_FRAGMENT_SHADER_ARB)); - gCustomAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gCustomAlphaProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gCustomAlphaProgram.createShader(NULL, NULL); } @@ -3380,7 +3513,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gSplatTextureRectProgram.mShaderFiles.clear(); gSplatTextureRectProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectV.glsl", GL_VERTEX_SHADER_ARB)); gSplatTextureRectProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSplatTextureRectProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gSplatTextureRectProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gSplatTextureRectProgram.createShader(NULL, NULL); if (success) { @@ -3396,7 +3529,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gGlowCombineProgram.mShaderFiles.clear(); gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineV.glsl", GL_VERTEX_SHADER_ARB)); gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineF.glsl", GL_FRAGMENT_SHADER_ARB)); - gGlowCombineProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gGlowCombineProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gGlowCombineProgram.createShader(NULL, NULL); if (success) { @@ -3413,7 +3546,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gGlowCombineFXAAProgram.mShaderFiles.clear(); gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAV.glsl", GL_VERTEX_SHADER_ARB)); gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAF.glsl", GL_FRAGMENT_SHADER_ARB)); - gGlowCombineFXAAProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gGlowCombineFXAAProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gGlowCombineFXAAProgram.createShader(NULL, NULL); if (success) { @@ -3431,7 +3564,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gTwoTextureAddProgram.mShaderFiles.clear(); gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddV.glsl", GL_VERTEX_SHADER_ARB)); gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddF.glsl", GL_FRAGMENT_SHADER_ARB)); - gTwoTextureAddProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gTwoTextureAddProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gTwoTextureAddProgram.createShader(NULL, NULL); if (success) { @@ -3448,7 +3581,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gTwoTextureCompareProgram.mShaderFiles.clear(); gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareV.glsl", GL_VERTEX_SHADER_ARB)); gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareF.glsl", GL_FRAGMENT_SHADER_ARB)); - gTwoTextureCompareProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gTwoTextureCompareProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gTwoTextureCompareProgram.createShader(NULL, NULL); if (success) { @@ -3465,7 +3598,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gOneTextureFilterProgram.mShaderFiles.clear(); gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterV.glsl", GL_VERTEX_SHADER_ARB)); gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gOneTextureFilterProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gOneTextureFilterProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gOneTextureFilterProgram.createShader(NULL, NULL); if (success) { @@ -3481,7 +3614,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gOneTextureNoColorProgram.mShaderFiles.clear(); gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorV.glsl", GL_VERTEX_SHADER_ARB)); gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorF.glsl", GL_FRAGMENT_SHADER_ARB)); - gOneTextureNoColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gOneTextureNoColorProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gOneTextureNoColorProgram.createShader(NULL, NULL); if (success) { @@ -3496,7 +3629,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gSolidColorProgram.mShaderFiles.clear(); gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorV.glsl", GL_VERTEX_SHADER_ARB)); gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSolidColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gSolidColorProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gSolidColorProgram.createShader(NULL, NULL); if (success) { @@ -3512,7 +3645,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gOcclusionProgram.mShaderFiles.clear(); gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionV.glsl", GL_VERTEX_SHADER_ARB)); gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB)); - gOcclusionProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gOcclusionProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gOcclusionProgram.createShader(NULL, NULL); } @@ -3522,7 +3655,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gOcclusionCubeProgram.mShaderFiles.clear(); gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionCubeV.glsl", GL_VERTEX_SHADER_ARB)); gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB)); - gOcclusionCubeProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gOcclusionCubeProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gOcclusionCubeProgram.createShader(NULL, NULL); } @@ -3532,7 +3665,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gDebugProgram.mShaderFiles.clear(); gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER_ARB)); gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDebugProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gDebugProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gDebugProgram.createShader(NULL, NULL); } @@ -3542,7 +3675,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gClipProgram.mShaderFiles.clear(); gClipProgram.mShaderFiles.push_back(make_pair("interface/clipV.glsl", GL_VERTEX_SHADER_ARB)); gClipProgram.mShaderFiles.push_back(make_pair("interface/clipF.glsl", GL_FRAGMENT_SHADER_ARB)); - gClipProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gClipProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gClipProgram.createShader(NULL, NULL); } @@ -3552,7 +3685,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gDownsampleDepthProgram.mShaderFiles.clear(); gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB)); gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDownsampleDepthProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gDownsampleDepthProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gDownsampleDepthProgram.createShader(NULL, NULL); } @@ -3562,7 +3695,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gBenchmarkProgram.mShaderFiles.clear(); gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkV.glsl", GL_VERTEX_SHADER_ARB)); gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkF.glsl", GL_FRAGMENT_SHADER_ARB)); - gBenchmarkProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gBenchmarkProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gBenchmarkProgram.createShader(NULL, NULL); } @@ -3572,7 +3705,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gDownsampleDepthRectProgram.mShaderFiles.clear(); gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB)); gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthRectF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDownsampleDepthRectProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gDownsampleDepthRectProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gDownsampleDepthRectProgram.createShader(NULL, NULL); } @@ -3582,13 +3715,13 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gAlphaMaskProgram.mShaderFiles.clear(); gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskV.glsl", GL_VERTEX_SHADER_ARB)); gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskF.glsl", GL_FRAGMENT_SHADER_ARB)); - gAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gAlphaMaskProgram.createShader(NULL, NULL); } if( !success ) { - mVertexShaderLevel[SHADER_INTERFACE] = 0; + mShaderLevel[SHADER_INTERFACE] = 0; return FALSE; } @@ -3599,7 +3732,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight() { BOOL success = TRUE; - if (mVertexShaderLevel[SHADER_WINDLIGHT] < 2) + if (mShaderLevel[SHADER_WINDLIGHT] < 2) { gWLSkyProgram.unload(); gWLCloudProgram.unload(); @@ -3629,7 +3762,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight() gWLSkyProgram.mFeatures.hasGamma = true; gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyV.glsl", GL_VERTEX_SHADER_ARB)); gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gWLSkyProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT]; + gWLSkyProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT]; gWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY; success = gWLSkyProgram.createShader(NULL, NULL); } @@ -3644,7 +3777,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight() gWLCloudProgram.mFeatures.hasGamma = true; gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsV.glsl", GL_VERTEX_SHADER_ARB)); gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB)); - gWLCloudProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT]; + gWLCloudProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT]; gWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY; success = gWLCloudProgram.createShader(NULL, NULL); } @@ -3662,7 +3795,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight() gWLSunProgram.mShaderGroup = LLGLSLShader::SG_SKY; gWLSunProgram.mShaderFiles.push_back(make_pair("windlight/sunDiscV.glsl", GL_VERTEX_SHADER_ARB)); gWLSunProgram.mShaderFiles.push_back(make_pair("windlight/sunDiscF.glsl", GL_FRAGMENT_SHADER_ARB)); - gWLSunProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT]; + gWLSunProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT]; gWLSunProgram.mShaderGroup = LLGLSLShader::SG_SKY; success = gWLSunProgram.createShader(NULL, NULL); } @@ -3680,7 +3813,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight() gWLMoonProgram.mShaderGroup = LLGLSLShader::SG_SKY; gWLMoonProgram.mShaderFiles.push_back(make_pair("windlight/moonV.glsl", GL_VERTEX_SHADER_ARB)); gWLMoonProgram.mShaderFiles.push_back(make_pair("windlight/moonF.glsl", GL_FRAGMENT_SHADER_ARB)); - gWLMoonProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT]; + gWLMoonProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT]; gWLMoonProgram.mShaderGroup = LLGLSLShader::SG_SKY; success = gWLMoonProgram.createShader(NULL, NULL); } @@ -3692,7 +3825,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders() { BOOL success = TRUE; - if (mVertexShaderLevel[SHADER_TRANSFORM] < 1) + if (mShaderLevel[SHADER_TRANSFORM] < 1) { gTransformPositionProgram.unload(); gTransformTexCoordProgram.unload(); @@ -3707,7 +3840,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders() gTransformPositionProgram.mName = "Position Transform Shader"; gTransformPositionProgram.mShaderFiles.clear(); gTransformPositionProgram.mShaderFiles.push_back(make_pair("transform/positionV.glsl", GL_VERTEX_SHADER_ARB)); - gTransformPositionProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + gTransformPositionProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM]; const char* varyings[] = { "position_out", @@ -3722,7 +3855,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders() gTransformTexCoordProgram.mName = "TexCoord Transform Shader"; gTransformTexCoordProgram.mShaderFiles.clear(); gTransformTexCoordProgram.mShaderFiles.push_back(make_pair("transform/texcoordV.glsl", GL_VERTEX_SHADER_ARB)); - gTransformTexCoordProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + gTransformTexCoordProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM]; const char* varyings[] = { "texcoord_out", @@ -3736,7 +3869,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders() gTransformNormalProgram.mName = "Normal Transform Shader"; gTransformNormalProgram.mShaderFiles.clear(); gTransformNormalProgram.mShaderFiles.push_back(make_pair("transform/normalV.glsl", GL_VERTEX_SHADER_ARB)); - gTransformNormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + gTransformNormalProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM]; const char* varyings[] = { "normal_out", @@ -3750,7 +3883,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders() gTransformColorProgram.mName = "Color Transform Shader"; gTransformColorProgram.mShaderFiles.clear(); gTransformColorProgram.mShaderFiles.push_back(make_pair("transform/colorV.glsl", GL_VERTEX_SHADER_ARB)); - gTransformColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + gTransformColorProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM]; const char* varyings[] = { "color_out", @@ -3764,7 +3897,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders() gTransformTangentProgram.mName = "Binormal Transform Shader"; gTransformTangentProgram.mShaderFiles.clear(); gTransformTangentProgram.mShaderFiles.push_back(make_pair("transform/binormalV.glsl", GL_VERTEX_SHADER_ARB)); - gTransformTangentProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + gTransformTangentProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM]; const char* varyings[] = { "tangent_out", diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 250f8f1ee3..ac2cfc1160 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -48,7 +48,7 @@ public: void initAttribsAndUniforms(void); void setShaders(); void unloadShaders(); - S32 getVertexShaderLevel(S32 type); + S32 getShaderLevel(S32 type); BOOL loadBasicShaders(); BOOL loadShadersEffects(); BOOL loadShadersDeferred(); @@ -60,7 +60,7 @@ public: BOOL loadShadersWindLight(); BOOL loadTransformShaders(); - std::vector mVertexShaderLevel; + std::vector mShaderLevel; S32 mMaxAvatarShaderLevel; enum EShaderClass diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 321f774210..cc030dfb60 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2950,7 +2950,7 @@ void LLVOAvatar::idleUpdateLoadingEffect() void LLVOAvatar::idleUpdateWindEffect() { // update wind effect - if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH)) + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH)) { F32 hover_strength = 0.f; F32 time_delta = mRippleTimer.getElapsedTimeF32() - mRippleTimeLast; @@ -4651,7 +4651,7 @@ U32 LLVOAvatar::renderSkinned() } } - if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) + if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) { if (mNeedsSkin) { diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index d30bb260e1..af078251b3 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -1074,7 +1074,7 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) if (mFace[FACE_REFLECTION] == NULL) { LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER); - if (gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() != 0) + if (gPipeline.getPool(LLDrawPool::POOL_WATER)->getShaderLevel() != 0) { mFace[FACE_REFLECTION] = drawable->addFace(poolp, NULL); } @@ -1177,7 +1177,7 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) } bool above_water = (height_above_water > 0); - bool render_ref = above_water && gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() == 0; + bool render_ref = above_water && gPipeline.getPool(LLDrawPool::POOL_WATER)->getShaderLevel() == 0; setDrawRefl(above_water ? (sun_flag ? 0 : 1) : -1); if (render_ref) { diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 0b1f1df4c8..2c9f6f02dc 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5859,7 +5859,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) spec_mask = spec_mask | LLVertexBuffer::MAP_EMISSIVE; } - BOOL batch_textures = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1; + BOOL batch_textures = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1; if (batch_textures) { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index cd2146ab4e..d56350f705 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1422,7 +1422,7 @@ bool LLPipeline::canUseVertexShaders() bool LLPipeline::canUseWindLightShaders() const { - bool usingWindlight = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1; + bool usingWindlight = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1; bool haveShaders = ((gWLSkyProgram.mProgramObject != 0) || (gDeferredWLSkyProgram.mProgramObject != 0)); return (!LLPipeline::sDisableShaders && haveShaders && usingWindlight); } @@ -1430,7 +1430,7 @@ bool LLPipeline::canUseWindLightShaders() const bool LLPipeline::canUseWindLightShadersOnObjects() const { return (canUseWindLightShaders() - && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0); + && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0); } bool LLPipeline::canUseAntiAliasing() const @@ -4244,7 +4244,7 @@ void LLPipeline::renderHighlights() //gGL.setSceneBlendType(LLRender::BT_ALPHA); } - if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) { gHighlightProgram.bind(); gGL.diffuseColor4f(1,1,1,0.5f); @@ -4291,7 +4291,7 @@ void LLPipeline::renderHighlights() // have touch-handlers. mHighlightFaces.clear(); - if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0) + if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0) { gHighlightProgram.unbind(); } @@ -4300,7 +4300,7 @@ void LLPipeline::renderHighlights() if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::NORMAL_MAP)) { color.setVec(1.0f, 0.5f, 0.5f, 0.5f); - if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) { gHighlightNormalProgram.bind(); gGL.diffuseColor4f(1,1,1,0.5f); @@ -4321,7 +4321,7 @@ void LLPipeline::renderHighlights() facep->renderSelected(mFaceSelectImagep, color); } - if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) { gHighlightNormalProgram.unbind(); } @@ -4330,7 +4330,7 @@ void LLPipeline::renderHighlights() if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::SPECULAR_MAP)) { color.setVec(0.0f, 0.3f, 1.0f, 0.8f); - if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) { gHighlightSpecularProgram.bind(); gGL.diffuseColor4f(1,1,1,0.5f); @@ -4351,7 +4351,7 @@ void LLPipeline::renderHighlights() facep->renderSelected(mFaceSelectImagep, color); } - if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) { gHighlightSpecularProgram.unbind(); } -- cgit v1.3 From dc4b34966ae6830a06bf266da6f600b32da8cfbd Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Thu, 7 Mar 2019 13:46:40 -0800 Subject: SL-10421 Add pointer checks to possibly avoid bugsplat autoreported crash. --- indra/newview/llvovolume.cpp | 12183 +++++++++++++++++++++-------------------- 1 file changed, 6093 insertions(+), 6090 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 9c761cc4a6..07972e0d77 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -94,7 +94,7 @@ BOOL gAnimateTextures = TRUE; //extern BOOL gHideSelectedObjects; F32 LLVOVolume::sLODFactor = 1.f; -F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop +F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop F32 LLVOVolume::sDistanceFactor = 1.0f; S32 LLVOVolume::sNumLODChanges = 0; S32 LLVOVolume::mRenderComplexity_last = 0; @@ -112,200 +112,200 @@ extern BOOL gGLDebugLoggingEnabled; class LLMediaDataClientObjectImpl : public LLMediaDataClientObject { public: - LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew) - { - mObject->addMDCImpl(); - } - ~LLMediaDataClientObjectImpl() - { - mObject->removeMDCImpl(); - } - - virtual U8 getMediaDataCount() const - { return mObject->getNumTEs(); } - - virtual LLSD getMediaDataLLSD(U8 index) const - { - LLSD result; - LLTextureEntry *te = mObject->getTE(index); - if (NULL != te) - { - llassert((te->getMediaData() != NULL) == te->hasMedia()); - if (te->getMediaData() != NULL) - { - result = te->getMediaData()->asLLSD(); - // XXX HACK: workaround bug in asLLSD() where whitelist is not set properly - // See DEV-41949 - if (!result.has(LLMediaEntry::WHITELIST_KEY)) - { - result[LLMediaEntry::WHITELIST_KEY] = LLSD::emptyArray(); - } - } - } - return result; - } - virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const - { - LLTextureEntry *te = mObject->getTE(index); - if (te) - { - if (te->getMediaData()) - { - return (te->getMediaData()->getCurrentURL() == url); - } - } - return url.empty(); - } - - virtual LLUUID getID() const - { return mObject->getID(); } - - virtual void mediaNavigateBounceBack(U8 index) - { mObject->mediaNavigateBounceBack(index); } - - virtual bool hasMedia() const - { return mObject->hasMedia(); } - - virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string) - { mObject->updateObjectMediaData(data, version_string); } - - virtual F64 getMediaInterest() const - { - F64 interest = mObject->getTotalMediaInterest(); - if (interest < (F64)0.0) - { - // media interest not valid yet, try pixel area - interest = mObject->getPixelArea(); - // HACK: force recalculation of pixel area if interest is the "magic default" of 1024. - if (interest == 1024.f) - { - const_cast(static_cast(mObject))->setPixelAreaAndAngle(gAgent); - interest = mObject->getPixelArea(); - } - } - return interest; - } - - virtual bool isInterestingEnough() const - { - return LLViewerMedia::isInterestingEnough(mObject, getMediaInterest()); - } - - virtual std::string getCapabilityUrl(const std::string &name) const - { return mObject->getRegion()->getCapability(name); } - - virtual bool isDead() const - { return mObject->isDead(); } - - virtual U32 getMediaVersion() const - { return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); } - - virtual bool isNew() const - { return mNew; } + LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew) + { + mObject->addMDCImpl(); + } + ~LLMediaDataClientObjectImpl() + { + mObject->removeMDCImpl(); + } + + virtual U8 getMediaDataCount() const + { return mObject->getNumTEs(); } + + virtual LLSD getMediaDataLLSD(U8 index) const + { + LLSD result; + LLTextureEntry *te = mObject->getTE(index); + if (NULL != te) + { + llassert((te->getMediaData() != NULL) == te->hasMedia()); + if (te->getMediaData() != NULL) + { + result = te->getMediaData()->asLLSD(); + // XXX HACK: workaround bug in asLLSD() where whitelist is not set properly + // See DEV-41949 + if (!result.has(LLMediaEntry::WHITELIST_KEY)) + { + result[LLMediaEntry::WHITELIST_KEY] = LLSD::emptyArray(); + } + } + } + return result; + } + virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const + { + LLTextureEntry *te = mObject->getTE(index); + if (te) + { + if (te->getMediaData()) + { + return (te->getMediaData()->getCurrentURL() == url); + } + } + return url.empty(); + } + + virtual LLUUID getID() const + { return mObject->getID(); } + + virtual void mediaNavigateBounceBack(U8 index) + { mObject->mediaNavigateBounceBack(index); } + + virtual bool hasMedia() const + { return mObject->hasMedia(); } + + virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string) + { mObject->updateObjectMediaData(data, version_string); } + + virtual F64 getMediaInterest() const + { + F64 interest = mObject->getTotalMediaInterest(); + if (interest < (F64)0.0) + { + // media interest not valid yet, try pixel area + interest = mObject->getPixelArea(); + // HACK: force recalculation of pixel area if interest is the "magic default" of 1024. + if (interest == 1024.f) + { + const_cast(static_cast(mObject))->setPixelAreaAndAngle(gAgent); + interest = mObject->getPixelArea(); + } + } + return interest; + } + + virtual bool isInterestingEnough() const + { + return LLViewerMedia::isInterestingEnough(mObject, getMediaInterest()); + } + + virtual std::string getCapabilityUrl(const std::string &name) const + { return mObject->getRegion()->getCapability(name); } + + virtual bool isDead() const + { return mObject->isDead(); } + + virtual U32 getMediaVersion() const + { return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); } + + virtual bool isNew() const + { return mNew; } private: - LLPointer mObject; - bool mNew; + LLPointer mObject; + bool mNew; }; LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) - : LLViewerObject(id, pcode, regionp), - mVolumeImpl(NULL) + : LLViewerObject(id, pcode, regionp), + mVolumeImpl(NULL) { - mTexAnimMode = 0; - mRelativeXform.setIdentity(); - mRelativeXformInvTrans.setIdentity(); + mTexAnimMode = 0; + mRelativeXform.setIdentity(); + mRelativeXformInvTrans.setIdentity(); - mFaceMappingChanged = FALSE; - mLOD = MIN_LOD; + mFaceMappingChanged = FALSE; + mLOD = MIN_LOD; mLODDistance = 0.0f; mLODAdjustedDistance = 0.0f; mLODRadius = 0.0f; - mTextureAnimp = NULL; - mVolumeChanged = FALSE; - mVObjRadius = LLVector3(1,1,0.5f).length(); - mNumFaces = 0; - mLODChanged = FALSE; - mSculptChanged = FALSE; - mSpotLightPriority = 0.f; - - mMediaImplList.resize(getNumTEs()); - mLastFetchedMediaVersion = -1; - memset(&mIndexInTex, 0, sizeof(S32) * LLRender::NUM_VOLUME_TEXTURE_CHANNELS); - mMDCImplCount = 0; + mTextureAnimp = NULL; + mVolumeChanged = FALSE; + mVObjRadius = LLVector3(1,1,0.5f).length(); + mNumFaces = 0; + mLODChanged = FALSE; + mSculptChanged = FALSE; + mSpotLightPriority = 0.f; + + mMediaImplList.resize(getNumTEs()); + mLastFetchedMediaVersion = -1; + memset(&mIndexInTex, 0, sizeof(S32) * LLRender::NUM_VOLUME_TEXTURE_CHANNELS); + mMDCImplCount = 0; mLastRiggingInfoLOD = -1; } LLVOVolume::~LLVOVolume() { - delete mTextureAnimp; - mTextureAnimp = NULL; - delete mVolumeImpl; - mVolumeImpl = NULL; + delete mTextureAnimp; + mTextureAnimp = NULL; + delete mVolumeImpl; + mVolumeImpl = NULL; - if(!mMediaImplList.empty()) - { - for(U32 i = 0 ; i < mMediaImplList.size() ; i++) - { - if(mMediaImplList[i].notNull()) - { - mMediaImplList[i]->removeObject(this) ; - } - } - } + if(!mMediaImplList.empty()) + { + for(U32 i = 0 ; i < mMediaImplList.size() ; i++) + { + if(mMediaImplList[i].notNull()) + { + mMediaImplList[i]->removeObject(this) ; + } + } + } } void LLVOVolume::markDead() { - if (!mDead) - { - LLSculptIDSize::instance().rem(getVolume()->getParams().getSculptID()); - - if(getMDCImplCount() > 0) - { - LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast(this), false); - if (sObjectMediaClient) sObjectMediaClient->removeFromQueue(obj); - if (sObjectMediaNavigateClient) sObjectMediaNavigateClient->removeFromQueue(obj); - } - - // Detach all media impls from this object - for(U32 i = 0 ; i < mMediaImplList.size() ; i++) - { - removeMediaImpl(i); - } - - if (mSculptTexture.notNull()) - { - mSculptTexture->removeVolume(LLRender::SCULPT_TEX, this); - } - - if (mLightTexture.notNull()) - { - mLightTexture->removeVolume(LLRender::LIGHT_TEX, this); - } - } - - LLViewerObject::markDead(); + if (!mDead) + { + LLSculptIDSize::instance().rem(getVolume()->getParams().getSculptID()); + + if(getMDCImplCount() > 0) + { + LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast(this), false); + if (sObjectMediaClient) sObjectMediaClient->removeFromQueue(obj); + if (sObjectMediaNavigateClient) sObjectMediaNavigateClient->removeFromQueue(obj); + } + + // Detach all media impls from this object + for(U32 i = 0 ; i < mMediaImplList.size() ; i++) + { + removeMediaImpl(i); + } + + if (mSculptTexture.notNull()) + { + mSculptTexture->removeVolume(LLRender::SCULPT_TEX, this); + } + + if (mLightTexture.notNull()) + { + mLightTexture->removeVolume(LLRender::LIGHT_TEX, this); + } + } + + LLViewerObject::markDead(); } // static void LLVOVolume::initClass() { - // gSavedSettings better be around - if (gSavedSettings.getBOOL("PrimMediaMasterEnabled")) - { - const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay"); - const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay"); - const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries"); - const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize"); - const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize"); - sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries, - max_sorted_queue_size, max_round_robin_queue_size); - sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, - max_retries, max_sorted_queue_size, max_round_robin_queue_size); - } + // gSavedSettings better be around + if (gSavedSettings.getBOOL("PrimMediaMasterEnabled")) + { + const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay"); + const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay"); + const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries"); + const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize"); + const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize"); + sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries, + max_sorted_queue_size, max_round_robin_queue_size); + sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, + max_retries, max_sorted_queue_size, max_round_robin_queue_size); + } } // static @@ -316,6442 +316,6445 @@ void LLVOVolume::cleanupClass() } U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, EObjectUpdateType update_type, - LLDataPacker *dp) + void **user_data, + U32 block_num, EObjectUpdateType update_type, + LLDataPacker *dp) { - - LLColor4U color; - const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA); + + LLColor4U color; + const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA); - // Do base class updates... - U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); + // Do base class updates... + U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); - LLUUID sculpt_id; - U8 sculpt_type = 0; - if (isSculpted()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - sculpt_id = sculpt_params->getSculptTexture(); - sculpt_type = sculpt_params->getSculptType(); + LLUUID sculpt_id; + U8 sculpt_type = 0; + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + sculpt_id = sculpt_params->getSculptTexture(); + sculpt_type = sculpt_params->getSculptType(); LL_DEBUGS("ObjectUpdate") << "uuid " << mID << " set sculpt_id " << sculpt_id << LL_ENDL; dumpStack("ObjectUpdateStack"); - } - - if (!dp) - { - if (update_type == OUT_FULL) - { - //////////////////////////////// - // - // Unpack texture animation data - // - // - - if (mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureAnim)) - { - if (!mTextureAnimp) - { - mTextureAnimp = new LLViewerTextureAnim(this); - } - else - { - if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) - { - mTextureAnimp->reset(); - } - } - mTexAnimMode = 0; - - mTextureAnimp->unpackTAMessage(mesgsys, block_num); - } - else - { - if (mTextureAnimp) - { - delete mTextureAnimp; - mTextureAnimp = NULL; - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - mTexAnimMode = 0; - } - } - - // Unpack volume data - LLVolumeParams volume_params; - LLVolumeMessage::unpackVolumeParams(&volume_params, mesgsys, _PREHASH_ObjectData, block_num); - volume_params.setSculptID(sculpt_id, sculpt_type); - - if (setVolume(volume_params, 0)) - { - markForUpdate(TRUE); - } - } - - // Sigh, this needs to be done AFTER the volume is set as well, otherwise bad stuff happens... - //////////////////////////// - // - // Unpack texture entry data - // - - S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, (S32) block_num); - if (result & teDirtyBits) - { - updateTEData(); - } - if (result & TEM_CHANGE_MEDIA) - { - retval |= MEDIA_FLAGS_CHANGED; - } - } - else - { - if (update_type != OUT_TERSE_IMPROVED) - { - LLVolumeParams volume_params; - BOOL res = LLVolumeMessage::unpackVolumeParams(&volume_params, *dp); - if (!res) - { - LL_WARNS() << "Bogus volume parameters in object " << getID() << LL_ENDL; - LL_WARNS() << getRegion()->getOriginGlobal() << LL_ENDL; - } - - volume_params.setSculptID(sculpt_id, sculpt_type); - - if (setVolume(volume_params, 0)) - { - markForUpdate(TRUE); - } - S32 res2 = unpackTEMessage(*dp); - if (TEM_INVALID == res2) - { - // There's something bogus in the data that we're unpacking. - dp->dumpBufferToLog(); - LL_WARNS() << "Flushing cache files" << LL_ENDL; - - if(LLVOCache::instanceExists() && getRegion()) - { - LLVOCache::getInstance()->removeEntry(getRegion()->getHandle()) ; - } - - LL_WARNS() << "Bogus TE data in " << getID() << LL_ENDL; - } - else - { - if (res2 & teDirtyBits) - { - updateTEData(); - } - if (res2 & TEM_CHANGE_MEDIA) - { - retval |= MEDIA_FLAGS_CHANGED; - } - } - - U32 value = dp->getPassFlags(); - - if (value & 0x40) - { - if (!mTextureAnimp) - { - mTextureAnimp = new LLViewerTextureAnim(this); - } - else - { - if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) - { - mTextureAnimp->reset(); - } - } - mTexAnimMode = 0; - mTextureAnimp->unpackTAMessage(*dp); - } - else if (mTextureAnimp) - { - delete mTextureAnimp; - mTextureAnimp = NULL; - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - mTexAnimMode = 0; - } - - if (value & 0x400) - { //particle system (new) - unpackParticleSource(*dp, mOwnerID, false); - } - } - else - { - S32 texture_length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureEntry); - if (texture_length) - { - U8 tdpbuffer[1024]; - LLDataPackerBinaryBuffer tdp(tdpbuffer, 1024); - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num, 1024); - S32 result = unpackTEMessage(tdp); - if (result & teDirtyBits) - { - updateTEData(); - } - if (result & TEM_CHANGE_MEDIA) - { - retval |= MEDIA_FLAGS_CHANGED; - } - } - } - } - if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) - { - // If only the media URL changed, and it isn't a media version URL, - // ignore it - if ( ! ( retval & (MEDIA_URL_ADDED | MEDIA_URL_UPDATED) && - mMedia && ! mMedia->mMediaURL.empty() && - ! LLTextureEntry::isMediaVersionString(mMedia->mMediaURL) ) ) - { - // If the media changed at all, request new media data - LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " << + } + + if (!dp) + { + if (update_type == OUT_FULL) + { + //////////////////////////////// + // + // Unpack texture animation data + // + // + + if (mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureAnim)) + { + if (!mTextureAnimp) + { + mTextureAnimp = new LLViewerTextureAnim(this); + } + else + { + if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) + { + mTextureAnimp->reset(); + } + } + mTexAnimMode = 0; + + mTextureAnimp->unpackTAMessage(mesgsys, block_num); + } + else + { + if (mTextureAnimp) + { + delete mTextureAnimp; + mTextureAnimp = NULL; + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; + } + } + + // Unpack volume data + LLVolumeParams volume_params; + LLVolumeMessage::unpackVolumeParams(&volume_params, mesgsys, _PREHASH_ObjectData, block_num); + volume_params.setSculptID(sculpt_id, sculpt_type); + + if (setVolume(volume_params, 0)) + { + markForUpdate(TRUE); + } + } + + // Sigh, this needs to be done AFTER the volume is set as well, otherwise bad stuff happens... + //////////////////////////// + // + // Unpack texture entry data + // + + S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, (S32) block_num); + if (result & teDirtyBits) + { + updateTEData(); + } + if (result & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } + } + else + { + if (update_type != OUT_TERSE_IMPROVED) + { + LLVolumeParams volume_params; + BOOL res = LLVolumeMessage::unpackVolumeParams(&volume_params, *dp); + if (!res) + { + LL_WARNS() << "Bogus volume parameters in object " << getID() << LL_ENDL; + LL_WARNS() << getRegion()->getOriginGlobal() << LL_ENDL; + } + + volume_params.setSculptID(sculpt_id, sculpt_type); + + if (setVolume(volume_params, 0)) + { + markForUpdate(TRUE); + } + S32 res2 = unpackTEMessage(*dp); + if (TEM_INVALID == res2) + { + // There's something bogus in the data that we're unpacking. + dp->dumpBufferToLog(); + LL_WARNS() << "Flushing cache files" << LL_ENDL; + + if(LLVOCache::instanceExists() && getRegion()) + { + LLVOCache::getInstance()->removeEntry(getRegion()->getHandle()) ; + } + + LL_WARNS() << "Bogus TE data in " << getID() << LL_ENDL; + } + else + { + if (res2 & teDirtyBits) + { + updateTEData(); + } + if (res2 & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } + } + + U32 value = dp->getPassFlags(); + + if (value & 0x40) + { + if (!mTextureAnimp) + { + mTextureAnimp = new LLViewerTextureAnim(this); + } + else + { + if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) + { + mTextureAnimp->reset(); + } + } + mTexAnimMode = 0; + mTextureAnimp->unpackTAMessage(*dp); + } + else if (mTextureAnimp) + { + delete mTextureAnimp; + mTextureAnimp = NULL; + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; + } + + if (value & 0x400) + { //particle system (new) + unpackParticleSource(*dp, mOwnerID, false); + } + } + else + { + S32 texture_length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureEntry); + if (texture_length) + { + U8 tdpbuffer[1024]; + LLDataPackerBinaryBuffer tdp(tdpbuffer, 1024); + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num, 1024); + S32 result = unpackTEMessage(tdp); + if (result & teDirtyBits) + { + updateTEData(); + } + if (result & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } + } + } + } + if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) + { + // If only the media URL changed, and it isn't a media version URL, + // ignore it + if ( ! ( retval & (MEDIA_URL_ADDED | MEDIA_URL_UPDATED) && + mMedia && ! mMedia->mMediaURL.empty() && + ! LLTextureEntry::isMediaVersionString(mMedia->mMediaURL) ) ) + { + // If the media changed at all, request new media data + LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " << ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL; - requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED); - } + requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED); + } else { LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " << ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL; } - } - // ...and clean up any media impls - cleanUpMediaImpls(); + } + // ...and clean up any media impls + cleanUpMediaImpls(); - return retval; + return retval; } void LLVOVolume::animateTextures() { - if (!mDead) - { - F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f; - S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot); - - if (result) - { - if (!mTexAnimMode) - { - mFaceMappingChanged = TRUE; - gPipeline.markTextured(mDrawable); - } - mTexAnimMode = result | mTextureAnimp->mMode; - - S32 start=0, end=mDrawable->getNumFaces()-1; - if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end) - { - start = end = mTextureAnimp->mFace; - } - - for (S32 i = start; i <= end; i++) - { - LLFace* facep = mDrawable->getFace(i); - if (!facep) continue; - if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; - - const LLTextureEntry* te = facep->getTextureEntry(); - - if (!te) - { - continue; - } - - if (!(result & LLViewerTextureAnim::ROTATE)) - { - te->getRotation(&rot); - } - if (!(result & LLViewerTextureAnim::TRANSLATE)) - { - te->getOffset(&off_s,&off_t); - } - if (!(result & LLViewerTextureAnim::SCALE)) - { - te->getScale(&scale_s, &scale_t); - } - - if (!facep->mTextureMatrix) - { - facep->mTextureMatrix = new LLMatrix4(); - } - - LLMatrix4& tex_mat = *facep->mTextureMatrix; - tex_mat.setIdentity(); - LLVector3 trans ; - - trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f)); - tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); - - LLVector3 scale(scale_s, scale_t, 1.f); - LLQuaternion quat; - quat.setQuat(rot, 0, 0, -1.f); - - tex_mat.rotate(quat); - - LLMatrix4 mat; - mat.initAll(scale, LLQuaternion(), LLVector3()); - tex_mat *= mat; - - tex_mat.translate(trans); - } - } - else - { - if (mTexAnimMode && mTextureAnimp->mRate == 0) - { - U8 start, count; - - if (mTextureAnimp->mFace == -1) - { - start = 0; - count = getNumTEs(); - } - else - { - start = (U8) mTextureAnimp->mFace; - count = 1; - } - - for (S32 i = start; i < start + count; i++) - { - if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE) - { - setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT); - } - if (mTexAnimMode & LLViewerTextureAnim::SCALE) - { - setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT); - } - if (mTexAnimMode & LLViewerTextureAnim::ROTATE) - { - setTERotation(i, mTextureAnimp->mRot); - } - } - - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - mTexAnimMode = 0; - } - } - } -} - -void LLVOVolume::updateTextures() -{ - const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds - if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) - { - updateTextureVirtualSize(); - - if (mDrawable.notNull() && !isVisible() && !mDrawable->isActive()) - { //delete vertex buffer to free up some VRAM - LLSpatialGroup* group = mDrawable->getSpatialGroup(); - if (group && (group->mVertexBuffer.notNull() || !group->mBufferMap.empty() || !group->mDrawMap.empty())) - { - group->destroyGL(true); - - //flag the group as having changed geometry so it gets a rebuild next time - //it becomes visible - group->setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); - } - } + if (!mDead) + { + F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f; + S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot); + + if (result) + { + if (!mTexAnimMode) + { + mFaceMappingChanged = TRUE; + gPipeline.markTextured(mDrawable); + } + mTexAnimMode = result | mTextureAnimp->mMode; + + S32 start=0, end=mDrawable->getNumFaces()-1; + if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end) + { + start = end = mTextureAnimp->mFace; + } + + for (S32 i = start; i <= end; i++) + { + LLFace* facep = mDrawable->getFace(i); + if (!facep) continue; + if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; + const LLTextureEntry* te = facep->getTextureEntry(); + + if (!te) + { + continue; + } + + if (!(result & LLViewerTextureAnim::ROTATE)) + { + te->getRotation(&rot); + } + if (!(result & LLViewerTextureAnim::TRANSLATE)) + { + te->getOffset(&off_s,&off_t); + } + if (!(result & LLViewerTextureAnim::SCALE)) + { + te->getScale(&scale_s, &scale_t); + } - } -} + if (!facep->mTextureMatrix) + { + facep->mTextureMatrix = new LLMatrix4(); + } -BOOL LLVOVolume::isVisible() const -{ - if(mDrawable.notNull() && mDrawable->isVisible()) - { - return TRUE ; - } + LLMatrix4& tex_mat = *facep->mTextureMatrix; + tex_mat.setIdentity(); + LLVector3 trans ; - if(isAttachment()) - { - LLViewerObject* objp = (LLViewerObject*)getParent() ; - while(objp && !objp->isAvatar()) - { - objp = (LLViewerObject*)objp->getParent() ; - } + trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f)); + tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); - return objp && objp->mDrawable.notNull() && objp->mDrawable->isVisible() ; - } + LLVector3 scale(scale_s, scale_t, 1.f); + LLQuaternion quat; + quat.setQuat(rot, 0, 0, -1.f); + + tex_mat.rotate(quat); - return FALSE ; -} + LLMatrix4 mat; + mat.initAll(scale, LLQuaternion(), LLVector3()); + tex_mat *= mat; + + tex_mat.translate(trans); + } + } + else + { + if (mTexAnimMode && mTextureAnimp->mRate == 0) + { + U8 start, count; -void LLVOVolume::updateTextureVirtualSize(bool forced) -{ - LL_RECORD_BLOCK_TIME(FTM_VOLUME_TEXTURES); - // Update the pixel area of all faces - - if(!forced) - { - if(!isVisible()) - { //don't load textures for non-visible faces - const S32 num_faces = mDrawable->getNumFaces(); - for (S32 i = 0; i < num_faces; i++) - { - LLFace* face = mDrawable->getFace(i); - if (face) - { - face->setPixelArea(0.f); - face->setVirtualSize(0.f); - } - } - - return ; - } - - if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) - { - return; - } - } - - static LLCachedControl dont_load_textures(gSavedSettings,"TextureDisable", false); - - if (dont_load_textures || LLAppViewer::getTextureFetch()->mDebugPause) // || !mDrawable->isVisible()) - { - return; - } - - mTextureUpdateTimer.reset(); - - F32 old_area = mPixelArea; - mPixelArea = 0.f; - - const S32 num_faces = mDrawable->getNumFaces(); - F32 min_vsize=999999999.f, max_vsize=0.f; - LLViewerCamera* camera = LLViewerCamera::getInstance(); - for (S32 i = 0; i < num_faces; i++) - { - LLFace* face = mDrawable->getFace(i); - if (!face) continue; - const LLTextureEntry *te = face->getTextureEntry(); - LLViewerTexture *imagep = face->getTexture(); - if (!imagep || !te || - face->mExtents[0].equals3(face->mExtents[1])) - { - continue; - } - - F32 vsize; - F32 old_size = face->getVirtualSize(); - - if (isHUDAttachment()) - { - F32 area = (F32) camera->getScreenPixelArea(); - vsize = area; - imagep->setBoostLevel(LLGLTexture::BOOST_HUD); - face->setPixelArea(area); // treat as full screen - face->setVirtualSize(vsize); - } - else - { - vsize = face->getTextureVirtualSize(); - } - - mPixelArea = llmax(mPixelArea, face->getPixelArea()); - - if (face->mTextureMatrix != NULL) - { - if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || - (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE); - } - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) - { - if (vsize < min_vsize) min_vsize = vsize; - if (vsize > max_vsize) max_vsize = vsize; - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) - { - LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ; - if(img) - { - F32 pri = img->getDecodePriority(); - pri = llmax(pri, 0.0f); - if (pri < min_vsize) min_vsize = pri; - if (pri > max_vsize) max_vsize = pri; - } - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) - { - F32 pri = mPixelArea; - if (pri < min_vsize) min_vsize = pri; - if (pri > max_vsize) max_vsize = pri; - } - } - - if (isSculpted()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID id = sculpt_params->getSculptTexture(); - - updateSculptTexture(); - - - - if (mSculptTexture.notNull()) - { - mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), - (S32)LLGLTexture::BOOST_SCULPTED)); - mSculptTexture->setForSculpt() ; - - if(!mSculptTexture->isCachedRawImageReady()) - { - S32 lod = llmin(mLOD, 3); - F32 lodf = ((F32)(lod + 1.0f)/4.f); - F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ; - mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE); - - //if the sculpty very close to the view point, load first - { - LLVector3 lookAt = getPositionAgent() - camera->getOrigin(); - F32 dist = lookAt.normVec() ; - F32 cos_angle_to_view_dir = lookAt * camera->getXAxis() ; - mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ; - } - } - - S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture - S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ; - - if (texture_discard >= 0 && //texture has some data available - (texture_discard < current_discard || //texture has more data than last rebuild - current_discard < 0)) //no previous rebuild - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); - mSculptChanged = TRUE; - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) - { - setDebugText(llformat("T%d C%d V%d\n%dx%d", - texture_discard, current_discard, getVolume()->getSculptLevel(), - mSculptTexture->getHeight(), mSculptTexture->getWidth())); - } - } - - } - - if (getLightTextureID().notNull()) - { - LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - LLUUID id = params->getLightTexture(); - mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM); - if (mLightTexture.notNull()) - { - F32 rad = getLightRadius(); - mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(), - LLVector3(rad,rad,rad), - *camera)); - } - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) - { - setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) - { - setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) - { - setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); - } - - if (mPixelArea == 0) - { //flexi phasing issues make this happen - mPixelArea = old_area; - } -} + if (mTextureAnimp->mFace == -1) + { + start = 0; + count = getNumTEs(); + } + else + { + start = (U8) mTextureAnimp->mFace; + count = 1; + } -BOOL LLVOVolume::isActive() const -{ - return !mStatic; -} + for (S32 i = start; i < start + count; i++) + { + if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE) + { + setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT); + } + if (mTexAnimMode & LLViewerTextureAnim::SCALE) + { + setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT); + } + if (mTexAnimMode & LLViewerTextureAnim::ROTATE) + { + setTERotation(i, mTextureAnimp->mRot); + } + } -BOOL LLVOVolume::setMaterial(const U8 material) -{ - BOOL res = LLViewerObject::setMaterial(material); - - return res; + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; + } + } + } } -void LLVOVolume::setTexture(const S32 face) +void LLVOVolume::updateTextures() { - llassert(face < getNumTEs()); - gGL.getTexUnit(0)->bind(getTEImage(face)); -} + const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds + if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) + { + updateTextureVirtualSize(); -void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped) -{ - if (scale != getScale()) - { - // store local radius - LLViewerObject::setScale(scale); + if (mDrawable.notNull() && !isVisible() && !mDrawable->isActive()) + { //delete vertex buffer to free up some VRAM + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group && (group->mVertexBuffer.notNull() || !group->mBufferMap.empty() || !group->mDrawMap.empty())) + { + group->destroyGL(true); - if (mVolumeImpl) - { - mVolumeImpl->onSetScale(scale, damped); - } - - updateRadius(); + //flag the group as having changed geometry so it gets a rebuild next time + //it becomes visible + group->setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); + } + } - //since drawable transforms do not include scale, changing volume scale - //requires an immediate rebuild of volume verts. - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION, TRUE); - } -} -LLFace* LLVOVolume::addFace(S32 f) -{ - const LLTextureEntry* te = getTE(f); - LLViewerTexture* imagep = getTEImage(f); - if (te->getMaterialParams().notNull()) - { - LLViewerTexture* normalp = getTENormalMap(f); - LLViewerTexture* specularp = getTESpecularMap(f); - return mDrawable->addFace(te, imagep, normalp, specularp); - } - return mDrawable->addFace(te, imagep); + } } -LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) +BOOL LLVOVolume::isVisible() const { - pipeline->allocDrawable(this); - - mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); - - S32 max_tes_to_set = getNumTEs(); - for (S32 i = 0; i < max_tes_to_set; i++) - { - addFace(i); - } - mNumFaces = max_tes_to_set; - - if (isAttachment()) - { - mDrawable->makeActive(); - } + if(mDrawable.notNull() && mDrawable->isVisible()) + { + return TRUE ; + } - if (getIsLight()) - { - // Add it to the pipeline mLightSet - gPipeline.setLight(mDrawable, TRUE); - } - - updateRadius(); - bool force_update = true; // avoid non-alpha mDistance update being optimized away - mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update); + if(isAttachment()) + { + LLViewerObject* objp = (LLViewerObject*)getParent() ; + while(objp && !objp->isAvatar()) + { + objp = (LLViewerObject*)objp->getParent() ; + } - return mDrawable; -} + return objp && objp->mDrawable.notNull() && objp->mDrawable->isVisible() ; + } -BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bool unique_volume) -{ - LLVolumeParams volume_params = params_in; - - S32 last_lod = mVolumep.notNull() ? LLVolumeLODGroup::getVolumeDetailFromScale(mVolumep->getDetail()) : -1; - S32 lod = mLOD; - - BOOL is404 = FALSE; - - if (isSculpted()) - { - // if it's a mesh - if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - { //meshes might not have all LODs, get the force detail to best existing LOD - if (NO_LOD != lod) - { - lod = gMeshRepo.getActualMeshLOD(volume_params, lod); - if (lod == -1) - { - is404 = TRUE; - lod = 0; - } - } - } - } - - // Check if we need to change implementations - bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE); - if (is_flexible) - { - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, false); - if (!mVolumeImpl) - { - LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); - mVolumeImpl = new LLVolumeImplFlexible(this, data); - } - } - else - { - // Mark the parameter not in use - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, false); - if (mVolumeImpl) - { - delete mVolumeImpl; - mVolumeImpl = NULL; - if (mDrawable.notNull()) - { - // Undo the damage we did to this matrix - mDrawable->updateXform(FALSE); - } - } - } - - if (is404) - { - setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI)); - //render prim proxy when mesh loading attempts give up - volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE); - - } - - if ((LLPrimitive::setVolume(volume_params, lod, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged) - { - mFaceMappingChanged = TRUE; - - if (mVolumeImpl) - { - mVolumeImpl->onSetVolume(volume_params, mLOD); - } - - updateSculptTexture(); - - if (isSculpted()) - { - updateSculptTexture(); - // if it's a mesh - if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - { - if (!getVolume()->isMeshAssetLoaded()) - { - //load request not yet issued, request pipeline load this mesh - LLUUID asset_id = volume_params.getSculptID(); - S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod, last_lod); - if (available_lod != lod) - { - LLPrimitive::setVolume(volume_params, available_lod); - } - } - - } - else // otherwise is sculptie - { - if (mSculptTexture.notNull()) - { - sculpt(); - } - } - } - - static LLCachedControl use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false); - - bool cache_in_vram = use_transform_feedback && gTransformPositionProgram.mProgramObject && - (!mVolumeImpl || !mVolumeImpl->isVolumeUnique()); - - if (cache_in_vram) - { //this volume might be used as source data for a transform object, put it in vram - LLVolume* volume = getVolume(); - for (S32 i = 0; i < volume->getNumFaces(); ++i) - { - const LLVolumeFace& face = volume->getVolumeFace(i); - if (face.mVertexBuffer.notNull()) - { //already cached - break; - } - volume->genTangents(i); - LLFace::cacheFaceInVRAM(face); - } - } - - return TRUE; - } - else if (NO_LOD == lod) - { - LLSculptIDSize::instance().resetSizeSum(volume_params.getSculptID()); - } - - return FALSE; + return FALSE ; } -void LLVOVolume::updateSculptTexture() +void LLVOVolume::updateTextureVirtualSize(bool forced) { - LLPointer old_sculpt = mSculptTexture; - - if (isSculpted() && !isMesh()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID id = sculpt_params->getSculptTexture(); - if (id.notNull()) - { - mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - } - } - else - { - mSculptTexture = NULL; - } - - if (mSculptTexture != old_sculpt) - { - if (old_sculpt.notNull()) - { - old_sculpt->removeVolume(LLRender::SCULPT_TEX, this); - } - if (mSculptTexture.notNull()) - { - mSculptTexture->addVolume(LLRender::SCULPT_TEX, this); - } - } - -} + LL_RECORD_BLOCK_TIME(FTM_VOLUME_TEXTURES); + // Update the pixel area of all faces -void LLVOVolume::updateVisualComplexity() -{ - LLVOAvatar* avatar = getAvatarAncestor(); - if (avatar) + if(!forced) { - avatar->updateVisualComplexity(); + if(!isVisible()) + { //don't load textures for non-visible faces + const S32 num_faces = mDrawable->getNumFaces(); + for (S32 i = 0; i < num_faces; i++) + { + LLFace* face = mDrawable->getFace(i); + if (face) + { + face->setPixelArea(0.f); + face->setVirtualSize(0.f); + } + } + + return ; + } + + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) + { + return; + } } - LLVOAvatar* rigged_avatar = getAvatar(); - if(rigged_avatar && (rigged_avatar != avatar)) + + static LLCachedControl dont_load_textures(gSavedSettings,"TextureDisable", false); + + if (dont_load_textures || LLAppViewer::getTextureFetch()->mDebugPause) // || !mDrawable->isVisible()) { - rigged_avatar->updateVisualComplexity(); + return; } -} -void LLVOVolume::notifyMeshLoaded() -{ - mSculptChanged = TRUE; - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); + mTextureUpdateTimer.reset(); + + F32 old_area = mPixelArea; + mPixelArea = 0.f; - if (getAvatar() && !isAnimatedObject()) + const S32 num_faces = mDrawable->getNumFaces(); + F32 min_vsize=999999999.f, max_vsize=0.f; + LLViewerCamera* camera = LLViewerCamera::getInstance(); + for (S32 i = 0; i < num_faces; i++) { - getAvatar()->addAttachmentOverridesForObject(this); - } - if (getControlAvatar() && isAnimatedObject()) - { - getControlAvatar()->addAttachmentOverridesForObject(this); - } - updateVisualComplexity(); -} - -// sculpt replaces generate() for sculpted surfaces -void LLVOVolume::sculpt() -{ - if (mSculptTexture.notNull()) - { - U16 sculpt_height = 0; - U16 sculpt_width = 0; - S8 sculpt_components = 0; - const U8* sculpt_data = NULL; - - S32 discard_level = mSculptTexture->getCachedRawImageLevel() ; - LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ; - - S32 max_discard = mSculptTexture->getMaxDiscardLevel(); - if (discard_level > max_discard) - { - discard_level = max_discard; // clamp to the best we can do - } - if(discard_level > MAX_DISCARD_LEVEL) - { - return; //we think data is not ready yet. - } - - S32 current_discard = getVolume()->getSculptLevel() ; - if(current_discard < -2) - { - static S32 low_sculpty_discard_warning_count = 1; - S32 exponent = llmax(1, llfloor( log10((F64) low_sculpty_discard_warning_count) )); - S32 interval = pow(10.0, exponent); - if ( low_sculpty_discard_warning_count < 10 || - (low_sculpty_discard_warning_count % interval) == 0) - { // Log first 10 time, then decreasing intervals afterwards otherwise this can flood the logs - LL_WARNS() << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() - << " at " << current_discard - << " is less than -2." - << " Hit this " << low_sculpty_discard_warning_count << " times" - << LL_ENDL; - } - low_sculpty_discard_warning_count++; - - // corrupted volume... don't update the sculpty - return; - } - else if (current_discard > MAX_DISCARD_LEVEL) - { - static S32 high_sculpty_discard_warning_count = 1; - S32 exponent = llmax(1, llfloor( log10((F64) high_sculpty_discard_warning_count) )); - S32 interval = pow(10.0, exponent); - if ( high_sculpty_discard_warning_count < 10 || - (high_sculpty_discard_warning_count % interval) == 0) - { // Log first 10 time, then decreasing intervals afterwards otherwise this can flood the logs - LL_WARNS() << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() - << " at " << current_discard - << " is more than than allowed max of " << MAX_DISCARD_LEVEL - << ". Hit this " << high_sculpty_discard_warning_count << " times" - << LL_ENDL; - } - high_sculpty_discard_warning_count++; - - // corrupted volume... don't update the sculpty - return; - } - - if (current_discard == discard_level) // no work to do here - return; - - if(!raw_image) - { - llassert(discard_level < 0) ; - - sculpt_width = 0; - sculpt_height = 0; - sculpt_data = NULL ; - - if(LLViewerTextureManager::sTesterp) - { - LLViewerTextureManager::sTesterp->updateGrayTextureBinding(); - } - } - else - { - sculpt_height = raw_image->getHeight(); - sculpt_width = raw_image->getWidth(); - sculpt_components = raw_image->getComponents(); - - sculpt_data = raw_image->getData(); - - if(LLViewerTextureManager::sTesterp) - { - mSculptTexture->updateBindStatsForTester() ; - } - } - getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level, mSculptTexture->isMissingAsset()); - - //notify rebuild any other VOVolumes that reference this sculpty volume - for (S32 i = 0; i < mSculptTexture->getNumVolumes(LLRender::SCULPT_TEX); ++i) - { - LLVOVolume* volume = (*(mSculptTexture->getVolumeList(LLRender::SCULPT_TEX)))[i]; - if (volume != this && volume->getVolume() == getVolume()) - { - gPipeline.markRebuild(volume->mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE); - } - } - } -} - -S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius, F32 lod_factor) -{ - S32 cur_detail; - if (LLPipeline::sDynamicLOD) - { - // We've got LOD in the profile, and in the twist. Use radius. - F32 tan_angle = (lod_factor*radius)/distance; - cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f)); - } - else - { - cur_detail = llclamp((S32) (sqrtf(radius)*lod_factor*4.f), 0, 3); - } - return cur_detail; -} - -std::string get_debug_object_lod_text(LLVOVolume *rootp) -{ - std::string cam_dist_string = ""; - cam_dist_string += LLStringOps::getReadableNumber(rootp->mLODDistance) + " "; - std::string lod_string = llformat("%d",rootp->getLOD()); - F32 lod_radius = rootp->mLODRadius; - S32 cam_dist_count = 0; - LLViewerObject::const_child_list_t& child_list = rootp->getChildren(); - for (LLViewerObject::const_child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); ++iter) - { - LLViewerObject *childp = *iter; - LLVOVolume *volp = dynamic_cast(childp); - if (volp) + LLFace* face = mDrawable->getFace(i); + if (!face) continue; + const LLTextureEntry *te = face->getTextureEntry(); + LLViewerTexture *imagep = face->getTexture(); + if (!imagep || !te || + face->mExtents[0].equals3(face->mExtents[1])) { - lod_string += llformat("%d",volp->getLOD()); - if (volp->isRiggedMesh()) - { - // Rigged/animatable mesh. This is computed from the - // avatar dynamic box, so value from any vol will be - // the same. - lod_radius = volp->mLODRadius; - } - if (volp->mDrawable) - { - if (cam_dist_count < 4) - { - cam_dist_string += LLStringOps::getReadableNumber(volp->mLODDistance) + " "; - cam_dist_count++; - } - } + continue; } - } - std::string result = llformat("lod_radius %s dists %s lods %s", - LLStringOps::getReadableNumber(lod_radius).c_str(), - cam_dist_string.c_str(), - lod_string.c_str()); - return result; -} - -BOOL LLVOVolume::calcLOD() -{ - if (mDrawable.isNull()) - { - return FALSE; - } - - S32 cur_detail = 0; - - F32 radius; - F32 distance; - F32 lod_factor = LLVOVolume::sLODFactor; - - if (mDrawable->isState(LLDrawable::RIGGED)) - { - LLVOAvatar* avatar = getAvatar(); - - // Not sure how this can really happen, but alas it does. Better exit here than crashing. - if( !avatar || !avatar->mDrawable ) - { - return FALSE; - } - - distance = avatar->mDrawable->mDistanceWRTCamera; - + + F32 vsize; + F32 old_size = face->getVirtualSize(); - if (avatar->isControlAvatar()) + if (isHUDAttachment()) { - // MAINT-7926 Handle volumes in an animated object as a special case - const LLVector3* box = avatar->getLastAnimExtents(); - LLVector3 diag = box[1] - box[0]; - radius = diag.magVec() * 0.5f; - LL_DEBUGS("DynamicBox") << avatar->getFullname() << " diag " << diag << " radius " << radius << LL_ENDL; + F32 area = (F32) camera->getScreenPixelArea(); + vsize = area; + imagep->setBoostLevel(LLGLTexture::BOOST_HUD); + face->setPixelArea(area); // treat as full screen + face->setVirtualSize(vsize); } else { - // Volume in a rigged mesh attached to a regular avatar. - // Note this isn't really a radius, so distance calcs are off by factor of 2 - //radius = avatar->getBinRadius(); - // SL-937: add dynamic box handling for rigged mesh on regular avatars. - const LLVector3* box = avatar->getLastAnimExtents(); - LLVector3 diag = box[1] - box[0]; - radius = diag.magVec(); // preserve old BinRadius behavior - 2x off - LL_DEBUGS("DynamicBox") << avatar->getFullname() << " diag " << diag << " radius " << radius << LL_ENDL; + vsize = face->getTextureVirtualSize(); } - if (distance <= 0.f || radius <= 0.f) + + mPixelArea = llmax(mPixelArea, face->getPixelArea()); + + if (face->mTextureMatrix != NULL) { - LL_DEBUGS("DynamicBox","CalcLOD") << "avatar distance/radius uninitialized, skipping" << LL_ENDL; - return FALSE; + if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || + (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE); + } } - } - else - { - distance = mDrawable->mDistanceWRTCamera; - radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); - if (distance <= 0.f || radius <= 0.f) + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { - LL_DEBUGS("DynamicBox","CalcLOD") << "non-avatar distance/radius uninitialized, skipping" << LL_ENDL; - return FALSE; + if (vsize < min_vsize) min_vsize = vsize; + if (vsize > max_vsize) max_vsize = vsize; } - } - - //hold onto unmodified distance for debugging - //F32 debug_distance = distance; - - mLODDistance = distance; - mLODRadius = radius; - - if (gSavedSettings.getBOOL("DebugObjectLODs")) - { - if (getAvatar() && isRootEdit()) + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) { - std::string debug_object_text = get_debug_object_lod_text(this); - setDebugText(debug_object_text); + LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ; + if(img) + { + F32 pri = img->getDecodePriority(); + pri = llmax(pri, 0.0f); + if (pri < min_vsize) min_vsize = pri; + if (pri > max_vsize) max_vsize = pri; + } } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) + { + F32 pri = mPixelArea; + if (pri < min_vsize) min_vsize = pri; + if (pri > max_vsize) max_vsize = pri; + } } + + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID id = sculpt_params->getSculptTexture(); + + updateSculptTexture(); + + - distance *= sDistanceFactor; + if (mSculptTexture.notNull()) + { + mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), + (S32)LLGLTexture::BOOST_SCULPTED)); + mSculptTexture->setForSculpt() ; + + if(!mSculptTexture->isCachedRawImageReady()) + { + S32 lod = llmin(mLOD, 3); + F32 lodf = ((F32)(lod + 1.0f)/4.f); + F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ; + mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE); + + //if the sculpty very close to the view point, load first + { + LLVector3 lookAt = getPositionAgent() - camera->getOrigin(); + F32 dist = lookAt.normVec() ; + F32 cos_angle_to_view_dir = lookAt * camera->getXAxis() ; + mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ; + } + } + + S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture + S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ; - F32 rampDist = LLVOVolume::sLODFactor * 2; - - if (distance < rampDist) - { - // Boost LOD when you're REALLY close - distance *= 1.0f/rampDist; - distance *= distance; - distance *= rampDist; - } - - - distance *= F_PI/3.f; - - static LLCachedControl ignore_fov_zoom(gSavedSettings,"IgnoreFOVZoomForLODs"); - if(!ignore_fov_zoom) - { - lod_factor *= DEFAULT_FIELD_OF_VIEW / LLViewerCamera::getInstance()->getDefaultFOV(); - } + if (texture_discard >= 0 && //texture has some data available + (texture_discard < current_discard || //texture has more data than last rebuild + current_discard < 0)) //no previous rebuild + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + mSculptChanged = TRUE; + } - mLODAdjustedDistance = distance; + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) + { + setDebugText(llformat("T%d C%d V%d\n%dx%d", + texture_discard, current_discard, getVolume()->getSculptLevel(), + mSculptTexture->getHeight(), mSculptTexture->getWidth())); + } + } - if (isHUDAttachment()) + } + + if (getLightTextureID().notNull()) { - // HUDs always show at highest detail - cur_detail = 3; + LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + LLUUID id = params->getLightTexture(); + mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM); + if (mLightTexture.notNull()) + { + F32 rad = getLightRadius(); + mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(), + LLVector3(rad,rad,rad), + *camera)); + } } - else + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { - cur_detail = computeLODDetail(ll_round(distance, 0.01f), ll_round(radius, 0.01f), lod_factor); + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TRIANGLE_COUNT) && mDrawable->getFace(0)) + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) { - if (isRootEdit()) - { - S32 total_tris = recursiveGetTriangleCount(); - S32 est_max_tris = recursiveGetEstTrianglesMax(); - setDebugText(llformat("TRIS SHOWN %d EST %d", total_tris, est_max_tris)); - } + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) + { + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && - mDrawable->getFace(0)) - { - // This is a debug display for LODs. Please don't put the texture index here. - setDebugText(llformat("%d", cur_detail)); - } - - if (cur_detail != mLOD) - { - LL_DEBUGS("DynamicBox","CalcLOD") << "new LOD " << cur_detail << " change from " << mLOD - << " distance " << distance << " radius " << radius << " rampDist " << rampDist - << " drawable rigged? " << (mDrawable ? (S32) mDrawable->isState(LLDrawable::RIGGED) : (S32) -1) - << " mRiggedVolume " << (void*)getRiggedVolume() - << " distanceWRTCamera " << (mDrawable ? mDrawable->mDistanceWRTCamera : -1.f) - << LL_ENDL; - - mAppAngle = ll_round((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); - mLOD = cur_detail; - - return TRUE; - } - return FALSE; + if (mPixelArea == 0) + { //flexi phasing issues make this happen + mPixelArea = old_area; + } } -BOOL LLVOVolume::updateLOD() +BOOL LLVOVolume::isActive() const { - if (mDrawable.isNull()) - { - return FALSE; - } - - BOOL lod_changed = FALSE; - - if (!LLSculptIDSize::instance().isUnloaded(getVolume()->getParams().getSculptID())) - { - lod_changed = calcLOD(); - } - else - { - return FALSE; - } - - if (lod_changed) - { - if (debugLoggingEnabled("AnimatedObjectsLinkset")) - { - if (isAnimatedObject() && isRiggedMesh()) - { - std::string vobj_name = llformat("Vol%p", this); - F32 est_tris = getEstTrianglesMax(); - LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " updateLOD to " << getLOD() << ", tris " << est_tris << LL_ENDL; - } - } - - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); - mLODChanged = TRUE; - } - else - { - F32 new_radius = getBinRadius(); - F32 old_radius = mDrawable->getBinRadius(); - if (new_radius < old_radius * 0.9f || new_radius > old_radius*1.1f) - { - gPipeline.markPartitionMove(mDrawable); - } - } - - lod_changed = lod_changed || LLViewerObject::updateLOD(); - - return lod_changed; + return !mStatic; } -BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp) +BOOL LLVOVolume::setMaterial(const U8 material) { - if (!LLViewerObject::setDrawableParent(parentp)) - { - // no change in drawable parent - return FALSE; - } - - if (!mDrawable->isRoot()) - { - // rebuild vertices in parent relative space - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - - if (mDrawable->isActive() && !parentp->isActive()) - { - parentp->makeActive(); - } - else if (mDrawable->isStatic() && parentp->isActive()) - { - mDrawable->makeActive(); - } - } - - return TRUE; + BOOL res = LLViewerObject::setMaterial(material); + + return res; } -void LLVOVolume::updateFaceFlags() +void LLVOVolume::setTexture(const S32 face) { - // There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces() - for (S32 i = 0; i < getVolume()->getNumFaces() && i < mDrawable->getNumFaces(); i++) - { - LLFace *face = mDrawable->getFace(i); - if (face) - { - BOOL fullbright = getTE(i)->getFullbright(); - face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); - - if (fullbright || (mMaterial == LL_MCODE_LIGHT)) - { - face->setState(LLFace::FULLBRIGHT); - } - if (mDrawable->isLight()) - { - face->setState(LLFace::LIGHT); - } - if (isHUDAttachment()) - { - face->setState(LLFace::HUD_RENDER); - } - } - } + llassert(face < getNumTEs()); + gGL.getTexUnit(0)->bind(getTEImage(face)); } -BOOL LLVOVolume::setParent(LLViewerObject* parent) +void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped) { - BOOL ret = FALSE ; - LLViewerObject *old_parent = (LLViewerObject*) getParent(); - if (parent != old_parent) - { - ret = LLViewerObject::setParent(parent); - if (ret && mDrawable) - { - gPipeline.markMoved(mDrawable); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - } - onReparent(old_parent, parent); - } + if (scale != getScale()) + { + // store local radius + LLViewerObject::setScale(scale); + + if (mVolumeImpl) + { + mVolumeImpl->onSetScale(scale, damped); + } + + updateRadius(); - return ret ; + //since drawable transforms do not include scale, changing volume scale + //requires an immediate rebuild of volume verts. + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION, TRUE); + } } -// NOTE: regenFaces() MUST be followed by genTriangles()! -void LLVOVolume::regenFaces() +LLFace* LLVOVolume::addFace(S32 f) { - // remove existing faces - BOOL count_changed = mNumFaces != getNumTEs(); - - if (count_changed) - { - deleteFaces(); - // add new faces - mNumFaces = getNumTEs(); - } - - for (S32 i = 0; i < mNumFaces; i++) - { - LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i); - if (!facep) continue; - - facep->setTEOffset(i); - facep->setTexture(getTEImage(i)); - if (facep->getTextureEntry()->getMaterialParams().notNull()) - { - facep->setNormalMap(getTENormalMap(i)); - facep->setSpecularMap(getTESpecularMap(i)); - } - facep->setViewerObject(this); - - // If the face had media on it, this will have broken the link between the LLViewerMediaTexture and the face. - // Re-establish the link. - if((int)mMediaImplList.size() > i) - { - if(mMediaImplList[i]) - { - LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[i]->getMediaTextureID()) ; - if(media_tex) - { - media_tex->addMediaToFace(facep) ; - } - } - } - } - - if (!count_changed) - { - updateFaceFlags(); - } + const LLTextureEntry* te = getTE(f); + LLViewerTexture* imagep = getTEImage(f); + if (te->getMaterialParams().notNull()) + { + LLViewerTexture* normalp = getTENormalMap(f); + LLViewerTexture* specularp = getTESpecularMap(f); + return mDrawable->addFace(te, imagep, normalp, specularp); + } + return mDrawable->addFace(te, imagep); } -BOOL LLVOVolume::genBBoxes(BOOL force_global) +LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) { - BOOL res = TRUE; - - LLVector4a min,max; - - min.clear(); - max.clear(); + pipeline->allocDrawable(this); + + mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); - BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED); + S32 max_tes_to_set = getNumTEs(); + for (S32 i = 0; i < max_tes_to_set; i++) + { + addFace(i); + } + mNumFaces = max_tes_to_set; - if (getRiggedVolume()) + if (isAttachment()) { - // MAINT-8264 - better to use the existing call in calling - // func LLVOVolume::updateGeometry() if we can detect when - // updates needed, set REBUILD_RIGGED accordingly. + mDrawable->makeActive(); + } - // Without the flag, this will remove unused rigged volumes, which we are not currently very aggressive about. - updateRiggedVolume(); + if (getIsLight()) + { + // Add it to the pipeline mLightSet + gPipeline.setLight(mDrawable, TRUE); } - LLVolume* volume = mRiggedVolume; - if (!volume) - { - volume = getVolume(); - } + updateRadius(); + bool force_update = true; // avoid non-alpha mDistance update being optimized away + mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update); - bool any_valid_boxes = false; + return mDrawable; +} + +BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bool unique_volume) +{ + LLVolumeParams volume_params = params_in; + + S32 last_lod = mVolumep.notNull() ? LLVolumeLODGroup::getVolumeDetailFromScale(mVolumep->getDetail()) : -1; + S32 lod = mLOD; + + BOOL is404 = FALSE; - if (getRiggedVolume()) + if (isSculpted()) { - LL_DEBUGS("RiggedBox") << "rebuilding box, volume face count " << getVolume()->getNumVolumeFaces() << " drawable face count " << mDrawable->getNumFaces() << LL_ENDL; + // if it's a mesh + if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { //meshes might not have all LODs, get the force detail to best existing LOD + if (NO_LOD != lod) + { + lod = gMeshRepo.getActualMeshLOD(volume_params, lod); + if (lod == -1) + { + is404 = TRUE; + lod = 0; + } + } + } } - // There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces() - for (S32 i = 0; - i < getVolume()->getNumVolumeFaces() && i < mDrawable->getNumFaces() && i < getNumTEs(); - i++) - { - LLFace *face = mDrawable->getFace(i); - if (!face) - { - continue; - } - BOOL face_res = face->genVolumeBBoxes(*volume, i, - mRelativeXform, - (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global); - res &= face_res; // note that this result is never used - - // MAINT-8264 - ignore bboxes of ill-formed faces. - if (!face_res) + // Check if we need to change implementations + bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE); + if (is_flexible) + { + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, false); + if (!mVolumeImpl) { - continue; + LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + mVolumeImpl = new LLVolumeImplFlexible(this, data); } - if (rebuild) - { - if (getRiggedVolume()) - { - LL_DEBUGS("RiggedBox") << "rebuilding box, face " << i << " extents " << face->mExtents[0] << ", " << face->mExtents[1] << LL_ENDL; - } - if (!any_valid_boxes) - { - min = face->mExtents[0]; - max = face->mExtents[1]; - any_valid_boxes = true; - } - else - { - min.setMin(min, face->mExtents[0]); - max.setMax(max, face->mExtents[1]); - } - } - } - - if (any_valid_boxes) + } + else { - if (rebuild) + // Mark the parameter not in use + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, false); + if (mVolumeImpl) { - if (getRiggedVolume()) + delete mVolumeImpl; + mVolumeImpl = NULL; + if (mDrawable.notNull()) { - LL_DEBUGS("RiggedBox") << "rebuilding got extents " << min << ", " << max << LL_ENDL; + // Undo the damage we did to this matrix + mDrawable->updateXform(FALSE); } - mDrawable->setSpatialExtents(min,max); - min.add(max); - min.mul(0.5f); - mDrawable->setPositionGroup(min); } - - updateRadius(); - mDrawable->movePartition(); } - else + + if (is404) { - LL_DEBUGS("RiggedBox") << "genBBoxes failed to find any valid face boxes" << LL_ENDL; - } - - return res; -} - -void LLVOVolume::preRebuild() -{ - if (mVolumeImpl != NULL) - { - mVolumeImpl->preRebuild(); - } -} + setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI)); + //render prim proxy when mesh loading attempts give up + volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE); -void LLVOVolume::updateRelativeXform(bool force_identity) -{ - if (mVolumeImpl) - { - mVolumeImpl->updateRelativeXform(force_identity); - return; - } - - LLDrawable* drawable = mDrawable; - - if (drawable->isState(LLDrawable::RIGGED) && mRiggedVolume.notNull()) - { //rigged volume (which is in agent space) is used for generating bounding boxes etc - //inverse of render matrix should go to partition space - mRelativeXform = getRenderMatrix(); - - F32* dst = (F32*) mRelativeXformInvTrans.mMatrix; - F32* src = (F32*) mRelativeXform.mMatrix; - dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; - dst[3] = src[4]; dst[4] = src[5]; dst[5] = src[6]; - dst[6] = src[8]; dst[7] = src[9]; dst[8] = src[10]; - - mRelativeXform.invert(); - mRelativeXformInvTrans.transpose(); - } - else if (drawable->isActive() || force_identity) - { - // setup relative transforms - LLQuaternion delta_rot; - LLVector3 delta_pos, delta_scale; - - //matrix from local space to parent relative/global space - bool use_identity = force_identity || drawable->isSpatialRoot(); - delta_rot = use_identity ? LLQuaternion() : mDrawable->getRotation(); - delta_pos = use_identity ? LLVector3(0,0,0) : mDrawable->getPosition(); - delta_scale = mDrawable->getScale(); - - // Vertex transform (4x4) - LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot; - LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot; - LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot; - - mRelativeXform.initRows(LLVector4(x_axis, 0.f), - LLVector4(y_axis, 0.f), - LLVector4(z_axis, 0.f), - LLVector4(delta_pos, 1.f)); - - - // compute inverse transpose for normals - // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); - // mRelativeXformInvTrans.invert(); - // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); - // grumble - invert is NOT a matrix invert, so we do it by hand: - - LLMatrix3 rot_inverse = LLMatrix3(~delta_rot); - - LLMatrix3 scale_inverse; - scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX], - LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY], - LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]); - - - mRelativeXformInvTrans = rot_inverse * scale_inverse; - - mRelativeXformInvTrans.transpose(); - } - else - { - LLVector3 pos = getPosition(); - LLVector3 scale = getScale(); - LLQuaternion rot = getRotation(); - - if (mParent) - { - pos *= mParent->getRotation(); - pos += mParent->getPosition(); - rot *= mParent->getRotation(); - } - - //LLViewerRegion* region = getRegion(); - //pos += region->getOriginAgent(); - - LLVector3 x_axis = LLVector3(scale.mV[VX], 0.f, 0.f) * rot; - LLVector3 y_axis = LLVector3(0.f, scale.mV[VY], 0.f) * rot; - LLVector3 z_axis = LLVector3(0.f, 0.f, scale.mV[VZ]) * rot; - - mRelativeXform.initRows(LLVector4(x_axis, 0.f), - LLVector4(y_axis, 0.f), - LLVector4(z_axis, 0.f), - LLVector4(pos, 1.f)); - - // compute inverse transpose for normals - LLMatrix3 rot_inverse = LLMatrix3(~rot); - - LLMatrix3 scale_inverse; - scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX], - LLVector3(0.0, 1.0, 0.0) / scale.mV[VY], - LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]); - - - mRelativeXformInvTrans = rot_inverse * scale_inverse; - - mRelativeXformInvTrans.transpose(); - } -} + } -static LLTrace::BlockTimerStatHandle FTM_GEN_FLEX("Generate Flexies"); -static LLTrace::BlockTimerStatHandle FTM_UPDATE_PRIMITIVES("Update Primitives"); -static LLTrace::BlockTimerStatHandle FTM_UPDATE_RIGGED_VOLUME("Update Rigged"); + if ((LLPrimitive::setVolume(volume_params, lod, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged) + { + mFaceMappingChanged = TRUE; + + if (mVolumeImpl) + { + mVolumeImpl->onSetVolume(volume_params, mLOD); + } + + updateSculptTexture(); -bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) + if (isSculpted()) + { + updateSculptTexture(); + // if it's a mesh + if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { + if (!getVolume()->isMeshAssetLoaded()) + { + //load request not yet issued, request pipeline load this mesh + LLUUID asset_id = volume_params.getSculptID(); + S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod, last_lod); + if (available_lod != lod) + { + LLPrimitive::setVolume(volume_params, available_lod); + } + } + + } + else // otherwise is sculptie + { + if (mSculptTexture.notNull()) + { + sculpt(); + } + } + } + + static LLCachedControl use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false); + + bool cache_in_vram = use_transform_feedback && gTransformPositionProgram.mProgramObject && + (!mVolumeImpl || !mVolumeImpl->isVolumeUnique()); + + if (cache_in_vram) + { //this volume might be used as source data for a transform object, put it in vram + LLVolume* volume = getVolume(); + for (S32 i = 0; i < volume->getNumFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + if (face.mVertexBuffer.notNull()) + { //already cached + break; + } + volume->genTangents(i); + LLFace::cacheFaceInVRAM(face); + } + } + + return TRUE; + } + else if (NO_LOD == lod) + { + LLSculptIDSize::instance().resetSizeSum(volume_params.getSculptID()); + } + + return FALSE; +} + +void LLVOVolume::updateSculptTexture() +{ + LLPointer old_sculpt = mSculptTexture; + + if (isSculpted() && !isMesh()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID id = sculpt_params->getSculptTexture(); + if (id.notNull()) + { + mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } + } + else + { + mSculptTexture = NULL; + } + + if (mSculptTexture != old_sculpt) + { + if (old_sculpt.notNull()) + { + old_sculpt->removeVolume(LLRender::SCULPT_TEX, this); + } + if (mSculptTexture.notNull()) + { + mSculptTexture->addVolume(LLRender::SCULPT_TEX, this); + } + } + +} + +void LLVOVolume::updateVisualComplexity() +{ + LLVOAvatar* avatar = getAvatarAncestor(); + if (avatar) + { + avatar->updateVisualComplexity(); + } + LLVOAvatar* rigged_avatar = getAvatar(); + if(rigged_avatar && (rigged_avatar != avatar)) + { + rigged_avatar->updateVisualComplexity(); + } +} + +void LLVOVolume::notifyMeshLoaded() +{ + mSculptChanged = TRUE; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); + + if (getAvatar() && !isAnimatedObject()) + { + getAvatar()->addAttachmentOverridesForObject(this); + } + if (getControlAvatar() && isAnimatedObject()) + { + getControlAvatar()->addAttachmentOverridesForObject(this); + } + updateVisualComplexity(); +} + +// sculpt replaces generate() for sculpted surfaces +void LLVOVolume::sculpt() +{ + if (mSculptTexture.notNull()) + { + U16 sculpt_height = 0; + U16 sculpt_width = 0; + S8 sculpt_components = 0; + const U8* sculpt_data = NULL; + + S32 discard_level = mSculptTexture->getCachedRawImageLevel() ; + LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ; + + S32 max_discard = mSculptTexture->getMaxDiscardLevel(); + if (discard_level > max_discard) + { + discard_level = max_discard; // clamp to the best we can do + } + if(discard_level > MAX_DISCARD_LEVEL) + { + return; //we think data is not ready yet. + } + + S32 current_discard = getVolume()->getSculptLevel() ; + if(current_discard < -2) + { + static S32 low_sculpty_discard_warning_count = 1; + S32 exponent = llmax(1, llfloor( log10((F64) low_sculpty_discard_warning_count) )); + S32 interval = pow(10.0, exponent); + if ( low_sculpty_discard_warning_count < 10 || + (low_sculpty_discard_warning_count % interval) == 0) + { // Log first 10 time, then decreasing intervals afterwards otherwise this can flood the logs + LL_WARNS() << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() + << " at " << current_discard + << " is less than -2." + << " Hit this " << low_sculpty_discard_warning_count << " times" + << LL_ENDL; + } + low_sculpty_discard_warning_count++; + + // corrupted volume... don't update the sculpty + return; + } + else if (current_discard > MAX_DISCARD_LEVEL) + { + static S32 high_sculpty_discard_warning_count = 1; + S32 exponent = llmax(1, llfloor( log10((F64) high_sculpty_discard_warning_count) )); + S32 interval = pow(10.0, exponent); + if ( high_sculpty_discard_warning_count < 10 || + (high_sculpty_discard_warning_count % interval) == 0) + { // Log first 10 time, then decreasing intervals afterwards otherwise this can flood the logs + LL_WARNS() << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() + << " at " << current_discard + << " is more than than allowed max of " << MAX_DISCARD_LEVEL + << ". Hit this " << high_sculpty_discard_warning_count << " times" + << LL_ENDL; + } + high_sculpty_discard_warning_count++; + + // corrupted volume... don't update the sculpty + return; + } + + if (current_discard == discard_level) // no work to do here + return; + + if(!raw_image) + { + llassert(discard_level < 0) ; + + sculpt_width = 0; + sculpt_height = 0; + sculpt_data = NULL ; + + if(LLViewerTextureManager::sTesterp) + { + LLViewerTextureManager::sTesterp->updateGrayTextureBinding(); + } + } + else + { + sculpt_height = raw_image->getHeight(); + sculpt_width = raw_image->getWidth(); + sculpt_components = raw_image->getComponents(); + + sculpt_data = raw_image->getData(); + + if(LLViewerTextureManager::sTesterp) + { + mSculptTexture->updateBindStatsForTester() ; + } + } + getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level, mSculptTexture->isMissingAsset()); + + //notify rebuild any other VOVolumes that reference this sculpty volume + for (S32 i = 0; i < mSculptTexture->getNumVolumes(LLRender::SCULPT_TEX); ++i) + { + LLVOVolume* volume = (*(mSculptTexture->getVolumeList(LLRender::SCULPT_TEX)))[i]; + if (volume != this && volume->getVolume() == getVolume()) + { + gPipeline.markRebuild(volume->mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE); + } + } + } +} + +S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius, F32 lod_factor) +{ + S32 cur_detail; + if (LLPipeline::sDynamicLOD) + { + // We've got LOD in the profile, and in the twist. Use radius. + F32 tan_angle = (lod_factor*radius)/distance; + cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f)); + } + else + { + cur_detail = llclamp((S32) (sqrtf(radius)*lod_factor*4.f), 0, 3); + } + return cur_detail; +} + +std::string get_debug_object_lod_text(LLVOVolume *rootp) +{ + std::string cam_dist_string = ""; + cam_dist_string += LLStringOps::getReadableNumber(rootp->mLODDistance) + " "; + std::string lod_string = llformat("%d",rootp->getLOD()); + F32 lod_radius = rootp->mLODRadius; + S32 cam_dist_count = 0; + LLViewerObject::const_child_list_t& child_list = rootp->getChildren(); + for (LLViewerObject::const_child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); ++iter) + { + LLViewerObject *childp = *iter; + LLVOVolume *volp = dynamic_cast(childp); + if (volp) + { + lod_string += llformat("%d",volp->getLOD()); + if (volp->isRiggedMesh()) + { + // Rigged/animatable mesh. This is computed from the + // avatar dynamic box, so value from any vol will be + // the same. + lod_radius = volp->mLODRadius; + } + if (volp->mDrawable) + { + if (cam_dist_count < 4) + { + cam_dist_string += LLStringOps::getReadableNumber(volp->mLODDistance) + " "; + cam_dist_count++; + } + } + } + } + std::string result = llformat("lod_radius %s dists %s lods %s", + LLStringOps::getReadableNumber(lod_radius).c_str(), + cam_dist_string.c_str(), + lod_string.c_str()); + return result; +} + +BOOL LLVOVolume::calcLOD() +{ + if (mDrawable.isNull()) + { + return FALSE; + } + + S32 cur_detail = 0; + + F32 radius; + F32 distance; + F32 lod_factor = LLVOVolume::sLODFactor; + + if (mDrawable->isState(LLDrawable::RIGGED)) + { + LLVOAvatar* avatar = getAvatar(); + + // Not sure how this can really happen, but alas it does. Better exit here than crashing. + if( !avatar || !avatar->mDrawable ) + { + return FALSE; + } + + distance = avatar->mDrawable->mDistanceWRTCamera; + + + if (avatar->isControlAvatar()) + { + // MAINT-7926 Handle volumes in an animated object as a special case + const LLVector3* box = avatar->getLastAnimExtents(); + LLVector3 diag = box[1] - box[0]; + radius = diag.magVec() * 0.5f; + LL_DEBUGS("DynamicBox") << avatar->getFullname() << " diag " << diag << " radius " << radius << LL_ENDL; + } + else + { + // Volume in a rigged mesh attached to a regular avatar. + // Note this isn't really a radius, so distance calcs are off by factor of 2 + //radius = avatar->getBinRadius(); + // SL-937: add dynamic box handling for rigged mesh on regular avatars. + const LLVector3* box = avatar->getLastAnimExtents(); + LLVector3 diag = box[1] - box[0]; + radius = diag.magVec(); // preserve old BinRadius behavior - 2x off + LL_DEBUGS("DynamicBox") << avatar->getFullname() << " diag " << diag << " radius " << radius << LL_ENDL; + } + if (distance <= 0.f || radius <= 0.f) + { + LL_DEBUGS("DynamicBox","CalcLOD") << "avatar distance/radius uninitialized, skipping" << LL_ENDL; + return FALSE; + } + } + else + { + distance = mDrawable->mDistanceWRTCamera; + radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); + if (distance <= 0.f || radius <= 0.f) + { + LL_DEBUGS("DynamicBox","CalcLOD") << "non-avatar distance/radius uninitialized, skipping" << LL_ENDL; + return FALSE; + } + } + + //hold onto unmodified distance for debugging + //F32 debug_distance = distance; + + mLODDistance = distance; + mLODRadius = radius; + + if (gSavedSettings.getBOOL("DebugObjectLODs")) + { + if (getAvatar() && isRootEdit()) + { + std::string debug_object_text = get_debug_object_lod_text(this); + setDebugText(debug_object_text); + } + } + + distance *= sDistanceFactor; + + F32 rampDist = LLVOVolume::sLODFactor * 2; + + if (distance < rampDist) + { + // Boost LOD when you're REALLY close + distance *= 1.0f/rampDist; + distance *= distance; + distance *= rampDist; + } + + + distance *= F_PI/3.f; + + static LLCachedControl ignore_fov_zoom(gSavedSettings,"IgnoreFOVZoomForLODs"); + if(!ignore_fov_zoom) + { + lod_factor *= DEFAULT_FIELD_OF_VIEW / LLViewerCamera::getInstance()->getDefaultFOV(); + } + + mLODAdjustedDistance = distance; + + if (isHUDAttachment()) + { + // HUDs always show at highest detail + cur_detail = 3; + } + else + { + cur_detail = computeLODDetail(ll_round(distance, 0.01f), ll_round(radius, 0.01f), lod_factor); + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TRIANGLE_COUNT) && mDrawable->getFace(0)) + { + if (isRootEdit()) + { + S32 total_tris = recursiveGetTriangleCount(); + S32 est_max_tris = recursiveGetEstTrianglesMax(); + setDebugText(llformat("TRIS SHOWN %d EST %d", total_tris, est_max_tris)); + } + } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && + mDrawable->getFace(0)) + { + // This is a debug display for LODs. Please don't put the texture index here. + setDebugText(llformat("%d", cur_detail)); + } + + if (cur_detail != mLOD) + { + LL_DEBUGS("DynamicBox","CalcLOD") << "new LOD " << cur_detail << " change from " << mLOD + << " distance " << distance << " radius " << radius << " rampDist " << rampDist + << " drawable rigged? " << (mDrawable ? (S32) mDrawable->isState(LLDrawable::RIGGED) : (S32) -1) + << " mRiggedVolume " << (void*)getRiggedVolume() + << " distanceWRTCamera " << (mDrawable ? mDrawable->mDistanceWRTCamera : -1.f) + << LL_ENDL; + + mAppAngle = ll_round((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); + mLOD = cur_detail; + + return TRUE; + } + + return FALSE; +} + +BOOL LLVOVolume::updateLOD() +{ + if (mDrawable.isNull()) + { + return FALSE; + } + + BOOL lod_changed = FALSE; + + if (!LLSculptIDSize::instance().isUnloaded(getVolume()->getParams().getSculptID())) + { + lod_changed = calcLOD(); + } + else + { + return FALSE; + } + + if (lod_changed) + { + if (debugLoggingEnabled("AnimatedObjectsLinkset")) + { + if (isAnimatedObject() && isRiggedMesh()) + { + std::string vobj_name = llformat("Vol%p", this); + F32 est_tris = getEstTrianglesMax(); + LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " updateLOD to " << getLOD() << ", tris " << est_tris << LL_ENDL; + } + } + + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + mLODChanged = TRUE; + } + else + { + F32 new_radius = getBinRadius(); + F32 old_radius = mDrawable->getBinRadius(); + if (new_radius < old_radius * 0.9f || new_radius > old_radius*1.1f) + { + gPipeline.markPartitionMove(mDrawable); + } + } + + lod_changed = lod_changed || LLViewerObject::updateLOD(); + + return lod_changed; +} + +BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp) +{ + if (!LLViewerObject::setDrawableParent(parentp)) + { + // no change in drawable parent + return FALSE; + } + + if (!mDrawable->isRoot()) + { + // rebuild vertices in parent relative space + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); + + if (mDrawable->isActive() && !parentp->isActive()) + { + parentp->makeActive(); + } + else if (mDrawable->isStatic() && parentp->isActive()) + { + mDrawable->makeActive(); + } + } + + return TRUE; +} + +void LLVOVolume::updateFaceFlags() +{ + // There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces() + for (S32 i = 0; i < getVolume()->getNumFaces() && i < mDrawable->getNumFaces(); i++) + { + LLFace *face = mDrawable->getFace(i); + if (face) + { + BOOL fullbright = getTE(i)->getFullbright(); + face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); + + if (fullbright || (mMaterial == LL_MCODE_LIGHT)) + { + face->setState(LLFace::FULLBRIGHT); + } + if (mDrawable->isLight()) + { + face->setState(LLFace::LIGHT); + } + if (isHUDAttachment()) + { + face->setState(LLFace::HUD_RENDER); + } + } + } +} + +BOOL LLVOVolume::setParent(LLViewerObject* parent) +{ + BOOL ret = FALSE ; + LLViewerObject *old_parent = (LLViewerObject*) getParent(); + if (parent != old_parent) + { + ret = LLViewerObject::setParent(parent); + if (ret && mDrawable) + { + gPipeline.markMoved(mDrawable); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); + } + onReparent(old_parent, parent); + } + + return ret ; +} + +// NOTE: regenFaces() MUST be followed by genTriangles()! +void LLVOVolume::regenFaces() +{ + // remove existing faces + BOOL count_changed = mNumFaces != getNumTEs(); + + if (count_changed) + { + deleteFaces(); + // add new faces + mNumFaces = getNumTEs(); + } + + for (S32 i = 0; i < mNumFaces; i++) + { + LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i); + if (!facep) continue; + + facep->setTEOffset(i); + facep->setTexture(getTEImage(i)); + if (facep->getTextureEntry()->getMaterialParams().notNull()) + { + facep->setNormalMap(getTENormalMap(i)); + facep->setSpecularMap(getTESpecularMap(i)); + } + facep->setViewerObject(this); + + // If the face had media on it, this will have broken the link between the LLViewerMediaTexture and the face. + // Re-establish the link. + if((int)mMediaImplList.size() > i) + { + if(mMediaImplList[i]) + { + LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[i]->getMediaTextureID()) ; + if(media_tex) + { + media_tex->addMediaToFace(facep) ; + } + } + } + } + + if (!count_changed) + { + updateFaceFlags(); + } +} + +BOOL LLVOVolume::genBBoxes(BOOL force_global) +{ + BOOL res = TRUE; + + LLVector4a min,max; + + min.clear(); + max.clear(); + + BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED); + + if (getRiggedVolume()) + { + // MAINT-8264 - better to use the existing call in calling + // func LLVOVolume::updateGeometry() if we can detect when + // updates needed, set REBUILD_RIGGED accordingly. + + // Without the flag, this will remove unused rigged volumes, which we are not currently very aggressive about. + updateRiggedVolume(); + } + + LLVolume* volume = mRiggedVolume; + if (!volume) + { + volume = getVolume(); + } + + bool any_valid_boxes = false; + + if (getRiggedVolume()) + { + LL_DEBUGS("RiggedBox") << "rebuilding box, volume face count " << getVolume()->getNumVolumeFaces() << " drawable face count " << mDrawable->getNumFaces() << LL_ENDL; + } + // There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces() + for (S32 i = 0; + i < getVolume()->getNumVolumeFaces() && i < mDrawable->getNumFaces() && i < getNumTEs(); + i++) + { + LLFace *face = mDrawable->getFace(i); + if (!face) + { + continue; + } + + BOOL face_res = face->genVolumeBBoxes(*volume, i, + mRelativeXform, + (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global); + res &= face_res; // note that this result is never used + + // MAINT-8264 - ignore bboxes of ill-formed faces. + if (!face_res) + { + continue; + } + if (rebuild) + { + if (getRiggedVolume()) + { + LL_DEBUGS("RiggedBox") << "rebuilding box, face " << i << " extents " << face->mExtents[0] << ", " << face->mExtents[1] << LL_ENDL; + } + if (!any_valid_boxes) + { + min = face->mExtents[0]; + max = face->mExtents[1]; + any_valid_boxes = true; + } + else + { + min.setMin(min, face->mExtents[0]); + max.setMax(max, face->mExtents[1]); + } + } + } + + if (any_valid_boxes) + { + if (rebuild) + { + if (getRiggedVolume()) + { + LL_DEBUGS("RiggedBox") << "rebuilding got extents " << min << ", " << max << LL_ENDL; + } + mDrawable->setSpatialExtents(min,max); + min.add(max); + min.mul(0.5f); + mDrawable->setPositionGroup(min); + } + + updateRadius(); + mDrawable->movePartition(); + } + else + { + LL_DEBUGS("RiggedBox") << "genBBoxes failed to find any valid face boxes" << LL_ENDL; + } + + return res; +} + +void LLVOVolume::preRebuild() +{ + if (mVolumeImpl != NULL) + { + mVolumeImpl->preRebuild(); + } +} + +void LLVOVolume::updateRelativeXform(bool force_identity) +{ + if (mVolumeImpl) + { + mVolumeImpl->updateRelativeXform(force_identity); + return; + } + + LLDrawable* drawable = mDrawable; + + if (drawable->isState(LLDrawable::RIGGED) && mRiggedVolume.notNull()) + { //rigged volume (which is in agent space) is used for generating bounding boxes etc + //inverse of render matrix should go to partition space + mRelativeXform = getRenderMatrix(); + + F32* dst = (F32*) mRelativeXformInvTrans.mMatrix; + F32* src = (F32*) mRelativeXform.mMatrix; + dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; + dst[3] = src[4]; dst[4] = src[5]; dst[5] = src[6]; + dst[6] = src[8]; dst[7] = src[9]; dst[8] = src[10]; + + mRelativeXform.invert(); + mRelativeXformInvTrans.transpose(); + } + else if (drawable->isActive() || force_identity) + { + // setup relative transforms + LLQuaternion delta_rot; + LLVector3 delta_pos, delta_scale; + + //matrix from local space to parent relative/global space + bool use_identity = force_identity || drawable->isSpatialRoot(); + delta_rot = use_identity ? LLQuaternion() : mDrawable->getRotation(); + delta_pos = use_identity ? LLVector3(0,0,0) : mDrawable->getPosition(); + delta_scale = mDrawable->getScale(); + + // Vertex transform (4x4) + LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot; + LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot; + LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot; + + mRelativeXform.initRows(LLVector4(x_axis, 0.f), + LLVector4(y_axis, 0.f), + LLVector4(z_axis, 0.f), + LLVector4(delta_pos, 1.f)); + + + // compute inverse transpose for normals + // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); + // mRelativeXformInvTrans.invert(); + // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); + // grumble - invert is NOT a matrix invert, so we do it by hand: + + LLMatrix3 rot_inverse = LLMatrix3(~delta_rot); + + LLMatrix3 scale_inverse; + scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX], + LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY], + LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]); + + + mRelativeXformInvTrans = rot_inverse * scale_inverse; + + mRelativeXformInvTrans.transpose(); + } + else + { + LLVector3 pos = getPosition(); + LLVector3 scale = getScale(); + LLQuaternion rot = getRotation(); + + if (mParent) + { + pos *= mParent->getRotation(); + pos += mParent->getPosition(); + rot *= mParent->getRotation(); + } + + //LLViewerRegion* region = getRegion(); + //pos += region->getOriginAgent(); + + LLVector3 x_axis = LLVector3(scale.mV[VX], 0.f, 0.f) * rot; + LLVector3 y_axis = LLVector3(0.f, scale.mV[VY], 0.f) * rot; + LLVector3 z_axis = LLVector3(0.f, 0.f, scale.mV[VZ]) * rot; + + mRelativeXform.initRows(LLVector4(x_axis, 0.f), + LLVector4(y_axis, 0.f), + LLVector4(z_axis, 0.f), + LLVector4(pos, 1.f)); + + // compute inverse transpose for normals + LLMatrix3 rot_inverse = LLMatrix3(~rot); + + LLMatrix3 scale_inverse; + scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX], + LLVector3(0.0, 1.0, 0.0) / scale.mV[VY], + LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]); + + + mRelativeXformInvTrans = rot_inverse * scale_inverse; + + mRelativeXformInvTrans.transpose(); + } +} + +static LLTrace::BlockTimerStatHandle FTM_GEN_FLEX("Generate Flexies"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_PRIMITIVES("Update Primitives"); +static LLTrace::BlockTimerStatHandle FTM_UPDATE_RIGGED_VOLUME("Update Rigged"); + +bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) +{ + bool regen_faces = false; + + LLVolume *old_volumep, *new_volumep; + F32 old_lod, new_lod; + S32 old_num_faces, new_num_faces; + + old_volumep = getVolume(); + old_lod = old_volumep->getDetail(); + old_num_faces = old_volumep->getNumFaces(); + old_volumep = NULL; + + { + LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME); + const LLVolumeParams &volume_params = getVolume()->getParams(); + setVolume(volume_params, 0); + } + + new_volumep = getVolume(); + new_lod = new_volumep->getDetail(); + new_num_faces = new_volumep->getNumFaces(); + new_volumep = NULL; + + if ((new_lod != old_lod) || mSculptChanged) + { + if (mDrawable->isState(LLDrawable::RIGGED)) + { + updateVisualComplexity(); + } + + compiled = TRUE; + sNumLODChanges += new_num_faces; + + if ((S32)getNumTEs() != getVolume()->getNumFaces()) + { + setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. + } + + drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() + + { + LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); + regen_faces = new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs(); + if (regen_faces) + { + regenFaces(); + } + + if (mSculptChanged) + { //changes in sculpt maps can thrash an object bounding box without + //triggering a spatial group bounding box update -- force spatial group + //to update bounding boxes + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->unbound(); + } + } + } + } + + return regen_faces; +} + +BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) +{ + LL_RECORD_BLOCK_TIME(FTM_UPDATE_PRIMITIVES); + + if (mDrawable->isState(LLDrawable::REBUILD_RIGGED)) + { + { + LL_RECORD_BLOCK_TIME(FTM_UPDATE_RIGGED_VOLUME); + updateRiggedVolume(); + } + genBBoxes(FALSE); + mDrawable->clearState(LLDrawable::REBUILD_RIGGED); + } + + if (mVolumeImpl != NULL) + { + BOOL res; + { + LL_RECORD_BLOCK_TIME(FTM_GEN_FLEX); + res = mVolumeImpl->doUpdateGeometry(drawable); + } + updateFaceFlags(); + return res; + } + + LLSpatialGroup* group = drawable->getSpatialGroup(); + if (group) + { + group->dirtyMesh(); + } + + BOOL compiled = FALSE; + + updateRelativeXform(); + + if (mDrawable.isNull()) // Not sure why this is happening, but it is... + { + return TRUE; // No update to complete + } + + if (mVolumeChanged || mFaceMappingChanged) + { + dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + + bool was_regen_faces = false; + + if (mVolumeChanged) + { + was_regen_faces = lodOrSculptChanged(drawable, compiled); + drawable->setState(LLDrawable::REBUILD_VOLUME); + } + else if (mSculptChanged || mLODChanged) + { + compiled = TRUE; + was_regen_faces = lodOrSculptChanged(drawable, compiled); + } + + if (!was_regen_faces) { + LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); + regenFaces(); + } + + genBBoxes(FALSE); + } + else if (mLODChanged || mSculptChanged) + { + dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + compiled = TRUE; + lodOrSculptChanged(drawable, compiled); + + if(drawable->isState(LLDrawable::REBUILD_RIGGED | LLDrawable::RIGGED)) + { + updateRiggedVolume(false); + } + genBBoxes(FALSE); + } + // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local + else + { + compiled = TRUE; + // All it did was move or we changed the texture coordinate offset + LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); + genBBoxes(FALSE); + } + + // Update face flags + updateFaceFlags(); + + if(compiled) + { + LLPipeline::sCompiles++; + } + + mVolumeChanged = FALSE; + mLODChanged = FALSE; + mSculptChanged = FALSE; + mFaceMappingChanged = FALSE; + + return LLViewerObject::updateGeometry(drawable); +} + +void LLVOVolume::updateFaceSize(S32 idx) +{ + if( mDrawable->getNumFaces() <= idx ) + { + return; + } + + LLFace* facep = mDrawable->getFace(idx); + if (facep) + { + if (idx >= getVolume()->getNumVolumeFaces()) + { + facep->setSize(0,0, true); + } + else + { + const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); + facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, + true); // <--- volume faces should be padded for 16-byte alignment + + } + } +} + +BOOL LLVOVolume::isRootEdit() const +{ + if (mParent && !((LLViewerObject*)mParent)->isAvatar()) + { + return FALSE; + } + return TRUE; +} + +//virtual +void LLVOVolume::setNumTEs(const U8 num_tes) +{ + const U8 old_num_tes = getNumTEs() ; + + if(old_num_tes && old_num_tes < num_tes) //new faces added + { + LLViewerObject::setNumTEs(num_tes) ; + + if(mMediaImplList.size() >= old_num_tes && mMediaImplList[old_num_tes -1].notNull())//duplicate the last media textures if exists. + { + mMediaImplList.resize(num_tes) ; + const LLTextureEntry* te = getTE(old_num_tes - 1) ; + for(U8 i = old_num_tes; i < num_tes ; i++) + { + setTE(i, *te) ; + mMediaImplList[i] = mMediaImplList[old_num_tes -1] ; + } + mMediaImplList[old_num_tes -1]->setUpdated(TRUE) ; + } + } + else if(old_num_tes > num_tes && mMediaImplList.size() > num_tes) //old faces removed + { + U8 end = mMediaImplList.size() ; + for(U8 i = num_tes; i < end ; i++) + { + removeMediaImpl(i) ; + } + mMediaImplList.resize(num_tes) ; + + LLViewerObject::setNumTEs(num_tes) ; + } + else + { + LLViewerObject::setNumTEs(num_tes) ; + } + + return ; +} + +//virtual +void LLVOVolume::changeTEImage(S32 index, LLViewerTexture* imagep) +{ + BOOL changed = (mTEImages[index] != imagep); + LLViewerObject::changeTEImage(index, imagep); + if (changed) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } +} + +void LLVOVolume::setTEImage(const U8 te, LLViewerTexture *imagep) +{ + BOOL changed = (mTEImages[te] != imagep); + LLViewerObject::setTEImage(te, imagep); + if (changed) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } +} + +S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid) +{ + S32 res = LLViewerObject::setTETexture(te, uuid); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEColor(const U8 te, const LLColor3& color) +{ + return setTEColor(te, LLColor4(color)); +} + +S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color) +{ + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS("MaterialTEs") << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + } + else if (color != tep->getColor()) + { + F32 old_alpha = tep->getColor().mV[3]; + if (color.mV[3] != old_alpha) + { + gPipeline.markTextured(mDrawable); + //treat this alpha change as an LoD update since render batches may need to get rebuilt + mLODChanged = TRUE; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + } + retval = LLPrimitive::setTEColor(te, color); + if (mDrawable.notNull() && retval) + { + // These should only happen on updates which are not the initial update. + mDrawable->setState(LLDrawable::REBUILD_COLOR); + dirtyMesh(); + } + } + + return retval; +} + +S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap) +{ + S32 res = LLViewerObject::setTEBumpmap(te, bumpmap); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen) +{ + S32 res = LLViewerObject::setTETexGen(te, texgen); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEMediaTexGen(const U8 te, const U8 media) +{ + S32 res = LLViewerObject::setTEMediaTexGen(te, media); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny) +{ + S32 res = LLViewerObject::setTEShiny(te, shiny); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright) +{ + S32 res = LLViewerObject::setTEFullbright(te, fullbright); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump) +{ + S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags) +{ + S32 res = LLViewerObject::setTEMediaFlags(te, media_flags); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEGlow(const U8 te, const F32 glow) +{ + S32 res = LLViewerObject::setTEGlow(te, glow); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +void LLVOVolume::setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID &pMaterialID, const LLMaterialPtr pMaterialParams, U32 te) +{ + LLVOVolume* pVol = (LLVOVolume*)gObjectList.findObject(objectID); + if (pVol) + { + LL_DEBUGS("MaterialTEs") << "materialid " << pMaterialID.asString() << " to TE " << te << LL_ENDL; + if (te >= pVol->getNumTEs()) + return; + + LLTextureEntry* texture_entry = pVol->getTE(te); + if (texture_entry && (texture_entry->getMaterialID() == pMaterialID)) + { + pVol->setTEMaterialParams(te, pMaterialParams); + } + } +} + +S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) +{ + S32 res = LLViewerObject::setTEMaterialID(te, pMaterialID); + LL_DEBUGS("MaterialTEs") << "te "<< (S32)te << " materialid " << pMaterialID.asString() << " res " << res + << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this), te) ? " selected" : " not selected" ) + << LL_ENDL; + + LL_DEBUGS("MaterialTEs") << " " << pMaterialID.asString() << LL_ENDL; + if (res) + { + LLMaterialMgr::instance().getTE(getRegion()->getRegionID(), pMaterialID, te, boost::bind(&LLVOVolume::setTEMaterialParamsCallbackTE, getID(), _1, _2, _3)); + + setChanged(ALL_CHANGED); + if (!mDrawable.isNull()) + { + gPipeline.markTextured(mDrawable); + gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL); + } + mFaceMappingChanged = TRUE; + } + return res; +} + +bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture) +{ //Ok, here we have confirmation about texture creation, check our wait-list + //and make changes, or return false + + std::pair range = mWaitingTextureInfo.equal_range(texture->getID()); + + typedef std::map map_te_material; + map_te_material new_material; + + for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it) + { + LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te); + + //here we just interesting in DIFFUSE_MAP only! + if(NULL != cur_material.get() && LLRender::DIFFUSE_MAP == range_it->second.map && GL_RGBA != texture->getPrimaryFormat()) + { //ok let's check the diffuse mode + switch(cur_material->getDiffuseAlphaMode()) + { + case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: + case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: + case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: + { //uups... we have non 32 bit texture with LLMaterial::DIFFUSE_ALPHA_MODE_* => LLMaterial::DIFFUSE_ALPHA_MODE_NONE + + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } + + mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); + + } break; + } //switch + } //if + } //for + + //setup new materials + for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) + { + LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second); + LLViewerObject::setTEMaterialParams(it->first, it->second); + } + + //clear wait-list + mWaitingTextureInfo.erase(range.first, range.second); + + return 0 != new_material.size(); +} + +bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture) +{ //Ok, here if we wait information about texture and it's missing + //then depending from the texture map (diffuse, normal, or specular) + //make changes in material and confirm it. If not return false. + std::pair range = mWaitingTextureInfo.equal_range(texture->getID()); + if(range.first == range.second) return false; + + typedef std::map map_te_material; + map_te_material new_material; + + for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it) + { + LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te); + if (cur_material.isNull()) + continue; + + switch(range_it->second.map) + { + case LLRender::DIFFUSE_MAP: + { + if(LLMaterial::DIFFUSE_ALPHA_MODE_NONE != cur_material->getDiffuseAlphaMode()) + { //missing texture + !LLMaterial::DIFFUSE_ALPHA_MODE_NONE => LLMaterial::DIFFUSE_ALPHA_MODE_NONE + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } + + mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); + } + } break; + case LLRender::NORMAL_MAP: + { //missing texture => reset material texture id + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } + + mat->setNormalID(LLUUID::null); + } break; + case LLRender::SPECULAR_MAP: + { //missing texture => reset material texture id + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } + + mat->setSpecularID(LLUUID::null); + } break; + case LLRender::NUM_TEXTURE_CHANNELS: + //nothing to do, make compiler happy + break; + } //switch + } //for + + //setup new materials + for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) + { + LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), it->second); + LLViewerObject::setTEMaterialParams(it->first, it->second); + } + + //clear wait-list + mWaitingTextureInfo.erase(range.first, range.second); + + return 0 != new_material.size(); +} + +S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) +{ + LLMaterialPtr pMaterial = const_cast(pMaterialParams); + + if(pMaterialParams) + { //check all of them according to material settings + + LLViewerTexture *img_diffuse = getTEImage(te); + LLViewerTexture *img_normal = getTENormalMap(te); + LLViewerTexture *img_specular = getTESpecularMap(te); + + llassert(NULL != img_diffuse); + + LLMaterialPtr new_material = NULL; + + //diffuse + if(NULL != img_diffuse) + { //guard + if(0 == img_diffuse->getPrimaryFormat() && !img_diffuse->isMissingAsset()) + { //ok here we don't have information about texture, let's belief and leave material settings + //but we remember this case + mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(img_diffuse->getID(), material_info(LLRender::DIFFUSE_MAP, te))); + } + else + { + bool bSetDiffuseNone = false; + if(img_diffuse->isMissingAsset()) + { + bSetDiffuseNone = true; + } + else + { + switch(pMaterialParams->getDiffuseAlphaMode()) + { + case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: + case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: + case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: + { //all of them modes available only for 32 bit textures + if(GL_RGBA != img_diffuse->getPrimaryFormat()) + { + bSetDiffuseNone = true; + } + } break; + } + } //else + + + if(bSetDiffuseNone) + { //upps... we should substitute this material with LLMaterial::DIFFUSE_ALPHA_MODE_NONE + new_material = new LLMaterial(pMaterialParams->asLLSD()); + new_material->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); + } + } + } + + //normal + if(LLUUID::null != pMaterialParams->getNormalID()) + { + if(img_normal && img_normal->isMissingAsset() && img_normal->getID() == pMaterialParams->getNormalID()) + { + if(!new_material) { + new_material = new LLMaterial(pMaterialParams->asLLSD()); + } + new_material->setNormalID(LLUUID::null); + } + else if(NULL == img_normal || 0 == img_normal->getPrimaryFormat()) + { //ok here we don't have information about texture, let's belief and leave material settings + //but we remember this case + mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getNormalID(), material_info(LLRender::NORMAL_MAP,te))); + } + + } + + + //specular + if(LLUUID::null != pMaterialParams->getSpecularID()) + { + if(img_specular && img_specular->isMissingAsset() && img_specular->getID() == pMaterialParams->getSpecularID()) + { + if(!new_material) { + new_material = new LLMaterial(pMaterialParams->asLLSD()); + } + new_material->setSpecularID(LLUUID::null); + } + else if(NULL == img_specular || 0 == img_specular->getPrimaryFormat()) + { //ok here we don't have information about texture, let's belief and leave material settings + //but we remember this case + mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getSpecularID(), material_info(LLRender::SPECULAR_MAP, te))); + } + } + + if(new_material) { + pMaterial = new_material; + LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), pMaterial); + } + } + + S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial); + + LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterial) ? pMaterial->asLLSD() : LLSD("null")) << " res " << res + << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this), te) ? " selected" : " not selected" ) + << LL_ENDL; + setChanged(ALL_CHANGED); + if (!mDrawable.isNull()) + { + gPipeline.markTextured(mDrawable); + gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL); + } + mFaceMappingChanged = TRUE; + return TEM_CHANGE_TEXTURE; +} + +S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t) +{ + S32 res = LLViewerObject::setTEScale(te, s, t); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s) +{ + S32 res = LLViewerObject::setTEScaleS(te, s); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t) +{ + S32 res = LLViewerObject::setTEScaleT(te, t); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; +} + +void LLVOVolume::updateTEData() +{ + /*if (mDrawable.notNull()) + { + mFaceMappingChanged = TRUE; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE); + }*/ +} + +bool LLVOVolume::hasMedia() const +{ + bool result = false; + const U8 numTEs = getNumTEs(); + for (U8 i = 0; i < numTEs; i++) + { + const LLTextureEntry* te = getTE(i); + if(te->hasMedia()) + { + result = true; + break; + } + } + return result; +} + +LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id) +{ + LLVolume* volume = getVolume(); + LLVector4a result; + result.clear(); + + LLVector3 ret; + + if (volume && face_id < volume->getNumVolumeFaces()) + { + const LLVolumeFace& face = volume->getVolumeFace(face_id); + for (S32 i = 0; i < (S32)face.mNumVertices; ++i) + { + result.add(face.mNormals[i]); + } + + LLVector3 ret(result.getF32ptr()); + ret = volumeDirectionToAgent(ret); + ret.normVec(); + } + + return ret; +} + +void LLVOVolume::requestMediaDataUpdate(bool isNew) +{ + if (sObjectMediaClient) + sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew)); +} + +bool LLVOVolume::isMediaDataBeingFetched() const +{ + // I know what I'm doing by const_casting this away: this is just + // a wrapper class that is only going to do a lookup. + return (sObjectMediaClient) ? sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast(this), false)) : false; +} + +void LLVOVolume::cleanUpMediaImpls() +{ + // Iterate through our TEs and remove any Impls that are no longer used + const U8 numTEs = getNumTEs(); + for (U8 i = 0; i < numTEs; i++) + { + const LLTextureEntry* te = getTE(i); + if( ! te->hasMedia()) + { + // Delete the media IMPL! + removeMediaImpl(i) ; + } + } +} + +void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version) +{ + // media_data_array is an array of media entry maps + // media_version is the version string in the response. + U32 fetched_version = LLTextureEntry::getVersionFromMediaVersionString(media_version); + + // Only update it if it is newer! + if ( (S32)fetched_version > mLastFetchedMediaVersion) + { + mLastFetchedMediaVersion = fetched_version; + //LL_INFOS() << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << LL_ENDL; + + LLSD::array_const_iterator iter = media_data_array.beginArray(); + LLSD::array_const_iterator end = media_data_array.endArray(); + U8 texture_index = 0; + for (; iter != end; ++iter, ++texture_index) + { + syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/); + } + } +} + +void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool merge, bool ignore_agent) +{ + if(mDead) + { + // If the object has been marked dead, don't process media updates. + return; + } + + LLTextureEntry *te = getTE(texture_index); + if(!te) + { + return ; + } + + LL_DEBUGS("MediaOnAPrim") << "BEFORE: texture_index = " << texture_index + << " hasMedia = " << te->hasMedia() << " : " + << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << LL_ENDL; + + std::string previous_url; + LLMediaEntry* mep = te->getMediaData(); + if(mep) + { + // Save the "current url" from before the update so we can tell if + // it changes. + previous_url = mep->getCurrentURL(); + } + + if (merge) + { + te->mergeIntoMediaData(media_data); + } + else { + // XXX Question: what if the media data is undefined LLSD, but the + // update we got above said that we have media flags?? Here we clobber + // that, assuming the data from the service is more up-to-date. + te->updateMediaData(media_data); + } + + mep = te->getMediaData(); + if(mep) + { + bool update_from_self = false; + if (!ignore_agent) + { + LLUUID updating_agent = LLTextureEntry::getAgentIDFromMediaVersionString(getMediaURL()); + update_from_self = (updating_agent == gAgent.getID()); + } + viewer_media_t media_impl = LLViewerMedia::updateMediaImpl(mep, previous_url, update_from_self); + + addMediaImpl(media_impl, texture_index) ; + } + else + { + removeMediaImpl(texture_index); + } + + LL_DEBUGS("MediaOnAPrim") << "AFTER: texture_index = " << texture_index + << " hasMedia = " << te->hasMedia() << " : " + << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << LL_ENDL; +} + +void LLVOVolume::mediaNavigateBounceBack(U8 texture_index) +{ + // Find the media entry for this navigate + const LLMediaEntry* mep = NULL; + viewer_media_t impl = getMediaImpl(texture_index); + LLTextureEntry *te = getTE(texture_index); + if(te) + { + mep = te->getMediaData(); + } + + if (mep && impl) + { + std::string url = mep->getCurrentURL(); + // Look for a ":", if not there, assume "http://" + if (!url.empty() && std::string::npos == url.find(':')) + { + url = "http://" + url; + } + // If the url we're trying to "bounce back" to is either empty or not + // allowed by the whitelist, try the home url. If *that* doesn't work, + // set the media as failed and unload it + if (url.empty() || !mep->checkCandidateUrl(url)) + { + url = mep->getHomeURL(); + // Look for a ":", if not there, assume "http://" + if (!url.empty() && std::string::npos == url.find(':')) + { + url = "http://" + url; + } + } + if (url.empty() || !mep->checkCandidateUrl(url)) + { + // The url to navigate back to is not good, and we have nowhere else + // to go. + LL_WARNS("MediaOnAPrim") << "FAILED to bounce back URL \"" << url << "\" -- unloading impl" << LL_ENDL; + impl->setMediaFailed(true); + } + // Make sure we are not bouncing to url we came from + else if (impl->getCurrentMediaURL() != url) + { + // Okay, navigate now + LL_INFOS("MediaOnAPrim") << "bouncing back to URL: " << url << LL_ENDL; + impl->navigateTo(url, "", false, true); + } + } +} + +bool LLVOVolume::hasMediaPermission(const LLMediaEntry* media_entry, MediaPermType perm_type) +{ + // NOTE: This logic ALMOST duplicates the logic in the server (in particular, in llmediaservice.cpp). + if (NULL == media_entry ) return false; // XXX should we assert here? + + // The agent has permissions if: + // - world permissions are on, or + // - group permissions are on, and agent_id is in the group, or + // - agent permissions are on, and agent_id is the owner + + // *NOTE: We *used* to check for modify permissions here (i.e. permissions were + // granted if permModify() was true). However, this doesn't make sense in the + // viewer: we don't want to show controls or allow interaction if the author + // has deemed it so. See DEV-42115. + + U8 media_perms = (perm_type == MEDIA_PERM_INTERACT) ? media_entry->getPermsInteract() : media_entry->getPermsControl(); + + // World permissions + if (0 != (media_perms & LLMediaEntry::PERM_ANYONE)) + { + return true; + } + + // Group permissions + else if (0 != (media_perms & LLMediaEntry::PERM_GROUP)) + { + LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(this); + if (obj_perm && gAgent.isInGroup(obj_perm->getGroup())) + { + return true; + } + } + + // Owner permissions + else if (0 != (media_perms & LLMediaEntry::PERM_OWNER) && permYouOwner()) + { + return true; + } + + return false; + +} + +void LLVOVolume::mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location) +{ + bool block_navigation = false; + // FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed + // to deal with multiple face indices. + int face_index = getFaceIndexWithMediaImpl(impl, -1); + + // Find the media entry for this navigate + LLMediaEntry* mep = NULL; + LLTextureEntry *te = getTE(face_index); + if(te) + { + mep = te->getMediaData(); + } + + if(mep) + { + if(!mep->checkCandidateUrl(new_location)) + { + block_navigation = true; + } + if (!block_navigation && !hasMediaPermission(mep, MEDIA_PERM_INTERACT)) + { + block_navigation = true; + } + } + else + { + LL_WARNS("MediaOnAPrim") << "Couldn't find media entry!" << LL_ENDL; + } + + if(block_navigation) + { + LL_INFOS("MediaOnAPrim") << "blocking navigate to URI " << new_location << LL_ENDL; + + // "bounce back" to the current URL from the media entry + mediaNavigateBounceBack(face_index); + } + else if (sObjectMediaNavigateClient) + { + + LL_DEBUGS("MediaOnAPrim") << "broadcasting navigate with URI " << new_location << LL_ENDL; + + sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this, false), face_index, new_location); + } +} + +void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event) +{ + switch(event) + { + + case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED: + { + switch(impl->getNavState()) + { + case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED: + { + // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. + mediaNavigated(impl, plugin, plugin->getLocation()); + } + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS: + // This navigate didn't change the current URL. + LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: + // This is the first location changed event after the start of a server-directed nav. Don't broadcast it. + LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; + break; + + default: + // This is a subsequent location-changed due to a redirect. Don't broadcast. + LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (redirect)" << LL_ENDL; + break; + } + } + break; + + case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE: + { + switch(impl->getNavState()) + { + case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: + { + // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. + mediaNavigated(impl, plugin, plugin->getNavigateURI()); + } + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS: + // This navigate didn't change the current URL. + LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: + // This is the the navigate complete event from a server-directed nav. Don't broadcast it. + LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; + break; + + default: + // For all other states, the navigate should have been handled by LOCATION_CHANGED events already. + break; + } + } + break; + + default: + break; + } + +} + +void LLVOVolume::sendMediaDataUpdate() +{ + if (sObjectMediaClient) + sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this, false)); +} + +void LLVOVolume::removeMediaImpl(S32 texture_index) +{ + if(mMediaImplList.size() <= (U32)texture_index || mMediaImplList[texture_index].isNull()) + { + return ; + } + + //make the face referencing to mMediaImplList[texture_index] to point back to the old texture. + if(mDrawable && texture_index < mDrawable->getNumFaces()) + { + LLFace* facep = mDrawable->getFace(texture_index) ; + if(facep) + { + LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; + if(media_tex) + { + media_tex->removeMediaFromFace(facep) ; + } + } + } + + //check if some other face(s) of this object reference(s)to this media impl. + S32 i ; + S32 end = (S32)mMediaImplList.size() ; + for(i = 0; i < end ; i++) + { + if( i != texture_index && mMediaImplList[i] == mMediaImplList[texture_index]) + { + break ; + } + } + + if(i == end) //this object does not need this media impl. + { + mMediaImplList[texture_index]->removeObject(this) ; + } + + mMediaImplList[texture_index] = NULL ; + return ; +} + +void LLVOVolume::addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) +{ + if((S32)mMediaImplList.size() < texture_index + 1) + { + mMediaImplList.resize(texture_index + 1) ; + } + + if(mMediaImplList[texture_index].notNull()) + { + if(mMediaImplList[texture_index] == media_impl) + { + return ; + } + + removeMediaImpl(texture_index) ; + } + + mMediaImplList[texture_index] = media_impl; + media_impl->addObject(this) ; + + //add the face to show the media if it is in playing + if(mDrawable) + { + LLFace* facep(NULL); + if( texture_index < mDrawable->getNumFaces() ) + { + facep = mDrawable->getFace(texture_index) ; + } + + if(facep) + { + LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; + if(media_tex) + { + media_tex->addMediaToFace(facep) ; + } + } + else //the face is not available now, start media on this face later. + { + media_impl->setUpdated(TRUE) ; + } + } + return ; +} + +viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const +{ + if(mMediaImplList.size() > face_id) + { + return mMediaImplList[face_id]; + } + return NULL; +} + +F64 LLVOVolume::getTotalMediaInterest() const +{ + // If this object is currently focused, this object has "high" interest + if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == getID()) + return F64_MAX; + + F64 interest = (F64)-1.0; // means not interested; + + // If this object is selected, this object has "high" interest, but since + // there can be more than one, we still add in calculated impl interest + // XXX Sadly, 'contains()' doesn't take a const :( + if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this))) + interest = F64_MAX / 2.0; + + int i = 0; + const int end = getNumTEs(); + for ( ; i < end; ++i) + { + const viewer_media_t &impl = getMediaImpl(i); + if (!impl.isNull()) + { + if (interest == (F64)-1.0) interest = (F64)0.0; + interest += impl->getInterest(); + } + } + return interest; +} + +S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id) +{ + S32 end = (S32)mMediaImplList.size() ; + for(S32 face_id = start_face_id + 1; face_id < end; face_id++) + { + if(mMediaImplList[face_id] == media_impl) + { + return face_id ; + } + } + return -1 ; +} + +//---------------------------------------------------------------------------- + +void LLVOVolume::setLightTextureID(LLUUID id) +{ + LLViewerTexture* old_texturep = getLightTexture(); // same as mLightTexture, but inits if nessesary + if (id.notNull()) + { + if (!hasLightTexture()) + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true); + } + else if (old_texturep) + { + old_texturep->removeVolume(LLRender::LIGHT_TEX, this); + } + LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block && param_block->getLightTexture() != id) + { + param_block->setLightTexture(id); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + } + LLViewerTexture* tex = getLightTexture(); + if (tex) + { + tex->addVolume(LLRender::LIGHT_TEX, this); // new texture + } + else + { + LL_WARNS() << "Can't get light texture for ID " << id.asString() << LL_ENDL; + } + } + else if (hasLightTexture()) + { + if (old_texturep) + { + old_texturep->removeVolume(LLRender::LIGHT_TEX, this); + } + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + mLightTexture = NULL; + } +} + +void LLVOVolume::setSpotLightParams(LLVector3 params) +{ + LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block && param_block->getParams() != params) + { + param_block->setParams(params); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + } +} + +void LLVOVolume::setIsLight(BOOL is_light) +{ + BOOL was_light = getIsLight(); + if (is_light != was_light) + { + if (is_light) + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, TRUE, true); + } + else + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, FALSE, true); + } + + if (is_light) + { + // Add it to the pipeline mLightSet + gPipeline.setLight(mDrawable, TRUE); + } + else + { + // Not a light. Remove it from the pipeline's light set. + gPipeline.setLight(mDrawable, FALSE); + } + } +} + +void LLVOVolume::setLightColor(const LLColor3& color) +{ + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getColor() != color) + { + param_block->setColor(LLColor4(color, param_block->getColor().mV[3])); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + } +} + +void LLVOVolume::setLightIntensity(F32 intensity) +{ + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getColor().mV[3] != intensity) + { + param_block->setColor(LLColor4(LLColor3(param_block->getColor()), intensity)); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } +} + +void LLVOVolume::setLightRadius(F32 radius) +{ + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getRadius() != radius) + { + param_block->setRadius(radius); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } +} + +void LLVOVolume::setLightFalloff(F32 falloff) +{ + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getFalloff() != falloff) + { + param_block->setFalloff(falloff); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } +} + +void LLVOVolume::setLightCutoff(F32 cutoff) +{ + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getCutoff() != cutoff) + { + param_block->setCutoff(cutoff); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } +} + +//---------------------------------------------------------------------------- + +BOOL LLVOVolume::getIsLight() const +{ + return getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT); +} + +LLColor3 LLVOVolume::getLightBaseColor() const +{ + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return LLColor3(param_block->getColor()); + } + else + { + return LLColor3(1,1,1); + } +} + +LLColor3 LLVOVolume::getLightColor() const +{ + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return LLColor3(param_block->getColor()) * param_block->getColor().mV[3]; + } + else + { + return LLColor3(1,1,1); + } +} + +LLUUID LLVOVolume::getLightTextureID() const +{ + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block) + { + return param_block->getLightTexture(); + } + } + + return LLUUID::null; +} + + +LLVector3 LLVOVolume::getSpotLightParams() const +{ + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block) + { + return param_block->getParams(); + } + } + + return LLVector3(); +} + +F32 LLVOVolume::getSpotLightPriority() const +{ + return mSpotLightPriority; +} + +void LLVOVolume::updateSpotLightPriority() +{ + LLVector3 pos = mDrawable->getPositionAgent(); + LLVector3 at(0,0,-1); + at *= getRenderRotation(); + + F32 r = getLightRadius()*0.5f; + + pos += at * r; + + at = LLViewerCamera::getInstance()->getAtAxis(); + + pos -= at * r; + + mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); + + if (mLightTexture.notNull()) + { + mLightTexture->addTextureStats(mSpotLightPriority); + mLightTexture->setBoostLevel(LLGLTexture::BOOST_CLOUDS); + } +} + + +bool LLVOVolume::isLightSpotlight() const +{ + LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (params && getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + return params->isLightSpotlight(); + } + return false; +} + + +LLViewerTexture* LLVOVolume::getLightTexture() +{ + LLUUID id = getLightTextureID(); + + if (id.notNull()) + { + if (mLightTexture.isNull() || id != mLightTexture->getID()) + { + mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM); + } + } + else + { + mLightTexture = NULL; + } + + return mLightTexture; +} + +F32 LLVOVolume::getLightIntensity() const +{ + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getColor().mV[3]; + } + else + { + return 1.f; + } +} + +F32 LLVOVolume::getLightRadius() const +{ + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getRadius(); + } + else + { + return 0.f; + } +} + +F32 LLVOVolume::getLightFalloff() const +{ + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getFalloff(); + } + else + { + return 0.f; + } +} + +F32 LLVOVolume::getLightCutoff() const +{ + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getCutoff(); + } + else + { + return 0.f; + } +} + +U32 LLVOVolume::getVolumeInterfaceID() const +{ + if (mVolumeImpl) + { + return mVolumeImpl->getID(); + } + + return 0; +} + +BOOL LLVOVolume::isFlexible() const +{ + if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE)) + { + LLVolume* volume = getVolume(); + if (volume && volume->getParams().getPathParams().getCurveType() != LL_PCODE_PATH_FLEXIBLE) + { + LLVolumeParams volume_params = getVolume()->getParams(); + U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); + volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); + } + return TRUE; + } + else + { + return FALSE; + } +} + +BOOL LLVOVolume::isSculpted() const +{ + if (getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + { + return TRUE; + } + + return FALSE; +} + +BOOL LLVOVolume::isMesh() const +{ + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + U8 sculpt_type = sculpt_params->getSculptType(); + + if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + // mesh is a mesh + { + return TRUE; + } + } + + return FALSE; +} + +BOOL LLVOVolume::hasLightTexture() const +{ + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + return TRUE; + } + + return FALSE; +} + +BOOL LLVOVolume::isVolumeGlobal() const +{ + if (mVolumeImpl) + { + return mVolumeImpl->isVolumeGlobal() ? TRUE : FALSE; + } + else if (mRiggedVolume.notNull()) + { + return TRUE; + } + + return FALSE; +} + +BOOL LLVOVolume::canBeFlexible() const +{ + U8 path = getVolume()->getParams().getPathParams().getCurveType(); + return (path == LL_PCODE_PATH_FLEXIBLE || path == LL_PCODE_PATH_LINE); +} + +BOOL LLVOVolume::setIsFlexible(BOOL is_flexible) +{ + BOOL res = FALSE; + BOOL was_flexible = isFlexible(); + LLVolumeParams volume_params; + if (is_flexible) + { + if (!was_flexible) + { + volume_params = getVolume()->getParams(); + U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); + volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); + res = TRUE; + setFlags(FLAGS_USE_PHYSICS, FALSE); + setFlags(FLAGS_PHANTOM, TRUE); + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, true); + if (mDrawable) + { + mDrawable->makeActive(); + } + } + } + else + { + if (was_flexible) + { + volume_params = getVolume()->getParams(); + U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); + volume_params.setType(profile_and_hole, LL_PCODE_PATH_LINE); + res = TRUE; + setFlags(FLAGS_PHANTOM, FALSE); + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, true); + } + } + if (res) + { + res = setVolume(volume_params, 1); + if (res) + { + markForUpdate(TRUE); + } + } + return res; +} + +const LLMeshSkinInfo* LLVOVolume::getSkinInfo() const +{ + if (getVolume()) + { + return gMeshRepo.getSkinInfo(getVolume()->getParams().getSculptID(), this); + } + else + { + return NULL; + } +} + +// virtual +BOOL LLVOVolume::isRiggedMesh() const +{ + return isMesh() && getSkinInfo(); +} + +//---------------------------------------------------------------------------- +U32 LLVOVolume::getExtendedMeshFlags() const +{ + const LLExtendedMeshParams *param_block = + (const LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH); + if (param_block) + { + return param_block->getFlags(); + } + else + { + return 0; + } +} + +void LLVOVolume::onSetExtendedMeshFlags(U32 flags) +{ + + // The isAnySelected() check was needed at one point to prevent + // graphics problems. These are now believed to be fixed so the + // check has been disabled. + if (/*!getRootEdit()->isAnySelected() &&*/ mDrawable.notNull()) + { + // Need to trigger rebuildGeom(), which is where control avatars get created/removed + getRootEdit()->recursiveMarkForUpdate(TRUE); + } + if (isAttachment() && getAvatarAncestor()) + { + updateVisualComplexity(); + if (flags & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG) + { + // Making a rigged mesh into an animated object + getAvatarAncestor()->updateAttachmentOverrides(); + } + else + { + // Making an animated object into a rigged mesh + getAvatarAncestor()->updateAttachmentOverrides(); + } + } +} + +void LLVOVolume::setExtendedMeshFlags(U32 flags) +{ + U32 curr_flags = getExtendedMeshFlags(); + if (curr_flags != flags) + { + bool in_use = true; + setParameterEntryInUse(LLNetworkData::PARAMS_EXTENDED_MESH, in_use, true); + LLExtendedMeshParams *param_block = + (LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH); + if (param_block) + { + param_block->setFlags(flags); + } + parameterChanged(LLNetworkData::PARAMS_EXTENDED_MESH, true); + LL_DEBUGS("AnimatedObjects") << this + << " new flags " << flags << " curr_flags " << curr_flags + << ", calling onSetExtendedMeshFlags()" + << LL_ENDL; + onSetExtendedMeshFlags(flags); + } +} + +bool LLVOVolume::canBeAnimatedObject() const +{ + F32 est_tris = recursiveGetEstTrianglesMax(); + if (est_tris < 0 || est_tris > getAnimatedObjectMaxTris()) + { + return false; + } + return true; +} + +bool LLVOVolume::isAnimatedObject() const +{ + LLVOVolume *root_vol = (LLVOVolume*)getRootEdit(); + bool root_is_animated_flag = root_vol->getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG; + return root_is_animated_flag; +} + +// Called any time parenting changes for a volume. Update flags and +// control av accordingly. This is called after parent has been +// changed to new_parent, but before new_parent's mChildList has changed. + +// virtual +void LLVOVolume::onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent) +{ + LLVOVolume *old_volp = dynamic_cast(old_parent); + + if (new_parent && !new_parent->isAvatar()) + { + if (mControlAvatar.notNull()) + { + // Here an animated object is being made the child of some + // other prim. Should remove the control av from the child. + LLControlAvatar *av = mControlAvatar; + mControlAvatar = NULL; + av->markForDeath(); + } + } + if (old_volp && old_volp->isAnimatedObject()) + { + if (old_volp->getControlAvatar()) + { + // We have been removed from an animated object, need to do cleanup. + old_volp->getControlAvatar()->updateAttachmentOverrides(); + old_volp->getControlAvatar()->updateAnimations(); + } + } +} + +// This needs to be called after onReparent(), because mChildList is +// not updated until the end of LLViewerObject::addChild() + +// virtual +void LLVOVolume::afterReparent() +{ + { + LL_DEBUGS("AnimatedObjects") << "new child added for parent " + << ((LLViewerObject*)getParent())->getID() << LL_ENDL; + } + + if (isAnimatedObject() && getControlAvatar()) + { + LL_DEBUGS("AnimatedObjects") << "adding attachment overrides, parent is animated object " + << ((LLViewerObject*)getParent())->getID() << LL_ENDL; + + // MAINT-8239 - doing a full rebuild whenever parent is set + // makes the joint overrides load more robustly. In theory, + // addAttachmentOverrides should be sufficient, but in + // practice doing a full rebuild helps compensate for + // notifyMeshLoaded() not being called reliably enough. + + // was: getControlAvatar()->addAttachmentOverridesForObject(this); + //getControlAvatar()->rebuildAttachmentOverrides(); + getControlAvatar()->updateAnimations(); + } + else + { + LL_DEBUGS("AnimatedObjects") << "not adding overrides, parent: " + << ((LLViewerObject*)getParent())->getID() + << " isAnimated: " << isAnimatedObject() << " cav " + << getControlAvatar() << LL_ENDL; + } +} + +//---------------------------------------------------------------------------- +static LLTrace::BlockTimerStatHandle FTM_VOVOL_RIGGING_INFO("VOVol Rigging Info"); + +void LLVOVolume::updateRiggingInfo() +{ + LL_RECORD_BLOCK_TIME(FTM_VOVOL_RIGGING_INFO); + if (isRiggedMesh()) + { + const LLMeshSkinInfo* skin = getSkinInfo(); + LLVOAvatar *avatar = getAvatar(); + LLVolume *volume = getVolume(); + if (skin && avatar && volume) + { + LL_DEBUGS("RigSpammish") << "starting, vovol " << this << " lod " << getLOD() << " last " << mLastRiggingInfoLOD << LL_ENDL; + if (getLOD()>mLastRiggingInfoLOD || getLOD()==3) + { + // Rigging info may need update + mJointRiggingInfoTab.clear(); + for (S32 f = 0; f < volume->getNumVolumeFaces(); ++f) + { + LLVolumeFace& vol_face = volume->getVolumeFace(f); + LLSkinningUtil::updateRiggingInfo(skin, avatar, vol_face); + if (vol_face.mJointRiggingInfoTab.size()>0) + { + mJointRiggingInfoTab.merge(vol_face.mJointRiggingInfoTab); + } + } + // Keep the highest LOD info available. + mLastRiggingInfoLOD = getLOD(); + LL_DEBUGS("RigSpammish") << "updated rigging info for LLVOVolume " + << this << " lod " << mLastRiggingInfoLOD + << LL_ENDL; + } + } + } +} + +//---------------------------------------------------------------------------- + +void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point) +{ + LLVolume *volume = getVolume(); + + if (volume) + { + LLVector3 view_vector; + view_vector = view_point; + + //transform view vector into volume space + view_vector -= getRenderPosition(); + //mDrawable->mDistanceWRTCamera = view_vector.length(); + LLQuaternion worldRot = getRenderRotation(); + view_vector = view_vector * ~worldRot; + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + view_vector.scaleVec(invObjScale); + } + + updateRelativeXform(); + LLMatrix4 trans_mat = mRelativeXform; + if (mDrawable->isStatic()) + { + trans_mat.translate(getRegion()->getOriginAgent()); + } + + volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, view_vector, trans_mat, mRelativeXformInvTrans, nodep->getTESelectMask()); + + nodep->mSilhouetteExists = TRUE; + } +} + +void LLVOVolume::deleteFaces() +{ + S32 face_count = mNumFaces; + if (mDrawable.notNull()) + { + mDrawable->deleteFaces(0, face_count); + } + + mNumFaces = 0; +} + +void LLVOVolume::updateRadius() +{ + if (mDrawable.isNull()) + { + return; + } + + mVObjRadius = getScale().length(); + mDrawable->setRadius(mVObjRadius); +} + + +BOOL LLVOVolume::isAttachment() const +{ + return mAttachmentState != 0 ; +} + +BOOL LLVOVolume::isHUDAttachment() const +{ + // *NOTE: we assume hud attachment points are in defined range + // since this range is constant for backwards compatibility + // reasons this is probably a reasonable assumption to make + S32 attachment_id = ATTACHMENT_ID_FROM_STATE(mAttachmentState); + return ( attachment_id >= 31 && attachment_id <= 38 ); +} + + +const LLMatrix4 LLVOVolume::getRenderMatrix() const +{ + if (mDrawable->isActive() && !mDrawable->isRoot()) + { + return mDrawable->getParent()->getWorldMatrix(); + } + return mDrawable->getWorldMatrix(); +} + +// Returns a base cost and adds textures to passed in set. +// total cost is returned value + 5 * size of the resulting set. +// Cannot include cost of textures, as they may be re-used in linked +// children, and cost should only be increased for unique textures -Nyx +U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const { - bool regen_faces = false; + /***************************************************************** + * This calculation should not be modified by third party viewers, + * since it is used to limit rendering and should be uniform for + * everyone. If you have suggested improvements, submit them to + * the official viewer for consideration. + *****************************************************************/ + + // Get access to params we'll need at various points. + // Skip if this is object doesn't have a volume (e.g. is an avatar). + BOOL has_volume = (getVolume() != NULL); + LLVolumeParams volume_params; + LLPathParams path_params; + LLProfileParams profile_params; + + U32 num_triangles = 0; + + // per-prim costs + static const U32 ARC_PARTICLE_COST = 1; // determined experimentally + static const U32 ARC_PARTICLE_MAX = 2048; // default values + static const U32 ARC_TEXTURE_COST = 16; // multiplier for texture resolution - performance tested + static const U32 ARC_LIGHT_COST = 500; // static cost for light-producing prims + static const U32 ARC_MEDIA_FACE_COST = 1500; // static cost per media-enabled face + + + // per-prim multipliers + static const F32 ARC_GLOW_MULT = 1.5f; // tested based on performance + static const F32 ARC_BUMP_MULT = 1.25f; // tested based on performance + static const F32 ARC_FLEXI_MULT = 5; // tested based on performance + static const F32 ARC_SHINY_MULT = 1.6f; // tested based on performance + static const F32 ARC_INVISI_COST = 1.2f; // tested based on performance + static const F32 ARC_WEIGHTED_MESH = 1.2f; // tested based on performance + + static const F32 ARC_PLANAR_COST = 1.0f; // tested based on performance to have negligible impact + static const F32 ARC_ANIM_TEX_COST = 4.f; // tested based on performance + static const F32 ARC_ALPHA_COST = 4.f; // 4x max - based on performance + + F32 shame = 0; + + U32 invisi = 0; + U32 shiny = 0; + U32 glow = 0; + U32 alpha = 0; + U32 flexi = 0; + U32 animtex = 0; + U32 particles = 0; + U32 bump = 0; + U32 planar = 0; + U32 weighted_mesh = 0; + U32 produces_light = 0; + U32 media_faces = 0; + + const LLDrawable* drawablep = mDrawable; + U32 num_faces = drawablep->getNumFaces(); + + if (has_volume) + { + volume_params = getVolume()->getParams(); + path_params = volume_params.getPathParams(); + profile_params = volume_params.getProfileParams(); + + LLMeshCostData costs; + if (getCostData(costs)) + { + if (isAnimatedObject() && isRiggedMesh()) + { + // Scaling here is to make animated object vs + // non-animated object ARC proportional to the + // corresponding calculations for streaming cost. + num_triangles = (ANIMATED_OBJECT_COST_PER_KTRI * 0.001 * costs.getEstTrisForStreamingCost())/0.06; + } + else + { + F32 radius = getScale().length()*0.5f; + num_triangles = costs.getRadiusWeightedTris(radius); + } + } + } + + if (num_triangles <= 0) + { + num_triangles = 4; + } + + if (isSculpted()) + { + if (isMesh()) + { + // base cost is dependent on mesh complexity + // note that 3 is the highest LOD as of the time of this coding. + S32 size = gMeshRepo.getMeshSize(volume_params.getSculptID(), getLOD()); + if ( size > 0) + { + if (isRiggedMesh()) + { + // weighted attachment - 1 point for every 3 bytes + weighted_mesh = 1; + } + } + else + { + // something went wrong - user should know their content isn't render-free + return 0; + } + } + else + { + const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID sculpt_id = sculpt_params->getSculptTexture(); + if (textures.find(sculpt_id) == textures.end()) + { + LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(sculpt_id); + if (texture) + { + S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (texture->getFullHeight() / 128.f + texture->getFullWidth() / 128.f)); + textures.insert(texture_cost_t::value_type(sculpt_id, texture_cost)); + } + } + } + } - LLVolume *old_volumep, *new_volumep; - F32 old_lod, new_lod; - S32 old_num_faces, new_num_faces; + if (isFlexible()) + { + flexi = 1; + } + if (isParticleSource()) + { + particles = 1; + } - old_volumep = getVolume(); - old_lod = old_volumep->getDetail(); - old_num_faces = old_volumep->getNumFaces(); - old_volumep = NULL; + if (getIsLight()) + { + produces_light = 1; + } + + for (S32 i = 0; i < num_faces; ++i) + { + const LLFace* face = drawablep->getFace(i); + if (!face) continue; + const LLTextureEntry* te = face->getTextureEntry(); + const LLViewerTexture* img = face->getTexture(); - { - LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME); - const LLVolumeParams &volume_params = getVolume()->getParams(); - setVolume(volume_params, 0); - } + if (img) + { + if (textures.find(img->getID()) == textures.end()) + { + S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (img->getFullHeight() / 128.f + img->getFullWidth() / 128.f)); + textures.insert(texture_cost_t::value_type(img->getID(), texture_cost)); + } + } - new_volumep = getVolume(); - new_lod = new_volumep->getDetail(); - new_num_faces = new_volumep->getNumFaces(); - new_volumep = NULL; + if (face->getPoolType() == LLDrawPool::POOL_ALPHA) + { + alpha = 1; + } + else if (img && img->getPrimaryFormat() == GL_ALPHA) + { + invisi = 1; + } + if (face->hasMedia()) + { + media_faces++; + } - if ((new_lod != old_lod) || mSculptChanged) - { - if (mDrawable->isState(LLDrawable::RIGGED)) + if (te) { - updateVisualComplexity(); + if (te->getBumpmap()) + { + // bump is a multiplier, don't add per-face + bump = 1; + } + if (te->getShiny()) + { + // shiny is a multiplier, don't add per-face + shiny = 1; + } + if (te->getGlow() > 0.f) + { + // glow is a multiplier, don't add per-face + glow = 1; + } + if (face->mTextureMatrix != NULL) + { + animtex = 1; + } + if (te->getTexGen()) + { + planar = 1; + } } + } - compiled = TRUE; - sNumLODChanges += new_num_faces; + // shame currently has the "base" cost of 1 point per 15 triangles, min 2. + shame = num_triangles * 5.f; + shame = shame < 2.f ? 2.f : shame; - if ((S32)getNumTEs() != getVolume()->getNumFaces()) - { - setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. - } + // multiply by per-face modifiers + if (planar) + { + shame *= planar * ARC_PLANAR_COST; + } - drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() + if (animtex) + { + shame *= animtex * ARC_ANIM_TEX_COST; + } - { - LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); - regen_faces = new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs(); - if (regen_faces) - { - regenFaces(); - } + if (alpha) + { + shame *= alpha * ARC_ALPHA_COST; + } - if (mSculptChanged) - { //changes in sculpt maps can thrash an object bounding box without - //triggering a spatial group bounding box update -- force spatial group - //to update bounding boxes - LLSpatialGroup* group = mDrawable->getSpatialGroup(); - if (group) - { - group->unbound(); - } - } - } - } + if(invisi) + { + shame *= invisi * ARC_INVISI_COST; + } - return regen_faces; -} + if (glow) + { + shame *= glow * ARC_GLOW_MULT; + } -BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) -{ - LL_RECORD_BLOCK_TIME(FTM_UPDATE_PRIMITIVES); - - if (mDrawable->isState(LLDrawable::REBUILD_RIGGED)) - { - { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_RIGGED_VOLUME); - updateRiggedVolume(); - } - genBBoxes(FALSE); - mDrawable->clearState(LLDrawable::REBUILD_RIGGED); - } - - if (mVolumeImpl != NULL) - { - BOOL res; - { - LL_RECORD_BLOCK_TIME(FTM_GEN_FLEX); - res = mVolumeImpl->doUpdateGeometry(drawable); - } - updateFaceFlags(); - return res; - } - - LLSpatialGroup* group = drawable->getSpatialGroup(); - if (group) - { - group->dirtyMesh(); - } - - BOOL compiled = FALSE; - - updateRelativeXform(); - - if (mDrawable.isNull()) // Not sure why this is happening, but it is... - { - return TRUE; // No update to complete - } - - if (mVolumeChanged || mFaceMappingChanged) - { - dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); - - bool was_regen_faces = false; - - if (mVolumeChanged) - { - was_regen_faces = lodOrSculptChanged(drawable, compiled); - drawable->setState(LLDrawable::REBUILD_VOLUME); - } - else if (mSculptChanged || mLODChanged) - { - compiled = TRUE; - was_regen_faces = lodOrSculptChanged(drawable, compiled); - } - - if (!was_regen_faces) { - LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); - regenFaces(); - } - - genBBoxes(FALSE); - } - else if (mLODChanged || mSculptChanged) - { - dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); - compiled = TRUE; - lodOrSculptChanged(drawable, compiled); - - if(drawable->isState(LLDrawable::REBUILD_RIGGED | LLDrawable::RIGGED)) - { - updateRiggedVolume(false); - } - genBBoxes(FALSE); - } - // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local - else - { - compiled = TRUE; - // All it did was move or we changed the texture coordinate offset - LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); - genBBoxes(FALSE); - } - - // Update face flags - updateFaceFlags(); - - if(compiled) - { - LLPipeline::sCompiles++; - } - - mVolumeChanged = FALSE; - mLODChanged = FALSE; - mSculptChanged = FALSE; - mFaceMappingChanged = FALSE; - - return LLViewerObject::updateGeometry(drawable); -} + if (bump) + { + shame *= bump * ARC_BUMP_MULT; + } -void LLVOVolume::updateFaceSize(S32 idx) -{ - if( mDrawable->getNumFaces() <= idx ) - { - return; - } - - LLFace* facep = mDrawable->getFace(idx); - if (facep) - { - if (idx >= getVolume()->getNumVolumeFaces()) - { - facep->setSize(0,0, true); - } - else - { - const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); - facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, - true); // <--- volume faces should be padded for 16-byte alignment - - } - } -} + if (shiny) + { + shame *= shiny * ARC_SHINY_MULT; + } -BOOL LLVOVolume::isRootEdit() const -{ - if (mParent && !((LLViewerObject*)mParent)->isAvatar()) - { - return FALSE; - } - return TRUE; -} -//virtual -void LLVOVolume::setNumTEs(const U8 num_tes) -{ - const U8 old_num_tes = getNumTEs() ; - - if(old_num_tes && old_num_tes < num_tes) //new faces added - { - LLViewerObject::setNumTEs(num_tes) ; - - if(mMediaImplList.size() >= old_num_tes && mMediaImplList[old_num_tes -1].notNull())//duplicate the last media textures if exists. - { - mMediaImplList.resize(num_tes) ; - const LLTextureEntry* te = getTE(old_num_tes - 1) ; - for(U8 i = old_num_tes; i < num_tes ; i++) - { - setTE(i, *te) ; - mMediaImplList[i] = mMediaImplList[old_num_tes -1] ; - } - mMediaImplList[old_num_tes -1]->setUpdated(TRUE) ; - } - } - else if(old_num_tes > num_tes && mMediaImplList.size() > num_tes) //old faces removed - { - U8 end = mMediaImplList.size() ; - for(U8 i = num_tes; i < end ; i++) - { - removeMediaImpl(i) ; - } - mMediaImplList.resize(num_tes) ; - - LLViewerObject::setNumTEs(num_tes) ; - } - else - { - LLViewerObject::setNumTEs(num_tes) ; - } - - return ; -} + // multiply shame by multipliers + if (weighted_mesh) + { + shame *= weighted_mesh * ARC_WEIGHTED_MESH; + } -//virtual -void LLVOVolume::changeTEImage(S32 index, LLViewerTexture* imagep) -{ - BOOL changed = (mTEImages[index] != imagep); - LLViewerObject::changeTEImage(index, imagep); - if (changed) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } -} + if (flexi) + { + shame *= flexi * ARC_FLEXI_MULT; + } -void LLVOVolume::setTEImage(const U8 te, LLViewerTexture *imagep) -{ - BOOL changed = (mTEImages[te] != imagep); - LLViewerObject::setTEImage(te, imagep); - if (changed) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } -} -S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid) -{ - S32 res = LLViewerObject::setTETexture(te, uuid); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} + // add additional costs + if (particles) + { + const LLPartSysData *part_sys_data = &(mPartSourcep->mPartSysData); + const LLPartData *part_data = &(part_sys_data->mPartData); + U32 num_particles = (U32)(part_sys_data->mBurstPartCount * llceil( part_data->mMaxAge / part_sys_data->mBurstRate)); + num_particles = num_particles > ARC_PARTICLE_MAX ? ARC_PARTICLE_MAX : num_particles; + F32 part_size = (llmax(part_data->mStartScale[0], part_data->mEndScale[0]) + llmax(part_data->mStartScale[1], part_data->mEndScale[1])) / 2.f; + shame += num_particles * part_size * ARC_PARTICLE_COST; + } -S32 LLVOVolume::setTEColor(const U8 te, const LLColor3& color) -{ - return setTEColor(te, LLColor4(color)); -} + if (produces_light) + { + shame += ARC_LIGHT_COST; + } -S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color) -{ - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS("MaterialTEs") << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; - } - else if (color != tep->getColor()) - { - F32 old_alpha = tep->getColor().mV[3]; - if (color.mV[3] != old_alpha) - { - gPipeline.markTextured(mDrawable); - //treat this alpha change as an LoD update since render batches may need to get rebuilt - mLODChanged = TRUE; - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); - } - retval = LLPrimitive::setTEColor(te, color); - if (mDrawable.notNull() && retval) - { - // These should only happen on updates which are not the initial update. - mDrawable->setState(LLDrawable::REBUILD_COLOR); - dirtyMesh(); - } - } - - return retval; -} + if (media_faces) + { + shame += media_faces * ARC_MEDIA_FACE_COST; + } -S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap) -{ - S32 res = LLViewerObject::setTEBumpmap(te, bumpmap); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} + // Streaming cost for animated objects includes a fixed cost + // per linkset. Add a corresponding charge here translated into + // triangles, but not weighted by any graphics properties. + if (isAnimatedObject() && isRootEdit()) + { + shame += (ANIMATED_OBJECT_BASE_COST/0.06) * 5.0f; + } -S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen) -{ - S32 res = LLViewerObject::setTETexGen(te, texgen); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} + if (shame > mRenderComplexity_current) + { + mRenderComplexity_current = (S32)shame; + } -S32 LLVOVolume::setTEMediaTexGen(const U8 te, const U8 media) -{ - S32 res = LLViewerObject::setTEMediaTexGen(te, media); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + return (U32)shame; } -S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny) +F32 LLVOVolume::getEstTrianglesMax() const { - S32 res = LLViewerObject::setTEShiny(te, shiny); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + if (isMesh() && getVolume()) + { + return gMeshRepo.getEstTrianglesMax(getVolume()->getParams().getSculptID()); + } + return 0.f; } -S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright) +F32 LLVOVolume::getEstTrianglesStreamingCost() const { - S32 res = LLViewerObject::setTEFullbright(te, fullbright); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + if (isMesh() && getVolume()) + { + return gMeshRepo.getEstTrianglesStreamingCost(getVolume()->getParams().getSculptID()); + } + return 0.f; } -S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump) +F32 LLVOVolume::getStreamingCost() const { - S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} + F32 radius = getScale().length()*0.5f; + F32 linkset_base_cost = 0.f; -S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags) -{ - S32 res = LLViewerObject::setTEMediaFlags(te, media_flags); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + LLMeshCostData costs; + if (getCostData(costs)) + { + if (isAnimatedObject() && isRootEdit()) + { + // Root object of an animated object has this to account for skeleton overhead. + linkset_base_cost = ANIMATED_OBJECT_BASE_COST; + } + if (isMesh()) + { + if (isAnimatedObject() && isRiggedMesh()) + { + return linkset_base_cost + costs.getTriangleBasedStreamingCost(); + } + else + { + return linkset_base_cost + costs.getRadiusBasedStreamingCost(radius); + } + } + else + { + return linkset_base_cost + costs.getRadiusBasedStreamingCost(radius); + } + } + else + { + return 0.f; + } } -S32 LLVOVolume::setTEGlow(const U8 te, const F32 glow) +// virtual +bool LLVOVolume::getCostData(LLMeshCostData& costs) const { - S32 res = LLViewerObject::setTEGlow(te, glow); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; -} + if (isMesh()) + { + return gMeshRepo.getCostData(getVolume()->getParams().getSculptID(), costs); + } + else + { + LLVolume* volume = getVolume(); + S32 counts[4]; + LLVolume::getLoDTriangleCounts(volume->getParams(), counts); -void LLVOVolume::setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID &pMaterialID, const LLMaterialPtr pMaterialParams, U32 te) -{ - LLVOVolume* pVol = (LLVOVolume*)gObjectList.findObject(objectID); - if (pVol) - { - LL_DEBUGS("MaterialTEs") << "materialid " << pMaterialID.asString() << " to TE " << te << LL_ENDL; - if (te >= pVol->getNumTEs()) - return; + LLSD header; + header["lowest_lod"]["size"] = counts[0] * 10; + header["low_lod"]["size"] = counts[1] * 10; + header["medium_lod"]["size"] = counts[2] * 10; + header["high_lod"]["size"] = counts[3] * 10; - LLTextureEntry* texture_entry = pVol->getTE(te); - if (texture_entry && (texture_entry->getMaterialID() == pMaterialID)) - { - pVol->setTEMaterialParams(te, pMaterialParams); - } - } + return gMeshRepo.getCostData(header, costs); + } } -S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) +//static +void LLVOVolume::updateRenderComplexity() { - S32 res = LLViewerObject::setTEMaterialID(te, pMaterialID); - LL_DEBUGS("MaterialTEs") << "te "<< (S32)te << " materialid " << pMaterialID.asString() << " res " << res - << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this), te) ? " selected" : " not selected" ) - << LL_ENDL; - - LL_DEBUGS("MaterialTEs") << " " << pMaterialID.asString() << LL_ENDL; - if (res) - { - LLMaterialMgr::instance().getTE(getRegion()->getRegionID(), pMaterialID, te, boost::bind(&LLVOVolume::setTEMaterialParamsCallbackTE, getID(), _1, _2, _3)); - - setChanged(ALL_CHANGED); - if (!mDrawable.isNull()) - { - gPipeline.markTextured(mDrawable); - gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL); - } - mFaceMappingChanged = TRUE; - } - return res; + mRenderComplexity_last = mRenderComplexity_current; + mRenderComplexity_current = 0; } -bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture) -{ //Ok, here we have confirmation about texture creation, check our wait-list - //and make changes, or return false - - std::pair range = mWaitingTextureInfo.equal_range(texture->getID()); - - typedef std::map map_te_material; - map_te_material new_material; - - for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it) - { - LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te); - - //here we just interesting in DIFFUSE_MAP only! - if(NULL != cur_material.get() && LLRender::DIFFUSE_MAP == range_it->second.map && GL_RGBA != texture->getPrimaryFormat()) - { //ok let's check the diffuse mode - switch(cur_material->getDiffuseAlphaMode()) - { - case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: - case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: - case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: - { //uups... we have non 32 bit texture with LLMaterial::DIFFUSE_ALPHA_MODE_* => LLMaterial::DIFFUSE_ALPHA_MODE_NONE - - LLMaterialPtr mat = NULL; - map_te_material::iterator it = new_material.find(range_it->second.te); - if(new_material.end() == it) { - mat = new LLMaterial(cur_material->asLLSD()); - new_material.insert(map_te_material::value_type(range_it->second.te, mat)); - } else { - mat = it->second; - } - - mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); +U32 LLVOVolume::getTriangleCount(S32* vcount) const +{ + U32 count = 0; + LLVolume* volume = getVolume(); + if (volume) + { + count = volume->getNumTriangles(vcount); + } - } break; - } //switch - } //if - } //for + return count; +} - //setup new materials - for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) - { - LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second); - LLViewerObject::setTEMaterialParams(it->first, it->second); - } +U32 LLVOVolume::getHighLODTriangleCount() +{ + U32 ret = 0; - //clear wait-list - mWaitingTextureInfo.erase(range.first, range.second); + LLVolume* volume = getVolume(); - return 0 != new_material.size(); -} + if (!isSculpted()) + { + LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); + ret = ref->getNumTriangles(); + LLPrimitive::getVolumeManager()->unrefVolume(ref); + } + else if (isMesh()) + { + LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); + if (!ref->isMeshAssetLoaded() || ref->getNumVolumeFaces() == 0) + { + gMeshRepo.loadMesh(this, volume->getParams(), LLModel::LOD_HIGH); + } + ret = ref->getNumTriangles(); + LLPrimitive::getVolumeManager()->unrefVolume(ref); + } + else + { //default sculpts have a constant number of triangles + ret = 31*2*31; //31 rows of 31 columns of quads for a 32x32 vertex patch + } -bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture) -{ //Ok, here if we wait information about texture and it's missing - //then depending from the texture map (diffuse, normal, or specular) - //make changes in material and confirm it. If not return false. - std::pair range = mWaitingTextureInfo.equal_range(texture->getID()); - if(range.first == range.second) return false; - - typedef std::map map_te_material; - map_te_material new_material; - - for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it) - { - LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te); - if (cur_material.isNull()) - continue; - - switch(range_it->second.map) - { - case LLRender::DIFFUSE_MAP: - { - if(LLMaterial::DIFFUSE_ALPHA_MODE_NONE != cur_material->getDiffuseAlphaMode()) - { //missing texture + !LLMaterial::DIFFUSE_ALPHA_MODE_NONE => LLMaterial::DIFFUSE_ALPHA_MODE_NONE - LLMaterialPtr mat = NULL; - map_te_material::iterator it = new_material.find(range_it->second.te); - if(new_material.end() == it) { - mat = new LLMaterial(cur_material->asLLSD()); - new_material.insert(map_te_material::value_type(range_it->second.te, mat)); - } else { - mat = it->second; - } - - mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); - } - } break; - case LLRender::NORMAL_MAP: - { //missing texture => reset material texture id - LLMaterialPtr mat = NULL; - map_te_material::iterator it = new_material.find(range_it->second.te); - if(new_material.end() == it) { - mat = new LLMaterial(cur_material->asLLSD()); - new_material.insert(map_te_material::value_type(range_it->second.te, mat)); - } else { - mat = it->second; - } - - mat->setNormalID(LLUUID::null); - } break; - case LLRender::SPECULAR_MAP: - { //missing texture => reset material texture id - LLMaterialPtr mat = NULL; - map_te_material::iterator it = new_material.find(range_it->second.te); - if(new_material.end() == it) { - mat = new LLMaterial(cur_material->asLLSD()); - new_material.insert(map_te_material::value_type(range_it->second.te, mat)); - } else { - mat = it->second; - } - - mat->setSpecularID(LLUUID::null); - } break; - case LLRender::NUM_TEXTURE_CHANNELS: - //nothing to do, make compiler happy - break; - } //switch - } //for - - //setup new materials - for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) - { - LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), it->second); - LLViewerObject::setTEMaterialParams(it->first, it->second); - } - - //clear wait-list - mWaitingTextureInfo.erase(range.first, range.second); - - return 0 != new_material.size(); + return ret; } -S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) +//static +void LLVOVolume::preUpdateGeom() { - LLMaterialPtr pMaterial = const_cast(pMaterialParams); - - if(pMaterialParams) - { //check all of them according to material settings - - LLViewerTexture *img_diffuse = getTEImage(te); - LLViewerTexture *img_normal = getTENormalMap(te); - LLViewerTexture *img_specular = getTESpecularMap(te); - - llassert(NULL != img_diffuse); - - LLMaterialPtr new_material = NULL; - - //diffuse - if(NULL != img_diffuse) - { //guard - if(0 == img_diffuse->getPrimaryFormat() && !img_diffuse->isMissingAsset()) - { //ok here we don't have information about texture, let's belief and leave material settings - //but we remember this case - mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(img_diffuse->getID(), material_info(LLRender::DIFFUSE_MAP, te))); - } - else - { - bool bSetDiffuseNone = false; - if(img_diffuse->isMissingAsset()) - { - bSetDiffuseNone = true; - } - else - { - switch(pMaterialParams->getDiffuseAlphaMode()) - { - case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: - case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: - case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: - { //all of them modes available only for 32 bit textures - if(GL_RGBA != img_diffuse->getPrimaryFormat()) - { - bSetDiffuseNone = true; - } - } break; - } - } //else - - - if(bSetDiffuseNone) - { //upps... we should substitute this material with LLMaterial::DIFFUSE_ALPHA_MODE_NONE - new_material = new LLMaterial(pMaterialParams->asLLSD()); - new_material->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); - } - } - } - - //normal - if(LLUUID::null != pMaterialParams->getNormalID()) - { - if(img_normal && img_normal->isMissingAsset() && img_normal->getID() == pMaterialParams->getNormalID()) - { - if(!new_material) { - new_material = new LLMaterial(pMaterialParams->asLLSD()); - } - new_material->setNormalID(LLUUID::null); - } - else if(NULL == img_normal || 0 == img_normal->getPrimaryFormat()) - { //ok here we don't have information about texture, let's belief and leave material settings - //but we remember this case - mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getNormalID(), material_info(LLRender::NORMAL_MAP,te))); - } - - } - - - //specular - if(LLUUID::null != pMaterialParams->getSpecularID()) - { - if(img_specular && img_specular->isMissingAsset() && img_specular->getID() == pMaterialParams->getSpecularID()) - { - if(!new_material) { - new_material = new LLMaterial(pMaterialParams->asLLSD()); - } - new_material->setSpecularID(LLUUID::null); - } - else if(NULL == img_specular || 0 == img_specular->getPrimaryFormat()) - { //ok here we don't have information about texture, let's belief and leave material settings - //but we remember this case - mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getSpecularID(), material_info(LLRender::SPECULAR_MAP, te))); - } - } - - if(new_material) { - pMaterial = new_material; - LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), pMaterial); - } - } - - S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial); - - LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterial) ? pMaterial->asLLSD() : LLSD("null")) << " res " << res - << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this), te) ? " selected" : " not selected" ) - << LL_ENDL; - setChanged(ALL_CHANGED); - if (!mDrawable.isNull()) - { - gPipeline.markTextured(mDrawable); - gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL); - } - mFaceMappingChanged = TRUE; - return TEM_CHANGE_TEXTURE; + sNumLODChanges = 0; } -S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t) +void LLVOVolume::parameterChanged(U16 param_type, bool local_origin) { - S32 res = LLViewerObject::setTEScale(te, s, t); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + LLViewerObject::parameterChanged(param_type, local_origin); } -S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s) +void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin) { - S32 res = LLViewerObject::setTEScaleS(te, s); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + LLViewerObject::parameterChanged(param_type, data, in_use, local_origin); + if (mVolumeImpl) + { + mVolumeImpl->onParameterChanged(param_type, data, in_use, local_origin); + } + if (!local_origin && param_type == LLNetworkData::PARAMS_EXTENDED_MESH) + { + U32 extended_mesh_flags = getExtendedMeshFlags(); + bool enabled = (extended_mesh_flags & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG); + bool was_enabled = (getControlAvatar() != NULL); + if (enabled != was_enabled) + { + LL_DEBUGS("AnimatedObjects") << this + << " calling onSetExtendedMeshFlags, enabled " << (U32) enabled + << " was_enabled " << (U32) was_enabled + << " local_origin " << (U32) local_origin + << LL_ENDL; + onSetExtendedMeshFlags(extended_mesh_flags); + } + } + if (mDrawable.notNull()) + { + BOOL is_light = getIsLight(); + if (is_light != mDrawable->isState(LLDrawable::LIGHT)) + { + gPipeline.setLight(mDrawable, is_light); + } + } } -S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t) +void LLVOVolume::setSelected(BOOL sel) { - S32 res = LLViewerObject::setTEScaleT(te, t); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + LLViewerObject::setSelected(sel); + if (isAnimatedObject()) + { + getRootEdit()->recursiveMarkForUpdate(TRUE); + } + else + { + if (mDrawable.notNull()) + { + markForUpdate(TRUE); + } + } } -void LLVOVolume::updateTEData() -{ - /*if (mDrawable.notNull()) - { - mFaceMappingChanged = TRUE; - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE); - }*/ +void LLVOVolume::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) +{ } -bool LLVOVolume::hasMedia() const +F32 LLVOVolume::getBinRadius() { - bool result = false; - const U8 numTEs = getNumTEs(); - for (U8 i = 0; i < numTEs; i++) - { - const LLTextureEntry* te = getTE(i); - if(te->hasMedia()) - { - result = true; - break; - } - } - return result; -} + F32 radius; + + F32 scale = 1.f; -LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id) -{ - LLVolume* volume = getVolume(); - LLVector4a result; - result.clear(); + S32 size_factor = llmax(gSavedSettings.getS32("OctreeStaticObjectSizeFactor"), 1); + S32 attachment_size_factor = llmax(gSavedSettings.getS32("OctreeAttachmentSizeFactor"), 1); + LLVector3 distance_factor = gSavedSettings.getVector3("OctreeDistanceFactor"); + LLVector3 alpha_distance_factor = gSavedSettings.getVector3("OctreeAlphaDistanceFactor"); + const LLVector4a* ext = mDrawable->getSpatialExtents(); + + BOOL shrink_wrap = mDrawable->isAnimating(); + BOOL alpha_wrap = FALSE; + + if (!isHUDAttachment()) + { + for (S32 i = 0; i < mDrawable->getNumFaces(); i++) + { + LLFace* face = mDrawable->getFace(i); + if (!face) continue; + if (face->getPoolType() == LLDrawPool::POOL_ALPHA && + !face->canRenderAsMask()) + { + alpha_wrap = TRUE; + break; + } + } + } + else + { + shrink_wrap = FALSE; + } - LLVector3 ret; + if (alpha_wrap) + { + LLVector3 bounds = getScale(); + radius = llmin(bounds.mV[1], bounds.mV[2]); + radius = llmin(radius, bounds.mV[0]); + radius *= 0.5f; + radius *= 1.f+mDrawable->mDistanceWRTCamera*alpha_distance_factor[1]; + radius += mDrawable->mDistanceWRTCamera*alpha_distance_factor[0]; + } + else if (shrink_wrap) + { + LLVector4a rad; + rad.setSub(ext[1], ext[0]); + + radius = rad.getLength3().getF32()*0.5f; + } + else if (mDrawable->isStatic()) + { + F32 szf = size_factor; - if (volume && face_id < volume->getNumVolumeFaces()) - { - const LLVolumeFace& face = volume->getVolumeFace(face_id); - for (S32 i = 0; i < (S32)face.mNumVertices; ++i) - { - result.add(face.mNormals[i]); - } + radius = llmax(mDrawable->getRadius(), szf); + + radius = powf(radius, 1.f+szf/radius); - LLVector3 ret(result.getF32ptr()); - ret = volumeDirectionToAgent(ret); - ret.normVec(); - } - - return ret; -} + radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1]; + radius += mDrawable->mDistanceWRTCamera * distance_factor[0]; + } + else if (mDrawable->getVObj()->isAttachment()) + { + radius = llmax((S32) mDrawable->getRadius(),1)*attachment_size_factor; + } + else + { + radius = mDrawable->getRadius(); + radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1]; + radius += mDrawable->mDistanceWRTCamera * distance_factor[0]; + } -void LLVOVolume::requestMediaDataUpdate(bool isNew) -{ - if (sObjectMediaClient) - sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew)); + return llclamp(radius*scale, 0.5f, 256.f); } -bool LLVOVolume::isMediaDataBeingFetched() const +const LLVector3 LLVOVolume::getPivotPositionAgent() const { - // I know what I'm doing by const_casting this away: this is just - // a wrapper class that is only going to do a lookup. - return (sObjectMediaClient) ? sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast(this), false)) : false; + if (mVolumeImpl) + { + return mVolumeImpl->getPivotPosition(); + } + return LLViewerObject::getPivotPositionAgent(); } -void LLVOVolume::cleanUpMediaImpls() +void LLVOVolume::onShift(const LLVector4a &shift_vector) { - // Iterate through our TEs and remove any Impls that are no longer used - const U8 numTEs = getNumTEs(); - for (U8 i = 0; i < numTEs; i++) - { - const LLTextureEntry* te = getTE(i); - if( ! te->hasMedia()) - { - // Delete the media IMPL! - removeMediaImpl(i) ; - } - } -} + if (mVolumeImpl) + { + mVolumeImpl->onShift(shift_vector); + } -void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version) -{ - // media_data_array is an array of media entry maps - // media_version is the version string in the response. - U32 fetched_version = LLTextureEntry::getVersionFromMediaVersionString(media_version); - - // Only update it if it is newer! - if ( (S32)fetched_version > mLastFetchedMediaVersion) - { - mLastFetchedMediaVersion = fetched_version; - //LL_INFOS() << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << LL_ENDL; - - LLSD::array_const_iterator iter = media_data_array.beginArray(); - LLSD::array_const_iterator end = media_data_array.endArray(); - U8 texture_index = 0; - for (; iter != end; ++iter, ++texture_index) - { - syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/); - } - } + updateRelativeXform(); } -void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool merge, bool ignore_agent) +const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const { - if(mDead) - { - // If the object has been marked dead, don't process media updates. - return; - } - - LLTextureEntry *te = getTE(texture_index); - if(!te) - { - return ; - } - - LL_DEBUGS("MediaOnAPrim") << "BEFORE: texture_index = " << texture_index - << " hasMedia = " << te->hasMedia() << " : " - << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << LL_ENDL; - - std::string previous_url; - LLMediaEntry* mep = te->getMediaData(); - if(mep) - { - // Save the "current url" from before the update so we can tell if - // it changes. - previous_url = mep->getCurrentURL(); - } - - if (merge) - { - te->mergeIntoMediaData(media_data); - } - else { - // XXX Question: what if the media data is undefined LLSD, but the - // update we got above said that we have media flags?? Here we clobber - // that, assuming the data from the service is more up-to-date. - te->updateMediaData(media_data); - } - - mep = te->getMediaData(); - if(mep) - { - bool update_from_self = false; - if (!ignore_agent) - { - LLUUID updating_agent = LLTextureEntry::getAgentIDFromMediaVersionString(getMediaURL()); - update_from_self = (updating_agent == gAgent.getID()); - } - viewer_media_t media_impl = LLViewerMedia::updateMediaImpl(mep, previous_url, update_from_self); - - addMediaImpl(media_impl, texture_index) ; - } - else - { - removeMediaImpl(texture_index); - } - - LL_DEBUGS("MediaOnAPrim") << "AFTER: texture_index = " << texture_index - << " hasMedia = " << te->hasMedia() << " : " - << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << LL_ENDL; + if (mVolumeImpl) + { + return mVolumeImpl->getWorldMatrix(xform); + } + return xform->getWorldMatrix(); } -void LLVOVolume::mediaNavigateBounceBack(U8 texture_index) -{ - // Find the media entry for this navigate - const LLMediaEntry* mep = NULL; - viewer_media_t impl = getMediaImpl(texture_index); - LLTextureEntry *te = getTE(texture_index); - if(te) - { - mep = te->getMediaData(); - } - - if (mep && impl) - { - std::string url = mep->getCurrentURL(); - // Look for a ":", if not there, assume "http://" - if (!url.empty() && std::string::npos == url.find(':')) - { - url = "http://" + url; - } - // If the url we're trying to "bounce back" to is either empty or not - // allowed by the whitelist, try the home url. If *that* doesn't work, - // set the media as failed and unload it - if (url.empty() || !mep->checkCandidateUrl(url)) +void LLVOVolume::markForUpdate(BOOL priority) +{ + if (debugLoggingEnabled("AnimatedObjectsLinkset")) + { + if (isAnimatedObject() && isRiggedMesh()) { - url = mep->getHomeURL(); - // Look for a ":", if not there, assume "http://" - if (!url.empty() && std::string::npos == url.find(':')) - { - url = "http://" + url; - } - } - if (url.empty() || !mep->checkCandidateUrl(url)) - { - // The url to navigate back to is not good, and we have nowhere else - // to go. - LL_WARNS("MediaOnAPrim") << "FAILED to bounce back URL \"" << url << "\" -- unloading impl" << LL_ENDL; - impl->setMediaFailed(true); - } - // Make sure we are not bouncing to url we came from - else if (impl->getCurrentMediaURL() != url) - { - // Okay, navigate now - LL_INFOS("MediaOnAPrim") << "bouncing back to URL: " << url << LL_ENDL; - impl->navigateTo(url, "", false, true); + std::string vobj_name = llformat("Vol%p", this); + F32 est_tris = getEstTrianglesMax(); + LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " markForUpdate, tris " << est_tris << LL_ENDL; } } + + LLViewerObject::markForUpdate(priority); + mVolumeChanged = TRUE; } -bool LLVOVolume::hasMediaPermission(const LLMediaEntry* media_entry, MediaPermType perm_type) +LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const { - // NOTE: This logic ALMOST duplicates the logic in the server (in particular, in llmediaservice.cpp). - if (NULL == media_entry ) return false; // XXX should we assert here? - - // The agent has permissions if: - // - world permissions are on, or - // - group permissions are on, and agent_id is in the group, or - // - agent permissions are on, and agent_id is the owner - - // *NOTE: We *used* to check for modify permissions here (i.e. permissions were - // granted if permModify() was true). However, this doesn't make sense in the - // viewer: we don't want to show controls or allow interaction if the author - // has deemed it so. See DEV-42115. - - U8 media_perms = (perm_type == MEDIA_PERM_INTERACT) ? media_entry->getPermsInteract() : media_entry->getPermsControl(); - - // World permissions - if (0 != (media_perms & LLMediaEntry::PERM_ANYONE)) - { - return true; - } - - // Group permissions - else if (0 != (media_perms & LLMediaEntry::PERM_GROUP)) - { - LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(this); - if (obj_perm && gAgent.isInGroup(obj_perm->getGroup())) - { - return true; - } - } - - // Owner permissions - else if (0 != (media_perms & LLMediaEntry::PERM_OWNER) && permYouOwner()) + LLVector3 ret = pos - getRenderPosition(); + ret = ret * ~getRenderRotation(); + if (!isVolumeGlobal()) { - return true; + LLVector3 objScale = getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + ret.scaleVec(invObjScale); } - return false; - + return ret; } -void LLVOVolume::mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location) +LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const { - bool block_navigation = false; - // FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed - // to deal with multiple face indices. - int face_index = getFaceIndexWithMediaImpl(impl, -1); - - // Find the media entry for this navigate - LLMediaEntry* mep = NULL; - LLTextureEntry *te = getTE(face_index); - if(te) - { - mep = te->getMediaData(); - } - - if(mep) - { - if(!mep->checkCandidateUrl(new_location)) - { - block_navigation = true; - } - if (!block_navigation && !hasMediaPermission(mep, MEDIA_PERM_INTERACT)) - { - block_navigation = true; - } - } - else - { - LL_WARNS("MediaOnAPrim") << "Couldn't find media entry!" << LL_ENDL; - } - - if(block_navigation) - { - LL_INFOS("MediaOnAPrim") << "blocking navigate to URI " << new_location << LL_ENDL; - - // "bounce back" to the current URL from the media entry - mediaNavigateBounceBack(face_index); - } - else if (sObjectMediaNavigateClient) - { - - LL_DEBUGS("MediaOnAPrim") << "broadcasting navigate with URI " << new_location << LL_ENDL; - - sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this, false), face_index, new_location); - } + LLVector3 ret = dir * ~getRenderRotation(); + + LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); + ret.scaleVec(objScale); + + return ret; } -void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event) +LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const { - switch(event) - { - - case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED: - { - switch(impl->getNavState()) - { - case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED: - { - // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. - mediaNavigated(impl, plugin, plugin->getLocation()); - } - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS: - // This navigate didn't change the current URL. - LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: - // This is the first location changed event after the start of a server-directed nav. Don't broadcast it. - LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; - break; - - default: - // This is a subsequent location-changed due to a redirect. Don't broadcast. - LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (redirect)" << LL_ENDL; - break; - } - } - break; - - case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE: - { - switch(impl->getNavState()) - { - case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: - { - // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. - mediaNavigated(impl, plugin, plugin->getNavigateURI()); - } - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS: - // This navigate didn't change the current URL. - LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: - // This is the the navigate complete event from a server-directed nav. Don't broadcast it. - LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; - break; - - default: - // For all other states, the navigate should have been handled by LOCATION_CHANGED events already. - break; - } - } - break; - - default: - break; - } + LLVector3 ret = dir; + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + ret.scaleVec(objScale); + } + ret = ret * getRenderRotation(); + ret += getRenderPosition(); + + return ret; } -void LLVOVolume::sendMediaDataUpdate() +LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const { - if (sObjectMediaClient) - sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this, false)); -} + LLVector3 ret = dir; + LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + ret.scaleVec(invObjScale); + ret = ret * getRenderRotation(); -void LLVOVolume::removeMediaImpl(S32 texture_index) -{ - if(mMediaImplList.size() <= (U32)texture_index || mMediaImplList[texture_index].isNull()) - { - return ; - } - - //make the face referencing to mMediaImplList[texture_index] to point back to the old texture. - if(mDrawable && texture_index < mDrawable->getNumFaces()) - { - LLFace* facep = mDrawable->getFace(texture_index) ; - if(facep) - { - LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; - if(media_tex) - { - media_tex->removeMediaFromFace(facep) ; - } - } - } - - //check if some other face(s) of this object reference(s)to this media impl. - S32 i ; - S32 end = (S32)mMediaImplList.size() ; - for(i = 0; i < end ; i++) - { - if( i != texture_index && mMediaImplList[i] == mMediaImplList[texture_index]) - { - break ; - } - } - - if(i == end) //this object does not need this media impl. - { - mMediaImplList[texture_index]->removeObject(this) ; - } - - mMediaImplList[texture_index] = NULL ; - return ; + return ret; } -void LLVOVolume::addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) -{ - if((S32)mMediaImplList.size() < texture_index + 1) - { - mMediaImplList.resize(texture_index + 1) ; - } - - if(mMediaImplList[texture_index].notNull()) - { - if(mMediaImplList[texture_index] == media_impl) - { - return ; - } - - removeMediaImpl(texture_index) ; - } - - mMediaImplList[texture_index] = media_impl; - media_impl->addObject(this) ; - - //add the face to show the media if it is in playing - if(mDrawable) - { - LLFace* facep(NULL); - if( texture_index < mDrawable->getNumFaces() ) - { - facep = mDrawable->getFace(texture_index) ; - } - - if(facep) - { - LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; - if(media_tex) - { - media_tex->addMediaToFace(facep) ; - } - } - else //the face is not available now, start media on this face later. - { - media_impl->setUpdated(TRUE) ; - } - } - return ; -} -viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const +BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp, + LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) + { - if(mMediaImplList.size() > face_id) - { - return mMediaImplList[face_id]; - } - return NULL; -} + if (!mbCanSelect + || mDrawable->isDead() + || !gPipeline.hasRenderType(mDrawable->getRenderType())) + { + return FALSE; + } -F64 LLVOVolume::getTotalMediaInterest() const -{ - // If this object is currently focused, this object has "high" interest - if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == getID()) - return F64_MAX; - - F64 interest = (F64)-1.0; // means not interested; + BOOL ret = FALSE; + + LLVolume* volume = getVolume(); + + bool transform = true; + + if (mDrawable->isState(LLDrawable::RIGGED)) + { + if ((pick_rigged) || (getAvatar() && (getAvatar()->isSelf()) && (LLFloater::isVisible(gFloaterTools)))) + { + updateRiggedVolume(true); + volume = mRiggedVolume; + transform = false; + } + else + { //cannot pick rigged attachments on other avatars or when not in build mode + return FALSE; + } + } - // If this object is selected, this object has "high" interest, but since - // there can be more than one, we still add in calculated impl interest - // XXX Sadly, 'contains()' doesn't take a const :( - if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this))) - interest = F64_MAX / 2.0; - - int i = 0; - const int end = getNumTEs(); - for ( ; i < end; ++i) - { - const viewer_media_t &impl = getMediaImpl(i); - if (!impl.isNull()) - { - if (interest == (F64)-1.0) interest = (F64)0.0; - interest += impl->getInterest(); - } - } - return interest; -} + if (volume) + { + LLVector4a local_start = start; + LLVector4a local_end = end; + + if (transform) + { + LLVector3 v_start(start.getF32ptr()); + LLVector3 v_end(end.getF32ptr()); + + v_start = agentPositionToVolume(v_start); + v_end = agentPositionToVolume(v_end); -S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id) -{ - S32 end = (S32)mMediaImplList.size() ; - for(S32 face_id = start_face_id + 1; face_id < end; face_id++) - { - if(mMediaImplList[face_id] == media_impl) - { - return face_id ; - } - } - return -1 ; -} + local_start.load3(v_start.mV); + local_end.load3(v_end.mV); + } + + LLVector4a p; + LLVector4a n; + LLVector2 tc; + LLVector4a tn; -//---------------------------------------------------------------------------- + if (intersection != NULL) + { + p = *intersection; + } -void LLVOVolume::setLightTextureID(LLUUID id) -{ - LLViewerTexture* old_texturep = getLightTexture(); // same as mLightTexture, but inits if nessesary - if (id.notNull()) - { - if (!hasLightTexture()) - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true); - } - else if (old_texturep) - { - old_texturep->removeVolume(LLRender::LIGHT_TEX, this); - } - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block && param_block->getLightTexture() != id) - { - param_block->setLightTexture(id); - parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); - } - LLViewerTexture* tex = getLightTexture(); - if (tex) - { - tex->addVolume(LLRender::LIGHT_TEX, this); // new texture - } - else - { - LL_WARNS() << "Can't get light texture for ID " << id.asString() << LL_ENDL; - } - } - else if (hasLightTexture()) - { - if (old_texturep) - { - old_texturep->removeVolume(LLRender::LIGHT_TEX, this); - } - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); - parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); - mLightTexture = NULL; - } -} + if (tex_coord != NULL) + { + tc = *tex_coord; + } -void LLVOVolume::setSpotLightParams(LLVector3 params) -{ - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block && param_block->getParams() != params) - { - param_block->setParams(params); - parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); - } -} - -void LLVOVolume::setIsLight(BOOL is_light) -{ - BOOL was_light = getIsLight(); - if (is_light != was_light) - { - if (is_light) - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, TRUE, true); - } - else - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, FALSE, true); - } - - if (is_light) - { - // Add it to the pipeline mLightSet - gPipeline.setLight(mDrawable, TRUE); - } - else - { - // Not a light. Remove it from the pipeline's light set. - gPipeline.setLight(mDrawable, FALSE); - } - } -} + if (normal != NULL) + { + n = *normal; + } -void LLVOVolume::setLightColor(const LLColor3& color) -{ - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getColor() != color) - { - param_block->setColor(LLColor4(color, param_block->getColor().mV[3])); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - } + if (tangent != NULL) + { + tn = *tangent; + } + + S32 face_hit = -1; + + S32 start_face, end_face; + if (face == -1) + { + start_face = 0; + end_face = volume->getNumVolumeFaces(); + } + else + { + start_face = face; + end_face = face+1; + } + pick_transparent |= isHiglightedOrBeacon(); + bool special_cursor = specialHoverCursor(); + for (S32 i = start_face; i < end_face; ++i) + { + if (!special_cursor && !pick_transparent && getTE(i) && getTE(i)->getColor().mV[3] == 0.f) + { //don't attempt to pick completely transparent faces unless + //pick_transparent is true + continue; + } + + face_hit = volume->lineSegmentIntersect(local_start, local_end, i, + &p, &tc, &n, &tn); + + if (face_hit >= 0 && mDrawable->getNumFaces() > face_hit) + { + LLFace* face = mDrawable->getFace(face_hit); + + bool ignore_alpha = false; + + const LLTextureEntry* te = face->getTextureEntry(); + if (te) + { + LLMaterial* mat = te->getMaterialParams(); + if (mat) + { + U8 mode = mat->getDiffuseAlphaMode(); + + if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE || + mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE) + { + ignore_alpha = true; + } + } + } + + if (face && + (ignore_alpha || + pick_transparent || + !face->getTexture() || + !face->getTexture()->hasGLTexture() || + face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)))) + { + local_end = p; + if (face_hitp != NULL) + { + *face_hitp = face_hit; + } + + if (intersection != NULL) + { + if (transform) + { + LLVector3 v_p(p.getF32ptr()); + + intersection->load3(volumePositionToAgent(v_p).mV); // must map back to agent space + } + else + { + *intersection = p; + } + } + + if (normal != NULL) + { + if (transform) + { + LLVector3 v_n(n.getF32ptr()); + normal->load3(volumeDirectionToAgent(v_n).mV); + } + else + { + *normal = n; + } + (*normal).normalize3fast(); + } + + if (tangent != NULL) + { + if (transform) + { + LLVector3 v_tn(tn.getF32ptr()); + + LLVector4a trans_tangent; + trans_tangent.load3(volumeDirectionToAgent(v_tn).mV); + + LLVector4Logical mask; + mask.clear(); + mask.setElement<3>(); + + tangent->setSelectWithMask(mask, tn, trans_tangent); + } + else + { + *tangent = tn; + } + (*tangent).normalize3fast(); + } + + if (tex_coord != NULL) + { + *tex_coord = tc; + } + + ret = TRUE; + } + } + } + } + + return ret; } -void LLVOVolume::setLightIntensity(F32 intensity) +bool LLVOVolume::treatAsRigged() { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getColor().mV[3] != intensity) - { - param_block->setColor(LLColor4(LLColor3(param_block->getColor()), intensity)); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } + return isSelected() && + (isAttachment() || isAnimatedObject()) && + mDrawable.notNull() && + mDrawable->isState(LLDrawable::RIGGED); } -void LLVOVolume::setLightRadius(F32 radius) +LLRiggedVolume* LLVOVolume::getRiggedVolume() { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getRadius() != radius) - { - param_block->setRadius(radius); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } + return mRiggedVolume; } -void LLVOVolume::setLightFalloff(F32 falloff) +void LLVOVolume::clearRiggedVolume() { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getFalloff() != falloff) - { - param_block->setFalloff(falloff); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } + if (mRiggedVolume.notNull()) + { + mRiggedVolume = NULL; + updateRelativeXform(); + } } -void LLVOVolume::setLightCutoff(F32 cutoff) +void LLVOVolume::updateRiggedVolume(bool force_update) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getCutoff() != cutoff) - { - param_block->setCutoff(cutoff); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } -} + //Update mRiggedVolume to match current animation frame of avatar. + //Also update position/size in octree. -//---------------------------------------------------------------------------- + if ((!force_update) && (!treatAsRigged())) + { + clearRiggedVolume(); + + return; + } -BOOL LLVOVolume::getIsLight() const -{ - return getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT); -} + LLVolume* volume = getVolume(); + const LLMeshSkinInfo* skin = getSkinInfo(); + if (!skin) + { + clearRiggedVolume(); + return; + } -LLColor3 LLVOVolume::getLightBaseColor() const -{ - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return LLColor3(param_block->getColor()); - } - else - { - return LLColor3(1,1,1); - } -} + LLVOAvatar* avatar = getAvatar(); + if (!avatar) + { + clearRiggedVolume(); + return; + } -LLColor3 LLVOVolume::getLightColor() const -{ - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return LLColor3(param_block->getColor()) * param_block->getColor().mV[3]; - } - else - { - return LLColor3(1,1,1); - } -} + if (!mRiggedVolume) + { + LLVolumeParams p; + mRiggedVolume = new LLRiggedVolume(p); + updateRelativeXform(); + } -LLUUID LLVOVolume::getLightTextureID() const -{ - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block) - { - return param_block->getLightTexture(); - } - } - - return LLUUID::null; + mRiggedVolume->update(skin, avatar, volume); } +static LLTrace::BlockTimerStatHandle FTM_SKIN_RIGGED("Skin"); +static LLTrace::BlockTimerStatHandle FTM_RIGGED_OCTREE("Octree"); -LLVector3 LLVOVolume::getSpotLightParams() const +void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume) { - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block) - { - return param_block->getParams(); - } - } - - return LLVector3(); -} + bool copy = false; + if (volume->getNumVolumeFaces() != getNumVolumeFaces()) + { + copy = true; + } -F32 LLVOVolume::getSpotLightPriority() const -{ - return mSpotLightPriority; -} + for (S32 i = 0; i < volume->getNumVolumeFaces() && !copy; ++i) + { + const LLVolumeFace& src_face = volume->getVolumeFace(i); + const LLVolumeFace& dst_face = getVolumeFace(i); -void LLVOVolume::updateSpotLightPriority() -{ - LLVector3 pos = mDrawable->getPositionAgent(); - LLVector3 at(0,0,-1); - at *= getRenderRotation(); + if (src_face.mNumIndices != dst_face.mNumIndices || + src_face.mNumVertices != dst_face.mNumVertices) + { + copy = true; + } + } + + if (copy) + { + copyVolumeFaces(volume); + } + else + { + bool is_paused = avatar && avatar->areAnimationsPaused(); + if (is_paused) + { + S32 frames_paused = LLFrameTimer::getFrameCount() - avatar->getMotionController().getPausedFrame(); + if (frames_paused > 2) + { + return; + } + } + } + + + //build matrix palette + static const size_t kMaxJoints = LL_MAX_JOINTS_PER_MESH_OBJECT; + + LLMatrix4a mat[kMaxJoints]; + U32 maxJoints = LLSkinningUtil::getMeshJointCount(skin); + LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, maxJoints, skin, avatar); - F32 r = getLightRadius()*0.5f; + S32 rigged_vert_count = 0; + S32 rigged_face_count = 0; + LLVector4a box_min, box_max; + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& vol_face = volume->getVolumeFace(i); + + LLVolumeFace& dst_face = mVolumeFaces[i]; + + LLVector4a* weight = vol_face.mWeights; + + if ( weight ) + { + LLSkinningUtil::checkSkinWeights(weight, dst_face.mNumVertices, skin); + LLMatrix4a bind_shape_matrix; + bind_shape_matrix.loadu(skin->mBindShapeMatrix); - pos += at * r; + LLVector4a* pos = dst_face.mPositions; - at = LLViewerCamera::getInstance()->getAtAxis(); + if (pos && dst_face.mExtents) + { + LL_RECORD_BLOCK_TIME(FTM_SKIN_RIGGED); - pos -= at * r; - - mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); + U32 max_joints = LLSkinningUtil::getMaxJointCount(); + rigged_vert_count += dst_face.mNumVertices; + rigged_face_count++; + for (U32 j = 0; j < dst_face.mNumVertices; ++j) + { + LLMatrix4a final_mat; + LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); + + LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + } - if (mLightTexture.notNull()) - { - mLightTexture->addTextureStats(mSpotLightPriority); - mLightTexture->setBoostLevel(LLGLTexture::BOOST_CLOUDS); - } -} + //update bounding box + // VFExtents change + LLVector4a& min = dst_face.mExtents[0]; + LLVector4a& max = dst_face.mExtents[1]; + min = pos[0]; + max = pos[1]; + if (i==0) + { + box_min = min; + box_max = max; + } -bool LLVOVolume::isLightSpotlight() const -{ - LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (params && getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - return params->isLightSpotlight(); - } - return false; -} + for (U32 j = 1; j < dst_face.mNumVertices; ++j) + { + min.setMin(min, pos[j]); + max.setMax(max, pos[j]); + } + box_min.setMin(min,box_min); + box_max.setMax(max,box_max); -LLViewerTexture* LLVOVolume::getLightTexture() -{ - LLUUID id = getLightTextureID(); + dst_face.mCenter->setAdd(dst_face.mExtents[0], dst_face.mExtents[1]); + dst_face.mCenter->mul(0.5f); - if (id.notNull()) - { - if (mLightTexture.isNull() || id != mLightTexture->getID()) - { - mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM); - } - } - else - { - mLightTexture = NULL; - } + } - return mLightTexture; -} + { + LL_RECORD_BLOCK_TIME(FTM_RIGGED_OCTREE); + delete dst_face.mOctree; + dst_face.mOctree = NULL; -F32 LLVOVolume::getLightIntensity() const -{ - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getColor().mV[3]; - } - else - { - return 1.f; - } + LLVector4a size; + size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]); + size.splat(size.getLength3().getF32()*0.5f); + + dst_face.createOctree(1.f); + } + } + } + mExtraDebugText = llformat("rigged %d/%d - box (%f %f %f) (%f %f %f)", + rigged_face_count, rigged_vert_count, + box_min[0], box_min[1], box_min[2], + box_max[0], box_max[1], box_max[2]); } -F32 LLVOVolume::getLightRadius() const +U32 LLVOVolume::getPartitionType() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getRadius(); - } - else - { - return 0.f; - } -} + if (isHUDAttachment()) + { + return LLViewerRegion::PARTITION_HUD; + } -F32 LLVOVolume::getLightFalloff() const -{ - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getFalloff(); - } - else - { - return 0.f; - } + return LLViewerRegion::PARTITION_VOLUME; } -F32 LLVOVolume::getLightCutoff() const +LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp) +: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB, regionp), +LLVolumeGeometryManager() { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getCutoff(); - } - else - { - return 0.f; - } + mLODPeriod = 32; + mDepthMask = FALSE; + mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; + mPartitionType = LLViewerRegion::PARTITION_VOLUME; + mSlopRatio = 0.25f; + mBufferUsage = GL_DYNAMIC_DRAW_ARB; } -U32 LLVOVolume::getVolumeInterfaceID() const +LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep, LLViewerRegion* regionp) +: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK, regionp), +LLVolumeGeometryManager() { - if (mVolumeImpl) - { - return mVolumeImpl->getID(); - } - - return 0; -} + mDepthMask = FALSE; + mLODPeriod = 32; + mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; + mPartitionType = LLViewerRegion::PARTITION_BRIDGE; + + mBufferUsage = GL_DYNAMIC_DRAW_ARB; -BOOL LLVOVolume::isFlexible() const -{ - if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE)) - { - LLVolume* volume = getVolume(); - if (volume && volume->getParams().getPathParams().getCurveType() != LL_PCODE_PATH_FLEXIBLE) - { - LLVolumeParams volume_params = getVolume()->getParams(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); - } - return TRUE; - } - else - { - return FALSE; - } + mSlopRatio = 0.25f; } -BOOL LLVOVolume::isSculpted() const +bool can_batch_texture(LLFace* facep) { - if (getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) - { - return TRUE; - } - - return FALSE; -} + if (facep->getTextureEntry()->getBumpmap()) + { //bump maps aren't worked into texture batching yet + return false; + } -BOOL LLVOVolume::isMesh() const -{ - if (isSculpted()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - U8 sculpt_type = sculpt_params->getSculptType(); + if (facep->getTextureEntry()->getMaterialParams().notNull()) + { //materials don't work with texture batching yet + return false; + } - if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - // mesh is a mesh - { - return TRUE; - } - } + if (facep->getTexture() && facep->getTexture()->getPrimaryFormat() == GL_ALPHA) + { //can't batch invisiprims + return false; + } - return FALSE; + if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) + { //texture animation breaks batches + return false; + } + + return true; } -BOOL LLVOVolume::hasLightTexture() const -{ - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - return TRUE; - } - - return FALSE; -} +const static U32 MAX_FACE_COUNT = 4096U; +int32_t LLVolumeGeometryManager::sInstanceCount = 0; +LLFace** LLVolumeGeometryManager::sFullbrightFaces = NULL; +LLFace** LLVolumeGeometryManager::sBumpFaces = NULL; +LLFace** LLVolumeGeometryManager::sSimpleFaces = NULL; +LLFace** LLVolumeGeometryManager::sNormFaces = NULL; +LLFace** LLVolumeGeometryManager::sSpecFaces = NULL; +LLFace** LLVolumeGeometryManager::sNormSpecFaces = NULL; +LLFace** LLVolumeGeometryManager::sAlphaFaces = NULL; -BOOL LLVOVolume::isVolumeGlobal() const +LLVolumeGeometryManager::LLVolumeGeometryManager() + : LLGeometryManager() { - if (mVolumeImpl) - { - return mVolumeImpl->isVolumeGlobal() ? TRUE : FALSE; - } - else if (mRiggedVolume.notNull()) - { - return TRUE; - } - - return FALSE; -} + llassert(sInstanceCount >= 0); + if (sInstanceCount == 0) + { + allocateFaces(MAX_FACE_COUNT); + } -BOOL LLVOVolume::canBeFlexible() const -{ - U8 path = getVolume()->getParams().getPathParams().getCurveType(); - return (path == LL_PCODE_PATH_FLEXIBLE || path == LL_PCODE_PATH_LINE); + ++sInstanceCount; } -BOOL LLVOVolume::setIsFlexible(BOOL is_flexible) +LLVolumeGeometryManager::~LLVolumeGeometryManager() { - BOOL res = FALSE; - BOOL was_flexible = isFlexible(); - LLVolumeParams volume_params; - if (is_flexible) - { - if (!was_flexible) - { - volume_params = getVolume()->getParams(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); - res = TRUE; - setFlags(FLAGS_USE_PHYSICS, FALSE); - setFlags(FLAGS_PHANTOM, TRUE); - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, true); - if (mDrawable) - { - mDrawable->makeActive(); - } - } - } - else - { - if (was_flexible) - { - volume_params = getVolume()->getParams(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - volume_params.setType(profile_and_hole, LL_PCODE_PATH_LINE); - res = TRUE; - setFlags(FLAGS_PHANTOM, FALSE); - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, true); - } - } - if (res) - { - res = setVolume(volume_params, 1); - if (res) - { - markForUpdate(TRUE); - } - } - return res; -} + llassert(sInstanceCount > 0); + --sInstanceCount; -const LLMeshSkinInfo* LLVOVolume::getSkinInfo() const -{ - if (getVolume()) - { - return gMeshRepo.getSkinInfo(getVolume()->getParams().getSculptID(), this); - } - else + if (sInstanceCount <= 0) { - return NULL; + freeFaces(); + sInstanceCount = 0; } } -// virtual -BOOL LLVOVolume::isRiggedMesh() const -{ - return isMesh() && getSkinInfo(); -} - -//---------------------------------------------------------------------------- -U32 LLVOVolume::getExtendedMeshFlags() const +void LLVolumeGeometryManager::allocateFaces(U32 pMaxFaceCount) { - const LLExtendedMeshParams *param_block = - (const LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH); - if (param_block) - { - return param_block->getFlags(); - } - else - { - return 0; - } + sFullbrightFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sBumpFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sSimpleFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sNormFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sSpecFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sNormSpecFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sAlphaFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); } -void LLVOVolume::onSetExtendedMeshFlags(U32 flags) +void LLVolumeGeometryManager::freeFaces() { + ll_aligned_free<64>(sFullbrightFaces); + ll_aligned_free<64>(sBumpFaces); + ll_aligned_free<64>(sSimpleFaces); + ll_aligned_free<64>(sNormFaces); + ll_aligned_free<64>(sSpecFaces); + ll_aligned_free<64>(sNormSpecFaces); + ll_aligned_free<64>(sAlphaFaces); - // The isAnySelected() check was needed at one point to prevent - // graphics problems. These are now believed to be fixed so the - // check has been disabled. - if (/*!getRootEdit()->isAnySelected() &&*/ mDrawable.notNull()) - { - // Need to trigger rebuildGeom(), which is where control avatars get created/removed - getRootEdit()->recursiveMarkForUpdate(TRUE); - } - if (isAttachment() && getAvatarAncestor()) - { - updateVisualComplexity(); - if (flags & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG) - { - // Making a rigged mesh into an animated object - getAvatarAncestor()->updateAttachmentOverrides(); - } - else - { - // Making an animated object into a rigged mesh - getAvatarAncestor()->updateAttachmentOverrides(); - } - } + sFullbrightFaces = NULL; + sBumpFaces = NULL; + sSimpleFaces = NULL; + sNormFaces = NULL; + sSpecFaces = NULL; + sNormSpecFaces = NULL; + sAlphaFaces = NULL; } -void LLVOVolume::setExtendedMeshFlags(U32 flags) +static LLTrace::BlockTimerStatHandle FTM_REGISTER_FACE("Register Face"); + +void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) { - U32 curr_flags = getExtendedMeshFlags(); - if (curr_flags != flags) + LL_RECORD_BLOCK_TIME(FTM_REGISTER_FACE); + if (type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT)) { - bool in_use = true; - setParameterEntryInUse(LLNetworkData::PARAMS_EXTENDED_MESH, in_use, true); - LLExtendedMeshParams *param_block = - (LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH); - if (param_block) - { - param_block->setFlags(flags); - } - parameterChanged(LLNetworkData::PARAMS_EXTENDED_MESH, true); - LL_DEBUGS("AnimatedObjects") << this - << " new flags " << flags << " curr_flags " << curr_flags - << ", calling onSetExtendedMeshFlags()" - << LL_ENDL; - onSetExtendedMeshFlags(flags); + LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL; } -} -bool LLVOVolume::canBeAnimatedObject() const -{ - F32 est_tris = recursiveGetEstTrianglesMax(); - if (est_tris < 0 || est_tris > getAnimatedObjectMaxTris()) + bool selected = facep->getViewerObject()->isSelected(); + + if (selected && LLSelectMgr::getInstance()->mHideSelectedObjects) { - return false; + return; } - return true; -} - -bool LLVOVolume::isAnimatedObject() const -{ - LLVOVolume *root_vol = (LLVOVolume*)getRootEdit(); - bool root_is_animated_flag = root_vol->getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG; - return root_is_animated_flag; -} -// Called any time parenting changes for a volume. Update flags and -// control av accordingly. This is called after parent has been -// changed to new_parent, but before new_parent's mChildList has changed. + //add face to drawmap + LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[type]; -// virtual -void LLVOVolume::onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent) -{ - LLVOVolume *old_volp = dynamic_cast(old_parent); + S32 idx = draw_vec.size()-1; - if (new_parent && !new_parent->isAvatar()) + BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) || + (type == LLRenderPass::PASS_INVISIBLE) || + (type == LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK) || + (type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)) || + (facep->getTextureEntry()->getFullbright()); + + if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_NORMAL)) { - if (mControlAvatar.notNull()) - { - // Here an animated object is being made the child of some - // other prim. Should remove the control av from the child. - LLControlAvatar *av = mControlAvatar; - mControlAvatar = NULL; - av->markForDeath(); - } + LL_WARNS() << "Non fullbright face has no normals!" << LL_ENDL; + return; } - if (old_volp && old_volp->isAnimatedObject()) + + const LLMatrix4* tex_mat = NULL; + if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) { - if (old_volp->getControlAvatar()) - { - // We have been removed from an animated object, need to do cleanup. - old_volp->getControlAvatar()->updateAttachmentOverrides(); - old_volp->getControlAvatar()->updateAnimations(); - } + tex_mat = facep->mTextureMatrix; } -} -// This needs to be called after onReparent(), because mChildList is -// not updated until the end of LLViewerObject::addChild() + const LLMatrix4* model_mat = NULL; -// virtual -void LLVOVolume::afterReparent() -{ - { - LL_DEBUGS("AnimatedObjects") << "new child added for parent " - << ((LLViewerObject*)getParent())->getID() << LL_ENDL; - } - - if (isAnimatedObject() && getControlAvatar()) + LLDrawable* drawable = facep->getDrawable(); + + if (drawable->isState(LLDrawable::ANIMATED_CHILD)) { - LL_DEBUGS("AnimatedObjects") << "adding attachment overrides, parent is animated object " - << ((LLViewerObject*)getParent())->getID() << LL_ENDL; - - // MAINT-8239 - doing a full rebuild whenever parent is set - // makes the joint overrides load more robustly. In theory, - // addAttachmentOverrides should be sufficient, but in - // practice doing a full rebuild helps compensate for - // notifyMeshLoaded() not being called reliably enough. - - // was: getControlAvatar()->addAttachmentOverridesForObject(this); - //getControlAvatar()->rebuildAttachmentOverrides(); - getControlAvatar()->updateAnimations(); + model_mat = &drawable->getWorldMatrix(); } - else + else if (drawable->isActive()) { - LL_DEBUGS("AnimatedObjects") << "not adding overrides, parent: " - << ((LLViewerObject*)getParent())->getID() - << " isAnimated: " << isAnimatedObject() << " cav " - << getControlAvatar() << LL_ENDL; + model_mat = &drawable->getRenderMatrix(); } -} - -//---------------------------------------------------------------------------- -static LLTrace::BlockTimerStatHandle FTM_VOVOL_RIGGING_INFO("VOVol Rigging Info"); - -void LLVOVolume::updateRiggingInfo() -{ - LL_RECORD_BLOCK_TIME(FTM_VOVOL_RIGGING_INFO); - if (isRiggedMesh()) - { - const LLMeshSkinInfo* skin = getSkinInfo(); - LLVOAvatar *avatar = getAvatar(); - LLVolume *volume = getVolume(); - if (skin && avatar && volume) - { - LL_DEBUGS("RigSpammish") << "starting, vovol " << this << " lod " << getLOD() << " last " << mLastRiggingInfoLOD << LL_ENDL; - if (getLOD()>mLastRiggingInfoLOD || getLOD()==3) - { - // Rigging info may need update - mJointRiggingInfoTab.clear(); - for (S32 f = 0; f < volume->getNumVolumeFaces(); ++f) - { - LLVolumeFace& vol_face = volume->getVolumeFace(f); - LLSkinningUtil::updateRiggingInfo(skin, avatar, vol_face); - if (vol_face.mJointRiggingInfoTab.size()>0) - { - mJointRiggingInfoTab.merge(vol_face.mJointRiggingInfoTab); - } - } - // Keep the highest LOD info available. - mLastRiggingInfoLOD = getLOD(); - LL_DEBUGS("RigSpammish") << "updated rigging info for LLVOVolume " - << this << " lod " << mLastRiggingInfoLOD - << LL_ENDL; - } - } + else + { + model_mat = &(drawable->getRegion()->mRenderMatrix); } -} -//---------------------------------------------------------------------------- + //drawable->getVObj()->setDebugText(llformat("%d", drawable->isState(LLDrawable::ANIMATED_CHILD))); -void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point) -{ - LLVolume *volume = getVolume(); - - if (volume) - { - LLVector3 view_vector; - view_vector = view_point; - - //transform view vector into volume space - view_vector -= getRenderPosition(); - //mDrawable->mDistanceWRTCamera = view_vector.length(); - LLQuaternion worldRot = getRenderRotation(); - view_vector = view_vector * ~worldRot; - if (!isVolumeGlobal()) - { - LLVector3 objScale = getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - view_vector.scaleVec(invObjScale); - } - - updateRelativeXform(); - LLMatrix4 trans_mat = mRelativeXform; - if (mDrawable->isStatic()) - { - trans_mat.translate(getRegion()->getOriginAgent()); - } - - volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, view_vector, trans_mat, mRelativeXformInvTrans, nodep->getTESelectMask()); - - nodep->mSilhouetteExists = TRUE; - } -} + U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0; + U8 shiny = facep->getTextureEntry()->getShiny(); + + LLViewerTexture* tex = facep->getTexture(); -void LLVOVolume::deleteFaces() -{ - S32 face_count = mNumFaces; - if (mDrawable.notNull()) - { - mDrawable->deleteFaces(0, face_count); - } + U8 index = facep->getTextureIndex(); - mNumFaces = 0; -} + LLMaterial* mat = facep->getTextureEntry()->getMaterialParams().get(); + LLMaterialID mat_id = facep->getTextureEntry()->getMaterialID(); -void LLVOVolume::updateRadius() -{ - if (mDrawable.isNull()) - { - return; - } - - mVObjRadius = getScale().length(); - mDrawable->setRadius(mVObjRadius); -} + bool batchable = false; + U32 shader_mask = 0xFFFFFFFF; //no shader -BOOL LLVOVolume::isAttachment() const -{ - return mAttachmentState != 0 ; -} + if (mat) + { + if (type == LLRenderPass::PASS_ALPHA) + { + shader_mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND); + } + else + { + shader_mask = mat->getShaderMask(); + } + } -BOOL LLVOVolume::isHUDAttachment() const -{ - // *NOTE: we assume hud attachment points are in defined range - // since this range is constant for backwards compatibility - // reasons this is probably a reasonable assumption to make - S32 attachment_id = ATTACHMENT_ID_FROM_STATE(mAttachmentState); - return ( attachment_id >= 31 && attachment_id <= 38 ); -} + if (index < 255 && idx >= 0) + { + if (mat || draw_vec[idx]->mMaterial) + { //can't batch textures when materials are present (yet) + batchable = false; + } + else if (index < draw_vec[idx]->mTextureList.size()) + { + if (draw_vec[idx]->mTextureList[index].isNull()) + { + batchable = true; + draw_vec[idx]->mTextureList[index] = tex; + } + else if (draw_vec[idx]->mTextureList[index] == tex) + { //this face's texture index can be used with this batch + batchable = true; + } + } + else + { //texture list can be expanded to fit this texture index + batchable = true; + } + } -const LLMatrix4 LLVOVolume::getRenderMatrix() const -{ - if (mDrawable->isActive() && !mDrawable->isRoot()) - { - return mDrawable->getParent()->getWorldMatrix(); - } - return mDrawable->getWorldMatrix(); -} + if (idx >= 0 && + draw_vec[idx]->mVertexBuffer == facep->getVertexBuffer() && + draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && + (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex || batchable) && +#if LL_DARWIN + draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && + draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && +#endif + draw_vec[idx]->mMaterial == mat && + draw_vec[idx]->mMaterialID == mat_id && + draw_vec[idx]->mFullbright == fullbright && + draw_vec[idx]->mBump == bump && + (!mat || (draw_vec[idx]->mShiny == shiny)) && // need to break batches when a material is shared, but legacy settings are different + draw_vec[idx]->mTextureMatrix == tex_mat && + draw_vec[idx]->mModelMatrix == model_mat && + draw_vec[idx]->mShaderMask == shader_mask && + draw_vec[idx]->mSelected == selected) + { + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mEnd += facep->getGeomCount(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize()); -// Returns a base cost and adds textures to passed in set. -// total cost is returned value + 5 * size of the resulting set. -// Cannot include cost of textures, as they may be re-used in linked -// children, and cost should only be increased for unique textures -Nyx -U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const -{ - /***************************************************************** - * This calculation should not be modified by third party viewers, - * since it is used to limit rendering and should be uniform for - * everyone. If you have suggested improvements, submit them to - * the official viewer for consideration. - *****************************************************************/ + if (index < 255 && index >= draw_vec[idx]->mTextureList.size()) + { + draw_vec[idx]->mTextureList.resize(index+1); + draw_vec[idx]->mTextureList[index] = tex; + } + draw_vec[idx]->validate(); + update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]); + update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[1]); + } + else + { + U32 start = facep->getGeomIndex(); + U32 end = start + facep->getGeomCount()-1; + U32 offset = facep->getIndicesStart(); + U32 count = facep->getIndicesCount(); + LLPointer draw_info = new LLDrawInfo(start,end,count,offset, tex, + facep->getVertexBuffer(), selected, fullbright, bump); + draw_info->mGroup = group; + draw_info->mVSize = facep->getVirtualSize(); + draw_vec.push_back(draw_info); + draw_info->mTextureMatrix = tex_mat; + draw_info->mModelMatrix = model_mat; + + draw_info->mBump = bump; + draw_info->mShiny = shiny; - // Get access to params we'll need at various points. - // Skip if this is object doesn't have a volume (e.g. is an avatar). - BOOL has_volume = (getVolume() != NULL); - LLVolumeParams volume_params; - LLPathParams path_params; - LLProfileParams profile_params; - - U32 num_triangles = 0; - - // per-prim costs - static const U32 ARC_PARTICLE_COST = 1; // determined experimentally - static const U32 ARC_PARTICLE_MAX = 2048; // default values - static const U32 ARC_TEXTURE_COST = 16; // multiplier for texture resolution - performance tested - static const U32 ARC_LIGHT_COST = 500; // static cost for light-producing prims - static const U32 ARC_MEDIA_FACE_COST = 1500; // static cost per media-enabled face - - - // per-prim multipliers - static const F32 ARC_GLOW_MULT = 1.5f; // tested based on performance - static const F32 ARC_BUMP_MULT = 1.25f; // tested based on performance - static const F32 ARC_FLEXI_MULT = 5; // tested based on performance - static const F32 ARC_SHINY_MULT = 1.6f; // tested based on performance - static const F32 ARC_INVISI_COST = 1.2f; // tested based on performance - static const F32 ARC_WEIGHTED_MESH = 1.2f; // tested based on performance - - static const F32 ARC_PLANAR_COST = 1.0f; // tested based on performance to have negligible impact - static const F32 ARC_ANIM_TEX_COST = 4.f; // tested based on performance - static const F32 ARC_ALPHA_COST = 4.f; // 4x max - based on performance - - F32 shame = 0; - - U32 invisi = 0; - U32 shiny = 0; - U32 glow = 0; - U32 alpha = 0; - U32 flexi = 0; - U32 animtex = 0; - U32 particles = 0; - U32 bump = 0; - U32 planar = 0; - U32 weighted_mesh = 0; - U32 produces_light = 0; - U32 media_faces = 0; - - const LLDrawable* drawablep = mDrawable; - U32 num_faces = drawablep->getNumFaces(); - - if (has_volume) - { - volume_params = getVolume()->getParams(); - path_params = volume_params.getPathParams(); - profile_params = volume_params.getProfileParams(); + static const float alpha[4] = + { + 0.00f, + 0.25f, + 0.5f, + 0.75f + }; + float spec = alpha[shiny & TEM_SHINY_MASK]; + LLVector4 specColor(spec, spec, spec, spec); + draw_info->mSpecColor = specColor; + draw_info->mEnvIntensity = spec; + draw_info->mSpecularMap = NULL; + draw_info->mMaterial = mat; + draw_info->mShaderMask = shader_mask; + + if (mat) + { + draw_info->mMaterialID = mat_id; - LLMeshCostData costs; - if (getCostData(costs)) - { - if (isAnimatedObject() && isRiggedMesh()) + // We have a material. Update our draw info accordingly. + + if (!mat->getSpecularID().isNull()) { - // Scaling here is to make animated object vs - // non-animated object ARC proportional to the - // corresponding calculations for streaming cost. - num_triangles = (ANIMATED_OBJECT_COST_PER_KTRI * 0.001 * costs.getEstTrisForStreamingCost())/0.06; + LLVector4 specColor; + specColor.mV[0] = mat->getSpecularLightColor().mV[0] * (1.f / 255.f); + specColor.mV[1] = mat->getSpecularLightColor().mV[1] * (1.f / 255.f); + specColor.mV[2] = mat->getSpecularLightColor().mV[2] * (1.f / 255.f); + specColor.mV[3] = mat->getSpecularLightExponent() * (1.f / 255.f); + draw_info->mSpecColor = specColor; + draw_info->mEnvIntensity = mat->getEnvironmentIntensity() * (1.f / 255.f); + draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTEOffset()); + } + + draw_info->mAlphaMaskCutoff = mat->getAlphaMaskCutoff() * (1.f / 255.f); + draw_info->mDiffuseAlphaMode = mat->getDiffuseAlphaMode(); + draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTEOffset()); + } + else + { + if (type == LLRenderPass::PASS_GRASS) + { + draw_info->mAlphaMaskCutoff = 0.5f; } else { - F32 radius = getScale().length()*0.5f; - num_triangles = costs.getRadiusWeightedTris(radius); + draw_info->mAlphaMaskCutoff = 0.33f; } - } - } - - if (num_triangles <= 0) - { - num_triangles = 4; - } - - if (isSculpted()) - { - if (isMesh()) - { - // base cost is dependent on mesh complexity - // note that 3 is the highest LOD as of the time of this coding. - S32 size = gMeshRepo.getMeshSize(volume_params.getSculptID(), getLOD()); - if ( size > 0) - { - if (isRiggedMesh()) - { - // weighted attachment - 1 point for every 3 bytes - weighted_mesh = 1; - } - } - else - { - // something went wrong - user should know their content isn't render-free - return 0; - } - } - else - { - const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID sculpt_id = sculpt_params->getSculptTexture(); - if (textures.find(sculpt_id) == textures.end()) - { - LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(sculpt_id); - if (texture) - { - S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (texture->getFullHeight() / 128.f + texture->getFullWidth() / 128.f)); - textures.insert(texture_cost_t::value_type(sculpt_id, texture_cost)); - } - } - } - } - - if (isFlexible()) - { - flexi = 1; - } - if (isParticleSource()) - { - particles = 1; - } - - if (getIsLight()) - { - produces_light = 1; - } - - for (S32 i = 0; i < num_faces; ++i) - { - const LLFace* face = drawablep->getFace(i); - if (!face) continue; - const LLTextureEntry* te = face->getTextureEntry(); - const LLViewerTexture* img = face->getTexture(); - - if (img) - { - if (textures.find(img->getID()) == textures.end()) - { - S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (img->getFullHeight() / 128.f + img->getFullWidth() / 128.f)); - textures.insert(texture_cost_t::value_type(img->getID(), texture_cost)); - } - } - - if (face->getPoolType() == LLDrawPool::POOL_ALPHA) - { - alpha = 1; - } - else if (img && img->getPrimaryFormat() == GL_ALPHA) - { - invisi = 1; - } - if (face->hasMedia()) - { - media_faces++; - } - - if (te) - { - if (te->getBumpmap()) - { - // bump is a multiplier, don't add per-face - bump = 1; - } - if (te->getShiny()) - { - // shiny is a multiplier, don't add per-face - shiny = 1; - } - if (te->getGlow() > 0.f) - { - // glow is a multiplier, don't add per-face - glow = 1; - } - if (face->mTextureMatrix != NULL) - { - animtex = 1; - } - if (te->getTexGen()) - { - planar = 1; - } - } - } - - // shame currently has the "base" cost of 1 point per 15 triangles, min 2. - shame = num_triangles * 5.f; - shame = shame < 2.f ? 2.f : shame; - - // multiply by per-face modifiers - if (planar) - { - shame *= planar * ARC_PLANAR_COST; - } - - if (animtex) - { - shame *= animtex * ARC_ANIM_TEX_COST; - } - - if (alpha) - { - shame *= alpha * ARC_ALPHA_COST; - } - - if(invisi) - { - shame *= invisi * ARC_INVISI_COST; - } - - if (glow) - { - shame *= glow * ARC_GLOW_MULT; - } - - if (bump) - { - shame *= bump * ARC_BUMP_MULT; - } - - if (shiny) - { - shame *= shiny * ARC_SHINY_MULT; - } - - - // multiply shame by multipliers - if (weighted_mesh) - { - shame *= weighted_mesh * ARC_WEIGHTED_MESH; - } - - if (flexi) - { - shame *= flexi * ARC_FLEXI_MULT; - } - - - // add additional costs - if (particles) - { - const LLPartSysData *part_sys_data = &(mPartSourcep->mPartSysData); - const LLPartData *part_data = &(part_sys_data->mPartData); - U32 num_particles = (U32)(part_sys_data->mBurstPartCount * llceil( part_data->mMaxAge / part_sys_data->mBurstRate)); - num_particles = num_particles > ARC_PARTICLE_MAX ? ARC_PARTICLE_MAX : num_particles; - F32 part_size = (llmax(part_data->mStartScale[0], part_data->mEndScale[0]) + llmax(part_data->mStartScale[1], part_data->mEndScale[1])) / 2.f; - shame += num_particles * part_size * ARC_PARTICLE_COST; - } - - if (produces_light) - { - shame += ARC_LIGHT_COST; - } - - if (media_faces) - { - shame += media_faces * ARC_MEDIA_FACE_COST; - } - - // Streaming cost for animated objects includes a fixed cost - // per linkset. Add a corresponding charge here translated into - // triangles, but not weighted by any graphics properties. - if (isAnimatedObject() && isRootEdit()) - { - shame += (ANIMATED_OBJECT_BASE_COST/0.06) * 5.0f; - } + } + + if (type == LLRenderPass::PASS_ALPHA) + { //for alpha sorting + facep->setDrawInfo(draw_info); + } + draw_info->mExtents[0] = facep->mExtents[0]; + draw_info->mExtents[1] = facep->mExtents[1]; - if (shame > mRenderComplexity_current) - { - mRenderComplexity_current = (S32)shame; - } + if (LLPipeline::sUseTriStrips) + { + draw_info->mDrawMode = LLRender::TRIANGLE_STRIP; + } - return (U32)shame; + if (index < 255) + { //initialize texture list for texture batching + draw_info->mTextureList.resize(index+1); + draw_info->mTextureList[index] = tex; + } + draw_info->validate(); + } } -F32 LLVOVolume::getEstTrianglesMax() const +void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) { - if (isMesh() && getVolume()) - { - return gMeshRepo.getEstTrianglesMax(getVolume()->getParams().getSculptID()); - } - return 0.f; + } -F32 LLVOVolume::getEstTrianglesStreamingCost() const +static LLTrace::BlockTimerStatHandle FTM_REBUILD_VOLUME_VB("Volume VB"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_VOLUME_FACE_LIST("Build Face List"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_VOLUME_GEN_DRAW_INFO("Gen Draw Info"); + +static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) { - if (isMesh() && getVolume()) - { - return gMeshRepo.getEstTrianglesStreamingCost(getVolume()->getParams().getSculptID()); - } - return 0.f; + LLVOAvatar* avatar = vobj->getAvatar(); + + if (avatar) + { + LLDrawable* drawable = avatar->mDrawable; + if (drawable && drawable->getNumFaces() > 0) + { + LLFace* face = drawable->getFace(0); + if (face) + { + LLDrawPool* drawpool = face->getPool(); + if (drawpool) + { + if (drawpool->getType() == LLDrawPool::POOL_AVATAR) + { + return (LLDrawPoolAvatar*) drawpool; + } + } + } + } + } + + return NULL; } -F32 LLVOVolume::getStreamingCost() const +void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value) { - F32 radius = getScale().length()*0.5f; - F32 linkset_base_cost = 0.f; + static LLCachedControl render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U); - LLMeshCostData costs; - if (getCostData(costs)) + if (0 != render_auto_mute_byte_limit) { - if (isAnimatedObject() && isRootEdit()) - { - // Root object of an animated object has this to account for skeleton overhead. - linkset_base_cost = ANIMATED_OBJECT_BASE_COST; - } - if (isMesh()) + //for unload + LLSculptIDSize::container_BY_SIZE_view::iterator + itL = LLSculptIDSize::instance().getSizeInfo().get().lower_bound(render_auto_mute_byte_limit), + itU = LLSculptIDSize::instance().getSizeInfo().get().end(); + + for (; itL != itU; ++itL) { - if (isAnimatedObject() && isRiggedMesh()) - { - return linkset_base_cost + costs.getTriangleBasedStreamingCost(); - } - else + const LLSculptIDSize::Info &nfo = *itL; + LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); + if (pVVol + && !pVVol->isDead() + && pVVol->isAttachment() + && !pVVol->getAvatar()->isSelf() + && LLVOVolume::NO_LOD != pVVol->getLOD() + ) { - return linkset_base_cost + costs.getRadiusBasedStreamingCost(radius); + //postponed + pVVol->markForUnload(); + LLSculptIDSize::instance().addToUnloaded(nfo.getSculptId()); } } - else + + //for load if it was unload + itL = LLSculptIDSize::instance().getSizeInfo().get().begin(); + itU = LLSculptIDSize::instance().getSizeInfo().get().upper_bound(render_auto_mute_byte_limit); + + for (; itL != itU; ++itL) { - return linkset_base_cost + costs.getRadiusBasedStreamingCost(radius); + const LLSculptIDSize::Info &nfo = *itL; + LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); + if (pVVol + && !pVVol->isDead() + && pVVol->isAttachment() + && !pVVol->getAvatar()->isSelf() + && LLVOVolume::NO_LOD == pVVol->getLOD() + ) + { + LLSculptIDSize::instance().remFromUnloaded(nfo.getSculptId()); + pVVol->updateLOD(); + pVVol->markForUpdate(TRUE); + } } } else { - return 0.f; + LLSculptIDSize::instance().clearUnloaded(); + + LLSculptIDSize::container_BY_SIZE_view::iterator + itL = LLSculptIDSize::instance().getSizeInfo().get().begin(), + itU = LLSculptIDSize::instance().getSizeInfo().get().end(); + + for (; itL != itU; ++itL) + { + const LLSculptIDSize::Info &nfo = *itL; + LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); + if (pVVol + && !pVVol->isDead() + && pVVol->isAttachment() + && !pVVol->getAvatar()->isSelf() + && LLVOVolume::NO_LOD == pVVol->getLOD() + ) + { + pVVol->updateLOD(); + pVVol->markForUpdate(TRUE); + } + } } } -// virtual -bool LLVOVolume::getCostData(LLMeshCostData& costs) const +void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { - if (isMesh()) + if (group->changeLOD()) { - return gMeshRepo.getCostData(getVolume()->getParams().getSculptID(), costs); + group->mLastUpdateDistance = group->mDistance; } - else + + group->mLastUpdateViewAngle = group->mViewAngle; + + if (!group->hasState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY)) { - LLVolume* volume = getVolume(); - S32 counts[4]; - LLVolume::getLoDTriangleCounts(volume->getParams(), counts); + if (group->hasState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate) + { + rebuildMesh(group); + } + return; + } - LLSD header; - header["lowest_lod"]["size"] = counts[0] * 10; - header["low_lod"]["size"] = counts[1] * 10; - header["medium_lod"]["size"] = counts[2] * 10; - header["high_lod"]["size"] = counts[3] * 10; + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB); + + group->mBuilt = 1.f; + + LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); + LLViewerObject *vobj = NULL; + LLVOVolume *vol_obj = NULL; - return gMeshRepo.getCostData(header, costs); + if (bridge) + { + vobj = bridge->mDrawable->getVObj(); + vol_obj = dynamic_cast(vobj); + } + if (vol_obj) + { + vol_obj->updateVisualComplexity(); } -} -//static -void LLVOVolume::updateRenderComplexity() -{ - mRenderComplexity_last = mRenderComplexity_current; - mRenderComplexity_current = 0; -} + group->mGeometryBytes = 0; + group->mSurfaceArea = 0; + + //cache object box size since it might be used for determining visibility + const LLVector4a* bounds = group->getObjectBounds(); + group->mObjectBoxSize = bounds[1].getLength3().getF32(); -U32 LLVOVolume::getTriangleCount(S32* vcount) const -{ - U32 count = 0; - LLVolume* volume = getVolume(); - if (volume) - { - count = volume->getNumTriangles(vcount); - } + group->clearDrawMap(); - return count; -} + mFaceList.clear(); -U32 LLVOVolume::getHighLODTriangleCount() -{ - U32 ret = 0; - - LLVolume* volume = getVolume(); - - if (!isSculpted()) - { - LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); - ret = ref->getNumTriangles(); - LLPrimitive::getVolumeManager()->unrefVolume(ref); - } - else if (isMesh()) - { - LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); - if (!ref->isMeshAssetLoaded() || ref->getNumVolumeFaces() == 0) - { - gMeshRepo.loadMesh(this, volume->getParams(), LLModel::LOD_HIGH); - } - ret = ref->getNumTriangles(); - LLPrimitive::getVolumeManager()->unrefVolume(ref); - } - else - { //default sculpts have a constant number of triangles - ret = 31*2*31; //31 rows of 31 columns of quads for a 32x32 vertex patch - } - - return ret; -} + U32 fullbright_count = 0; + U32 bump_count = 0; + U32 simple_count = 0; + U32 alpha_count = 0; + U32 norm_count = 0; + U32 spec_count = 0; + U32 normspec_count = 0; -//static -void LLVOVolume::preUpdateGeom() -{ - sNumLODChanges = 0; -} -void LLVOVolume::parameterChanged(U16 param_type, bool local_origin) -{ - LLViewerObject::parameterChanged(param_type, local_origin); -} + U32 useage = group->getSpatialPartition()->mBufferUsage; -void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin) -{ - LLViewerObject::parameterChanged(param_type, data, in_use, local_origin); - if (mVolumeImpl) - { - mVolumeImpl->onParameterChanged(param_type, data, in_use, local_origin); - } - if (!local_origin && param_type == LLNetworkData::PARAMS_EXTENDED_MESH) - { - U32 extended_mesh_flags = getExtendedMeshFlags(); - bool enabled = (extended_mesh_flags & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG); - bool was_enabled = (getControlAvatar() != NULL); - if (enabled != was_enabled) - { - LL_DEBUGS("AnimatedObjects") << this - << " calling onSetExtendedMeshFlags, enabled " << (U32) enabled - << " was_enabled " << (U32) was_enabled - << " local_origin " << (U32) local_origin - << LL_ENDL; - onSetExtendedMeshFlags(extended_mesh_flags); - } - } - if (mDrawable.notNull()) - { - BOOL is_light = getIsLight(); - if (is_light != mDrawable->isState(LLDrawable::LIGHT)) - { - gPipeline.setLight(mDrawable, is_light); - } - } -} + U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); + U32 max_total = (gSavedSettings.getS32("RenderMaxNodeSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); + max_vertices = llmin(max_vertices, (U32) 65535); + + U32 cur_total = 0; + + bool emissive = false; + + //Determine if we've received skininfo that contains an + //alternate bind matrix - if it does then apply the translational component + //to the joints of the avatar. +#if 0 + bool pelvisGotSet = false; +#endif -void LLVOVolume::setSelected(BOOL sel) -{ - LLViewerObject::setSelected(sel); - if (isAnimatedObject()) - { - getRootEdit()->recursiveMarkForUpdate(TRUE); - } - else { - if (mDrawable.notNull()) + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_FACE_LIST); + + //get all the faces into a list + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); + drawable_iter != group->getDataEnd(); ++drawable_iter) { - markForUpdate(TRUE); - } - } -} + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + + if (!drawablep || drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) + { + continue; + } + + if (drawablep->isAnimating()) + { //fall back to stream draw for animating verts + useage = GL_STREAM_DRAW_ARB; + } -void LLVOVolume::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) -{ -} + LLVOVolume* vobj = drawablep->getVOVolume(); + + if (!vobj) + { + continue; + } -F32 LLVOVolume::getBinRadius() -{ - F32 radius; - - F32 scale = 1.f; - - S32 size_factor = llmax(gSavedSettings.getS32("OctreeStaticObjectSizeFactor"), 1); - S32 attachment_size_factor = llmax(gSavedSettings.getS32("OctreeAttachmentSizeFactor"), 1); - LLVector3 distance_factor = gSavedSettings.getVector3("OctreeDistanceFactor"); - LLVector3 alpha_distance_factor = gSavedSettings.getVector3("OctreeAlphaDistanceFactor"); - const LLVector4a* ext = mDrawable->getSpatialExtents(); - - BOOL shrink_wrap = mDrawable->isAnimating(); - BOOL alpha_wrap = FALSE; - - if (!isHUDAttachment()) - { - for (S32 i = 0; i < mDrawable->getNumFaces(); i++) - { - LLFace* face = mDrawable->getFace(i); - if (!face) continue; - if (face->getPoolType() == LLDrawPool::POOL_ALPHA && - !face->canRenderAsMask()) - { - alpha_wrap = TRUE; - break; - } - } - } - else - { - shrink_wrap = FALSE; - } - - if (alpha_wrap) - { - LLVector3 bounds = getScale(); - radius = llmin(bounds.mV[1], bounds.mV[2]); - radius = llmin(radius, bounds.mV[0]); - radius *= 0.5f; - radius *= 1.f+mDrawable->mDistanceWRTCamera*alpha_distance_factor[1]; - radius += mDrawable->mDistanceWRTCamera*alpha_distance_factor[0]; - } - else if (shrink_wrap) - { - LLVector4a rad; - rad.setSub(ext[1], ext[0]); - - radius = rad.getLength3().getF32()*0.5f; - } - else if (mDrawable->isStatic()) - { - F32 szf = size_factor; - - radius = llmax(mDrawable->getRadius(), szf); - - radius = powf(radius, 1.f+szf/radius); - - radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1]; - radius += mDrawable->mDistanceWRTCamera * distance_factor[0]; - } - else if (mDrawable->getVObj()->isAttachment()) - { - radius = llmax((S32) mDrawable->getRadius(),1)*attachment_size_factor; - } - else - { - radius = mDrawable->getRadius(); - radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1]; - radius += mDrawable->mDistanceWRTCamera * distance_factor[0]; - } - - return llclamp(radius*scale, 0.5f, 256.f); -} + std::string vobj_name = llformat("Vol%p", vobj); -const LLVector3 LLVOVolume::getPivotPositionAgent() const -{ - if (mVolumeImpl) - { - return mVolumeImpl->getPivotPosition(); - } - return LLViewerObject::getPivotPositionAgent(); -} + if (vobj->isMesh() && + ((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled())) + { + continue; + } -void LLVOVolume::onShift(const LLVector4a &shift_vector) -{ - if (mVolumeImpl) - { - mVolumeImpl->onShift(shift_vector); - } + LLVolume* volume = vobj->getVolume(); + if (volume) + { + const LLVector3& scale = vobj->getScale(); + group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); + } - updateRelativeXform(); -} + bool is_mesh = vobj->isMesh(); + F32 est_tris = vobj->getEstTrianglesMax(); + + vobj->updateControlAvatar(); + + LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " rebuilding, isAttachment: " << (U32) vobj->isAttachment() + << " is_mesh " << is_mesh + << " est_tris " << est_tris + << " is_animated " << vobj->isAnimatedObject() + << " can_animate " << vobj->canBeAnimatedObject() + << " cav " << vobj->getControlAvatar() + << " lod " << vobj->getLOD() + << " drawable rigged " << (drawablep->isState(LLDrawable::RIGGED)) + << " drawable state " << drawablep->getState() + << " playing " << (U32) (vobj->getControlAvatar() ? vobj->getControlAvatar()->mPlaying : false) + << " frame " << LLFrameTimer::getFrameCount() + << LL_ENDL; -const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const -{ - if (mVolumeImpl) - { - return mVolumeImpl->getWorldMatrix(xform); - } - return xform->getWorldMatrix(); -} + llassert_always(vobj); + vobj->updateTextureVirtualSize(true); + vobj->preRebuild(); -void LLVOVolume::markForUpdate(BOOL priority) -{ - if (debugLoggingEnabled("AnimatedObjectsLinkset")) - { - if (isAnimatedObject() && isRiggedMesh()) - { - std::string vobj_name = llformat("Vol%p", this); - F32 est_tris = getEstTrianglesMax(); - LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " markForUpdate, tris " << est_tris << LL_ENDL; - } - } + drawablep->clearState(LLDrawable::HAS_ALPHA); - LLViewerObject::markForUpdate(priority); - mVolumeChanged = TRUE; -} + if (vobj->isRiggedMesh() && + ((vobj->isAnimatedObject() && vobj->getControlAvatar()) || + (!vobj->isAnimatedObject() && vobj->getAvatar()))) + { + vobj->getAvatar()->addAttachmentOverridesForObject(vobj, NULL, false); + } + + // Standard rigged mesh attachments: + bool rigged = !vobj->isAnimatedObject() && vobj->isRiggedMesh() && vobj->isAttachment(); + // Animated objects. Have to check for isRiggedMesh() to + // exclude static objects in animated object linksets. + rigged = rigged || (vobj->isAnimatedObject() && vobj->isRiggedMesh() && + vobj->getControlAvatar() && vobj->getControlAvatar()->mPlaying); -LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const -{ - LLVector3 ret = pos - getRenderPosition(); - ret = ret * ~getRenderRotation(); - if (!isVolumeGlobal()) - { - LLVector3 objScale = getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - ret.scaleVec(invObjScale); - } - - return ret; -} + bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); + bool any_rigged_face = false; -LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const -{ - LLVector3 ret = dir * ~getRenderRotation(); - - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - ret.scaleVec(objScale); + //for each face + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + LLFace* facep = drawablep->getFace(i); + if (!facep) + { + continue; + } - return ret; -} + //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render + // batch, it will recover its vertex buffer reference from the spatial group + facep->setVertexBuffer(NULL); + + //sum up face verts and indices + drawablep->updateFaceSize(i); + + if (rigged) + { + if (!facep->isState(LLFace::RIGGED)) + { //completely reset vertex buffer + facep->clearVertexBuffer(); + } + + facep->setState(LLFace::RIGGED); + any_rigged_face = true; + + //get drawpool of avatar with rigged face + LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); + + if (pool) + { + //remove face from old pool if it exists + LLDrawPool* old_pool = facep->getPool(); + if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) + { + ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); + } + + //add face to new pool + LLViewerTexture* tex = facep->getTexture(); + + const LLTextureEntry* te = facep->getTextureEntry(); + llassert(te != nullptr); + if (te) + { + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + + if (te->getGlow()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); + } + + LLMaterial* mat = te->getMaterialParams().get(); + + if (mat && LLPipeline::sRenderDeferred) + { + U8 alpha_mode = mat->getDiffuseAlphaMode(); + + bool is_alpha = type == LLDrawPool::POOL_ALPHA && + (alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND || + te->getColor().mV[3] < 0.999f); + + if (is_alpha) + { //this face needs alpha blending, override alpha mode + alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; + } + + if (!is_alpha || te->getColor().mV[3] > 0.f) // //only add the face if it will actually be visible + { + U32 mask = mat->getShaderMask(alpha_mode); + pool->addRiggedFace(facep, mask); + } + } + else if (mat) + { + bool fullbright = te->getFullbright(); + bool is_alpha = type == LLDrawPool::POOL_ALPHA; + U8 mode = mat->getDiffuseAlphaMode(); + bool can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || + mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; + + if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && te->getColor().mV[3] >= 0.999f) + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); + } + else if (is_alpha || (te->getColor().mV[3] < 0.999f)) + { + if (te->getColor().mV[3] > 0.f) + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA : LLDrawPoolAvatar::RIGGED_ALPHA); + } + } + else if (gPipeline.canUseVertexShaders() + && LLPipeline::sRenderBump + && te->getShiny() + && can_be_shiny) + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY : LLDrawPoolAvatar::RIGGED_SHINY); + } + else + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); + } + } + else + { + if (type == LLDrawPool::POOL_ALPHA) + { + if (te->getColor().mV[3] > 0.f) + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); + } + } + } + else if (te->getShiny()) + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); + } + else + { + if (LLPipeline::sRenderDeferred) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); + } + } + } + else + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + } + + + if (LLPipeline::sRenderDeferred) + { + if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) + { + if (te->getBumpmap()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); + } + } + } + } + } + } -LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const -{ - LLVector3 ret = dir; - if (!isVolumeGlobal()) - { - LLVector3 objScale = getScale(); - ret.scaleVec(objScale); - } + continue; + } + else + { + if (facep->isState(LLFace::RIGGED)) + { //face is not rigged but used to be, remove from rigged face pool + LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); + if (pool) + { + pool->removeRiggedFace(facep); + } + facep->clearState(LLFace::RIGGED); + } + } - ret = ret * getRenderRotation(); - ret += getRenderPosition(); - - return ret; -} -LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const -{ - LLVector3 ret = dir; - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - ret.scaleVec(invObjScale); - ret = ret * getRenderRotation(); + if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) + { + facep->clearVertexBuffer(); + continue; + } - return ret; -} + cur_total += facep->getGeomCount(); + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) + { + const LLTextureEntry* te = facep->getTextureEntry(); + LLViewerTexture* tex = facep->getTexture(); -BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp, - LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) - -{ - if (!mbCanSelect - || mDrawable->isDead() - || !gPipeline.hasRenderType(mDrawable->getRenderType())) - { - return FALSE; - } - - BOOL ret = FALSE; - - LLVolume* volume = getVolume(); - - bool transform = true; - - if (mDrawable->isState(LLDrawable::RIGGED)) - { - if ((pick_rigged) || (getAvatar() && (getAvatar()->isSelf()) && (LLFloater::isVisible(gFloaterTools)))) - { - updateRiggedVolume(true); - volume = mRiggedVolume; - transform = false; - } - else - { //cannot pick rigged attachments on other avatars or when not in build mode - return FALSE; - } - } - - if (volume) - { - LLVector4a local_start = start; - LLVector4a local_end = end; - - if (transform) - { - LLVector3 v_start(start.getF32ptr()); - LLVector3 v_end(end.getF32ptr()); - - v_start = agentPositionToVolume(v_start); - v_end = agentPositionToVolume(v_end); - - local_start.load3(v_start.mV); - local_end.load3(v_end.mV); - } - - LLVector4a p; - LLVector4a n; - LLVector2 tc; - LLVector4a tn; - - if (intersection != NULL) - { - p = *intersection; - } - - if (tex_coord != NULL) - { - tc = *tex_coord; - } - - if (normal != NULL) - { - n = *normal; - } - - if (tangent != NULL) - { - tn = *tangent; - } - - S32 face_hit = -1; - - S32 start_face, end_face; - if (face == -1) - { - start_face = 0; - end_face = volume->getNumVolumeFaces(); - } - else - { - start_face = face; - end_face = face+1; - } - pick_transparent |= isHiglightedOrBeacon(); - bool special_cursor = specialHoverCursor(); - for (S32 i = start_face; i < end_face; ++i) - { - if (!special_cursor && !pick_transparent && getTE(i) && getTE(i)->getColor().mV[3] == 0.f) - { //don't attempt to pick completely transparent faces unless - //pick_transparent is true - continue; - } - - face_hit = volume->lineSegmentIntersect(local_start, local_end, i, - &p, &tc, &n, &tn); - - if (face_hit >= 0 && mDrawable->getNumFaces() > face_hit) - { - LLFace* face = mDrawable->getFace(face_hit); - - bool ignore_alpha = false; - - const LLTextureEntry* te = face->getTextureEntry(); - if (te) - { - LLMaterial* mat = te->getMaterialParams(); - if (mat) - { - U8 mode = mat->getDiffuseAlphaMode(); - - if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE || - mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE) - { - ignore_alpha = true; - } - } - } - - if (face && - (ignore_alpha || - pick_transparent || - !face->getTexture() || - !face->getTexture()->hasGLTexture() || - face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)))) - { - local_end = p; - if (face_hitp != NULL) - { - *face_hitp = face_hit; - } - - if (intersection != NULL) - { - if (transform) - { - LLVector3 v_p(p.getF32ptr()); - - intersection->load3(volumePositionToAgent(v_p).mV); // must map back to agent space - } - else - { - *intersection = p; - } - } - - if (normal != NULL) - { - if (transform) - { - LLVector3 v_n(n.getF32ptr()); - normal->load3(volumeDirectionToAgent(v_n).mV); - } - else - { - *normal = n; - } - (*normal).normalize3fast(); - } - - if (tangent != NULL) - { - if (transform) - { - LLVector3 v_tn(tn.getF32ptr()); - - LLVector4a trans_tangent; - trans_tangent.load3(volumeDirectionToAgent(v_tn).mV); - - LLVector4Logical mask; - mask.clear(); - mask.setElement<3>(); - - tangent->setSelectWithMask(mask, tn, trans_tangent); - } - else - { - *tangent = tn; - } - (*tangent).normalize3fast(); - } - - if (tex_coord != NULL) - { - *tex_coord = tc; - } - - ret = TRUE; - } - } - } - } - - return ret; -} + if (te->getGlow() >= 1.f/255.f) + { + emissive = true; + } -bool LLVOVolume::treatAsRigged() -{ - return isSelected() && - (isAttachment() || isAnimatedObject()) && - mDrawable.notNull() && - mDrawable->isState(LLDrawable::RIGGED); -} + if (facep->isState(LLFace::TEXTURE_ANIM)) + { + if (!vobj->mTexAnimMode) + { + facep->clearState(LLFace::TEXTURE_ANIM); + } + } -LLRiggedVolume* LLVOVolume::getRiggedVolume() -{ - return mRiggedVolume; -} + BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + if (type != LLDrawPool::POOL_ALPHA && force_simple) + { + type = LLDrawPool::POOL_SIMPLE; + } + facep->setPoolType(type); -void LLVOVolume::clearRiggedVolume() -{ - if (mRiggedVolume.notNull()) - { - mRiggedVolume = NULL; - updateRelativeXform(); - } -} + if (vobj->isHUDAttachment()) + { + facep->setState(LLFace::FULLBRIGHT); + } -void LLVOVolume::updateRiggedVolume(bool force_update) -{ - //Update mRiggedVolume to match current animation frame of avatar. - //Also update position/size in octree. - - if ((!force_update) && (!treatAsRigged())) - { - clearRiggedVolume(); - - return; - } - - LLVolume* volume = getVolume(); - const LLMeshSkinInfo* skin = getSkinInfo(); - if (!skin) - { - clearRiggedVolume(); - return; - } - - LLVOAvatar* avatar = getAvatar(); - if (!avatar) - { - clearRiggedVolume(); - return; - } - - if (!mRiggedVolume) - { - LLVolumeParams p; - mRiggedVolume = new LLRiggedVolume(p); - updateRelativeXform(); - } - - mRiggedVolume->update(skin, avatar, volume); -} + if (vobj->mTextureAnimp && vobj->mTexAnimMode) + { + if (vobj->mTextureAnimp->mFace <= -1) + { + S32 face; + for (face = 0; face < vobj->getNumTEs(); face++) + { + LLFace * facep = drawablep->getFace(face); + if (facep) + { + facep->setState(LLFace::TEXTURE_ANIM); + } + } + } + else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) + { + LLFace * facep = drawablep->getFace(vobj->mTextureAnimp->mFace); + if (facep) + { + facep->setState(LLFace::TEXTURE_ANIM); + } + } + } -static LLTrace::BlockTimerStatHandle FTM_SKIN_RIGGED("Skin"); -static LLTrace::BlockTimerStatHandle FTM_RIGGED_OCTREE("Octree"); + if (type == LLDrawPool::POOL_ALPHA) + { + if (facep->canRenderAsMask()) + { //can be treated as alpha mask + if (simple_count < MAX_FACE_COUNT) + { + sSimpleFaces[simple_count++] = facep; + } + } + else + { + if (te->getColor().mV[3] > 0.f) + { //only treat as alpha in the pipeline if < 100% transparent + drawablep->setState(LLDrawable::HAS_ALPHA); + } + if (alpha_count < MAX_FACE_COUNT) + { + sAlphaFaces[alpha_count++] = facep; + } + } + } + else + { + if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) + { + facep->mLastUpdateTime = gFrameTimeSeconds; + } + + if (gPipeline.canUseWindLightShadersOnObjects() + && LLPipeline::sRenderBump) + { + if (LLPipeline::sRenderDeferred && te->getMaterialParams().notNull() && !te->getMaterialID().isNull()) + { + LLMaterial* mat = te->getMaterialParams().get(); + if (mat->getNormalID().notNull()) + { + if (mat->getSpecularID().notNull()) + { //has normal and specular maps (needs texcoord1, texcoord2, and tangent) + if (normspec_count < MAX_FACE_COUNT) + { + sNormSpecFaces[normspec_count++] = facep; + } + } + else + { //has normal map (needs texcoord1 and tangent) + if (norm_count < MAX_FACE_COUNT) + { + sNormFaces[norm_count++] = facep; + } + } + } + else if (mat->getSpecularID().notNull()) + { //has specular map but no normal map, needs texcoord2 + if (spec_count < MAX_FACE_COUNT) + { + sSpecFaces[spec_count++] = facep; + } + } + else + { //has neither specular map nor normal map, only needs texcoord0 + if (simple_count < MAX_FACE_COUNT) + { + sSimpleFaces[simple_count++] = facep; + } + } + } + else if (te->getBumpmap()) + { //needs normal + tangent + if (bump_count < MAX_FACE_COUNT) + { + sBumpFaces[bump_count++] = facep; + } + } + else if (te->getShiny() || !te->getFullbright()) + { //needs normal + if (simple_count < MAX_FACE_COUNT) + { + sSimpleFaces[simple_count++] = facep; + } + } + else + { //doesn't need normal + facep->setState(LLFace::FULLBRIGHT); + if (fullbright_count < MAX_FACE_COUNT) + { + sFullbrightFaces[fullbright_count++] = facep; + } + } + } + else + { + if (te->getBumpmap() && LLPipeline::sRenderBump) + { //needs normal + tangent + if (bump_count < MAX_FACE_COUNT) + { + sBumpFaces[bump_count++] = facep; + } + } + else if ((te->getShiny() && LLPipeline::sRenderBump) || + !(te->getFullbright() || bake_sunlight)) + { //needs normal + if (simple_count < MAX_FACE_COUNT) + { + sSimpleFaces[simple_count++] = facep; + } + } + else + { //doesn't need normal + facep->setState(LLFace::FULLBRIGHT); + if (fullbright_count < MAX_FACE_COUNT) + { + sFullbrightFaces[fullbright_count++] = facep; + } + } + } + } + } + else + { //face has no renderable geometry + facep->clearVertexBuffer(); + } + } + + if (any_rigged_face) + { + if (!drawablep->isState(LLDrawable::RIGGED)) + { + drawablep->setState(LLDrawable::RIGGED); -void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume) -{ - bool copy = false; - if (volume->getNumVolumeFaces() != getNumVolumeFaces()) - { - copy = true; - } - - for (S32 i = 0; i < volume->getNumVolumeFaces() && !copy; ++i) - { - const LLVolumeFace& src_face = volume->getVolumeFace(i); - const LLVolumeFace& dst_face = getVolumeFace(i); - - if (src_face.mNumIndices != dst_face.mNumIndices || - src_face.mNumVertices != dst_face.mNumVertices) - { - copy = true; - } - } - - if (copy) - { - copyVolumeFaces(volume); - } - else - { - bool is_paused = avatar && avatar->areAnimationsPaused(); - if (is_paused) - { - S32 frames_paused = LLFrameTimer::getFrameCount() - avatar->getMotionController().getPausedFrame(); - if (frames_paused > 2) + //first time this is drawable is being marked as rigged, + // do another LoD update to use avatar bounding box + vobj->updateLOD(); + } + } + else { - return; + drawablep->clearState(LLDrawable::RIGGED); + vobj->updateRiggedVolume(); } - } + } } + group->mBufferUsage = useage; + + //PROCESS NON-ALPHA FACES + U32 simple_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + U32 alpha_mask = simple_mask | 0x80000000; //hack to give alpha verts their own VBO + U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + + U32 norm_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TANGENT; + U32 normspec_mask = norm_mask | LLVertexBuffer::MAP_TEXCOORD2; + U32 spec_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD2; + + if (emissive) + { //emissive faces are present, include emissive byte to preserve batching + simple_mask = simple_mask | LLVertexBuffer::MAP_EMISSIVE; + alpha_mask = alpha_mask | LLVertexBuffer::MAP_EMISSIVE; + bump_mask = bump_mask | LLVertexBuffer::MAP_EMISSIVE; + fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_EMISSIVE; + norm_mask = norm_mask | LLVertexBuffer::MAP_EMISSIVE; + normspec_mask = normspec_mask | LLVertexBuffer::MAP_EMISSIVE; + spec_mask = spec_mask | LLVertexBuffer::MAP_EMISSIVE; + } - //build matrix palette - static const size_t kMaxJoints = LL_MAX_JOINTS_PER_MESH_OBJECT; - - LLMatrix4a mat[kMaxJoints]; - U32 maxJoints = LLSkinningUtil::getMeshJointCount(skin); - LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, maxJoints, skin, avatar); - - S32 rigged_vert_count = 0; - S32 rigged_face_count = 0; - LLVector4a box_min, box_max; - for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) - { - const LLVolumeFace& vol_face = volume->getVolumeFace(i); - - LLVolumeFace& dst_face = mVolumeFaces[i]; - - LLVector4a* weight = vol_face.mWeights; - - if ( weight ) - { - LLSkinningUtil::checkSkinWeights(weight, dst_face.mNumVertices, skin); - LLMatrix4a bind_shape_matrix; - bind_shape_matrix.loadu(skin->mBindShapeMatrix); + BOOL batch_textures = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1; - LLVector4a* pos = dst_face.mPositions; + if (batch_textures) + { + bump_mask = bump_mask | LLVertexBuffer::MAP_TANGENT; + simple_mask = simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX; + alpha_mask = alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2; + fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX; + } - if (pos && dst_face.mExtents) - { - LL_RECORD_BLOCK_TIME(FTM_SKIN_RIGGED); + group->mGeometryBytes = 0; - U32 max_joints = LLSkinningUtil::getMaxJointCount(); - rigged_vert_count += dst_face.mNumVertices; - rigged_face_count++; - for (U32 j = 0; j < dst_face.mNumVertices; ++j) - { - LLMatrix4a final_mat; - LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); - - LLVector4a& v = vol_face.mPositions[j]; - LLVector4a t; - LLVector4a dst; - bind_shape_matrix.affineTransform(v, t); - final_mat.affineTransform(t, dst); - pos[j] = dst; - } - - //update bounding box - // VFExtents change - LLVector4a& min = dst_face.mExtents[0]; - LLVector4a& max = dst_face.mExtents[1]; - - min = pos[0]; - max = pos[1]; - if (i==0) - { - box_min = min; - box_max = max; - } + U32 geometryBytes = 0; - for (U32 j = 1; j < dst_face.mNumVertices; ++j) - { - min.setMin(min, pos[j]); - max.setMax(max, pos[j]); - } + geometryBytes += genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE); + geometryBytes += genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures); + geometryBytes += genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures); + geometryBytes += genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE); + geometryBytes += genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE); + geometryBytes += genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE); + geometryBytes += genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE); - box_min.setMin(min,box_min); - box_max.setMax(max,box_max); + group->mGeometryBytes = geometryBytes; - dst_face.mCenter->setAdd(dst_face.mExtents[0], dst_face.mExtents[1]); - dst_face.mCenter->mul(0.5f); + if (!LLPipeline::sDelayVBUpdate) + { + //drawables have been rebuilt, clear rebuild status + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) + { + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + if(drawablep) + { + drawablep->clearState(LLDrawable::REBUILD_ALL); + } + } + } - } + group->mLastUpdateTime = gFrameTimeSeconds; + group->mBuilt = 1.f; + group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY); - { - LL_RECORD_BLOCK_TIME(FTM_RIGGED_OCTREE); - delete dst_face.mOctree; - dst_face.mOctree = NULL; + if (LLPipeline::sDelayVBUpdate) + { + group->setState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); + } - LLVector4a size; - size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]); - size.splat(size.getLength3().getF32()*0.5f); - - dst_face.createOctree(1.f); - } - } - } - mExtraDebugText = llformat("rigged %d/%d - box (%f %f %f) (%f %f %f)", - rigged_face_count, rigged_vert_count, - box_min[0], box_min[1], box_min[2], - box_max[0], box_max[1], box_max[2]); + mFaceList.clear(); } -U32 LLVOVolume::getPartitionType() const -{ - if (isHUDAttachment()) - { - return LLViewerRegion::PARTITION_HUD; - } - - return LLViewerRegion::PARTITION_VOLUME; -} +static LLTrace::BlockTimerStatHandle FTM_REBUILD_MESH_FLUSH("Flush Mesh"); -LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp) -: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB, regionp), -LLVolumeGeometryManager() +void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) { - mLODPeriod = 32; - mDepthMask = FALSE; - mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; - mPartitionType = LLViewerRegion::PARTITION_VOLUME; - mSlopRatio = 0.25f; - mBufferUsage = GL_DYNAMIC_DRAW_ARB; -} + llassert(group); + if (group && group->hasState(LLSpatialGroup::MESH_DIRTY) && !group->hasState(LLSpatialGroup::GEOM_DIRTY)) + { + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers -LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep, LLViewerRegion* regionp) -: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK, regionp), -LLVolumeGeometryManager() -{ - mDepthMask = FALSE; - mLODPeriod = 32; - mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; - mPartitionType = LLViewerRegion::PARTITION_BRIDGE; - - mBufferUsage = GL_DYNAMIC_DRAW_ARB; + group->mBuilt = 1.f; + + S32 num_mapped_vertex_buffer = LLVertexBuffer::sMappedCount ; - mSlopRatio = 0.25f; -} + const U32 MAX_BUFFER_COUNT = 4096; + LLVertexBuffer* locked_buffer[MAX_BUFFER_COUNT]; + + U32 buffer_count = 0; -bool can_batch_texture(LLFace* facep) -{ - if (facep->getTextureEntry()->getBumpmap()) - { //bump maps aren't worked into texture batching yet - return false; - } + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) + { + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - if (facep->getTextureEntry()->getMaterialParams().notNull()) - { //materials don't work with texture batching yet - return false; - } + if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) + { + LLVOVolume* vobj = drawablep->getVOVolume(); + if (debugLoggingEnabled("AnimatedObjectsLinkset")) + { + if (vobj->isAnimatedObject() && vobj->isRiggedMesh()) + { + std::string vobj_name = llformat("Vol%p", vobj); + F32 est_tris = vobj->getEstTrianglesMax(); + LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " rebuildMesh, tris " << est_tris << LL_ENDL; + } + } + if (vobj->isNoLOD()) continue; - if (facep->getTexture() && facep->getTexture()->getPrimaryFormat() == GL_ALPHA) - { //can't batch invisiprims - return false; - } + vobj->preRebuild(); - if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) - { //texture animation breaks batches - return false; - } - - return true; -} + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(true); + } -const static U32 MAX_FACE_COUNT = 4096U; -int32_t LLVolumeGeometryManager::sInstanceCount = 0; -LLFace** LLVolumeGeometryManager::sFullbrightFaces = NULL; -LLFace** LLVolumeGeometryManager::sBumpFaces = NULL; -LLFace** LLVolumeGeometryManager::sSimpleFaces = NULL; -LLFace** LLVolumeGeometryManager::sNormFaces = NULL; -LLFace** LLVolumeGeometryManager::sSpecFaces = NULL; -LLFace** LLVolumeGeometryManager::sNormSpecFaces = NULL; -LLFace** LLVolumeGeometryManager::sAlphaFaces = NULL; + LLVolume* volume = vobj->getVolume(); + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + LLFace* face = drawablep->getFace(i); + if (face) + { + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff) + { + llassert(!face->isState(LLFace::RIGGED)); + + if (!face->getGeometryVolume(*volume, face->getTEOffset(), + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex())) + { //something's gone wrong with the vertex buffer accounting, rebuild this group + group->dirtyGeom(); + gPipeline.markRebuild(group, TRUE); + } + + + if (buff->isLocked() && buffer_count < MAX_BUFFER_COUNT) + { + locked_buffer[buffer_count++] = buff; + } + } + } + } -LLVolumeGeometryManager::LLVolumeGeometryManager() - : LLGeometryManager() -{ - llassert(sInstanceCount >= 0); - if (sInstanceCount == 0) - { - allocateFaces(MAX_FACE_COUNT); - } + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(); + } - ++sInstanceCount; -} + + drawablep->clearState(LLDrawable::REBUILD_ALL); + } + } + + { + LL_RECORD_BLOCK_TIME(FTM_REBUILD_MESH_FLUSH); + for (LLVertexBuffer** iter = locked_buffer, ** end_iter = locked_buffer+buffer_count; iter != end_iter; ++iter) + { + (*iter)->flush(); + } -LLVolumeGeometryManager::~LLVolumeGeometryManager() -{ - llassert(sInstanceCount > 0); - --sInstanceCount; + // don't forget alpha + if(group != NULL && + !group->mVertexBuffer.isNull() && + group->mVertexBuffer->isLocked()) + { + group->mVertexBuffer->flush(); + } + } - if (sInstanceCount <= 0) - { - freeFaces(); - sInstanceCount = 0; - } -} + //if not all buffers are unmapped + if(num_mapped_vertex_buffer != LLVertexBuffer::sMappedCount) + { + LL_WARNS() << "Not all mapped vertex buffers are unmapped!" << LL_ENDL ; + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) + { + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + if(!drawablep) + { + continue; + } + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + LLFace* face = drawablep->getFace(i); + if (face) + { + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff && buff->isLocked()) + { + buff->flush(); + } + } + } + } + } -void LLVolumeGeometryManager::allocateFaces(U32 pMaxFaceCount) -{ - sFullbrightFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sBumpFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sSimpleFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sNormFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sSpecFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sNormSpecFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sAlphaFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); + } + +// llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO)); } -void LLVolumeGeometryManager::freeFaces() +struct CompareBatchBreakerModified { - ll_aligned_free<64>(sFullbrightFaces); - ll_aligned_free<64>(sBumpFaces); - ll_aligned_free<64>(sSimpleFaces); - ll_aligned_free<64>(sNormFaces); - ll_aligned_free<64>(sSpecFaces); - ll_aligned_free<64>(sNormSpecFaces); - ll_aligned_free<64>(sAlphaFaces); - - sFullbrightFaces = NULL; - sBumpFaces = NULL; - sSimpleFaces = NULL; - sNormFaces = NULL; - sSpecFaces = NULL; - sNormSpecFaces = NULL; - sAlphaFaces = NULL; -} + bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) + { + const LLTextureEntry* lte = lhs->getTextureEntry(); + const LLTextureEntry* rte = rhs->getTextureEntry(); -static LLTrace::BlockTimerStatHandle FTM_REGISTER_FACE("Register Face"); + if (lte->getBumpmap() != rte->getBumpmap()) + { + return lte->getBumpmap() < rte->getBumpmap(); + } + else if (lte->getFullbright() != rte->getFullbright()) + { + return lte->getFullbright() < rte->getFullbright(); + } + else if (LLPipeline::sRenderDeferred && lte->getMaterialParams() != rte->getMaterialParams()) + { + return lte->getMaterialParams() < rte->getMaterialParams(); + } + else if (LLPipeline::sRenderDeferred && (lte->getMaterialParams() == rte->getMaterialParams()) && (lte->getShiny() != rte->getShiny())) + { + return lte->getShiny() < rte->getShiny(); + } + else + { + return lhs->getTexture() < rhs->getTexture(); + } + } +}; -void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) -{ - LL_RECORD_BLOCK_TIME(FTM_REGISTER_FACE); - if (type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT)) - { - LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL; - } - - bool selected = facep->getViewerObject()->isSelected(); - - if (selected && LLSelectMgr::getInstance()->mHideSelectedObjects) - { - return; - } - - //add face to drawmap - LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[type]; - - S32 idx = draw_vec.size()-1; - - BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) || - (type == LLRenderPass::PASS_INVISIBLE) || - (type == LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK) || - (type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)) || - (facep->getTextureEntry()->getFullbright()); - - if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_NORMAL)) - { - LL_WARNS() << "Non fullbright face has no normals!" << LL_ENDL; - return; - } - - const LLMatrix4* tex_mat = NULL; - if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) - { - tex_mat = facep->mTextureMatrix; - } - - const LLMatrix4* model_mat = NULL; - - LLDrawable* drawable = facep->getDrawable(); - - if (drawable->isState(LLDrawable::ANIMATED_CHILD)) - { - model_mat = &drawable->getWorldMatrix(); - } - else if (drawable->isActive()) - { - model_mat = &drawable->getRenderMatrix(); - } - else - { - model_mat = &(drawable->getRegion()->mRenderMatrix); - } - - //drawable->getVObj()->setDebugText(llformat("%d", drawable->isState(LLDrawable::ANIMATED_CHILD))); - - U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0; - U8 shiny = facep->getTextureEntry()->getShiny(); - - LLViewerTexture* tex = facep->getTexture(); - - U8 index = facep->getTextureIndex(); - - LLMaterial* mat = facep->getTextureEntry()->getMaterialParams().get(); - LLMaterialID mat_id = facep->getTextureEntry()->getMaterialID(); - - bool batchable = false; - - U32 shader_mask = 0xFFFFFFFF; //no shader - - if (mat) - { - if (type == LLRenderPass::PASS_ALPHA) - { - shader_mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND); - } - else - { - shader_mask = mat->getShaderMask(); - } - } - - - if (index < 255 && idx >= 0) - { - if (mat || draw_vec[idx]->mMaterial) - { //can't batch textures when materials are present (yet) - batchable = false; - } - else if (index < draw_vec[idx]->mTextureList.size()) - { - if (draw_vec[idx]->mTextureList[index].isNull()) - { - batchable = true; - draw_vec[idx]->mTextureList[index] = tex; - } - else if (draw_vec[idx]->mTextureList[index] == tex) - { //this face's texture index can be used with this batch - batchable = true; - } - } - else - { //texture list can be expanded to fit this texture index - batchable = true; - } - } - - if (idx >= 0 && - draw_vec[idx]->mVertexBuffer == facep->getVertexBuffer() && - draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && - (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex || batchable) && -#if LL_DARWIN - draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && - draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && -#endif - draw_vec[idx]->mMaterial == mat && - draw_vec[idx]->mMaterialID == mat_id && - draw_vec[idx]->mFullbright == fullbright && - draw_vec[idx]->mBump == bump && - (!mat || (draw_vec[idx]->mShiny == shiny)) && // need to break batches when a material is shared, but legacy settings are different - draw_vec[idx]->mTextureMatrix == tex_mat && - draw_vec[idx]->mModelMatrix == model_mat && - draw_vec[idx]->mShaderMask == shader_mask && - draw_vec[idx]->mSelected == selected) - { - draw_vec[idx]->mCount += facep->getIndicesCount(); - draw_vec[idx]->mEnd += facep->getGeomCount(); - draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize()); - - if (index < 255 && index >= draw_vec[idx]->mTextureList.size()) - { - draw_vec[idx]->mTextureList.resize(index+1); - draw_vec[idx]->mTextureList[index] = tex; - } - draw_vec[idx]->validate(); - update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]); - update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[1]); - } - else - { - U32 start = facep->getGeomIndex(); - U32 end = start + facep->getGeomCount()-1; - U32 offset = facep->getIndicesStart(); - U32 count = facep->getIndicesCount(); - LLPointer draw_info = new LLDrawInfo(start,end,count,offset, tex, - facep->getVertexBuffer(), selected, fullbright, bump); - draw_info->mGroup = group; - draw_info->mVSize = facep->getVirtualSize(); - draw_vec.push_back(draw_info); - draw_info->mTextureMatrix = tex_mat; - draw_info->mModelMatrix = model_mat; - - draw_info->mBump = bump; - draw_info->mShiny = shiny; - - static const float alpha[4] = - { - 0.00f, - 0.25f, - 0.5f, - 0.75f - }; - float spec = alpha[shiny & TEM_SHINY_MASK]; - LLVector4 specColor(spec, spec, spec, spec); - draw_info->mSpecColor = specColor; - draw_info->mEnvIntensity = spec; - draw_info->mSpecularMap = NULL; - draw_info->mMaterial = mat; - draw_info->mShaderMask = shader_mask; - - if (mat) - { - draw_info->mMaterialID = mat_id; - - // We have a material. Update our draw info accordingly. - - if (!mat->getSpecularID().isNull()) - { - LLVector4 specColor; - specColor.mV[0] = mat->getSpecularLightColor().mV[0] * (1.f / 255.f); - specColor.mV[1] = mat->getSpecularLightColor().mV[1] * (1.f / 255.f); - specColor.mV[2] = mat->getSpecularLightColor().mV[2] * (1.f / 255.f); - specColor.mV[3] = mat->getSpecularLightExponent() * (1.f / 255.f); - draw_info->mSpecColor = specColor; - draw_info->mEnvIntensity = mat->getEnvironmentIntensity() * (1.f / 255.f); - draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTEOffset()); - } - - draw_info->mAlphaMaskCutoff = mat->getAlphaMaskCutoff() * (1.f / 255.f); - draw_info->mDiffuseAlphaMode = mat->getDiffuseAlphaMode(); - draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTEOffset()); - } - else - { - if (type == LLRenderPass::PASS_GRASS) - { - draw_info->mAlphaMaskCutoff = 0.5f; - } - else - { - draw_info->mAlphaMaskCutoff = 0.33f; - } - } - - if (type == LLRenderPass::PASS_ALPHA) - { //for alpha sorting - facep->setDrawInfo(draw_info); - } - draw_info->mExtents[0] = facep->mExtents[0]; - draw_info->mExtents[1] = facep->mExtents[1]; - - if (LLPipeline::sUseTriStrips) - { - draw_info->mDrawMode = LLRender::TRIANGLE_STRIP; - } - - if (index < 255) - { //initialize texture list for texture batching - draw_info->mTextureList.resize(index+1); - draw_info->mTextureList[index] = tex; - } - draw_info->validate(); - } -} +static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_SORT("Draw Info Face Sort"); +static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_FACE_SIZE("Face Sizing"); +static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_ALLOCATE("Allocate VB"); +static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_FIND_VB("Find VB"); +static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); -void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) -{ -} -static LLTrace::BlockTimerStatHandle FTM_REBUILD_VOLUME_VB("Volume VB"); -static LLTrace::BlockTimerStatHandle FTM_REBUILD_VOLUME_FACE_LIST("Build Face List"); -static LLTrace::BlockTimerStatHandle FTM_REBUILD_VOLUME_GEN_DRAW_INFO("Gen Draw Info"); -static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) -{ - LLVOAvatar* avatar = vobj->getAvatar(); - - if (avatar) - { - LLDrawable* drawable = avatar->mDrawable; - if (drawable && drawable->getNumFaces() > 0) - { - LLFace* face = drawable->getFace(0); - if (face) - { - LLDrawPool* drawpool = face->getPool(); - if (drawpool) - { - if (drawpool->getType() == LLDrawPool::POOL_AVATAR) - { - return (LLDrawPoolAvatar*) drawpool; - } - } - } - } - } - - return NULL; -} -void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value) +U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL no_materials) { - static LLCachedControl render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U); - - if (0 != render_auto_mute_byte_limit) - { - //for unload - LLSculptIDSize::container_BY_SIZE_view::iterator - itL = LLSculptIDSize::instance().getSizeInfo().get().lower_bound(render_auto_mute_byte_limit), - itU = LLSculptIDSize::instance().getSizeInfo().get().end(); - - for (; itL != itU; ++itL) - { - const LLSculptIDSize::Info &nfo = *itL; - LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); - if (pVVol - && !pVVol->isDead() - && pVVol->isAttachment() - && !pVVol->getAvatar()->isSelf() - && LLVOVolume::NO_LOD != pVVol->getLOD() - ) - { - //postponed - pVVol->markForUnload(); - LLSculptIDSize::instance().addToUnloaded(nfo.getSculptId()); - } - } - - //for load if it was unload - itL = LLSculptIDSize::instance().getSizeInfo().get().begin(); - itU = LLSculptIDSize::instance().getSizeInfo().get().upper_bound(render_auto_mute_byte_limit); - - for (; itL != itU; ++itL) - { - const LLSculptIDSize::Info &nfo = *itL; - LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); - if (pVVol - && !pVVol->isDead() - && pVVol->isAttachment() - && !pVVol->getAvatar()->isSelf() - && LLVOVolume::NO_LOD == pVVol->getLOD() - ) - { - LLSculptIDSize::instance().remFromUnloaded(nfo.getSculptId()); - pVVol->updateLOD(); - pVVol->markForUpdate(TRUE); - } - } - } - else - { - LLSculptIDSize::instance().clearUnloaded(); - - LLSculptIDSize::container_BY_SIZE_view::iterator - itL = LLSculptIDSize::instance().getSizeInfo().get().begin(), - itU = LLSculptIDSize::instance().getSizeInfo().get().end(); - - for (; itL != itU; ++itL) - { - const LLSculptIDSize::Info &nfo = *itL; - LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); - if (pVVol - && !pVVol->isDead() - && pVVol->isAttachment() - && !pVVol->getAvatar()->isSelf() - && LLVOVolume::NO_LOD == pVVol->getLOD() - ) - { - pVVol->updateLOD(); - pVVol->markForUpdate(TRUE); - } - } - } -} + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); -void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) -{ - if (group->changeLOD()) - { - group->mLastUpdateDistance = group->mDistance; - } + U32 geometryBytes = 0; + U32 buffer_usage = group->mBufferUsage; + + static LLCachedControl use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false); - group->mLastUpdateViewAngle = group->mViewAngle; + if (use_transform_feedback && + gTransformPositionProgram.mProgramObject && //transform shaders are loaded + buffer_usage == GL_DYNAMIC_DRAW_ARB && //target buffer is in VRAM + !(mask & LLVertexBuffer::MAP_WEIGHT4)) //TODO: add support for weights + { + buffer_usage = GL_DYNAMIC_COPY_ARB; + } - if (!group->hasState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY)) - { - if (group->hasState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate) - { - rebuildMesh(group); - } - return; - } +#if LL_DARWIN + // HACK from Leslie: + // Disable VBO usage for alpha on Mac OS X because it kills the framerate + // due to implicit calls to glTexSubImage that are beyond our control. + // (this works because the only calls here that sort by distance are alpha) + if (distance_sort) + { + buffer_usage = 0x0; + } +#endif + + //calculate maximum number of vertices to store in a single buffer + U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); + max_vertices = llmin(max_vertices, (U32) 65535); - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB); + { + LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_SORT); + if (!distance_sort) + { + //sort faces by things that break batches + std::sort(faces, faces+face_count, CompareBatchBreakerModified()); + } + else + { + //sort faces by distance + std::sort(faces, faces+face_count, LLFace::CompareDistanceGreater()); + } + } + + bool hud_group = group->isHUDGroup() ; + LLFace** face_iter = faces; + LLFace** end_faces = faces+face_count; + + LLSpatialGroup::buffer_map_t buffer_map; - group->mBuilt = 1.f; - - LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); - LLViewerObject *vobj = NULL; - LLVOVolume *vol_obj = NULL; + LLViewerTexture* last_tex = NULL; + S32 buffer_index = 0; - if (bridge) - { - vobj = bridge->mDrawable->getVObj(); - vol_obj = dynamic_cast(vobj); - } - if (vol_obj) + if (distance_sort) { - vol_obj->updateVisualComplexity(); + buffer_index = -1; + } + + S32 texture_index_channels = 1; + + if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) + { + texture_index_channels = LLGLSLShader::sIndexedTextureChannels-1; //always reserve one for shiny for now just for simplicity; } - group->mGeometryBytes = 0; - group->mSurfaceArea = 0; - - //cache object box size since it might be used for determining visibility - const LLVector4a* bounds = group->getObjectBounds(); - group->mObjectBoxSize = bounds[1].getLength3().getF32(); + if (LLPipeline::sRenderDeferred && distance_sort) + { + texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels; + } - group->clearDrawMap(); + texture_index_channels = llmin(texture_index_channels, (S32) gSavedSettings.getU32("RenderMaxTextureIndex")); + + //NEVER use more than 16 texture index channels (workaround for prevalent driver bug) + texture_index_channels = llmin(texture_index_channels, 16); - mFaceList.clear(); + bool flexi = false; - U32 fullbright_count = 0; - U32 bump_count = 0; - U32 simple_count = 0; - U32 alpha_count = 0; - U32 norm_count = 0; - U32 spec_count = 0; - U32 normspec_count = 0; + while (face_iter != end_faces) + { + //pull off next face + LLFace* facep = *face_iter; + LLViewerTexture* tex = facep->getTexture(); + LLMaterialPtr mat = facep->getTextureEntry()->getMaterialParams(); + if (distance_sort) + { + tex = NULL; + } - U32 useage = group->getSpatialPartition()->mBufferUsage; + if (last_tex == tex) + { + buffer_index++; + } + else + { + last_tex = tex; + buffer_index = 0; + } - U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); - U32 max_total = (gSavedSettings.getS32("RenderMaxNodeSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); - max_vertices = llmin(max_vertices, (U32) 65535); + bool bake_sunlight = LLPipeline::sBakeSunlight && facep->getDrawable()->isStatic(); - U32 cur_total = 0; + U32 index_count = facep->getIndicesCount(); + U32 geom_count = facep->getGeomCount(); - bool emissive = false; + flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); - //Determine if we've received skininfo that contains an - //alternate bind matrix - if it does then apply the translational component - //to the joints of the avatar. -#if 0 - bool pelvisGotSet = false; -#endif + //sum up vertices needed for this render batch + LLFace** i = face_iter; + ++i; + + const U32 MAX_TEXTURE_COUNT = 32; + LLViewerTexture* texture_list[MAX_TEXTURE_COUNT]; + + U32 texture_count = 0; - { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_FACE_LIST); + { + LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_FACE_SIZE); + if (batch_textures) + { + U8 cur_tex = 0; + facep->setTextureIndex(cur_tex); + if (texture_count < MAX_TEXTURE_COUNT) + { + texture_list[texture_count++] = tex; + } - //get all the faces into a list - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); - drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - - if (!drawablep || drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) - { - continue; - } - - if (drawablep->isAnimating()) - { //fall back to stream draw for animating verts - useage = GL_STREAM_DRAW_ARB; - } - - LLVOVolume* vobj = drawablep->getVOVolume(); + if (can_batch_texture(facep)) + { //populate texture_list with any textures that can be batched + //move i to the next unbatchable face + while (i != end_faces) + { + facep = *i; + + if (!can_batch_texture(facep)) + { //face is bump mapped or has an animated texture matrix -- can't + //batch more than 1 texture at a time + facep->setTextureIndex(0); + break; + } + + if (facep->getTexture() != tex) + { + if (distance_sort) + { //textures might be out of order, see if texture exists in current batch + bool found = false; + for (U32 tex_idx = 0; tex_idx < texture_count; ++tex_idx) + { + if (facep->getTexture() == texture_list[tex_idx]) + { + cur_tex = tex_idx; + found = true; + break; + } + } + + if (!found) + { + cur_tex = texture_count; + } + } + else + { + cur_tex++; + } + + if (cur_tex >= texture_index_channels) + { //cut batches when index channels are depleted + break; + } + + tex = facep->getTexture(); + + if (texture_count < MAX_TEXTURE_COUNT) + { + texture_list[texture_count++] = tex; + } + } + + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut batches on geom count too big + break; + } + + ++i; + + flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); + + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); + + facep->setTextureIndex(cur_tex); + } + } + else + { + facep->setTextureIndex(0); + } + + tex = texture_list[0]; + } + else + { + while (i != end_faces && + (LLPipeline::sTextureBindTest || + (distance_sort || + ((*i)->getTexture() == tex && + ((*i)->getTextureEntry()->getMaterialParams() == mat))))) + { + facep = *i; - if (!vobj) - { - continue; - } - std::string vobj_name = llformat("Vol%p", vobj); + //face has no texture index + facep->mDrawInfo = NULL; + facep->setTextureIndex(255); - if (vobj->isMesh() && - ((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled())) - { - continue; - } + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut batches on geom count too big + break; + } - LLVolume* volume = vobj->getVolume(); - if (volume) - { - const LLVector3& scale = vobj->getScale(); - group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); - } + ++i; + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); - bool is_mesh = vobj->isMesh(); - F32 est_tris = vobj->getEstTrianglesMax(); + flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); + } + } + } - vobj->updateControlAvatar(); - - LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " rebuilding, isAttachment: " << (U32) vobj->isAttachment() - << " is_mesh " << is_mesh - << " est_tris " << est_tris - << " is_animated " << vobj->isAnimatedObject() - << " can_animate " << vobj->canBeAnimatedObject() - << " cav " << vobj->getControlAvatar() - << " lod " << vobj->getLOD() - << " drawable rigged " << (drawablep->isState(LLDrawable::RIGGED)) - << " drawable state " << drawablep->getState() - << " playing " << (U32) (vobj->getControlAvatar() ? vobj->getControlAvatar()->mPlaying : false) - << " frame " << LLFrameTimer::getFrameCount() - << LL_ENDL; - llassert_always(vobj); - vobj->updateTextureVirtualSize(true); - vobj->preRebuild(); + if (flexi && buffer_usage && buffer_usage != GL_STREAM_DRAW_ARB) + { + buffer_usage = GL_STREAM_DRAW_ARB; + } - drawablep->clearState(LLDrawable::HAS_ALPHA); + //create vertex buffer + LLPointer buffer; - if (vobj->isRiggedMesh() && - ((vobj->isAnimatedObject() && vobj->getControlAvatar()) || - (!vobj->isAnimatedObject() && vobj->getAvatar()))) + { + LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_ALLOCATE); + buffer = createVertexBuffer(mask, buffer_usage); + if(!buffer->allocateBuffer(geom_count, index_count, TRUE)) { - vobj->getAvatar()->addAttachmentOverridesForObject(vobj, NULL, false); + LL_WARNS() << "Failed to allocate group Vertex Buffer to " + << geom_count << " vertices and " + << index_count << " indices" << LL_ENDL; + buffer = NULL; } - - // Standard rigged mesh attachments: - bool rigged = !vobj->isAnimatedObject() && vobj->isRiggedMesh() && vobj->isAttachment(); - // Animated objects. Have to check for isRiggedMesh() to - // exclude static objects in animated object linksets. - rigged = rigged || (vobj->isAnimatedObject() && vobj->isRiggedMesh() && - vobj->getControlAvatar() && vobj->getControlAvatar()->mPlaying); + } - bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); - bool any_rigged_face = false; - - //for each face - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - LLFace* facep = drawablep->getFace(i); - if (!facep) - { - continue; - } - - //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render - // batch, it will recover its vertex buffer reference from the spatial group - facep->setVertexBuffer(NULL); - - //sum up face verts and indices - drawablep->updateFaceSize(i); - - if (rigged) - { - if (!facep->isState(LLFace::RIGGED)) - { //completely reset vertex buffer - facep->clearVertexBuffer(); - } - - facep->setState(LLFace::RIGGED); - any_rigged_face = true; - - //get drawpool of avatar with rigged face - LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); - - if (pool) - { - const LLTextureEntry* te = facep->getTextureEntry(); - - //remove face from old pool if it exists - LLDrawPool* old_pool = facep->getPool(); - if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) - { - ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); - } - - //add face to new pool - LLViewerTexture* tex = facep->getTexture(); - U32 type = gPipeline.getPoolTypeFromTE(te, tex); - - - if (te->getGlow()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); - } - - LLMaterial* mat = te->getMaterialParams().get(); - - if (mat && LLPipeline::sRenderDeferred) - { - U8 alpha_mode = mat->getDiffuseAlphaMode(); - - bool is_alpha = type == LLDrawPool::POOL_ALPHA && - (alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND || - te->getColor().mV[3] < 0.999f); - - if (is_alpha) - { //this face needs alpha blending, override alpha mode - alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; - } - - if (!is_alpha || te->getColor().mV[3] > 0.f) // //only add the face if it will actually be visible - { - U32 mask = mat->getShaderMask(alpha_mode); - pool->addRiggedFace(facep, mask); - } - } - else if (mat) - { - bool fullbright = te->getFullbright(); - bool is_alpha = type == LLDrawPool::POOL_ALPHA; - U8 mode = mat->getDiffuseAlphaMode(); - bool can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || - mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; - - if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && te->getColor().mV[3] >= 0.999f) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); - } - else if (is_alpha || (te->getColor().mV[3] < 0.999f)) - { - if (te->getColor().mV[3] > 0.f) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA : LLDrawPoolAvatar::RIGGED_ALPHA); - } - } - else if (gPipeline.canUseVertexShaders() - && LLPipeline::sRenderBump - && te->getShiny() - && can_be_shiny) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY : LLDrawPoolAvatar::RIGGED_SHINY); - } - else - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); - } - } - else - { - if (type == LLDrawPool::POOL_ALPHA) - { - if (te->getColor().mV[3] > 0.f) - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); - } - } - } - else if (te->getShiny()) - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); - } - else - { - if (LLPipeline::sRenderDeferred) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); - } - } - } - else - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); - } - } - - - if (LLPipeline::sRenderDeferred) - { - if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) - { - if (te->getBumpmap()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); - } - } - } - } - } - - continue; - } - else - { - if (facep->isState(LLFace::RIGGED)) - { //face is not rigged but used to be, remove from rigged face pool - LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); - if (pool) - { - pool->removeRiggedFace(facep); - } - facep->clearState(LLFace::RIGGED); - } - } - - - if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) - { - facep->clearVertexBuffer(); - continue; - } - - cur_total += facep->getGeomCount(); - - if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) - { - const LLTextureEntry* te = facep->getTextureEntry(); - LLViewerTexture* tex = facep->getTexture(); - - if (te->getGlow() >= 1.f/255.f) - { - emissive = true; - } - - if (facep->isState(LLFace::TEXTURE_ANIM)) - { - if (!vobj->mTexAnimMode) - { - facep->clearState(LLFace::TEXTURE_ANIM); - } - } - - BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); - U32 type = gPipeline.getPoolTypeFromTE(te, tex); - if (type != LLDrawPool::POOL_ALPHA && force_simple) - { - type = LLDrawPool::POOL_SIMPLE; - } - facep->setPoolType(type); - - if (vobj->isHUDAttachment()) - { - facep->setState(LLFace::FULLBRIGHT); - } - - if (vobj->mTextureAnimp && vobj->mTexAnimMode) - { - if (vobj->mTextureAnimp->mFace <= -1) - { - S32 face; - for (face = 0; face < vobj->getNumTEs(); face++) - { - LLFace * facep = drawablep->getFace(face); - if (facep) - { - facep->setState(LLFace::TEXTURE_ANIM); - } - } - } - else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) - { - LLFace * facep = drawablep->getFace(vobj->mTextureAnimp->mFace); - if (facep) - { - facep->setState(LLFace::TEXTURE_ANIM); - } - } - } - - if (type == LLDrawPool::POOL_ALPHA) - { - if (facep->canRenderAsMask()) - { //can be treated as alpha mask - if (simple_count < MAX_FACE_COUNT) - { - sSimpleFaces[simple_count++] = facep; - } - } - else - { - if (te->getColor().mV[3] > 0.f) - { //only treat as alpha in the pipeline if < 100% transparent - drawablep->setState(LLDrawable::HAS_ALPHA); - } - if (alpha_count < MAX_FACE_COUNT) - { - sAlphaFaces[alpha_count++] = facep; - } - } - } - else - { - if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) - { - facep->mLastUpdateTime = gFrameTimeSeconds; - } - - if (gPipeline.canUseWindLightShadersOnObjects() - && LLPipeline::sRenderBump) - { - if (LLPipeline::sRenderDeferred && te->getMaterialParams().notNull() && !te->getMaterialID().isNull()) - { - LLMaterial* mat = te->getMaterialParams().get(); - if (mat->getNormalID().notNull()) - { - if (mat->getSpecularID().notNull()) - { //has normal and specular maps (needs texcoord1, texcoord2, and tangent) - if (normspec_count < MAX_FACE_COUNT) - { - sNormSpecFaces[normspec_count++] = facep; - } - } - else - { //has normal map (needs texcoord1 and tangent) - if (norm_count < MAX_FACE_COUNT) - { - sNormFaces[norm_count++] = facep; - } - } - } - else if (mat->getSpecularID().notNull()) - { //has specular map but no normal map, needs texcoord2 - if (spec_count < MAX_FACE_COUNT) - { - sSpecFaces[spec_count++] = facep; - } - } - else - { //has neither specular map nor normal map, only needs texcoord0 - if (simple_count < MAX_FACE_COUNT) - { - sSimpleFaces[simple_count++] = facep; - } - } - } - else if (te->getBumpmap()) - { //needs normal + tangent - if (bump_count < MAX_FACE_COUNT) - { - sBumpFaces[bump_count++] = facep; - } - } - else if (te->getShiny() || !te->getFullbright()) - { //needs normal - if (simple_count < MAX_FACE_COUNT) - { - sSimpleFaces[simple_count++] = facep; - } - } - else - { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); - if (fullbright_count < MAX_FACE_COUNT) - { - sFullbrightFaces[fullbright_count++] = facep; - } - } - } - else - { - if (te->getBumpmap() && LLPipeline::sRenderBump) - { //needs normal + tangent - if (bump_count < MAX_FACE_COUNT) - { - sBumpFaces[bump_count++] = facep; - } - } - else if ((te->getShiny() && LLPipeline::sRenderBump) || - !(te->getFullbright() || bake_sunlight)) - { //needs normal - if (simple_count < MAX_FACE_COUNT) - { - sSimpleFaces[simple_count++] = facep; - } - } - else - { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); - if (fullbright_count < MAX_FACE_COUNT) - { - sFullbrightFaces[fullbright_count++] = facep; - } - } - } - } - } - else - { //face has no renderable geometry - facep->clearVertexBuffer(); - } - } - - if (any_rigged_face) - { - if (!drawablep->isState(LLDrawable::RIGGED)) - { - drawablep->setState(LLDrawable::RIGGED); - - //first time this is drawable is being marked as rigged, - // do another LoD update to use avatar bounding box - vobj->updateLOD(); - } - } - else - { - drawablep->clearState(LLDrawable::RIGGED); - vobj->updateRiggedVolume(); - } - } - } - - group->mBufferUsage = useage; - - //PROCESS NON-ALPHA FACES - U32 simple_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; - U32 alpha_mask = simple_mask | 0x80000000; //hack to give alpha verts their own VBO - U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; - U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; - - U32 norm_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TANGENT; - U32 normspec_mask = norm_mask | LLVertexBuffer::MAP_TEXCOORD2; - U32 spec_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD2; - - if (emissive) - { //emissive faces are present, include emissive byte to preserve batching - simple_mask = simple_mask | LLVertexBuffer::MAP_EMISSIVE; - alpha_mask = alpha_mask | LLVertexBuffer::MAP_EMISSIVE; - bump_mask = bump_mask | LLVertexBuffer::MAP_EMISSIVE; - fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_EMISSIVE; - norm_mask = norm_mask | LLVertexBuffer::MAP_EMISSIVE; - normspec_mask = normspec_mask | LLVertexBuffer::MAP_EMISSIVE; - spec_mask = spec_mask | LLVertexBuffer::MAP_EMISSIVE; - } - - BOOL batch_textures = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1; - - if (batch_textures) - { - bump_mask = bump_mask | LLVertexBuffer::MAP_TANGENT; - simple_mask = simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX; - alpha_mask = alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2; - fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX; - } - - group->mGeometryBytes = 0; - - U32 geometryBytes = 0; - - geometryBytes += genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE); - geometryBytes += genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures); - geometryBytes += genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures); - geometryBytes += genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE); - geometryBytes += genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE); - geometryBytes += genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE); - geometryBytes += genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE); - - group->mGeometryBytes = geometryBytes; - - if (!LLPipeline::sDelayVBUpdate) - { - //drawables have been rebuilt, clear rebuild status - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - if(drawablep) - { - drawablep->clearState(LLDrawable::REBUILD_ALL); - } + if (buffer) + { + geometryBytes += buffer->getSize() + buffer->getIndicesSize(); + buffer_map[mask][*face_iter].push_back(buffer); } - } - group->mLastUpdateTime = gFrameTimeSeconds; - group->mBuilt = 1.f; - group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY); + //add face geometry - if (LLPipeline::sDelayVBUpdate) - { - group->setState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); - } + U32 indices_index = 0; + U16 index_offset = 0; - mFaceList.clear(); -} + while (face_iter < i) + { + //update face indices for new buffer + facep = *face_iter; + if (buffer.isNull()) + { + // Bulk allocation failed + facep->setVertexBuffer(buffer); + facep->setSize(0, 0); // mark as no geometry + ++face_iter; + continue; + } + facep->setIndicesIndex(indices_index); + facep->setGeomIndex(index_offset); + facep->setVertexBuffer(buffer); + + if (batch_textures && facep->getTextureIndex() == 255) + { + LL_ERRS() << "Invalid texture index." << LL_ENDL; + } + + { + //for debugging, set last time face was updated vs moved + facep->updateRebuildFlags(); -static LLTrace::BlockTimerStatHandle FTM_REBUILD_MESH_FLUSH("Flush Mesh"); + if (!LLPipeline::sDelayVBUpdate) + { //copy face geometry into vertex buffer + LLDrawable* drawablep = facep->getDrawable(); + LLVOVolume* vobj = drawablep->getVOVolume(); + LLVolume* volume = vobj->getVolume(); -void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) -{ - llassert(group); - if (group && group->hasState(LLSpatialGroup::MESH_DIRTY) && !group->hasState(LLSpatialGroup::GEOM_DIRTY)) - { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB); - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(true); + } - group->mBuilt = 1.f; - - S32 num_mapped_vertex_buffer = LLVertexBuffer::sMappedCount ; + U32 te_idx = facep->getTEOffset(); - const U32 MAX_BUFFER_COUNT = 4096; - LLVertexBuffer* locked_buffer[MAX_BUFFER_COUNT]; - - U32 buffer_count = 0; + llassert(!facep->isState(LLFace::RIGGED)); - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + if (!facep->getGeometryVolume(*volume, te_idx, + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true)) + { + LL_WARNS() << "Failed to get geometry for face!" << LL_ENDL; + } - if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) - { - LLVOVolume* vobj = drawablep->getVOVolume(); - if (debugLoggingEnabled("AnimatedObjectsLinkset")) - { - if (vobj->isAnimatedObject() && vobj->isRiggedMesh()) + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) { - std::string vobj_name = llformat("Vol%p", vobj); - F32 est_tris = vobj->getEstTrianglesMax(); - LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " rebuildMesh, tris " << est_tris << LL_ENDL; + vobj->updateRelativeXform(false); } } - if (vobj->isNoLOD()) continue; - - vobj->preRebuild(); - - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { - vobj->updateRelativeXform(true); - } - - LLVolume* volume = vobj->getVolume(); - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) - { - LLFace* face = drawablep->getFace(i); - if (face) - { - LLVertexBuffer* buff = face->getVertexBuffer(); - if (buff) - { - llassert(!face->isState(LLFace::RIGGED)); - - if (!face->getGeometryVolume(*volume, face->getTEOffset(), - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex())) - { //something's gone wrong with the vertex buffer accounting, rebuild this group - group->dirtyGeom(); - gPipeline.markRebuild(group, TRUE); - } - - - if (buff->isLocked() && buffer_count < MAX_BUFFER_COUNT) - { - locked_buffer[buffer_count++] = buff; - } - } - } - } - - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { - vobj->updateRelativeXform(); - } - - - drawablep->clearState(LLDrawable::REBUILD_ALL); - } - } - - { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_MESH_FLUSH); - for (LLVertexBuffer** iter = locked_buffer, ** end_iter = locked_buffer+buffer_count; iter != end_iter; ++iter) - { - (*iter)->flush(); - } - - // don't forget alpha - if(group != NULL && - !group->mVertexBuffer.isNull() && - group->mVertexBuffer->isLocked()) - { - group->mVertexBuffer->flush(); - } - } - - //if not all buffers are unmapped - if(num_mapped_vertex_buffer != LLVertexBuffer::sMappedCount) - { - LL_WARNS() << "Not all mapped vertex buffers are unmapped!" << LL_ENDL ; - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - if(!drawablep) - { - continue; - } - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) - { - LLFace* face = drawablep->getFace(i); - if (face) - { - LLVertexBuffer* buff = face->getVertexBuffer(); - if (buff && buff->isLocked()) - { - buff->flush(); - } - } - } - } - } - - group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); - } - -// llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO)); -} + } -struct CompareBatchBreakerModified -{ - bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) - { - const LLTextureEntry* lte = lhs->getTextureEntry(); - const LLTextureEntry* rte = rhs->getTextureEntry(); - - if (lte->getBumpmap() != rte->getBumpmap()) - { - return lte->getBumpmap() < rte->getBumpmap(); - } - else if (lte->getFullbright() != rte->getFullbright()) - { - return lte->getFullbright() < rte->getFullbright(); - } - else if (LLPipeline::sRenderDeferred && lte->getMaterialParams() != rte->getMaterialParams()) - { - return lte->getMaterialParams() < rte->getMaterialParams(); - } - else if (LLPipeline::sRenderDeferred && (lte->getMaterialParams() == rte->getMaterialParams()) && (lte->getShiny() != rte->getShiny())) - { - return lte->getShiny() < rte->getShiny(); - } - else - { - return lhs->getTexture() < rhs->getTexture(); - } - } -}; + index_offset += facep->getGeomCount(); + indices_index += facep->getIndicesCount(); -static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_SORT("Draw Info Face Sort"); -static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_FACE_SIZE("Face Sizing"); -static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_ALLOCATE("Allocate VB"); -static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_FIND_VB("Find VB"); -static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); + //append face to appropriate render batch + BOOL force_simple = facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA; + BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); + if ((mask & LLVertexBuffer::MAP_NORMAL) == 0) + { //paranoia check to make sure GL doesn't try to read non-existant normals + fullbright = TRUE; + } + if (hud_group) + { //all hud attachments are fullbright + fullbright = TRUE; + } + const LLTextureEntry* te = facep->getTextureEntry(); + tex = facep->getTexture(); + BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE; + + LLMaterial* mat = te->getMaterialParams().get(); -U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL no_materials) -{ - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); + bool can_be_shiny = true; + if (mat) + { + U8 mode = mat->getDiffuseAlphaMode(); + can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || + mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; + } - U32 geometryBytes = 0; - U32 buffer_usage = group->mBufferUsage; - - static LLCachedControl use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false); + bool use_legacy_bump = te->getBumpmap() && (te->getBumpmap() < 18) && (!mat || mat->getNormalID().isNull()); + bool opaque = te->getColor().mV[3] >= 0.999f; - if (use_transform_feedback && - gTransformPositionProgram.mProgramObject && //transform shaders are loaded - buffer_usage == GL_DYNAMIC_DRAW_ARB && //target buffer is in VRAM - !(mask & LLVertexBuffer::MAP_WEIGHT4)) //TODO: add support for weights - { - buffer_usage = GL_DYNAMIC_COPY_ARB; - } + if (mat && LLPipeline::sRenderDeferred && !hud_group) + { + bool material_pass = false; -#if LL_DARWIN - // HACK from Leslie: - // Disable VBO usage for alpha on Mac OS X because it kills the framerate - // due to implicit calls to glTexSubImage that are beyond our control. - // (this works because the only calls here that sort by distance are alpha) - if (distance_sort) - { - buffer_usage = 0x0; - } -#endif - - //calculate maximum number of vertices to store in a single buffer - U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); - max_vertices = llmin(max_vertices, (U32) 65535); - - { - LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_SORT); - if (!distance_sort) - { - //sort faces by things that break batches - std::sort(faces, faces+face_count, CompareBatchBreakerModified()); - } - else - { - //sort faces by distance - std::sort(faces, faces+face_count, LLFace::CompareDistanceGreater()); - } - } - - bool hud_group = group->isHUDGroup() ; - LLFace** face_iter = faces; - LLFace** end_faces = faces+face_count; - - LLSpatialGroup::buffer_map_t buffer_map; - - LLViewerTexture* last_tex = NULL; - S32 buffer_index = 0; - - if (distance_sort) - { - buffer_index = -1; - } - - S32 texture_index_channels = 1; - - if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) - { - texture_index_channels = LLGLSLShader::sIndexedTextureChannels-1; //always reserve one for shiny for now just for simplicity; - } - - if (LLPipeline::sRenderDeferred && distance_sort) - { - texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels; - } - - texture_index_channels = llmin(texture_index_channels, (S32) gSavedSettings.getU32("RenderMaxTextureIndex")); - - //NEVER use more than 16 texture index channels (workaround for prevalent driver bug) - texture_index_channels = llmin(texture_index_channels, 16); - - bool flexi = false; - - while (face_iter != end_faces) - { - //pull off next face - LLFace* facep = *face_iter; - LLViewerTexture* tex = facep->getTexture(); - LLMaterialPtr mat = facep->getTextureEntry()->getMaterialParams(); - - if (distance_sort) - { - tex = NULL; - } - - if (last_tex == tex) - { - buffer_index++; - } - else - { - last_tex = tex; - buffer_index = 0; - } - - bool bake_sunlight = LLPipeline::sBakeSunlight && facep->getDrawable()->isStatic(); - - U32 index_count = facep->getIndicesCount(); - U32 geom_count = facep->getGeomCount(); - - flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); - - //sum up vertices needed for this render batch - LLFace** i = face_iter; - ++i; - - const U32 MAX_TEXTURE_COUNT = 32; - LLViewerTexture* texture_list[MAX_TEXTURE_COUNT]; - - U32 texture_count = 0; - - { - LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_FACE_SIZE); - if (batch_textures) - { - U8 cur_tex = 0; - facep->setTextureIndex(cur_tex); - if (texture_count < MAX_TEXTURE_COUNT) - { - texture_list[texture_count++] = tex; - } - - if (can_batch_texture(facep)) - { //populate texture_list with any textures that can be batched - //move i to the next unbatchable face - while (i != end_faces) - { - facep = *i; - - if (!can_batch_texture(facep)) - { //face is bump mapped or has an animated texture matrix -- can't - //batch more than 1 texture at a time - facep->setTextureIndex(0); - break; - } - - if (facep->getTexture() != tex) - { - if (distance_sort) - { //textures might be out of order, see if texture exists in current batch - bool found = false; - for (U32 tex_idx = 0; tex_idx < texture_count; ++tex_idx) - { - if (facep->getTexture() == texture_list[tex_idx]) - { - cur_tex = tex_idx; - found = true; - break; - } - } - - if (!found) - { - cur_tex = texture_count; - } - } - else - { - cur_tex++; - } - - if (cur_tex >= texture_index_channels) - { //cut batches when index channels are depleted - break; - } - - tex = facep->getTexture(); - - if (texture_count < MAX_TEXTURE_COUNT) - { - texture_list[texture_count++] = tex; - } - } - - if (geom_count + facep->getGeomCount() > max_vertices) - { //cut batches on geom count too big - break; - } - - ++i; - - flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); - - index_count += facep->getIndicesCount(); - geom_count += facep->getGeomCount(); - - facep->setTextureIndex(cur_tex); - } - } - else - { - facep->setTextureIndex(0); - } - - tex = texture_list[0]; - } - else - { - while (i != end_faces && - (LLPipeline::sTextureBindTest || - (distance_sort || - ((*i)->getTexture() == tex && - ((*i)->getTextureEntry()->getMaterialParams() == mat))))) - { - facep = *i; - - - //face has no texture index - facep->mDrawInfo = NULL; - facep->setTextureIndex(255); - - if (geom_count + facep->getGeomCount() > max_vertices) - { //cut batches on geom count too big - break; - } - - ++i; - index_count += facep->getIndicesCount(); - geom_count += facep->getGeomCount(); - - flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); - } - } - } - - - if (flexi && buffer_usage && buffer_usage != GL_STREAM_DRAW_ARB) - { - buffer_usage = GL_STREAM_DRAW_ARB; - } - - //create vertex buffer - LLPointer buffer; - - { - LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_ALLOCATE); - buffer = createVertexBuffer(mask, buffer_usage); - if(!buffer->allocateBuffer(geom_count, index_count, TRUE)) - { - LL_WARNS() << "Failed to allocate group Vertex Buffer to " - << geom_count << " vertices and " - << index_count << " indices" << LL_ENDL; - buffer = NULL; - } - } - - if (buffer) - { - geometryBytes += buffer->getSize() + buffer->getIndicesSize(); - buffer_map[mask][*face_iter].push_back(buffer); - } - - //add face geometry - - U32 indices_index = 0; - U16 index_offset = 0; - - while (face_iter < i) - { - //update face indices for new buffer - facep = *face_iter; - if (buffer.isNull()) - { - // Bulk allocation failed - facep->setVertexBuffer(buffer); - facep->setSize(0, 0); // mark as no geometry - ++face_iter; - continue; - } - facep->setIndicesIndex(indices_index); - facep->setGeomIndex(index_offset); - facep->setVertexBuffer(buffer); - - if (batch_textures && facep->getTextureIndex() == 255) - { - LL_ERRS() << "Invalid texture index." << LL_ENDL; - } - - { - //for debugging, set last time face was updated vs moved - facep->updateRebuildFlags(); - - if (!LLPipeline::sDelayVBUpdate) - { //copy face geometry into vertex buffer - LLDrawable* drawablep = facep->getDrawable(); - LLVOVolume* vobj = drawablep->getVOVolume(); - LLVolume* volume = vobj->getVolume(); - - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { - vobj->updateRelativeXform(true); - } - - U32 te_idx = facep->getTEOffset(); - - llassert(!facep->isState(LLFace::RIGGED)); - - if (!facep->getGeometryVolume(*volume, te_idx, - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true)) - { - LL_WARNS() << "Failed to get geometry for face!" << LL_ENDL; - } - - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { - vobj->updateRelativeXform(false); - } - } - } - - index_offset += facep->getGeomCount(); - indices_index += facep->getIndicesCount(); - - //append face to appropriate render batch - - BOOL force_simple = facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA; - BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); - if ((mask & LLVertexBuffer::MAP_NORMAL) == 0) - { //paranoia check to make sure GL doesn't try to read non-existant normals - fullbright = TRUE; - } - - if (hud_group) - { //all hud attachments are fullbright - fullbright = TRUE; - } - - const LLTextureEntry* te = facep->getTextureEntry(); - tex = facep->getTexture(); - - BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE; - - LLMaterial* mat = te->getMaterialParams().get(); - - bool can_be_shiny = true; - if (mat) - { - U8 mode = mat->getDiffuseAlphaMode(); - can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || - mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; - } - - bool use_legacy_bump = te->getBumpmap() && (te->getBumpmap() < 18) && (!mat || mat->getNormalID().isNull()); - bool opaque = te->getColor().mV[3] >= 0.999f; - - if (mat && LLPipeline::sRenderDeferred && !hud_group) - { - bool material_pass = false; - - // do NOT use 'fullbright' for this logic or you risk sending - // things without normals down the materials pipeline and will - // render poorly if not crash NORSPEC-240,314 - // - if (te->getFullbright()) - { - if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { - if (opaque) - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); - } - else - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - } - else if (is_alpha) - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - else - { - if (mat->getEnvironmentIntensity() > 0 || - te->getShiny() > 0) - { - material_pass = true; - } - else - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); - } - } - } - else if (no_materials) - { - registerFace(group, facep, LLRenderPass::PASS_SIMPLE); - } - else if (te->getColor().mV[3] < 0.999f) - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - else if (use_legacy_bump) - { - // we have a material AND legacy bump settings, but no normal map - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - else - { - material_pass = true; - } - - if (material_pass) - { - static const U32 pass[] = - { - LLRenderPass::PASS_MATERIAL, - LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_MATERIAL_ALPHA, - LLRenderPass::PASS_MATERIAL_ALPHA_MASK, - LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, - LLRenderPass::PASS_SPECMAP, - LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_SPECMAP_BLEND, - LLRenderPass::PASS_SPECMAP_MASK, - LLRenderPass::PASS_SPECMAP_EMISSIVE, - LLRenderPass::PASS_NORMMAP, - LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMMAP_BLEND, - LLRenderPass::PASS_NORMMAP_MASK, - LLRenderPass::PASS_NORMMAP_EMISSIVE, - LLRenderPass::PASS_NORMSPEC, - LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMSPEC_BLEND, - LLRenderPass::PASS_NORMSPEC_MASK, - LLRenderPass::PASS_NORMSPEC_EMISSIVE, - }; - - U32 mask = mat->getShaderMask(); - - llassert(mask < sizeof(pass)/sizeof(U32)); - - mask = llmin(mask, (U32)(sizeof(pass)/sizeof(U32)-1)); - - registerFace(group, facep, pass[mask]); - } - } - else if (mat) - { - U8 mode = mat->getDiffuseAlphaMode(); - if (te->getColor().mV[3] < 0.999f) - { - mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; - } - - if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { - registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK : LLRenderPass::PASS_ALPHA_MASK); - } - else if (is_alpha || (te->getColor().mV[3] < 0.999f)) - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - else if (gPipeline.canUseVertexShaders() - && LLPipeline::sRenderBump - && te->getShiny() - && can_be_shiny) - { - registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_SHINY : LLRenderPass::PASS_SHINY); - } - else - { - registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT : LLRenderPass::PASS_SIMPLE); - } - } - else if (is_alpha) - { - // can we safely treat this as an alpha mask? - if (facep->getFaceColor().mV[3] <= 0.f) - { //100% transparent, don't render unless we're highlighting transparent - registerFace(group, facep, LLRenderPass::PASS_ALPHA_INVISIBLE); - } - else if (facep->canRenderAsMask()) - { - if (te->getFullbright() || LLPipeline::sNoAlpha) - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); - } - else - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); - } - } - else - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - } - else if (gPipeline.canUseVertexShaders() - && LLPipeline::sRenderBump - && te->getShiny() - && can_be_shiny) - { //shiny - if (tex->getPrimaryFormat() == GL_ALPHA) - { //invisiprim+shiny - registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); - } - else if (LLPipeline::sRenderDeferred && !hud_group) - { //deferred rendering - if (te->getFullbright()) - { //register in post deferred fullbright shiny pass - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); - if (te->getBumpmap()) - { //register in post deferred bump pass - registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); - } - } - else if (use_legacy_bump) - { //register in deferred bump pass - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - else - { //register in deferred simple pass (deferred simple includes shiny) - llassert(mask & LLVertexBuffer::MAP_NORMAL); - registerFace(group, facep, LLRenderPass::PASS_SIMPLE); - } - } - else if (fullbright) - { //not deferred, register in standard fullbright shiny pass - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); - } - else - { //not deferred or fullbright, register in standard shiny pass - registerFace(group, facep, LLRenderPass::PASS_SHINY); - } - } - else - { //not alpha and not shiny - if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) - { //invisiprim - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); - } - else if (fullbright || bake_sunlight) - { //fullbright - if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); - } - else - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); - } - if (LLPipeline::sRenderDeferred && !hud_group && LLPipeline::sRenderBump && use_legacy_bump) - { //if this is the deferred render and a bump map is present, register in post deferred bump - registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); - } - } - else - { - if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && use_legacy_bump) - { //non-shiny or fullbright deferred bump - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - else - { //all around simple - llassert(mask & LLVertexBuffer::MAP_NORMAL); - if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { //material alpha mask can be respected in non-deferred - registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); - } - else - { - registerFace(group, facep, LLRenderPass::PASS_SIMPLE); - } - } - } - - - if (!gPipeline.canUseVertexShaders() && - !is_alpha && - te->getShiny() && - LLPipeline::sRenderBump) - { //shiny as an extra pass when shaders are disabled - registerFace(group, facep, LLRenderPass::PASS_SHINY); - } - } - - //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 - if (!is_alpha && (hud_group || !LLPipeline::sRenderDeferred)) - { - llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); - facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); - - if (!force_simple && LLPipeline::sRenderBump && use_legacy_bump) - { - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - } - - if (!is_alpha && LLPipeline::sRenderGlow && te->getGlow() > 0.f) - { - registerFace(group, facep, LLRenderPass::PASS_GLOW); - } - - ++face_iter; - } - - if (buffer) - { - buffer->flush(); - } - } - - group->mBufferMap[mask].clear(); - for (LLSpatialGroup::buffer_texture_map_t::iterator i = buffer_map[mask].begin(); i != buffer_map[mask].end(); ++i) - { - group->mBufferMap[mask][i->first] = i->second; - } - - return geometryBytes; + // do NOT use 'fullbright' for this logic or you risk sending + // things without normals down the materials pipeline and will + // render poorly if not crash NORSPEC-240,314 + // + if (te->getFullbright()) + { + if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { + if (opaque) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + } + else if (is_alpha) + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + else + { + if (mat->getEnvironmentIntensity() > 0 || + te->getShiny() > 0) + { + material_pass = true; + } + else + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + } + } + } + else if (no_materials) + { + registerFace(group, facep, LLRenderPass::PASS_SIMPLE); + } + else if (te->getColor().mV[3] < 0.999f) + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + else if (use_legacy_bump) + { + // we have a material AND legacy bump settings, but no normal map + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + else + { + material_pass = true; + } + + if (material_pass) + { + static const U32 pass[] = + { + LLRenderPass::PASS_MATERIAL, + LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_MATERIAL_ALPHA, + LLRenderPass::PASS_MATERIAL_ALPHA_MASK, + LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, + LLRenderPass::PASS_SPECMAP, + LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_SPECMAP_BLEND, + LLRenderPass::PASS_SPECMAP_MASK, + LLRenderPass::PASS_SPECMAP_EMISSIVE, + LLRenderPass::PASS_NORMMAP, + LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMMAP_BLEND, + LLRenderPass::PASS_NORMMAP_MASK, + LLRenderPass::PASS_NORMMAP_EMISSIVE, + LLRenderPass::PASS_NORMSPEC, + LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMSPEC_BLEND, + LLRenderPass::PASS_NORMSPEC_MASK, + LLRenderPass::PASS_NORMSPEC_EMISSIVE, + }; + + U32 mask = mat->getShaderMask(); + + llassert(mask < sizeof(pass)/sizeof(U32)); + + mask = llmin(mask, (U32)(sizeof(pass)/sizeof(U32)-1)); + + registerFace(group, facep, pass[mask]); + } + } + else if (mat) + { + U8 mode = mat->getDiffuseAlphaMode(); + if (te->getColor().mV[3] < 0.999f) + { + mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; + } + + if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { + registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK : LLRenderPass::PASS_ALPHA_MASK); + } + else if (is_alpha || (te->getColor().mV[3] < 0.999f)) + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + else if (gPipeline.canUseVertexShaders() + && LLPipeline::sRenderBump + && te->getShiny() + && can_be_shiny) + { + registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_SHINY : LLRenderPass::PASS_SHINY); + } + else + { + registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT : LLRenderPass::PASS_SIMPLE); + } + } + else if (is_alpha) + { + // can we safely treat this as an alpha mask? + if (facep->getFaceColor().mV[3] <= 0.f) + { //100% transparent, don't render unless we're highlighting transparent + registerFace(group, facep, LLRenderPass::PASS_ALPHA_INVISIBLE); + } + else if (facep->canRenderAsMask()) + { + if (te->getFullbright() || LLPipeline::sNoAlpha) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); + } + } + else + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + } + else if (gPipeline.canUseVertexShaders() + && LLPipeline::sRenderBump + && te->getShiny() + && can_be_shiny) + { //shiny + if (tex->getPrimaryFormat() == GL_ALPHA) + { //invisiprim+shiny + registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } + else if (LLPipeline::sRenderDeferred && !hud_group) + { //deferred rendering + if (te->getFullbright()) + { //register in post deferred fullbright shiny pass + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); + if (te->getBumpmap()) + { //register in post deferred bump pass + registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); + } + } + else if (use_legacy_bump) + { //register in deferred bump pass + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + else + { //register in deferred simple pass (deferred simple includes shiny) + llassert(mask & LLVertexBuffer::MAP_NORMAL); + registerFace(group, facep, LLRenderPass::PASS_SIMPLE); + } + } + else if (fullbright) + { //not deferred, register in standard fullbright shiny pass + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); + } + else + { //not deferred or fullbright, register in standard shiny pass + registerFace(group, facep, LLRenderPass::PASS_SHINY); + } + } + else + { //not alpha and not shiny + if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) + { //invisiprim + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } + else if (fullbright || bake_sunlight) + { //fullbright + if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + } + if (LLPipeline::sRenderDeferred && !hud_group && LLPipeline::sRenderBump && use_legacy_bump) + { //if this is the deferred render and a bump map is present, register in post deferred bump + registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); + } + } + else + { + if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && use_legacy_bump) + { //non-shiny or fullbright deferred bump + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + else + { //all around simple + llassert(mask & LLVertexBuffer::MAP_NORMAL); + if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { //material alpha mask can be respected in non-deferred + registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_SIMPLE); + } + } + } + + + if (!gPipeline.canUseVertexShaders() && + !is_alpha && + te->getShiny() && + LLPipeline::sRenderBump) + { //shiny as an extra pass when shaders are disabled + registerFace(group, facep, LLRenderPass::PASS_SHINY); + } + } + + //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 + if (!is_alpha && (hud_group || !LLPipeline::sRenderDeferred)) + { + llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); + facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); + + if (!force_simple && LLPipeline::sRenderBump && use_legacy_bump) + { + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + } + + if (!is_alpha && LLPipeline::sRenderGlow && te->getGlow() > 0.f) + { + registerFace(group, facep, LLRenderPass::PASS_GLOW); + } + + ++face_iter; + } + + if (buffer) + { + buffer->flush(); + } + } + + group->mBufferMap[mask].clear(); + for (LLSpatialGroup::buffer_texture_map_t::iterator i = buffer_map[mask].begin(); i != buffer_map[mask].end(); ++i) + { + group->mBufferMap[mask][i->first] = i->second; + } + + return geometryBytes; } void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count) -{ - //initialize to default usage for this partition - U32 usage = group->getSpatialPartition()->mBufferUsage; - - //clear off any old faces - mFaceList.clear(); - - //for each drawable - - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - - if (!drawablep || drawablep->isDead()) - { - continue; - } - - if (drawablep->isAnimating()) - { //fall back to stream draw for animating verts - usage = GL_STREAM_DRAW_ARB; - } - - //for each face - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - //sum up face verts and indices - drawablep->updateFaceSize(i); - LLFace* facep = drawablep->getFace(i); - if (facep) - { - if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA && - facep->getGeomCount() + vertex_count <= 65536) - { - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); - - //remember face (for sorting) - mFaceList.push_back(facep); - } - else - { - facep->clearVertexBuffer(); - } - } - } - } - - group->mBufferUsage = usage; +{ + //initialize to default usage for this partition + U32 usage = group->getSpatialPartition()->mBufferUsage; + + //clear off any old faces + mFaceList.clear(); + + //for each drawable + + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) + { + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + + if (!drawablep || drawablep->isDead()) + { + continue; + } + + if (drawablep->isAnimating()) + { //fall back to stream draw for animating verts + usage = GL_STREAM_DRAW_ARB; + } + + //for each face + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + //sum up face verts and indices + drawablep->updateFaceSize(i); + LLFace* facep = drawablep->getFace(i); + if (facep) + { + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA && + facep->getGeomCount() + vertex_count <= 65536) + { + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + + //remember face (for sorting) + mFaceList.push_back(facep); + } + else + { + facep->clearVertexBuffer(); + } + } + } + } + + group->mBufferUsage = usage; } LLHUDPartition::LLHUDPartition(LLViewerRegion* regionp) : LLBridgePartition(regionp) { - mPartitionType = LLViewerRegion::PARTITION_HUD; - mDrawableType = LLPipeline::RENDER_TYPE_HUD; - mSlopRatio = 0.f; - mLODPeriod = 1; + mPartitionType = LLViewerRegion::PARTITION_HUD; + mDrawableType = LLPipeline::RENDER_TYPE_HUD; + mSlopRatio = 0.f; + mLODPeriod = 1; } void LLHUDPartition::shift(const LLVector4a &offset) { - //HUD objects don't shift with region crossing. That would be silly. + //HUD objects don't shift with region crossing. That would be silly. } -- cgit v1.3 From 15270f697a0e6a4f14944ac20382f8bbcc8ea86b Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Tue, 12 Mar 2019 10:52:00 -0700 Subject: Tab restoration project. 'warn-on-failure:no-tabs' --- indra/llrender/llglslshader.cpp | 258 ++--- indra/llrender/llglslshader.h | 338 +++--- indra/llrender/llshadermgr.cpp | 2304 +++++++++++++++++++-------------------- indra/newview/llvovolume.cpp | 714 ++++++------ indra/newview/pipeline.cpp | 16 +- indra/newview/pipeline.h | 1638 ++++++++++++++-------------- 6 files changed, 2633 insertions(+), 2635 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 5659bd327b..9a4eeb59df 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -724,144 +724,144 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type) BOOL LLGLSLShader::mapUniforms(const vector * uniforms) { - BOOL res = TRUE; - - mTotalUniformSize = 0; - mActiveTextureChannels = 0; - mUniform.clear(); - mUniformMap.clear(); - mUniformNameMap.clear(); - mTexture.clear(); - mValue.clear(); - //initialize arrays - U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size(); - mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); - mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); - - bind(); - - //get the number of active uniforms - GLint activeCount; - glGetObjectParameterivARB(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount); - - //........................................................................................................................................ - //........................................................................................ - - /* - EXPLANATION: - This is part of code is temporary because as the final result the mapUniform() should be rewrited. - But it's a huge a volume of work which is need to be a more carefully performed for avoid possible - regression's (i.e. it should be formalized a separate ticket in JIRA). - - RESON: - The reason of this code is that SL engine is very sensitive to fact that "diffuseMap" should be appear - first as uniform parameter which is should get 0-"texture channel" index (see mapUniformTextureChannel() and mActiveTextureChannels) - it influence to which is texture matrix will be updated during rendering. - - But, order of indexe's of uniform variables is not defined and GLSL compiler can change it as want - , even if the "diffuseMap" will be appear and use first in shader code. - - As example where this situation appear see: "Deferred Material Shader 28/29/30/31" - And tickets: MAINT-4165, MAINT-4839, MAINT-3568, MAINT-6437 - */ - - - S32 diffuseMap = glGetUniformLocationARB(mProgramObject, "diffuseMap"); - S32 specularMap = glGetUniformLocationARB(mProgramObject, "specularMap"); - S32 bumpMap = glGetUniformLocationARB(mProgramObject, "bumpMap"); + BOOL res = TRUE; + + mTotalUniformSize = 0; + mActiveTextureChannels = 0; + mUniform.clear(); + mUniformMap.clear(); + mUniformNameMap.clear(); + mTexture.clear(); + mValue.clear(); + //initialize arrays + U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size(); + mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); + mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); + + bind(); + + //get the number of active uniforms + GLint activeCount; + glGetObjectParameterivARB(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount); + + //........................................................................................................................................ + //........................................................................................ + + /* + EXPLANATION: + This is part of code is temporary because as the final result the mapUniform() should be rewrited. + But it's a huge a volume of work which is need to be a more carefully performed for avoid possible + regression's (i.e. it should be formalized a separate ticket in JIRA). + + RESON: + The reason of this code is that SL engine is very sensitive to fact that "diffuseMap" should be appear + first as uniform parameter which is should get 0-"texture channel" index (see mapUniformTextureChannel() and mActiveTextureChannels) + it influence to which is texture matrix will be updated during rendering. + + But, order of indexe's of uniform variables is not defined and GLSL compiler can change it as want + , even if the "diffuseMap" will be appear and use first in shader code. + + As example where this situation appear see: "Deferred Material Shader 28/29/30/31" + And tickets: MAINT-4165, MAINT-4839, MAINT-3568, MAINT-6437 + */ + + + S32 diffuseMap = glGetUniformLocationARB(mProgramObject, "diffuseMap"); + S32 specularMap = glGetUniformLocationARB(mProgramObject, "specularMap"); + S32 bumpMap = glGetUniformLocationARB(mProgramObject, "bumpMap"); S32 altDiffuseMap = glGetUniformLocationARB(mProgramObject, "altDiffuseMap"); - S32 environmentMap = glGetUniformLocationARB(mProgramObject, "environmentMap"); + S32 environmentMap = glGetUniformLocationARB(mProgramObject, "environmentMap"); - std::set skip_index; + std::set skip_index; - if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap || -1 != altDiffuseMap)) - { - GLenum type; - GLsizei length; - GLint size = -1; - char name[1024]; + if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap || -1 != altDiffuseMap)) + { + GLenum type; + GLsizei length; + GLint size = -1; + char name[1024]; - diffuseMap = altDiffuseMap = specularMap = bumpMap = environmentMap = -1; + diffuseMap = altDiffuseMap = specularMap = bumpMap = environmentMap = -1; - for (S32 i = 0; i < activeCount; i++) - { - name[0] = '\0'; + for (S32 i = 0; i < activeCount; i++) + { + name[0] = '\0'; - glGetActiveUniformARB(mProgramObject, i, 1024, &length, &size, &type, (GLcharARB *)name); + glGetActiveUniformARB(mProgramObject, i, 1024, &length, &size, &type, (GLcharARB *)name); - if (-1 == diffuseMap && std::string(name) == "diffuseMap") - { - diffuseMap = i; - continue; - } + if (-1 == diffuseMap && std::string(name) == "diffuseMap") + { + diffuseMap = i; + continue; + } - if (-1 == specularMap && std::string(name) == "specularMap") - { - specularMap = i; - continue; - } + if (-1 == specularMap && std::string(name) == "specularMap") + { + specularMap = i; + continue; + } - if (-1 == bumpMap && std::string(name) == "bumpMap") - { - bumpMap = i; - continue; - } + if (-1 == bumpMap && std::string(name) == "bumpMap") + { + bumpMap = i; + continue; + } - if (-1 == environmentMap && std::string(name) == "environmentMap") - { - environmentMap = i; - continue; - } + if (-1 == environmentMap && std::string(name) == "environmentMap") + { + environmentMap = i; + continue; + } if (-1 == altDiffuseMap && std::string(name) == "altDiffuseMap") - { - altDiffuseMap = i; - continue; - } - } + { + altDiffuseMap = i; + continue; + } + } - bool specularDiff = specularMap < diffuseMap && -1 != specularMap; - bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap; - bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap; + bool specularDiff = specularMap < diffuseMap && -1 != specularMap; + bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap; + bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap; - if (specularDiff || bumpLessDiff || envLessDiff) - { - mapUniform(diffuseMap, uniforms); - skip_index.insert(diffuseMap); + if (specularDiff || bumpLessDiff || envLessDiff) + { + mapUniform(diffuseMap, uniforms); + skip_index.insert(diffuseMap); - if (-1 != specularMap) { - mapUniform(specularMap, uniforms); - skip_index.insert(specularMap); - } + if (-1 != specularMap) { + mapUniform(specularMap, uniforms); + skip_index.insert(specularMap); + } - if (-1 != bumpMap) { - mapUniform(bumpMap, uniforms); - skip_index.insert(bumpMap); - } + if (-1 != bumpMap) { + mapUniform(bumpMap, uniforms); + skip_index.insert(bumpMap); + } - if (-1 != environmentMap) { - mapUniform(environmentMap, uniforms); - skip_index.insert(environmentMap); - } - } - } + if (-1 != environmentMap) { + mapUniform(environmentMap, uniforms); + skip_index.insert(environmentMap); + } + } + } - //........................................................................................ + //........................................................................................ - for (S32 i = 0; i < activeCount; i++) - { - //........................................................................................ - if (skip_index.end() != skip_index.find(i)) continue; - //........................................................................................ + for (S32 i = 0; i < activeCount; i++) + { + //........................................................................................ + if (skip_index.end() != skip_index.find(i)) continue; + //........................................................................................ - mapUniform(i, uniforms); - } - //........................................................................................................................................ + mapUniform(i, uniforms); + } + //........................................................................................................................................ - unbind(); + unbind(); - LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL; - return res; + LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL; + return res; } @@ -1286,19 +1286,19 @@ void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, c void LLGLSLShader::uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v) { - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - glUniformMatrix3x4fv(mUniform[index], count, transpose, v); - } - } + if (mProgramObject) + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + glUniformMatrix3x4fv(mUniform[index], count, transpose, v); + } + } } void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v) diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 9c3effadbe..830bad2aef 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -34,201 +34,199 @@ class LLShaderFeatures { public: - bool atmosphericHelpers; - bool calculatesLighting; - bool calculatesAtmospherics; - bool hasLighting; // implies no transport (it's possible to have neither though) - bool isAlphaLighting; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions) - bool isShiny; - bool isFullbright; // implies no lighting - bool isSpecular; - bool hasWaterFog; // implies no gamma - bool hasTransport; // implies no lighting (it's possible to have neither though) - bool hasSkinning; - bool hasObjectSkinning; - bool hasAtmospherics; - bool hasGamma; + bool atmosphericHelpers; + bool calculatesLighting; + bool calculatesAtmospherics; + bool hasLighting; // implies no transport (it's possible to have neither though) + bool isAlphaLighting; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions) + bool isShiny; + bool isFullbright; // implies no lighting + bool isSpecular; + bool hasWaterFog; // implies no gamma + bool hasTransport; // implies no lighting (it's possible to have neither though) + bool hasSkinning; + bool hasObjectSkinning; + bool hasAtmospherics; + bool hasGamma; bool hasShadows; bool hasAmbientOcclusion; - bool hasSrgb; + bool hasSrgb; bool encodesNormal; bool isDeferred; bool hasIndirect; - S32 mIndexedTextureChannels; - bool disableTextureIndex; - bool hasAlphaMask; - bool attachNothing; - - // char numLights; - - LLShaderFeatures(); + S32 mIndexedTextureChannels; + bool disableTextureIndex; + bool hasAlphaMask; + bool attachNothing; + + // char numLights; + + LLShaderFeatures(); }; class LLGLSLShader { public: - enum - { - SG_DEFAULT = 0, - SG_SKY, - SG_WATER - }; - - static std::set sInstances; - static bool sProfileEnabled; - - LLGLSLShader(); - ~LLGLSLShader(); - - static GLhandleARB sCurBoundShader; - static LLGLSLShader* sCurBoundShaderPtr; - static S32 sIndexedTextureChannels; - static bool sNoFixedFunction; - - static void initProfile(); - static void finishProfile(bool emit_report = true); - - static void startProfile(); - static void stopProfile(U32 count, U32 mode); - - void unload(); - void clearStats(); - void dumpStats(); - void placeProfileQuery(); - void readProfileQuery(U32 count, U32 mode); - - BOOL createShader(std::vector * attributes, - std::vector * uniforms, - U32 varying_count = 0, - const char** varyings = NULL); - BOOL attachObject(std::string object); - void attachObject(GLhandleARB object); - void attachObjects(GLhandleARB* objects = NULL, S32 count = 0); - BOOL mapAttributes(const std::vector * attributes); - BOOL mapUniforms(const std::vector *); - void mapUniform(GLint index, const std::vector *); - void uniform1i(U32 index, GLint i); - void uniform1f(U32 index, GLfloat v); - void uniform2f(U32 index, GLfloat x, GLfloat y); - void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z); - void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - void uniform1iv(U32 index, U32 count, const GLint* i); - void uniform1fv(U32 index, U32 count, const GLfloat* v); - void uniform2fv(U32 index, U32 count, const GLfloat* v); - void uniform3fv(U32 index, U32 count, const GLfloat* v); - void uniform4fv(U32 index, U32 count, const GLfloat* v); - void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j); - void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v); - void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v); - void uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v); - void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v); - void uniform1i(const LLStaticHashedString& uniform, GLint i); - void uniform1f(const LLStaticHashedString& uniform, GLfloat v); - void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y); - void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z); - void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); - void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); - void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); - void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); - void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat *v); - - void setMinimumAlpha(F32 minimum); - - void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - void vertexAttrib4fv(U32 index, GLfloat* v); - - //GLint getUniformLocation(const std::string& uniform); - GLint getUniformLocation(const LLStaticHashedString& uniform); - GLint getUniformLocation(U32 index); - - GLint getAttribLocation(U32 attrib); - GLint mapUniformTextureChannel(GLint location, GLenum type); - + enum + { + SG_DEFAULT = 0, + SG_SKY, + SG_WATER + }; + + static std::set sInstances; + static bool sProfileEnabled; + + LLGLSLShader(); + ~LLGLSLShader(); + + static GLhandleARB sCurBoundShader; + static LLGLSLShader* sCurBoundShaderPtr; + static S32 sIndexedTextureChannels; + static bool sNoFixedFunction; + + static void initProfile(); + static void finishProfile(bool emit_report = true); + + static void startProfile(); + static void stopProfile(U32 count, U32 mode); + + void unload(); + void clearStats(); + void dumpStats(); + void placeProfileQuery(); + void readProfileQuery(U32 count, U32 mode); + + BOOL createShader(std::vector * attributes, + std::vector * uniforms, + U32 varying_count = 0, + const char** varyings = NULL); + BOOL attachObject(std::string object); + void attachObject(GLhandleARB object); + void attachObjects(GLhandleARB* objects = NULL, S32 count = 0); + BOOL mapAttributes(const std::vector * attributes); + BOOL mapUniforms(const std::vector *); + void mapUniform(GLint index, const std::vector *); + void uniform1i(U32 index, GLint i); + void uniform1f(U32 index, GLfloat v); + void uniform2f(U32 index, GLfloat x, GLfloat y); + void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z); + void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void uniform1iv(U32 index, U32 count, const GLint* i); + void uniform1fv(U32 index, U32 count, const GLfloat* v); + void uniform2fv(U32 index, U32 count, const GLfloat* v); + void uniform3fv(U32 index, U32 count, const GLfloat* v); + void uniform4fv(U32 index, U32 count, const GLfloat* v); + void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j); + void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v); + void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v); + void uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v); + void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v); + void uniform1i(const LLStaticHashedString& uniform, GLint i); + void uniform1f(const LLStaticHashedString& uniform, GLfloat v); + void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y); + void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z); + void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); + void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); + void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); + void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); + void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat *v); + + void setMinimumAlpha(F32 minimum); + + void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void vertexAttrib4fv(U32 index, GLfloat* v); + + //GLint getUniformLocation(const std::string& uniform); + GLint getUniformLocation(const LLStaticHashedString& uniform); + GLint getUniformLocation(U32 index); + + GLint getAttribLocation(U32 attrib); + GLint mapUniformTextureChannel(GLint location, GLenum type); + void clearPermutations(); - void addPermutation(std::string name, std::string value); - void removePermutation(std::string name); - - //enable/disable texture channel for specified uniform - //if given texture uniform is active in the shader, - //the corresponding channel will be active upon return - //returns channel texture is enabled in from [0-MAX) - S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); - S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); - - // bindTexture returns the texture unit we've bound the texture to. - // You can reuse the return value to unbind a texture when required. - S32 bindTexture(const std::string& uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); - S32 bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); - S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); - S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); - + void addPermutation(std::string name, std::string value); + void removePermutation(std::string name); + + //enable/disable texture channel for specified uniform + //if given texture uniform is active in the shader, + //the corresponding channel will be active upon return + //returns channel texture is enabled in from [0-MAX) + S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + + // bindTexture returns the texture unit we've bound the texture to. + // You can reuse the return value to unbind a texture when required. + S32 bindTexture(const std::string& uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + S32 bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + BOOL link(BOOL suppress_errors = FALSE); - void bind(); - void unbind(); + void bind(); + void unbind(); - // Unbinds any previously bound shader by explicitly binding no shader. - static void bindNoShader(void); + // Unbinds any previously bound shader by explicitly binding no shader. + static void bindNoShader(void); - U32 mMatHash[LLRender::NUM_MATRIX_MODES]; - U32 mLightHash; + U32 mMatHash[LLRender::NUM_MATRIX_MODES]; + U32 mLightHash; - GLhandleARB mProgramObject; + GLhandleARB mProgramObject; #if LL_RELEASE_WITH_DEBUG_INFO - struct attr_name - { - GLint loc; - const char *name; - void operator = (GLint _loc) { loc = _loc; } - operator GLint () { return loc; } - }; - std::vector mAttribute; //lookup table of attribute enum to attribute channel + struct attr_name + { + GLint loc; + const char *name; + void operator = (GLint _loc) { loc = _loc; } + operator GLint () { return loc; } + }; + std::vector mAttribute; //lookup table of attribute enum to attribute channel #else - std::vector mAttribute; //lookup table of attribute enum to attribute channel + std::vector mAttribute; //lookup table of attribute enum to attribute channel #endif - U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask()) - std::vector mUniform; //lookup table of uniform enum to uniform location - LLStaticStringTable mUniformMap; //lookup map of uniform name to uniform location - std::map mUniformNameMap; //lookup map of uniform location to uniform name - std::map mValue; //lookup map of uniform location to last known value - std::vector mTexture; - S32 mTotalUniformSize; - S32 mActiveTextureChannels; - S32 mShaderLevel; - S32 mShaderGroup; - BOOL mUniformsDirty; - LLShaderFeatures mFeatures; - std::vector< std::pair< std::string, GLenum > > mShaderFiles; - std::string mName; - boost::unordered_map mDefines; - - //statistcis for profiling shader performance - U32 mTimerQuery; - U32 mSamplesQuery; - U64 mTimeElapsed; - static U64 sTotalTimeElapsed; - U32 mTrianglesDrawn; - static U32 sTotalTrianglesDrawn; - U64 mSamplesDrawn; - static U64 sTotalSamplesDrawn; - U32 mDrawCalls; - static U32 sTotalDrawCalls; - - bool mTextureStateFetched; - std::vector mTextureMagFilter; - std::vector mTextureMinFilter; - - GLhandleARB mExtraLinkObject = 0; + U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask()) + std::vector mUniform; //lookup table of uniform enum to uniform location + LLStaticStringTable mUniformMap; //lookup map of uniform name to uniform location + std::map mUniformNameMap; //lookup map of uniform location to uniform name + std::map mValue; //lookup map of uniform location to last known value + std::vector mTexture; + S32 mTotalUniformSize; + S32 mActiveTextureChannels; + S32 mShaderLevel; + S32 mShaderGroup; + BOOL mUniformsDirty; + LLShaderFeatures mFeatures; + std::vector< std::pair< std::string, GLenum > > mShaderFiles; + std::string mName; + boost::unordered_map mDefines; + + //statistcis for profiling shader performance + U32 mTimerQuery; + U32 mSamplesQuery; + U64 mTimeElapsed; + static U64 sTotalTimeElapsed; + U32 mTrianglesDrawn; + static U32 sTotalTrianglesDrawn; + U64 mSamplesDrawn; + static U64 sTotalSamplesDrawn; + U32 mDrawCalls; + static U32 sTotalDrawCalls; + + bool mTextureStateFetched; + std::vector mTextureMagFilter; + std::vector mTextureMinFilter; private: - void unloadInternal(); + void unloadInternal(); }; //UI shader (declared here so llui_libtest will link properly) -extern LLGLSLShader gUIProgram; +extern LLGLSLShader gUIProgram; //output vec4(color.rgb,color.a*tex0[tc0].a) -extern LLGLSLShader gSolidColorProgram; +extern LLGLSLShader gSolidColorProgram; //Alpha mask shader (declared here so llappearance can access properly) -extern LLGLSLShader gAlphaMaskProgram; +extern LLGLSLShader gAlphaMaskProgram; #endif diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 5b96667f9f..ec8f05e4ca 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -53,489 +53,489 @@ LLShaderMgr::~LLShaderMgr() // static LLShaderMgr * LLShaderMgr::instance() { - if(NULL == sInstance) - { - LL_ERRS("Shaders") << "LLShaderMgr should already have been instantiated by the application!" << LL_ENDL; - } + if(NULL == sInstance) + { + LL_ERRS("Shaders") << "LLShaderMgr should already have been instantiated by the application!" << LL_ENDL; + } - return sInstance; + return sInstance; } BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) { - llassert_always(shader != NULL); - LLShaderFeatures *features = & shader->mFeatures; - - if (features->attachNothing) - { - return TRUE; - } - ////////////////////////////////////// - // Attach Vertex Shader Features First - ////////////////////////////////////// - - // NOTE order of shader object attaching is VERY IMPORTANT!!! - if (features->calculatesAtmospherics) - { - if (features->hasWaterFog) - { - if (!shader->attachObject("windlight/atmosphericsVarsWaterV.glsl")) - { - return FALSE; - } - } - else if (!shader->attachObject("windlight/atmosphericsVarsV.glsl")) - { - return FALSE; - } - } - - if (features->calculatesLighting || features->calculatesAtmospherics) - { - if (!shader->attachObject("windlight/atmosphericsHelpersV.glsl")) - { - return FALSE; - } - } - - if (features->calculatesLighting) - { - if (features->isSpecular) - { - if (!shader->attachObject("lighting/lightFuncSpecularV.glsl")) - { - return FALSE; - } - - if (!features->isAlphaLighting) - { - if (!shader->attachObject("lighting/sumLightsSpecularV.glsl")) - { - return FALSE; - } - } - - if (!shader->attachObject("lighting/lightSpecularV.glsl")) - { - return FALSE; - } - } - else - { - if (!shader->attachObject("lighting/lightFuncV.glsl")) - { - return FALSE; - } - - if (!features->isAlphaLighting) - { - if (!shader->attachObject("lighting/sumLightsV.glsl")) - { - return FALSE; - } - } - - if (!shader->attachObject("lighting/lightV.glsl")) - { - return FALSE; - } - } - } - - // NOTE order of shader object attaching is VERY IMPORTANT!!! - if (features->calculatesAtmospherics) - { - if (!shader->attachObject("windlight/atmosphericsV.glsl")) - { - return FALSE; - } - } - - if (features->hasSkinning) - { - if (!shader->attachObject("avatar/avatarSkinV.glsl")) - { - return FALSE; - } - } - - if (features->hasObjectSkinning) - { - if (!shader->attachObject("avatar/objectSkinV.glsl")) - { - return FALSE; - } - } - - /////////////////////////////////////// - // Attach Fragment Shader Features Next - /////////////////////////////////////// + llassert_always(shader != NULL); + LLShaderFeatures *features = & shader->mFeatures; + + if (features->attachNothing) + { + return TRUE; + } + ////////////////////////////////////// + // Attach Vertex Shader Features First + ////////////////////////////////////// + + // NOTE order of shader object attaching is VERY IMPORTANT!!! + if (features->calculatesAtmospherics) + { + if (features->hasWaterFog) + { + if (!shader->attachObject("windlight/atmosphericsVarsWaterV.glsl")) + { + return FALSE; + } + } + else if (!shader->attachObject("windlight/atmosphericsVarsV.glsl")) + { + return FALSE; + } + } + + if (features->calculatesLighting || features->calculatesAtmospherics) + { + if (!shader->attachObject("windlight/atmosphericsHelpersV.glsl")) + { + return FALSE; + } + } + + if (features->calculatesLighting) + { + if (features->isSpecular) + { + if (!shader->attachObject("lighting/lightFuncSpecularV.glsl")) + { + return FALSE; + } + + if (!features->isAlphaLighting) + { + if (!shader->attachObject("lighting/sumLightsSpecularV.glsl")) + { + return FALSE; + } + } + + if (!shader->attachObject("lighting/lightSpecularV.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFuncV.glsl")) + { + return FALSE; + } + + if (!features->isAlphaLighting) + { + if (!shader->attachObject("lighting/sumLightsV.glsl")) + { + return FALSE; + } + } + + if (!shader->attachObject("lighting/lightV.glsl")) + { + return FALSE; + } + } + } + + // NOTE order of shader object attaching is VERY IMPORTANT!!! + if (features->calculatesAtmospherics) + { + if (!shader->attachObject("windlight/atmosphericsV.glsl")) + { + return FALSE; + } + } + + if (features->hasSkinning) + { + if (!shader->attachObject("avatar/avatarSkinV.glsl")) + { + return FALSE; + } + } + + if (features->hasObjectSkinning) + { + if (!shader->attachObject("avatar/objectSkinV.glsl")) + { + return FALSE; + } + } + + /////////////////////////////////////// + // Attach Fragment Shader Features Next + /////////////////////////////////////// // NOTE order of shader object attaching is VERY IMPORTANT!!! - if(features->calculatesAtmospherics) - { - if (features->hasWaterFog) - { - if (!shader->attachObject("windlight/atmosphericsVarsWaterF.glsl")) - { - return FALSE; - } - } - else if (!shader->attachObject("windlight/atmosphericsVarsF.glsl")) - { - return FALSE; - } - } + if(features->calculatesAtmospherics) + { + if (features->hasWaterFog) + { + if (!shader->attachObject("windlight/atmosphericsVarsWaterF.glsl")) + { + return FALSE; + } + } + else if (!shader->attachObject("windlight/atmosphericsVarsF.glsl")) + { + return FALSE; + } + } if (features->calculatesLighting || features->calculatesAtmospherics) - { - if (!shader->attachObject("windlight/atmosphericsHelpersF.glsl")) - { - return FALSE; - } - } + { + if (!shader->attachObject("windlight/atmosphericsHelpersF.glsl")) + { + return FALSE; + } + } // we want this BEFORE shadows and AO because those facilities use pos/norm access if (features->isDeferred) - { - if (!shader->attachObject("deferred/deferredUtil.glsl")) - { - return FALSE; - } - } + { + if (!shader->attachObject("deferred/deferredUtil.glsl")) + { + return FALSE; + } + } if (features->hasShadows) - { - if (!shader->attachObject("deferred/shadowUtil.glsl")) - { - return FALSE; - } - } + { + if (!shader->attachObject("deferred/shadowUtil.glsl")) + { + return FALSE; + } + } if (features->hasAmbientOcclusion) - { - if (!shader->attachObject("deferred/aoUtil.glsl")) - { - return FALSE; - } - } + { + if (!shader->attachObject("deferred/aoUtil.glsl")) + { + return FALSE; + } + } if (features->hasIndirect) - { - if (!shader->attachObject("deferred/indirect.glsl")) - { - return FALSE; - } - } - - if (features->hasGamma) - { - if (!shader->attachObject("windlight/gammaF.glsl")) - { - return FALSE; - } - } - - if (features->hasSrgb) - { - if (!shader->attachObject("environment/srgbF.glsl")) - { - return FALSE; - } - } + { + if (!shader->attachObject("deferred/indirect.glsl")) + { + return FALSE; + } + } + + if (features->hasGamma) + { + if (!shader->attachObject("windlight/gammaF.glsl")) + { + return FALSE; + } + } + + if (features->hasSrgb) + { + if (!shader->attachObject("environment/srgbF.glsl")) + { + return FALSE; + } + } if (features->encodesNormal) - { - if (!shader->attachObject("environment/encodeNormF.glsl")) - { - return FALSE; - } - } - - if (features->hasAtmospherics) - { - if (!shader->attachObject("windlight/atmosphericsF.glsl")) - { - return FALSE; - } - } - - if (features->hasTransport) - { - if (!shader->attachObject("windlight/transportF.glsl")) - { - return FALSE; - } - - // Test hasFullbright and hasShiny and attach fullbright and - // fullbright shiny atmos transport if we split them out. - } - - // NOTE order of shader object attaching is VERY IMPORTANT!!! - if (features->hasWaterFog) - { - if (!shader->attachObject("environment/waterFogF.glsl")) - { - return FALSE; - } - } - - if (features->hasLighting) - { - if (features->hasWaterFog) - { - if (features->disableTextureIndex) - { - if (features->hasAlphaMask) - { - if (!shader->attachObject("lighting/lightWaterAlphaMaskNonIndexedF.glsl")) - { - return FALSE; - } - } - else - { - if (!shader->attachObject("lighting/lightWaterNonIndexedF.glsl")) - { - return FALSE; - } - } - } - else - { - if (features->hasAlphaMask) - { - if (!shader->attachObject("lighting/lightWaterAlphaMaskF.glsl")) - { - return FALSE; - } - } - else - { - if (!shader->attachObject("lighting/lightWaterF.glsl")) - { - return FALSE; - } - } - shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); - } - } - - else - { - if (features->disableTextureIndex) - { - if (features->hasAlphaMask) - { - if (!shader->attachObject("lighting/lightAlphaMaskNonIndexedF.glsl")) - { - return FALSE; - } - } - else - { - if (!shader->attachObject("lighting/lightNonIndexedF.glsl")) - { - return FALSE; - } - } - } - else - { - if (features->hasAlphaMask) - { - if (!shader->attachObject("lighting/lightAlphaMaskF.glsl")) - { - return FALSE; - } - } - else - { - if (!shader->attachObject("lighting/lightF.glsl")) - { - return FALSE; - } - } - shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); - } - } - } - - // NOTE order of shader object attaching is VERY IMPORTANT!!! - else if (features->isFullbright) - { - - if (features->isShiny && features->hasWaterFog) - { - if (features->disableTextureIndex) - { - if (!shader->attachObject("lighting/lightFullbrightShinyWaterNonIndexedF.glsl")) - { - return FALSE; - } - } - else - { - if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl")) - { - return FALSE; - } - shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); - } - } - else if (features->hasWaterFog) - { - if (features->disableTextureIndex) - { - if (features->hasAlphaMask) - { - if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl")) - { - return FALSE; - } - } - else if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.glsl")) - { - return FALSE; - } - } - else - { - if (features->hasAlphaMask) - { - if (!shader->attachObject("lighting/lightFullbrightWaterAlphaMaskF.glsl")) - { - return FALSE; - } - } - else if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl")) - { - return FALSE; - } - shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); - } - } - - else if (features->isShiny) - { - if (features->disableTextureIndex) - { - if (!shader->attachObject("lighting/lightFullbrightShinyNonIndexedF.glsl")) - { - return FALSE; - } - } - else - { - if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl")) - { - return FALSE; - } - shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); - } - } - - else - { - if (features->disableTextureIndex) - { - - if (features->hasAlphaMask) - { - if (!shader->attachObject("lighting/lightFullbrightNonIndexedAlphaMaskF.glsl")) - { - return FALSE; - } - } - else - { - if (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl")) - { - return FALSE; - } - } - } - else - { - if (features->hasAlphaMask) - { - if (!shader->attachObject("lighting/lightFullbrightAlphaMaskF.glsl")) - { - return FALSE; - } - } - else - { - if (!shader->attachObject("lighting/lightFullbrightF.glsl")) - { - return FALSE; - } - } - shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); - } - } - } - - // NOTE order of shader object attaching is VERY IMPORTANT!!! - else if (features->isShiny) - { - - if (features->hasWaterFog) - { - if (features->disableTextureIndex) - { - if (!shader->attachObject("lighting/lightShinyWaterNonIndexedF.glsl")) - { - return FALSE; - } - } - else - { - if (!shader->attachObject("lighting/lightShinyWaterF.glsl")) - { - return FALSE; - } - shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); - } - } - - else - { - if (features->disableTextureIndex) - { - if (!shader->attachObject("lighting/lightShinyNonIndexedF.glsl")) - { - return FALSE; - } - } - else - { - if (!shader->attachObject("lighting/lightShinyF.glsl")) - { - return FALSE; - } - shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); - } - } - } - - if (features->mIndexedTextureChannels <= 1) - { - if (!shader->attachObject("objects/nonindexedTextureV.glsl")) - { - return FALSE; - } - } - else - { - if (!shader->attachObject("objects/indexedTextureV.glsl")) - { - return FALSE; - } - } - - return TRUE; + { + if (!shader->attachObject("environment/encodeNormF.glsl")) + { + return FALSE; + } + } + + if (features->hasAtmospherics) + { + if (!shader->attachObject("windlight/atmosphericsF.glsl")) + { + return FALSE; + } + } + + if (features->hasTransport) + { + if (!shader->attachObject("windlight/transportF.glsl")) + { + return FALSE; + } + + // Test hasFullbright and hasShiny and attach fullbright and + // fullbright shiny atmos transport if we split them out. + } + + // NOTE order of shader object attaching is VERY IMPORTANT!!! + if (features->hasWaterFog) + { + if (!shader->attachObject("environment/waterFogF.glsl")) + { + return FALSE; + } + } + + if (features->hasLighting) + { + if (features->hasWaterFog) + { + if (features->disableTextureIndex) + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightWaterAlphaMaskNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightWaterNonIndexedF.glsl")) + { + return FALSE; + } + } + } + else + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightWaterAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightWaterF.glsl")) + { + return FALSE; + } + } + shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); + } + } + + else + { + if (features->disableTextureIndex) + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightAlphaMaskNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightNonIndexedF.glsl")) + { + return FALSE; + } + } + } + else + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightF.glsl")) + { + return FALSE; + } + } + shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); + } + } + } + + // NOTE order of shader object attaching is VERY IMPORTANT!!! + else if (features->isFullbright) + { + + if (features->isShiny && features->hasWaterFog) + { + if (features->disableTextureIndex) + { + if (!shader->attachObject("lighting/lightFullbrightShinyWaterNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); + } + } + else if (features->hasWaterFog) + { + if (features->disableTextureIndex) + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl")) + { + return FALSE; + } + } + else if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightWaterAlphaMaskF.glsl")) + { + return FALSE; + } + } + else if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); + } + } + + else if (features->isShiny) + { + if (features->disableTextureIndex) + { + if (!shader->attachObject("lighting/lightFullbrightShinyNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); + } + } + + else + { + if (features->disableTextureIndex) + { + + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightNonIndexedAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl")) + { + return FALSE; + } + } + } + else + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightF.glsl")) + { + return FALSE; + } + } + shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); + } + } + } + + // NOTE order of shader object attaching is VERY IMPORTANT!!! + else if (features->isShiny) + { + + if (features->hasWaterFog) + { + if (features->disableTextureIndex) + { + if (!shader->attachObject("lighting/lightShinyWaterNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightShinyWaterF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); + } + } + + else + { + if (features->disableTextureIndex) + { + if (!shader->attachObject("lighting/lightShinyNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightShinyF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); + } + } + } + + if (features->mIndexedTextureChannels <= 1) + { + if (!shader->attachObject("objects/nonindexedTextureV.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("objects/indexedTextureV.glsl")) + { + return FALSE; + } + } + + return TRUE; } //============================================================================ @@ -543,46 +543,46 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) static std::string get_object_log(GLhandleARB ret) { - std::string res; - - //get log length - GLint length; - glGetObjectParameterivARB(ret, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); - if (length > 0) - { - //the log could be any size, so allocate appropriately - GLcharARB* log = new GLcharARB[length]; - glGetInfoLogARB(ret, length, &length, log); - res = std::string((char *)log); - delete[] log; - } - return res; + std::string res; + + //get log length + GLint length; + glGetObjectParameterivARB(ret, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); + if (length > 0) + { + //the log could be any size, so allocate appropriately + GLcharARB* log = new GLcharARB[length]; + glGetInfoLogARB(ret, length, &length, log); + res = std::string((char *)log); + delete[] log; + } + return res; } //dump shader source for debugging void LLShaderMgr::dumpShaderSource(U32 shader_code_count, GLcharARB** shader_code_text) -{ - for (GLuint i = 0; i < shader_code_count; i++) - { - LL_SHADER_LOADING_WARNS() << i << ": " << shader_code_text[i] << LL_ENDL; - } +{ + for (GLuint i = 0; i < shader_code_count; i++) + { + LL_SHADER_LOADING_WARNS() << i << ": " << shader_code_text[i] << LL_ENDL; + } LL_SHADER_LOADING_WARNS() << LL_ENDL; } void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string& filename) { - std::string log = get_object_log(ret); + std::string log = get_object_log(ret); std::string fname = filename; if (filename.empty()) { fname = "unknown shader file"; } - if (log.length() > 0) - { + if (log.length() > 0) + { LL_SHADER_LOADING_WARNS() << "Shader loading from " << fname << ":\n" << LL_ENDL; LL_SHADER_LOADING_WARNS() << log << LL_ENDL; - } + } } GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map* defines, S32 texture_index_channels) @@ -596,38 +596,38 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade } #endif - GLenum error = GL_NO_ERROR; - if (gDebugGL) - { - error = glGetError(); - if (error != GL_NO_ERROR) - { - LL_SHADER_LOADING_WARNS() << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL; - } - } - - //LL_SHADER_LOADING_WARNS() << "Loading shader file: " << filename << " class " << shader_level << LL_ENDL; + GLenum error = GL_NO_ERROR; + if (gDebugGL) + { + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_SHADER_LOADING_WARNS() << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL; + } + } + + //LL_SHADER_LOADING_WARNS() << "Loading shader file: " << filename << " class " << shader_level << LL_ENDL; - if (filename.empty()) - { - return 0; - } + if (filename.empty()) + { + return 0; + } - //read in from file - LLFILE* file = NULL; + //read in from file + LLFILE* file = NULL; - S32 try_gpu_class = shader_level; - S32 gpu_class; + S32 try_gpu_class = shader_level; + S32 gpu_class; std::string open_file_name; - //find the most relevant file - for (gpu_class = try_gpu_class; gpu_class > 0; gpu_class--) - { //search from the current gpu class down to class 1 to find the most relevant shader - std::stringstream fname; - fname << getShaderDirPrefix(); - fname << gpu_class << "/" << filename; - + //find the most relevant file + for (gpu_class = try_gpu_class; gpu_class > 0; gpu_class--) + { //search from the current gpu class down to class 1 to find the most relevant shader + std::stringstream fname; + fname << getShaderDirPrefix(); + fname << gpu_class << "/" << filename; + open_file_name = fname.str(); /* @@ -643,23 +643,23 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade */ - LL_DEBUGS("ShaderLoading") << "Looking in " << open_file_name << LL_ENDL; - file = LLFile::fopen(open_file_name, "r"); /* Flawfinder: ignore */ - if (file) - { - LL_DEBUGS("ShaderLoading") << "Loading file: " << open_file_name << " (Want class " << gpu_class << ")" << LL_ENDL; - break; // done - } - } - - if (file == NULL) - { - LL_SHADER_LOADING_WARNS() << "GLSL Shader file not found: " << open_file_name << LL_ENDL; - return 0; - } - - //we can't have any lines longer than 1024 characters - //or any shaders longer than 4096 lines... deal - DaveP + LL_DEBUGS("ShaderLoading") << "Looking in " << open_file_name << LL_ENDL; + file = LLFile::fopen(open_file_name, "r"); /* Flawfinder: ignore */ + if (file) + { + LL_DEBUGS("ShaderLoading") << "Loading file: " << open_file_name << " (Want class " << gpu_class << ")" << LL_ENDL; + break; // done + } + } + + if (file == NULL) + { + LL_SHADER_LOADING_WARNS() << "GLSL Shader file not found: " << open_file_name << LL_ENDL; + return 0; + } + + //we can't have any lines longer than 1024 characters + //or any shaders longer than 4096 lines... deal - DaveP GLcharARB buff[1024]; GLcharARB *extra_code_text[1024]; GLcharARB *shader_code_text[4096 + LL_ARRAY_SIZE(extra_code_text)] = { NULL }; @@ -667,661 +667,661 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade BOOST_STATIC_ASSERT(LL_ARRAY_SIZE(extra_code_text) < LL_ARRAY_SIZE(shader_code_text)); - S32 major_version = gGLManager.mGLSLVersionMajor; - S32 minor_version = gGLManager.mGLSLVersionMinor; - - if (major_version == 1 && minor_version < 30) - { - if (minor_version < 10) - { - //should NEVER get here -- if major version is 1 and minor version is less than 10, - // viewer should never attempt to use shaders, continuing will result in undefined behavior - LL_ERRS() << "Unsupported GLSL Version." << LL_ENDL; - } - - if (minor_version <= 19) - { - shader_code_text[shader_code_count++] = strdup("#version 110\n"); - extra_code_text[extra_code_count++] = strdup("#define ATTRIBUTE attribute\n"); - extra_code_text[extra_code_count++] = strdup("#define VARYING varying\n"); - extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT varying\n"); - } - else if (minor_version <= 29) - { - //set version to 1.20 - shader_code_text[shader_code_count++] = strdup("#version 120\n"); - extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_120 1\n"); - extra_code_text[extra_code_count++] = strdup("#define FXAA_FAST_PIXEL_OFFSET 0\n"); - extra_code_text[extra_code_count++] = strdup("#define ATTRIBUTE attribute\n"); - extra_code_text[extra_code_count++] = strdup("#define VARYING varying\n"); - extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT varying\n"); - } - } - else - { - if (major_version < 4) - { - //set version to 1.30 - shader_code_text[shader_code_count++] = strdup("#version 130\n"); - //some implementations of GLSL 1.30 require integer precision be explicitly declared - extra_code_text[extra_code_count++] = strdup("precision mediump int;\n"); - extra_code_text[extra_code_count++] = strdup("precision highp float;\n"); - } - else - { //set version to 400 - shader_code_text[shader_code_count++] = strdup("#version 400\n"); - } - - extra_code_text[extra_code_count++] = strdup("#define DEFINE_GL_FRAGCOLOR 1\n"); - extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n"); - - extra_code_text[extra_code_count++] = strdup("#define ATTRIBUTE in\n"); - - if (type == GL_VERTEX_SHADER_ARB) - { //"varying" state is "out" in a vertex program, "in" in a fragment program - // ("varying" is deprecated after version 1.20) - extra_code_text[extra_code_count++] = strdup("#define VARYING out\n"); - extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT flat out\n"); - } - else - { - extra_code_text[extra_code_count++] = strdup("#define VARYING in\n"); - extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT flat in\n"); - } - - //backwards compatibility with legacy texture lookup syntax - extra_code_text[extra_code_count++] = strdup("#define texture2D texture\n"); - extra_code_text[extra_code_count++] = strdup("#define textureCube texture\n"); - extra_code_text[extra_code_count++] = strdup("#define texture2DLod textureLod\n"); - extra_code_text[extra_code_count++] = strdup("#define shadow2D(a,b) vec2(texture(a,b))\n"); - - if (major_version > 1 || minor_version >= 40) - { //GLSL 1.40 replaces texture2DRect et al with texture - extra_code_text[extra_code_count++] = strdup("#define texture2DRect texture\n"); - extra_code_text[extra_code_count++] = strdup("#define shadow2DRect(a,b) vec2(texture(a,b))\n"); - } - } - - if (defines) - { - for (boost::unordered_map::iterator iter = defines->begin(); iter != defines->end(); ++iter) - { - std::string define = "#define " + iter->first + " " + iter->second + "\n"; - extra_code_text[extra_code_count++] = (GLcharARB *) strdup(define.c_str()); - } - } - - if( gGLManager.mIsATI ) - { - extra_code_text[extra_code_count++] = strdup( "#define IS_AMD_CARD 1\n" ); - } - - if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB) - { - //use specified number of texture channels for indexed texture rendering - - /* prepend shader code that looks like this: - - uniform sampler2D tex0; - uniform sampler2D tex1; - uniform sampler2D tex2; - . - . - . - uniform sampler2D texN; - - VARYING_FLAT ivec4 vary_texture_index; - - vec4 ret = vec4(1,0,1,1); - - vec4 diffuseLookup(vec2 texcoord) - { - switch (vary_texture_index.r)) - { - case 0: ret = texture2D(tex0, texcoord); break; - case 1: ret = texture2D(tex1, texcoord); break; - case 2: ret = texture2D(tex2, texcoord); break; - . - . - . - case N: return texture2D(texN, texcoord); break; - } - - return ret; - } - */ - - extra_code_text[extra_code_count++] = strdup("#define HAS_DIFFUSE_LOOKUP\n"); - - //uniform declartion - for (S32 i = 0; i < texture_index_channels; ++i) - { - std::string decl = llformat("uniform sampler2D tex%d;\n", i); - extra_code_text[extra_code_count++] = strdup(decl.c_str()); - } - - if (texture_index_channels > 1) - { - extra_code_text[extra_code_count++] = strdup("VARYING_FLAT int vary_texture_index;\n"); - } - - extra_code_text[extra_code_count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n"); - extra_code_text[extra_code_count++] = strdup("{\n"); - - - if (texture_index_channels == 1) - { //don't use flow control, that's silly - extra_code_text[extra_code_count++] = strdup("return texture2D(tex0, texcoord);\n"); - extra_code_text[extra_code_count++] = strdup("}\n"); - } - else if (major_version > 1 || minor_version >= 30) - { //switches are supported in GLSL 1.30 and later - if (gGLManager.mIsNVIDIA) - { //switches are unreliable on some NVIDIA drivers - for (U32 i = 0; i < texture_index_channels; ++i) - { - std::string if_string = llformat("\t%sif (vary_texture_index == %d) { return texture2D(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i); - extra_code_text[extra_code_count++] = strdup(if_string.c_str()); - } - extra_code_text[extra_code_count++] = strdup("\treturn vec4(1,0,1,1);\n"); - extra_code_text[extra_code_count++] = strdup("}\n"); - } - else - { - extra_code_text[extra_code_count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n"); - extra_code_text[extra_code_count++] = strdup("\tswitch (vary_texture_index)\n"); - extra_code_text[extra_code_count++] = strdup("\t{\n"); - - //switch body - for (S32 i = 0; i < texture_index_channels; ++i) - { - std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i); - extra_code_text[extra_code_count++] = strdup(case_str.c_str()); - } - - extra_code_text[extra_code_count++] = strdup("\t}\n"); - extra_code_text[extra_code_count++] = strdup("\treturn ret;\n"); - extra_code_text[extra_code_count++] = strdup("}\n"); - } - } - else - { //should never get here. Indexed texture rendering requires GLSL 1.30 or later - // (for passing integers between vertex and fragment shaders) - LL_ERRS() << "Indexed texture rendering requires GLSL 1.30 or later." << LL_ENDL; - } - } - - //copy file into memory - enum { - flag_write_to_out_of_extra_block_area = 0x01 - , flag_extra_block_marker_was_found = 0x02 - }; - - unsigned char flags = flag_write_to_out_of_extra_block_area; - - GLuint out_of_extra_block_counter = 0, start_shader_code = shader_code_count, file_lines_count = 0; + S32 major_version = gGLManager.mGLSLVersionMajor; + S32 minor_version = gGLManager.mGLSLVersionMinor; + + if (major_version == 1 && minor_version < 30) + { + if (minor_version < 10) + { + //should NEVER get here -- if major version is 1 and minor version is less than 10, + // viewer should never attempt to use shaders, continuing will result in undefined behavior + LL_ERRS() << "Unsupported GLSL Version." << LL_ENDL; + } + + if (minor_version <= 19) + { + shader_code_text[shader_code_count++] = strdup("#version 110\n"); + extra_code_text[extra_code_count++] = strdup("#define ATTRIBUTE attribute\n"); + extra_code_text[extra_code_count++] = strdup("#define VARYING varying\n"); + extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT varying\n"); + } + else if (minor_version <= 29) + { + //set version to 1.20 + shader_code_text[shader_code_count++] = strdup("#version 120\n"); + extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_120 1\n"); + extra_code_text[extra_code_count++] = strdup("#define FXAA_FAST_PIXEL_OFFSET 0\n"); + extra_code_text[extra_code_count++] = strdup("#define ATTRIBUTE attribute\n"); + extra_code_text[extra_code_count++] = strdup("#define VARYING varying\n"); + extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT varying\n"); + } + } + else + { + if (major_version < 4) + { + //set version to 1.30 + shader_code_text[shader_code_count++] = strdup("#version 130\n"); + //some implementations of GLSL 1.30 require integer precision be explicitly declared + extra_code_text[extra_code_count++] = strdup("precision mediump int;\n"); + extra_code_text[extra_code_count++] = strdup("precision highp float;\n"); + } + else + { //set version to 400 + shader_code_text[shader_code_count++] = strdup("#version 400\n"); + } + + extra_code_text[extra_code_count++] = strdup("#define DEFINE_GL_FRAGCOLOR 1\n"); + extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n"); + + extra_code_text[extra_code_count++] = strdup("#define ATTRIBUTE in\n"); + + if (type == GL_VERTEX_SHADER_ARB) + { //"varying" state is "out" in a vertex program, "in" in a fragment program + // ("varying" is deprecated after version 1.20) + extra_code_text[extra_code_count++] = strdup("#define VARYING out\n"); + extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT flat out\n"); + } + else + { + extra_code_text[extra_code_count++] = strdup("#define VARYING in\n"); + extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT flat in\n"); + } + + //backwards compatibility with legacy texture lookup syntax + extra_code_text[extra_code_count++] = strdup("#define texture2D texture\n"); + extra_code_text[extra_code_count++] = strdup("#define textureCube texture\n"); + extra_code_text[extra_code_count++] = strdup("#define texture2DLod textureLod\n"); + extra_code_text[extra_code_count++] = strdup("#define shadow2D(a,b) vec2(texture(a,b))\n"); + + if (major_version > 1 || minor_version >= 40) + { //GLSL 1.40 replaces texture2DRect et al with texture + extra_code_text[extra_code_count++] = strdup("#define texture2DRect texture\n"); + extra_code_text[extra_code_count++] = strdup("#define shadow2DRect(a,b) vec2(texture(a,b))\n"); + } + } + + if (defines) + { + for (boost::unordered_map::iterator iter = defines->begin(); iter != defines->end(); ++iter) + { + std::string define = "#define " + iter->first + " " + iter->second + "\n"; + extra_code_text[extra_code_count++] = (GLcharARB *) strdup(define.c_str()); + } + } + + if( gGLManager.mIsATI ) + { + extra_code_text[extra_code_count++] = strdup( "#define IS_AMD_CARD 1\n" ); + } + + if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB) + { + //use specified number of texture channels for indexed texture rendering + + /* prepend shader code that looks like this: + + uniform sampler2D tex0; + uniform sampler2D tex1; + uniform sampler2D tex2; + . + . + . + uniform sampler2D texN; + + VARYING_FLAT ivec4 vary_texture_index; + + vec4 ret = vec4(1,0,1,1); + + vec4 diffuseLookup(vec2 texcoord) + { + switch (vary_texture_index.r)) + { + case 0: ret = texture2D(tex0, texcoord); break; + case 1: ret = texture2D(tex1, texcoord); break; + case 2: ret = texture2D(tex2, texcoord); break; + . + . + . + case N: return texture2D(texN, texcoord); break; + } + + return ret; + } + */ + + extra_code_text[extra_code_count++] = strdup("#define HAS_DIFFUSE_LOOKUP\n"); + + //uniform declartion + for (S32 i = 0; i < texture_index_channels; ++i) + { + std::string decl = llformat("uniform sampler2D tex%d;\n", i); + extra_code_text[extra_code_count++] = strdup(decl.c_str()); + } + + if (texture_index_channels > 1) + { + extra_code_text[extra_code_count++] = strdup("VARYING_FLAT int vary_texture_index;\n"); + } + + extra_code_text[extra_code_count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n"); + extra_code_text[extra_code_count++] = strdup("{\n"); + + + if (texture_index_channels == 1) + { //don't use flow control, that's silly + extra_code_text[extra_code_count++] = strdup("return texture2D(tex0, texcoord);\n"); + extra_code_text[extra_code_count++] = strdup("}\n"); + } + else if (major_version > 1 || minor_version >= 30) + { //switches are supported in GLSL 1.30 and later + if (gGLManager.mIsNVIDIA) + { //switches are unreliable on some NVIDIA drivers + for (U32 i = 0; i < texture_index_channels; ++i) + { + std::string if_string = llformat("\t%sif (vary_texture_index == %d) { return texture2D(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i); + extra_code_text[extra_code_count++] = strdup(if_string.c_str()); + } + extra_code_text[extra_code_count++] = strdup("\treturn vec4(1,0,1,1);\n"); + extra_code_text[extra_code_count++] = strdup("}\n"); + } + else + { + extra_code_text[extra_code_count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n"); + extra_code_text[extra_code_count++] = strdup("\tswitch (vary_texture_index)\n"); + extra_code_text[extra_code_count++] = strdup("\t{\n"); + + //switch body + for (S32 i = 0; i < texture_index_channels; ++i) + { + std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i); + extra_code_text[extra_code_count++] = strdup(case_str.c_str()); + } + + extra_code_text[extra_code_count++] = strdup("\t}\n"); + extra_code_text[extra_code_count++] = strdup("\treturn ret;\n"); + extra_code_text[extra_code_count++] = strdup("}\n"); + } + } + else + { //should never get here. Indexed texture rendering requires GLSL 1.30 or later + // (for passing integers between vertex and fragment shaders) + LL_ERRS() << "Indexed texture rendering requires GLSL 1.30 or later." << LL_ENDL; + } + } - while(NULL != fgets((char *)buff, 1024, file) - && shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text))) - { - file_lines_count++; - - bool extra_block_area_found = NULL != strstr((const char*)buff, "[EXTRA_CODE_HERE]"); - - if(extra_block_area_found && !(flag_extra_block_marker_was_found & flags)) - { - if(!(flag_write_to_out_of_extra_block_area & flags)) - { - //shift - for(GLuint to = start_shader_code, from = extra_code_count + start_shader_code; - from < shader_code_count; ++to, ++from) - { - shader_code_text[to] = shader_code_text[from]; - } - - shader_code_count -= extra_code_count; - } - - //copy extra code - for(GLuint n = 0; n < extra_code_count - && shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text)); ++n) - { - shader_code_text[shader_code_count++] = extra_code_text[n]; - } - - extra_code_count = 0; - - flags &= ~flag_write_to_out_of_extra_block_area; - flags |= flag_extra_block_marker_was_found; - } + //copy file into memory + enum { + flag_write_to_out_of_extra_block_area = 0x01 + , flag_extra_block_marker_was_found = 0x02 + }; + + unsigned char flags = flag_write_to_out_of_extra_block_area; + + GLuint out_of_extra_block_counter = 0, start_shader_code = shader_code_count, file_lines_count = 0; + + while(NULL != fgets((char *)buff, 1024, file) + && shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text))) + { + file_lines_count++; + + bool extra_block_area_found = NULL != strstr((const char*)buff, "[EXTRA_CODE_HERE]"); + + if(extra_block_area_found && !(flag_extra_block_marker_was_found & flags)) + { + if(!(flag_write_to_out_of_extra_block_area & flags)) + { + //shift + for(GLuint to = start_shader_code, from = extra_code_count + start_shader_code; + from < shader_code_count; ++to, ++from) + { + shader_code_text[to] = shader_code_text[from]; + } + + shader_code_count -= extra_code_count; + } + + //copy extra code + for(GLuint n = 0; n < extra_code_count + && shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text)); ++n) + { + shader_code_text[shader_code_count++] = extra_code_text[n]; + } + + extra_code_count = 0; + + flags &= ~flag_write_to_out_of_extra_block_area; + flags |= flag_extra_block_marker_was_found; + } else { shader_code_text[shader_code_count] = (GLcharARB *)strdup((char *)buff); - + if(flag_write_to_out_of_extra_block_area & flags) { shader_code_text[extra_code_count + start_shader_code + out_of_extra_block_counter] = shader_code_text[shader_code_count]; out_of_extra_block_counter++; - + if(out_of_extra_block_counter == extra_code_count) { shader_code_count += extra_code_count; flags &= ~flag_write_to_out_of_extra_block_area; } } - + ++shader_code_count; - } - } //while - - if(!(flag_extra_block_marker_was_found & flags)) - { - for(GLuint n = start_shader_code; n < extra_code_count + start_shader_code; ++n) - { - shader_code_text[n] = extra_code_text[n - start_shader_code]; - } - - if (file_lines_count < extra_code_count) - { - shader_code_count += extra_code_count; - } - - extra_code_count = 0; - } - - fclose(file); - - //create shader object - GLhandleARB ret = glCreateShaderObjectARB(type); - if (gDebugGL) - { - error = glGetError(); - if (error != GL_NO_ERROR) - { - LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL; - } - } - - //load source - glShaderSourceARB(ret, shader_code_count, (const GLcharARB**) shader_code_text, NULL); - - if (gDebugGL) - { - error = glGetError(); - if (error != GL_NO_ERROR) - { - LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSourceARB: " << error << LL_ENDL; - } - } - - //compile source - glCompileShaderARB(ret); - - if (gDebugGL) - { - error = glGetError(); - if (error != GL_NO_ERROR) - { - LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL; - } - } - - if (error == GL_NO_ERROR) - { - //check for errors - GLint success = GL_TRUE; - glGetObjectParameterivARB(ret, GL_OBJECT_COMPILE_STATUS_ARB, &success); - if (gDebugGL || success == GL_FALSE) - { - error = glGetError(); - if (error != GL_NO_ERROR || success == GL_FALSE) - { - //an error occured, print log - LL_WARNS("ShaderLoading") << "GLSL Compilation Error:" << LL_ENDL; - dumpObjectLog(ret, TRUE, open_file_name); + } + } //while + + if(!(flag_extra_block_marker_was_found & flags)) + { + for(GLuint n = start_shader_code; n < extra_code_count + start_shader_code; ++n) + { + shader_code_text[n] = extra_code_text[n - start_shader_code]; + } + + if (file_lines_count < extra_code_count) + { + shader_code_count += extra_code_count; + } + + extra_code_count = 0; + } + + fclose(file); + + //create shader object + GLhandleARB ret = glCreateShaderObjectARB(type); + if (gDebugGL) + { + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL; + } + } + + //load source + glShaderSourceARB(ret, shader_code_count, (const GLcharARB**) shader_code_text, NULL); + + if (gDebugGL) + { + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSourceARB: " << error << LL_ENDL; + } + } + + //compile source + glCompileShaderARB(ret); + + if (gDebugGL) + { + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL; + } + } + + if (error == GL_NO_ERROR) + { + //check for errors + GLint success = GL_TRUE; + glGetObjectParameterivARB(ret, GL_OBJECT_COMPILE_STATUS_ARB, &success); + if (gDebugGL || success == GL_FALSE) + { + error = glGetError(); + if (error != GL_NO_ERROR || success == GL_FALSE) + { + //an error occured, print log + LL_WARNS("ShaderLoading") << "GLSL Compilation Error:" << LL_ENDL; + dumpObjectLog(ret, TRUE, open_file_name); dumpShaderSource(shader_code_count, shader_code_text); - ret = 0; - } - } - } - else - { - ret = 0; - } - stop_glerror(); - - //free memory - for (GLuint i = 0; i < shader_code_count; i++) - { - free(shader_code_text[i]); - } - - //successfully loaded, save results - if (ret) - { - // Add shader file to map - mShaderObjects[filename] = ret; - shader_level = try_gpu_class; - } - else - { - if (shader_level > 1) - { - shader_level--; - return loadShaderFile(filename, shader_level, type, defines, texture_index_channels); - } - LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL; - } - return ret; + ret = 0; + } + } + } + else + { + ret = 0; + } + stop_glerror(); + + //free memory + for (GLuint i = 0; i < shader_code_count; i++) + { + free(shader_code_text[i]); + } + + //successfully loaded, save results + if (ret) + { + // Add shader file to map + mShaderObjects[filename] = ret; + shader_level = try_gpu_class; + } + else + { + if (shader_level > 1) + { + shader_level--; + return loadShaderFile(filename, shader_level, type, defines, texture_index_channels); + } + LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL; + } + return ret; } BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors) { - //check for errors - glLinkProgramARB(obj); - GLint success = GL_TRUE; - glGetObjectParameterivARB(obj, GL_OBJECT_LINK_STATUS_ARB, &success); - if (!suppress_errors && success == GL_FALSE) - { - //an error occured, print log - LL_SHADER_LOADING_WARNS() << "GLSL Linker Error:" << LL_ENDL; - } + //check for errors + glLinkProgramARB(obj); + GLint success = GL_TRUE; + glGetObjectParameterivARB(obj, GL_OBJECT_LINK_STATUS_ARB, &success); + if (!suppress_errors && success == GL_FALSE) + { + //an error occured, print log + LL_SHADER_LOADING_WARNS() << "GLSL Linker Error:" << LL_ENDL; + } #if LL_DARWIN - // For some reason this absolutely kills the frame rate when VBO's are enabled - if (0) - { - // Force an evaluation of the gl state so the driver can tell if the shader will run in hardware or software - // per Apple's suggestion - LLGLSLShader::sNoFixedFunction = false; - - glUseProgramObjectARB(obj); - - gGL.begin(LLRender::TRIANGLES); - gGL.vertex3f(0.0f, 0.0f, 0.0f); - gGL.vertex3f(0.0f, 0.0f, 0.0f); - gGL.vertex3f(0.0f, 0.0f, 0.0f); - gGL.end(); - gGL.flush(); - - glUseProgramObjectARB(0); - - LLGLSLShader::sNoFixedFunction = true; - - // Query whether the shader can or cannot run in hardware - // http://developer.apple.com/qa/qa2007/qa1502.html - GLint vertexGPUProcessing, fragmentGPUProcessing; - CGLContextObj ctx = CGLGetCurrentContext(); - CGLGetParameter(ctx, kCGLCPGPUVertexProcessing, &vertexGPUProcessing); - CGLGetParameter(ctx, kCGLCPGPUFragmentProcessing, &fragmentGPUProcessing); - if (!fragmentGPUProcessing || !vertexGPUProcessing) - { - LL_SHADER_LOADING_WARNS() << "GLSL Linker: Running in Software:" << LL_ENDL; - success = GL_FALSE; - suppress_errors = FALSE; - } - } + // For some reason this absolutely kills the frame rate when VBO's are enabled + if (0) + { + // Force an evaluation of the gl state so the driver can tell if the shader will run in hardware or software + // per Apple's suggestion + LLGLSLShader::sNoFixedFunction = false; + + glUseProgramObjectARB(obj); + + gGL.begin(LLRender::TRIANGLES); + gGL.vertex3f(0.0f, 0.0f, 0.0f); + gGL.vertex3f(0.0f, 0.0f, 0.0f); + gGL.vertex3f(0.0f, 0.0f, 0.0f); + gGL.end(); + gGL.flush(); + + glUseProgramObjectARB(0); + + LLGLSLShader::sNoFixedFunction = true; + + // Query whether the shader can or cannot run in hardware + // http://developer.apple.com/qa/qa2007/qa1502.html + GLint vertexGPUProcessing, fragmentGPUProcessing; + CGLContextObj ctx = CGLGetCurrentContext(); + CGLGetParameter(ctx, kCGLCPGPUVertexProcessing, &vertexGPUProcessing); + CGLGetParameter(ctx, kCGLCPGPUFragmentProcessing, &fragmentGPUProcessing); + if (!fragmentGPUProcessing || !vertexGPUProcessing) + { + LL_SHADER_LOADING_WARNS() << "GLSL Linker: Running in Software:" << LL_ENDL; + success = GL_FALSE; + suppress_errors = FALSE; + } + } #else - std::string log = get_object_log(obj); - LLStringUtil::toLower(log); - if (log.find("software") != std::string::npos) - { - LL_SHADER_LOADING_WARNS() << "GLSL Linker: Running in Software:" << LL_ENDL; - success = GL_FALSE; - suppress_errors = FALSE; - } + std::string log = get_object_log(obj); + LLStringUtil::toLower(log); + if (log.find("software") != std::string::npos) + { + LL_SHADER_LOADING_WARNS() << "GLSL Linker: Running in Software:" << LL_ENDL; + success = GL_FALSE; + suppress_errors = FALSE; + } #endif - return success; + return success; } BOOL LLShaderMgr::validateProgramObject(GLhandleARB obj) { - //check program validity against current GL - glValidateProgramARB(obj); - GLint success = GL_TRUE; - glGetObjectParameterivARB(obj, GL_OBJECT_VALIDATE_STATUS_ARB, &success); - if (success == GL_FALSE) - { - LL_SHADER_LOADING_WARNS() << "GLSL program not valid: " << LL_ENDL; - dumpObjectLog(obj); - } - else - { - dumpObjectLog(obj, FALSE); - } - - return success; + //check program validity against current GL + glValidateProgramARB(obj); + GLint success = GL_TRUE; + glGetObjectParameterivARB(obj, GL_OBJECT_VALIDATE_STATUS_ARB, &success); + if (success == GL_FALSE) + { + LL_SHADER_LOADING_WARNS() << "GLSL program not valid: " << LL_ENDL; + dumpObjectLog(obj); + } + else + { + dumpObjectLog(obj, FALSE); + } + + return success; } //virtual void LLShaderMgr::initAttribsAndUniforms() { - //MUST match order of enum in LLVertexBuffer.h - mReservedAttribs.push_back("position"); - mReservedAttribs.push_back("normal"); - mReservedAttribs.push_back("texcoord0"); - mReservedAttribs.push_back("texcoord1"); - mReservedAttribs.push_back("texcoord2"); - mReservedAttribs.push_back("texcoord3"); - mReservedAttribs.push_back("diffuse_color"); - mReservedAttribs.push_back("emissive"); - mReservedAttribs.push_back("tangent"); - mReservedAttribs.push_back("weight"); - mReservedAttribs.push_back("weight4"); - mReservedAttribs.push_back("clothing"); - mReservedAttribs.push_back("texture_index"); - - //matrix state - mReservedUniforms.push_back("modelview_matrix"); - mReservedUniforms.push_back("projection_matrix"); - mReservedUniforms.push_back("inv_proj"); - mReservedUniforms.push_back("modelview_projection_matrix"); + //MUST match order of enum in LLVertexBuffer.h + mReservedAttribs.push_back("position"); + mReservedAttribs.push_back("normal"); + mReservedAttribs.push_back("texcoord0"); + mReservedAttribs.push_back("texcoord1"); + mReservedAttribs.push_back("texcoord2"); + mReservedAttribs.push_back("texcoord3"); + mReservedAttribs.push_back("diffuse_color"); + mReservedAttribs.push_back("emissive"); + mReservedAttribs.push_back("tangent"); + mReservedAttribs.push_back("weight"); + mReservedAttribs.push_back("weight4"); + mReservedAttribs.push_back("clothing"); + mReservedAttribs.push_back("texture_index"); + + //matrix state + mReservedUniforms.push_back("modelview_matrix"); + mReservedUniforms.push_back("projection_matrix"); + mReservedUniforms.push_back("inv_proj"); + mReservedUniforms.push_back("modelview_projection_matrix"); mReservedUniforms.push_back("inv_modelview"); - mReservedUniforms.push_back("normal_matrix"); - mReservedUniforms.push_back("texture_matrix0"); - mReservedUniforms.push_back("texture_matrix1"); - mReservedUniforms.push_back("texture_matrix2"); - mReservedUniforms.push_back("texture_matrix3"); - mReservedUniforms.push_back("object_plane_s"); - mReservedUniforms.push_back("object_plane_t"); - llassert(mReservedUniforms.size() == LLShaderMgr::OBJECT_PLANE_T+1); - - mReservedUniforms.push_back("viewport"); - - mReservedUniforms.push_back("light_position"); - mReservedUniforms.push_back("light_direction"); - mReservedUniforms.push_back("light_attenuation"); - mReservedUniforms.push_back("light_diffuse"); - mReservedUniforms.push_back("light_ambient"); - mReservedUniforms.push_back("light_count"); - mReservedUniforms.push_back("light"); - mReservedUniforms.push_back("light_col"); - mReservedUniforms.push_back("far_z"); - - llassert(mReservedUniforms.size() == LLShaderMgr::MULTI_LIGHT_FAR_Z+1); - - - mReservedUniforms.push_back("proj_mat"); - mReservedUniforms.push_back("proj_near"); - mReservedUniforms.push_back("proj_p"); - mReservedUniforms.push_back("proj_n"); - mReservedUniforms.push_back("proj_origin"); - mReservedUniforms.push_back("proj_range"); - mReservedUniforms.push_back("proj_ambiance"); - mReservedUniforms.push_back("proj_shadow_idx"); - mReservedUniforms.push_back("shadow_fade"); - mReservedUniforms.push_back("proj_focus"); - mReservedUniforms.push_back("proj_lod"); - mReservedUniforms.push_back("proj_ambient_lod"); - - llassert(mReservedUniforms.size() == LLShaderMgr::PROJECTOR_AMBIENT_LOD+1); - - mReservedUniforms.push_back("color"); - - mReservedUniforms.push_back("diffuseMap"); + mReservedUniforms.push_back("normal_matrix"); + mReservedUniforms.push_back("texture_matrix0"); + mReservedUniforms.push_back("texture_matrix1"); + mReservedUniforms.push_back("texture_matrix2"); + mReservedUniforms.push_back("texture_matrix3"); + mReservedUniforms.push_back("object_plane_s"); + mReservedUniforms.push_back("object_plane_t"); + llassert(mReservedUniforms.size() == LLShaderMgr::OBJECT_PLANE_T+1); + + mReservedUniforms.push_back("viewport"); + + mReservedUniforms.push_back("light_position"); + mReservedUniforms.push_back("light_direction"); + mReservedUniforms.push_back("light_attenuation"); + mReservedUniforms.push_back("light_diffuse"); + mReservedUniforms.push_back("light_ambient"); + mReservedUniforms.push_back("light_count"); + mReservedUniforms.push_back("light"); + mReservedUniforms.push_back("light_col"); + mReservedUniforms.push_back("far_z"); + + llassert(mReservedUniforms.size() == LLShaderMgr::MULTI_LIGHT_FAR_Z+1); + + + mReservedUniforms.push_back("proj_mat"); + mReservedUniforms.push_back("proj_near"); + mReservedUniforms.push_back("proj_p"); + mReservedUniforms.push_back("proj_n"); + mReservedUniforms.push_back("proj_origin"); + mReservedUniforms.push_back("proj_range"); + mReservedUniforms.push_back("proj_ambiance"); + mReservedUniforms.push_back("proj_shadow_idx"); + mReservedUniforms.push_back("shadow_fade"); + mReservedUniforms.push_back("proj_focus"); + mReservedUniforms.push_back("proj_lod"); + mReservedUniforms.push_back("proj_ambient_lod"); + + llassert(mReservedUniforms.size() == LLShaderMgr::PROJECTOR_AMBIENT_LOD+1); + + mReservedUniforms.push_back("color"); + + mReservedUniforms.push_back("diffuseMap"); mReservedUniforms.push_back("altDiffuseMap"); - mReservedUniforms.push_back("specularMap"); - mReservedUniforms.push_back("bumpMap"); + mReservedUniforms.push_back("specularMap"); + mReservedUniforms.push_back("bumpMap"); mReservedUniforms.push_back("bumpMap2"); - mReservedUniforms.push_back("environmentMap"); - mReservedUniforms.push_back("cloud_noise_texture"); + mReservedUniforms.push_back("environmentMap"); + mReservedUniforms.push_back("cloud_noise_texture"); mReservedUniforms.push_back("cloud_noise_texture_next"); - mReservedUniforms.push_back("fullbright"); - mReservedUniforms.push_back("lightnorm"); - mReservedUniforms.push_back("sunlight_color"); - mReservedUniforms.push_back("ambient"); - mReservedUniforms.push_back("blue_horizon"); - mReservedUniforms.push_back("blue_density"); - mReservedUniforms.push_back("haze_horizon"); - mReservedUniforms.push_back("haze_density"); - mReservedUniforms.push_back("cloud_shadow"); - mReservedUniforms.push_back("density_multiplier"); - mReservedUniforms.push_back("distance_multiplier"); - mReservedUniforms.push_back("max_y"); - mReservedUniforms.push_back("glow"); - mReservedUniforms.push_back("cloud_color"); - mReservedUniforms.push_back("cloud_pos_density1"); - mReservedUniforms.push_back("cloud_pos_density2"); - mReservedUniforms.push_back("cloud_scale"); - mReservedUniforms.push_back("gamma"); - mReservedUniforms.push_back("scene_light_strength"); - - llassert(mReservedUniforms.size() == LLShaderMgr::SCENE_LIGHT_STRENGTH+1); - - mReservedUniforms.push_back("center"); - mReservedUniforms.push_back("size"); - mReservedUniforms.push_back("falloff"); - - mReservedUniforms.push_back("box_center"); - mReservedUniforms.push_back("box_size"); - - - mReservedUniforms.push_back("minLuminance"); - mReservedUniforms.push_back("maxExtractAlpha"); - mReservedUniforms.push_back("lumWeights"); - mReservedUniforms.push_back("warmthWeights"); - mReservedUniforms.push_back("warmthAmount"); - mReservedUniforms.push_back("glowStrength"); - mReservedUniforms.push_back("glowDelta"); - - llassert(mReservedUniforms.size() == LLShaderMgr::GLOW_DELTA+1); - - - mReservedUniforms.push_back("minimum_alpha"); - mReservedUniforms.push_back("emissive_brightness"); - - mReservedUniforms.push_back("shadow_matrix"); - mReservedUniforms.push_back("env_mat"); - mReservedUniforms.push_back("shadow_clip"); - mReservedUniforms.push_back("sun_wash"); - mReservedUniforms.push_back("shadow_noise"); - mReservedUniforms.push_back("blur_size"); - mReservedUniforms.push_back("ssao_radius"); - mReservedUniforms.push_back("ssao_max_radius"); - mReservedUniforms.push_back("ssao_factor"); - mReservedUniforms.push_back("ssao_factor_inv"); - mReservedUniforms.push_back("ssao_effect_mat"); - mReservedUniforms.push_back("screen_res"); - mReservedUniforms.push_back("near_clip"); - mReservedUniforms.push_back("shadow_offset"); - mReservedUniforms.push_back("shadow_bias"); - mReservedUniforms.push_back("spot_shadow_bias"); - mReservedUniforms.push_back("spot_shadow_offset"); - mReservedUniforms.push_back("sun_dir"); + mReservedUniforms.push_back("fullbright"); + mReservedUniforms.push_back("lightnorm"); + mReservedUniforms.push_back("sunlight_color"); + mReservedUniforms.push_back("ambient"); + mReservedUniforms.push_back("blue_horizon"); + mReservedUniforms.push_back("blue_density"); + mReservedUniforms.push_back("haze_horizon"); + mReservedUniforms.push_back("haze_density"); + mReservedUniforms.push_back("cloud_shadow"); + mReservedUniforms.push_back("density_multiplier"); + mReservedUniforms.push_back("distance_multiplier"); + mReservedUniforms.push_back("max_y"); + mReservedUniforms.push_back("glow"); + mReservedUniforms.push_back("cloud_color"); + mReservedUniforms.push_back("cloud_pos_density1"); + mReservedUniforms.push_back("cloud_pos_density2"); + mReservedUniforms.push_back("cloud_scale"); + mReservedUniforms.push_back("gamma"); + mReservedUniforms.push_back("scene_light_strength"); + + llassert(mReservedUniforms.size() == LLShaderMgr::SCENE_LIGHT_STRENGTH+1); + + mReservedUniforms.push_back("center"); + mReservedUniforms.push_back("size"); + mReservedUniforms.push_back("falloff"); + + mReservedUniforms.push_back("box_center"); + mReservedUniforms.push_back("box_size"); + + + mReservedUniforms.push_back("minLuminance"); + mReservedUniforms.push_back("maxExtractAlpha"); + mReservedUniforms.push_back("lumWeights"); + mReservedUniforms.push_back("warmthWeights"); + mReservedUniforms.push_back("warmthAmount"); + mReservedUniforms.push_back("glowStrength"); + mReservedUniforms.push_back("glowDelta"); + + llassert(mReservedUniforms.size() == LLShaderMgr::GLOW_DELTA+1); + + + mReservedUniforms.push_back("minimum_alpha"); + mReservedUniforms.push_back("emissive_brightness"); + + mReservedUniforms.push_back("shadow_matrix"); + mReservedUniforms.push_back("env_mat"); + mReservedUniforms.push_back("shadow_clip"); + mReservedUniforms.push_back("sun_wash"); + mReservedUniforms.push_back("shadow_noise"); + mReservedUniforms.push_back("blur_size"); + mReservedUniforms.push_back("ssao_radius"); + mReservedUniforms.push_back("ssao_max_radius"); + mReservedUniforms.push_back("ssao_factor"); + mReservedUniforms.push_back("ssao_factor_inv"); + mReservedUniforms.push_back("ssao_effect_mat"); + mReservedUniforms.push_back("screen_res"); + mReservedUniforms.push_back("near_clip"); + mReservedUniforms.push_back("shadow_offset"); + mReservedUniforms.push_back("shadow_bias"); + mReservedUniforms.push_back("spot_shadow_bias"); + mReservedUniforms.push_back("spot_shadow_offset"); + mReservedUniforms.push_back("sun_dir"); mReservedUniforms.push_back("moon_dir"); - mReservedUniforms.push_back("shadow_res"); - mReservedUniforms.push_back("proj_shadow_res"); - mReservedUniforms.push_back("depth_cutoff"); - mReservedUniforms.push_back("norm_cutoff"); - mReservedUniforms.push_back("shadow_target_width"); - - llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH+1); - - mReservedUniforms.push_back("tc_scale"); - mReservedUniforms.push_back("rcp_screen_res"); - mReservedUniforms.push_back("rcp_frame_opt"); - mReservedUniforms.push_back("rcp_frame_opt2"); - - mReservedUniforms.push_back("focal_distance"); - mReservedUniforms.push_back("blur_constant"); - mReservedUniforms.push_back("tan_pixel_angle"); - mReservedUniforms.push_back("magnification"); - mReservedUniforms.push_back("max_cof"); - mReservedUniforms.push_back("res_scale"); - mReservedUniforms.push_back("dof_width"); - mReservedUniforms.push_back("dof_height"); - - mReservedUniforms.push_back("depthMap"); - mReservedUniforms.push_back("shadowMap0"); - mReservedUniforms.push_back("shadowMap1"); - mReservedUniforms.push_back("shadowMap2"); - mReservedUniforms.push_back("shadowMap3"); - mReservedUniforms.push_back("shadowMap4"); - mReservedUniforms.push_back("shadowMap5"); - - llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW5+1); - - mReservedUniforms.push_back("normalMap"); - mReservedUniforms.push_back("positionMap"); - mReservedUniforms.push_back("diffuseRect"); - mReservedUniforms.push_back("specularRect"); - mReservedUniforms.push_back("noiseMap"); - mReservedUniforms.push_back("lightFunc"); - mReservedUniforms.push_back("lightMap"); - mReservedUniforms.push_back("bloomMap"); - mReservedUniforms.push_back("projectionMap"); - mReservedUniforms.push_back("norm_mat"); - - mReservedUniforms.push_back("global_gamma"); - mReservedUniforms.push_back("texture_gamma"); - - mReservedUniforms.push_back("specular_color"); - mReservedUniforms.push_back("env_intensity"); - - mReservedUniforms.push_back("matrixPalette"); - mReservedUniforms.push_back("translationPalette"); - - mReservedUniforms.push_back("screenTex"); - mReservedUniforms.push_back("screenDepth"); - mReservedUniforms.push_back("refTex"); - mReservedUniforms.push_back("eyeVec"); - mReservedUniforms.push_back("time"); - mReservedUniforms.push_back("waveDir1"); - mReservedUniforms.push_back("waveDir2"); - mReservedUniforms.push_back("lightDir"); - mReservedUniforms.push_back("specular"); - mReservedUniforms.push_back("lightExp"); - mReservedUniforms.push_back("waterFogColor"); - mReservedUniforms.push_back("waterFogDensity"); - mReservedUniforms.push_back("waterFogKS"); - mReservedUniforms.push_back("refScale"); - mReservedUniforms.push_back("waterHeight"); - mReservedUniforms.push_back("waterPlane"); - mReservedUniforms.push_back("normScale"); - mReservedUniforms.push_back("fresnelScale"); - mReservedUniforms.push_back("fresnelOffset"); - mReservedUniforms.push_back("blurMultiplier"); - mReservedUniforms.push_back("sunAngle"); - mReservedUniforms.push_back("scaledAngle"); - mReservedUniforms.push_back("sunAngle2"); - - mReservedUniforms.push_back("camPosLocal"); - - mReservedUniforms.push_back("gWindDir"); - mReservedUniforms.push_back("gSinWaveParams"); - mReservedUniforms.push_back("gGravity"); - - mReservedUniforms.push_back("detail_0"); - mReservedUniforms.push_back("detail_1"); - mReservedUniforms.push_back("detail_2"); - mReservedUniforms.push_back("detail_3"); - mReservedUniforms.push_back("alpha_ramp"); - - mReservedUniforms.push_back("origin"); - mReservedUniforms.push_back("display_gamma"); + mReservedUniforms.push_back("shadow_res"); + mReservedUniforms.push_back("proj_shadow_res"); + mReservedUniforms.push_back("depth_cutoff"); + mReservedUniforms.push_back("norm_cutoff"); + mReservedUniforms.push_back("shadow_target_width"); + + llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH+1); + + mReservedUniforms.push_back("tc_scale"); + mReservedUniforms.push_back("rcp_screen_res"); + mReservedUniforms.push_back("rcp_frame_opt"); + mReservedUniforms.push_back("rcp_frame_opt2"); + + mReservedUniforms.push_back("focal_distance"); + mReservedUniforms.push_back("blur_constant"); + mReservedUniforms.push_back("tan_pixel_angle"); + mReservedUniforms.push_back("magnification"); + mReservedUniforms.push_back("max_cof"); + mReservedUniforms.push_back("res_scale"); + mReservedUniforms.push_back("dof_width"); + mReservedUniforms.push_back("dof_height"); + + mReservedUniforms.push_back("depthMap"); + mReservedUniforms.push_back("shadowMap0"); + mReservedUniforms.push_back("shadowMap1"); + mReservedUniforms.push_back("shadowMap2"); + mReservedUniforms.push_back("shadowMap3"); + mReservedUniforms.push_back("shadowMap4"); + mReservedUniforms.push_back("shadowMap5"); + + llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW5+1); + + mReservedUniforms.push_back("normalMap"); + mReservedUniforms.push_back("positionMap"); + mReservedUniforms.push_back("diffuseRect"); + mReservedUniforms.push_back("specularRect"); + mReservedUniforms.push_back("noiseMap"); + mReservedUniforms.push_back("lightFunc"); + mReservedUniforms.push_back("lightMap"); + mReservedUniforms.push_back("bloomMap"); + mReservedUniforms.push_back("projectionMap"); + mReservedUniforms.push_back("norm_mat"); + + mReservedUniforms.push_back("global_gamma"); + mReservedUniforms.push_back("texture_gamma"); + + mReservedUniforms.push_back("specular_color"); + mReservedUniforms.push_back("env_intensity"); + + mReservedUniforms.push_back("matrixPalette"); + mReservedUniforms.push_back("translationPalette"); + + mReservedUniforms.push_back("screenTex"); + mReservedUniforms.push_back("screenDepth"); + mReservedUniforms.push_back("refTex"); + mReservedUniforms.push_back("eyeVec"); + mReservedUniforms.push_back("time"); + mReservedUniforms.push_back("waveDir1"); + mReservedUniforms.push_back("waveDir2"); + mReservedUniforms.push_back("lightDir"); + mReservedUniforms.push_back("specular"); + mReservedUniforms.push_back("lightExp"); + mReservedUniforms.push_back("waterFogColor"); + mReservedUniforms.push_back("waterFogDensity"); + mReservedUniforms.push_back("waterFogKS"); + mReservedUniforms.push_back("refScale"); + mReservedUniforms.push_back("waterHeight"); + mReservedUniforms.push_back("waterPlane"); + mReservedUniforms.push_back("normScale"); + mReservedUniforms.push_back("fresnelScale"); + mReservedUniforms.push_back("fresnelOffset"); + mReservedUniforms.push_back("blurMultiplier"); + mReservedUniforms.push_back("sunAngle"); + mReservedUniforms.push_back("scaledAngle"); + mReservedUniforms.push_back("sunAngle2"); + + mReservedUniforms.push_back("camPosLocal"); + + mReservedUniforms.push_back("gWindDir"); + mReservedUniforms.push_back("gSinWaveParams"); + mReservedUniforms.push_back("gGravity"); + + mReservedUniforms.push_back("detail_0"); + mReservedUniforms.push_back("detail_1"); + mReservedUniforms.push_back("detail_2"); + mReservedUniforms.push_back("detail_3"); + mReservedUniforms.push_back("alpha_ramp"); + + mReservedUniforms.push_back("origin"); + mReservedUniforms.push_back("display_gamma"); mReservedUniforms.push_back("inscatter"); mReservedUniforms.push_back("sun_size"); @@ -1350,17 +1350,17 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("sun_up_factor"); mReservedUniforms.push_back("moonlight_color"); - llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); + llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); - std::set dupe_check; + std::set dupe_check; - for (U32 i = 0; i < mReservedUniforms.size(); ++i) - { - if (dupe_check.find(mReservedUniforms[i]) != dupe_check.end()) - { - LL_ERRS() << "Duplicate reserved uniform name found: " << mReservedUniforms[i] << LL_ENDL; - } - dupe_check.insert(mReservedUniforms[i]); - } + for (U32 i = 0; i < mReservedUniforms.size(); ++i) + { + if (dupe_check.find(mReservedUniforms[i]) != dupe_check.end()) + { + LL_ERRS() << "Duplicate reserved uniform name found: " << mReservedUniforms[i] << LL_ENDL; + } + dupe_check.insert(mReservedUniforms[i]); + } } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 07972e0d77..641b42b56a 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -94,7 +94,7 @@ BOOL gAnimateTextures = TRUE; //extern BOOL gHideSelectedObjects; F32 LLVOVolume::sLODFactor = 1.f; -F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop +F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop F32 LLVOVolume::sDistanceFactor = 1.0f; S32 LLVOVolume::sNumLODChanges = 0; S32 LLVOVolume::mRenderComplexity_last = 0; @@ -112,200 +112,200 @@ extern BOOL gGLDebugLoggingEnabled; class LLMediaDataClientObjectImpl : public LLMediaDataClientObject { public: - LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew) - { - mObject->addMDCImpl(); - } - ~LLMediaDataClientObjectImpl() - { - mObject->removeMDCImpl(); - } - - virtual U8 getMediaDataCount() const - { return mObject->getNumTEs(); } - - virtual LLSD getMediaDataLLSD(U8 index) const - { - LLSD result; - LLTextureEntry *te = mObject->getTE(index); - if (NULL != te) - { - llassert((te->getMediaData() != NULL) == te->hasMedia()); - if (te->getMediaData() != NULL) - { - result = te->getMediaData()->asLLSD(); - // XXX HACK: workaround bug in asLLSD() where whitelist is not set properly - // See DEV-41949 - if (!result.has(LLMediaEntry::WHITELIST_KEY)) - { - result[LLMediaEntry::WHITELIST_KEY] = LLSD::emptyArray(); - } - } - } - return result; - } - virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const - { - LLTextureEntry *te = mObject->getTE(index); - if (te) - { - if (te->getMediaData()) - { - return (te->getMediaData()->getCurrentURL() == url); - } - } - return url.empty(); - } - - virtual LLUUID getID() const - { return mObject->getID(); } - - virtual void mediaNavigateBounceBack(U8 index) - { mObject->mediaNavigateBounceBack(index); } - - virtual bool hasMedia() const - { return mObject->hasMedia(); } - - virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string) - { mObject->updateObjectMediaData(data, version_string); } - - virtual F64 getMediaInterest() const - { - F64 interest = mObject->getTotalMediaInterest(); - if (interest < (F64)0.0) - { - // media interest not valid yet, try pixel area - interest = mObject->getPixelArea(); - // HACK: force recalculation of pixel area if interest is the "magic default" of 1024. - if (interest == 1024.f) - { - const_cast(static_cast(mObject))->setPixelAreaAndAngle(gAgent); - interest = mObject->getPixelArea(); - } - } - return interest; - } - - virtual bool isInterestingEnough() const - { - return LLViewerMedia::isInterestingEnough(mObject, getMediaInterest()); - } - - virtual std::string getCapabilityUrl(const std::string &name) const - { return mObject->getRegion()->getCapability(name); } - - virtual bool isDead() const - { return mObject->isDead(); } - - virtual U32 getMediaVersion() const - { return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); } - - virtual bool isNew() const - { return mNew; } + LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew) + { + mObject->addMDCImpl(); + } + ~LLMediaDataClientObjectImpl() + { + mObject->removeMDCImpl(); + } + + virtual U8 getMediaDataCount() const + { return mObject->getNumTEs(); } + + virtual LLSD getMediaDataLLSD(U8 index) const + { + LLSD result; + LLTextureEntry *te = mObject->getTE(index); + if (NULL != te) + { + llassert((te->getMediaData() != NULL) == te->hasMedia()); + if (te->getMediaData() != NULL) + { + result = te->getMediaData()->asLLSD(); + // XXX HACK: workaround bug in asLLSD() where whitelist is not set properly + // See DEV-41949 + if (!result.has(LLMediaEntry::WHITELIST_KEY)) + { + result[LLMediaEntry::WHITELIST_KEY] = LLSD::emptyArray(); + } + } + } + return result; + } + virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const + { + LLTextureEntry *te = mObject->getTE(index); + if (te) + { + if (te->getMediaData()) + { + return (te->getMediaData()->getCurrentURL() == url); + } + } + return url.empty(); + } + + virtual LLUUID getID() const + { return mObject->getID(); } + + virtual void mediaNavigateBounceBack(U8 index) + { mObject->mediaNavigateBounceBack(index); } + + virtual bool hasMedia() const + { return mObject->hasMedia(); } + + virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string) + { mObject->updateObjectMediaData(data, version_string); } + + virtual F64 getMediaInterest() const + { + F64 interest = mObject->getTotalMediaInterest(); + if (interest < (F64)0.0) + { + // media interest not valid yet, try pixel area + interest = mObject->getPixelArea(); + // HACK: force recalculation of pixel area if interest is the "magic default" of 1024. + if (interest == 1024.f) + { + const_cast(static_cast(mObject))->setPixelAreaAndAngle(gAgent); + interest = mObject->getPixelArea(); + } + } + return interest; + } + + virtual bool isInterestingEnough() const + { + return LLViewerMedia::isInterestingEnough(mObject, getMediaInterest()); + } + + virtual std::string getCapabilityUrl(const std::string &name) const + { return mObject->getRegion()->getCapability(name); } + + virtual bool isDead() const + { return mObject->isDead(); } + + virtual U32 getMediaVersion() const + { return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); } + + virtual bool isNew() const + { return mNew; } private: - LLPointer mObject; - bool mNew; + LLPointer mObject; + bool mNew; }; LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) - : LLViewerObject(id, pcode, regionp), - mVolumeImpl(NULL) + : LLViewerObject(id, pcode, regionp), + mVolumeImpl(NULL) { - mTexAnimMode = 0; - mRelativeXform.setIdentity(); - mRelativeXformInvTrans.setIdentity(); + mTexAnimMode = 0; + mRelativeXform.setIdentity(); + mRelativeXformInvTrans.setIdentity(); - mFaceMappingChanged = FALSE; - mLOD = MIN_LOD; + mFaceMappingChanged = FALSE; + mLOD = MIN_LOD; mLODDistance = 0.0f; mLODAdjustedDistance = 0.0f; mLODRadius = 0.0f; - mTextureAnimp = NULL; - mVolumeChanged = FALSE; - mVObjRadius = LLVector3(1,1,0.5f).length(); - mNumFaces = 0; - mLODChanged = FALSE; - mSculptChanged = FALSE; - mSpotLightPriority = 0.f; - - mMediaImplList.resize(getNumTEs()); - mLastFetchedMediaVersion = -1; - memset(&mIndexInTex, 0, sizeof(S32) * LLRender::NUM_VOLUME_TEXTURE_CHANNELS); - mMDCImplCount = 0; + mTextureAnimp = NULL; + mVolumeChanged = FALSE; + mVObjRadius = LLVector3(1,1,0.5f).length(); + mNumFaces = 0; + mLODChanged = FALSE; + mSculptChanged = FALSE; + mSpotLightPriority = 0.f; + + mMediaImplList.resize(getNumTEs()); + mLastFetchedMediaVersion = -1; + memset(&mIndexInTex, 0, sizeof(S32) * LLRender::NUM_VOLUME_TEXTURE_CHANNELS); + mMDCImplCount = 0; mLastRiggingInfoLOD = -1; } LLVOVolume::~LLVOVolume() { - delete mTextureAnimp; - mTextureAnimp = NULL; - delete mVolumeImpl; - mVolumeImpl = NULL; + delete mTextureAnimp; + mTextureAnimp = NULL; + delete mVolumeImpl; + mVolumeImpl = NULL; - if(!mMediaImplList.empty()) - { - for(U32 i = 0 ; i < mMediaImplList.size() ; i++) - { - if(mMediaImplList[i].notNull()) - { - mMediaImplList[i]->removeObject(this) ; - } - } - } + if(!mMediaImplList.empty()) + { + for(U32 i = 0 ; i < mMediaImplList.size() ; i++) + { + if(mMediaImplList[i].notNull()) + { + mMediaImplList[i]->removeObject(this) ; + } + } + } } void LLVOVolume::markDead() { - if (!mDead) - { - LLSculptIDSize::instance().rem(getVolume()->getParams().getSculptID()); - - if(getMDCImplCount() > 0) - { - LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast(this), false); - if (sObjectMediaClient) sObjectMediaClient->removeFromQueue(obj); - if (sObjectMediaNavigateClient) sObjectMediaNavigateClient->removeFromQueue(obj); - } - - // Detach all media impls from this object - for(U32 i = 0 ; i < mMediaImplList.size() ; i++) - { - removeMediaImpl(i); - } - - if (mSculptTexture.notNull()) - { - mSculptTexture->removeVolume(LLRender::SCULPT_TEX, this); - } - - if (mLightTexture.notNull()) - { - mLightTexture->removeVolume(LLRender::LIGHT_TEX, this); - } - } - - LLViewerObject::markDead(); + if (!mDead) + { + LLSculptIDSize::instance().rem(getVolume()->getParams().getSculptID()); + + if(getMDCImplCount() > 0) + { + LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast(this), false); + if (sObjectMediaClient) sObjectMediaClient->removeFromQueue(obj); + if (sObjectMediaNavigateClient) sObjectMediaNavigateClient->removeFromQueue(obj); + } + + // Detach all media impls from this object + for(U32 i = 0 ; i < mMediaImplList.size() ; i++) + { + removeMediaImpl(i); + } + + if (mSculptTexture.notNull()) + { + mSculptTexture->removeVolume(LLRender::SCULPT_TEX, this); + } + + if (mLightTexture.notNull()) + { + mLightTexture->removeVolume(LLRender::LIGHT_TEX, this); + } + } + + LLViewerObject::markDead(); } // static void LLVOVolume::initClass() { - // gSavedSettings better be around - if (gSavedSettings.getBOOL("PrimMediaMasterEnabled")) - { - const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay"); - const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay"); - const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries"); - const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize"); - const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize"); - sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries, - max_sorted_queue_size, max_round_robin_queue_size); - sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, - max_retries, max_sorted_queue_size, max_round_robin_queue_size); - } + // gSavedSettings better be around + if (gSavedSettings.getBOOL("PrimMediaMasterEnabled")) + { + const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay"); + const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay"); + const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries"); + const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize"); + const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize"); + sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries, + max_sorted_queue_size, max_round_robin_queue_size); + sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, + max_retries, max_sorted_queue_size, max_round_robin_queue_size); + } } // static @@ -316,201 +316,201 @@ void LLVOVolume::cleanupClass() } U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, EObjectUpdateType update_type, - LLDataPacker *dp) + void **user_data, + U32 block_num, EObjectUpdateType update_type, + LLDataPacker *dp) { - - LLColor4U color; - const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA); + + LLColor4U color; + const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA); - // Do base class updates... - U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); + // Do base class updates... + U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); - LLUUID sculpt_id; - U8 sculpt_type = 0; - if (isSculpted()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - sculpt_id = sculpt_params->getSculptTexture(); - sculpt_type = sculpt_params->getSculptType(); + LLUUID sculpt_id; + U8 sculpt_type = 0; + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + sculpt_id = sculpt_params->getSculptTexture(); + sculpt_type = sculpt_params->getSculptType(); LL_DEBUGS("ObjectUpdate") << "uuid " << mID << " set sculpt_id " << sculpt_id << LL_ENDL; dumpStack("ObjectUpdateStack"); - } - - if (!dp) - { - if (update_type == OUT_FULL) - { - //////////////////////////////// - // - // Unpack texture animation data - // - // - - if (mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureAnim)) - { - if (!mTextureAnimp) - { - mTextureAnimp = new LLViewerTextureAnim(this); - } - else - { - if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) - { - mTextureAnimp->reset(); - } - } - mTexAnimMode = 0; - - mTextureAnimp->unpackTAMessage(mesgsys, block_num); - } - else - { - if (mTextureAnimp) - { - delete mTextureAnimp; - mTextureAnimp = NULL; - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - mTexAnimMode = 0; - } - } - - // Unpack volume data - LLVolumeParams volume_params; - LLVolumeMessage::unpackVolumeParams(&volume_params, mesgsys, _PREHASH_ObjectData, block_num); - volume_params.setSculptID(sculpt_id, sculpt_type); - - if (setVolume(volume_params, 0)) - { - markForUpdate(TRUE); - } - } - - // Sigh, this needs to be done AFTER the volume is set as well, otherwise bad stuff happens... - //////////////////////////// - // - // Unpack texture entry data - // - - S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, (S32) block_num); - if (result & teDirtyBits) - { - updateTEData(); - } - if (result & TEM_CHANGE_MEDIA) - { - retval |= MEDIA_FLAGS_CHANGED; - } - } - else - { - if (update_type != OUT_TERSE_IMPROVED) - { - LLVolumeParams volume_params; - BOOL res = LLVolumeMessage::unpackVolumeParams(&volume_params, *dp); - if (!res) - { - LL_WARNS() << "Bogus volume parameters in object " << getID() << LL_ENDL; - LL_WARNS() << getRegion()->getOriginGlobal() << LL_ENDL; - } - - volume_params.setSculptID(sculpt_id, sculpt_type); - - if (setVolume(volume_params, 0)) - { - markForUpdate(TRUE); - } - S32 res2 = unpackTEMessage(*dp); - if (TEM_INVALID == res2) - { - // There's something bogus in the data that we're unpacking. - dp->dumpBufferToLog(); - LL_WARNS() << "Flushing cache files" << LL_ENDL; - - if(LLVOCache::instanceExists() && getRegion()) - { - LLVOCache::getInstance()->removeEntry(getRegion()->getHandle()) ; - } - - LL_WARNS() << "Bogus TE data in " << getID() << LL_ENDL; - } - else - { - if (res2 & teDirtyBits) - { - updateTEData(); - } - if (res2 & TEM_CHANGE_MEDIA) - { - retval |= MEDIA_FLAGS_CHANGED; - } - } - - U32 value = dp->getPassFlags(); - - if (value & 0x40) - { - if (!mTextureAnimp) - { - mTextureAnimp = new LLViewerTextureAnim(this); - } - else - { - if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) - { - mTextureAnimp->reset(); - } - } - mTexAnimMode = 0; - mTextureAnimp->unpackTAMessage(*dp); - } - else if (mTextureAnimp) - { - delete mTextureAnimp; - mTextureAnimp = NULL; - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - mTexAnimMode = 0; - } - - if (value & 0x400) - { //particle system (new) - unpackParticleSource(*dp, mOwnerID, false); - } - } - else - { - S32 texture_length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureEntry); - if (texture_length) - { - U8 tdpbuffer[1024]; - LLDataPackerBinaryBuffer tdp(tdpbuffer, 1024); - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num, 1024); - S32 result = unpackTEMessage(tdp); - if (result & teDirtyBits) - { - updateTEData(); - } - if (result & TEM_CHANGE_MEDIA) - { - retval |= MEDIA_FLAGS_CHANGED; - } - } - } - } - if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) - { - // If only the media URL changed, and it isn't a media version URL, - // ignore it - if ( ! ( retval & (MEDIA_URL_ADDED | MEDIA_URL_UPDATED) && - mMedia && ! mMedia->mMediaURL.empty() && - ! LLTextureEntry::isMediaVersionString(mMedia->mMediaURL) ) ) - { - // If the media changed at all, request new media data - LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " << + } + + if (!dp) + { + if (update_type == OUT_FULL) + { + //////////////////////////////// + // + // Unpack texture animation data + // + // + + if (mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureAnim)) + { + if (!mTextureAnimp) + { + mTextureAnimp = new LLViewerTextureAnim(this); + } + else + { + if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) + { + mTextureAnimp->reset(); + } + } + mTexAnimMode = 0; + + mTextureAnimp->unpackTAMessage(mesgsys, block_num); + } + else + { + if (mTextureAnimp) + { + delete mTextureAnimp; + mTextureAnimp = NULL; + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; + } + } + + // Unpack volume data + LLVolumeParams volume_params; + LLVolumeMessage::unpackVolumeParams(&volume_params, mesgsys, _PREHASH_ObjectData, block_num); + volume_params.setSculptID(sculpt_id, sculpt_type); + + if (setVolume(volume_params, 0)) + { + markForUpdate(TRUE); + } + } + + // Sigh, this needs to be done AFTER the volume is set as well, otherwise bad stuff happens... + //////////////////////////// + // + // Unpack texture entry data + // + + S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, (S32) block_num); + if (result & teDirtyBits) + { + updateTEData(); + } + if (result & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } + } + else + { + if (update_type != OUT_TERSE_IMPROVED) + { + LLVolumeParams volume_params; + BOOL res = LLVolumeMessage::unpackVolumeParams(&volume_params, *dp); + if (!res) + { + LL_WARNS() << "Bogus volume parameters in object " << getID() << LL_ENDL; + LL_WARNS() << getRegion()->getOriginGlobal() << LL_ENDL; + } + + volume_params.setSculptID(sculpt_id, sculpt_type); + + if (setVolume(volume_params, 0)) + { + markForUpdate(TRUE); + } + S32 res2 = unpackTEMessage(*dp); + if (TEM_INVALID == res2) + { + // There's something bogus in the data that we're unpacking. + dp->dumpBufferToLog(); + LL_WARNS() << "Flushing cache files" << LL_ENDL; + + if(LLVOCache::instanceExists() && getRegion()) + { + LLVOCache::getInstance()->removeEntry(getRegion()->getHandle()) ; + } + + LL_WARNS() << "Bogus TE data in " << getID() << LL_ENDL; + } + else + { + if (res2 & teDirtyBits) + { + updateTEData(); + } + if (res2 & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } + } + + U32 value = dp->getPassFlags(); + + if (value & 0x40) + { + if (!mTextureAnimp) + { + mTextureAnimp = new LLViewerTextureAnim(this); + } + else + { + if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) + { + mTextureAnimp->reset(); + } + } + mTexAnimMode = 0; + mTextureAnimp->unpackTAMessage(*dp); + } + else if (mTextureAnimp) + { + delete mTextureAnimp; + mTextureAnimp = NULL; + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; + } + + if (value & 0x400) + { //particle system (new) + unpackParticleSource(*dp, mOwnerID, false); + } + } + else + { + S32 texture_length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureEntry); + if (texture_length) + { + U8 tdpbuffer[1024]; + LLDataPackerBinaryBuffer tdp(tdpbuffer, 1024); + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num, 1024); + S32 result = unpackTEMessage(tdp); + if (result & teDirtyBits) + { + updateTEData(); + } + if (result & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } + } + } + } + if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) + { + // If only the media URL changed, and it isn't a media version URL, + // ignore it + if ( ! ( retval & (MEDIA_URL_ADDED | MEDIA_URL_UPDATED) && + mMedia && ! mMedia->mMediaURL.empty() && + ! LLTextureEntry::isMediaVersionString(mMedia->mMediaURL) ) ) + { + // If the media changed at all, request new media data + LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " << ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL; requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED); } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index b63f5bd05a..6e7e8eef21 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -9993,14 +9993,14 @@ bool LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade) { BOOL shaders = canUseVertexShaders(); - if(shaders) - { - gHighlightProgram.bind(); - } - else - { - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); - } + if(shaders) + { + gHighlightProgram.bind(); + } + else + { + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + } if (obj && obj->getVolume()) { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 38fb26d811..a31f880fbf 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -53,8 +53,8 @@ class LLDrawPoolAlpha; typedef enum e_avatar_skinning_method { - SKIN_METHOD_SOFTWARE, - SKIN_METHOD_VERTEX_PROGRAM + SKIN_METHOD_SOFTWARE, + SKIN_METHOD_VERTEX_PROGRAM } EAvatarSkinningMethod; bool compute_min_max(LLMatrix4& box, LLVector2& min, LLVector2& max); // Shouldn't be defined here! @@ -93,861 +93,861 @@ extern LLTrace::BlockTimerStatHandle FTM_RENDER_UI_SCENE_MON; class LLPipeline { public: - LLPipeline(); - ~LLPipeline(); - - void destroyGL(); - void restoreGL(); - void resetVertexBuffers(); - void doResetVertexBuffers(bool forced = false); - void resizeScreenTexture(); - void releaseGLBuffers(); - void releaseLUTBuffers(); - void releaseScreenBuffers(); - void createGLBuffers(); - void createLUTBuffers(); - - //allocate the largest screen buffer possible up to resX, resY - //returns true if full size buffer allocated, false if some other size is allocated - bool allocateScreenBuffer(U32 resX, U32 resY); - - typedef enum { - FBO_SUCCESS_FULLRES = 0, - FBO_SUCCESS_LOWRES, - FBO_FAILURE - } eFBOStatus; + LLPipeline(); + ~LLPipeline(); + + void destroyGL(); + void restoreGL(); + void resetVertexBuffers(); + void doResetVertexBuffers(bool forced = false); + void resizeScreenTexture(); + void releaseGLBuffers(); + void releaseLUTBuffers(); + void releaseScreenBuffers(); + void createGLBuffers(); + void createLUTBuffers(); + + //allocate the largest screen buffer possible up to resX, resY + //returns true if full size buffer allocated, false if some other size is allocated + bool allocateScreenBuffer(U32 resX, U32 resY); + + typedef enum { + FBO_SUCCESS_FULLRES = 0, + FBO_SUCCESS_LOWRES, + FBO_FAILURE + } eFBOStatus; private: - //implementation of above, wrapped for easy error handling - eFBOStatus doAllocateScreenBuffer(U32 resX, U32 resY); + //implementation of above, wrapped for easy error handling + eFBOStatus doAllocateScreenBuffer(U32 resX, U32 resY); public: - //attempt to allocate screen buffers at resX, resY - //returns true if allocation successful, false otherwise - bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples); - - void allocatePhysicsBuffer(); - - void resetVertexBuffers(LLDrawable* drawable); - void generateImpostor(LLVOAvatar* avatar); - void bindScreenToTexture(); - void renderBloom(bool for_snapshot, F32 zoom_factor = 1.f, int subfield = 0); - - void init(); - void cleanup(); - bool isInit() { return mInitialized; }; - - /// @brief Get a draw pool from pool type (POOL_SIMPLE, POOL_MEDIA) and texture. - /// @return Draw pool, or NULL if not found. - LLDrawPool *findPool(const U32 pool_type, LLViewerTexture *tex0 = NULL); - - /// @brief Get a draw pool for faces of the appropriate type and texture. Create if necessary. - /// @return Always returns a draw pool. - LLDrawPool *getPool(const U32 pool_type, LLViewerTexture *tex0 = NULL); - - /// @brief Figures out draw pool type from texture entry. Creates pool if necessary. - static LLDrawPool* getPoolFromTE(const LLTextureEntry* te, LLViewerTexture* te_image); - static U32 getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* imagep); - - void addPool(LLDrawPool *poolp); // Only to be used by LLDrawPool classes for splitting pools! - void removePool( LLDrawPool* poolp ); - - void allocDrawable(LLViewerObject *obj); - - void unlinkDrawable(LLDrawable*); - - static void removeMutedAVsLights(LLVOAvatar*); - - // Object related methods - void markVisible(LLDrawable *drawablep, LLCamera& camera); - void markOccluder(LLSpatialGroup* group); - - //downsample source to dest, taking the maximum depth value per pixel in source and writing to dest - // if source's depth buffer cannot be bound for reading, a scratch space depth buffer must be provided - void downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL); - - // Downsample depth buffer with gather and find local min/max depth values. Writes to a 16F RG render target. - void downsampleMinMaxDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL); - - void doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL); - void doOcclusion(LLCamera& camera); - void markNotCulled(LLSpatialGroup* group, LLCamera &camera); - void markMoved(LLDrawable *drawablep, bool damped_motion = false); - void markShift(LLDrawable *drawablep); - void markTextured(LLDrawable *drawablep); - void markGLRebuild(LLGLUpdate* glu); - void markRebuild(LLSpatialGroup* group, bool priority = false); - void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, bool priority = false); - void markPartitionMove(LLDrawable* drawablep); - void markMeshDirty(LLSpatialGroup* group); - - //get the object between start and end that's closest to start. - LLViewerObject* lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end, - bool pick_transparent, - bool pick_rigged, - S32* face_hit, // return the face hit - LLVector4a* intersection = NULL, // return the intersection point - LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point - LLVector4a* normal = NULL, // return the surface normal at the intersection point - LLVector4a* tangent = NULL // return the surface tangent at the intersection point - ); - - //get the closest particle to start between start and end, returns the LLVOPartGroup and particle index - LLVOPartGroup* lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection, - S32* face_hit); - - - LLViewerObject* lineSegmentIntersectInHUD(const LLVector4a& start, const LLVector4a& end, - bool pick_transparent, - S32* face_hit, // return the face hit - LLVector4a* intersection = NULL, // return the intersection point - LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point - LLVector4a* normal = NULL, // return the surface normal at the intersection point - LLVector4a* tangent = NULL // return the surface tangent at the intersection point - ); - - // Something about these textures has changed. Dirty them. - void dirtyPoolObjectTextures(const std::set& textures); - - void resetDrawOrders(); - - U32 addObject(LLViewerObject *obj); - - void enableShadows(const bool enable_shadows); + //attempt to allocate screen buffers at resX, resY + //returns true if allocation successful, false otherwise + bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples); + + void allocatePhysicsBuffer(); + + void resetVertexBuffers(LLDrawable* drawable); + void generateImpostor(LLVOAvatar* avatar); + void bindScreenToTexture(); + void renderBloom(bool for_snapshot, F32 zoom_factor = 1.f, int subfield = 0); + + void init(); + void cleanup(); + bool isInit() { return mInitialized; }; + + /// @brief Get a draw pool from pool type (POOL_SIMPLE, POOL_MEDIA) and texture. + /// @return Draw pool, or NULL if not found. + LLDrawPool *findPool(const U32 pool_type, LLViewerTexture *tex0 = NULL); + + /// @brief Get a draw pool for faces of the appropriate type and texture. Create if necessary. + /// @return Always returns a draw pool. + LLDrawPool *getPool(const U32 pool_type, LLViewerTexture *tex0 = NULL); + + /// @brief Figures out draw pool type from texture entry. Creates pool if necessary. + static LLDrawPool* getPoolFromTE(const LLTextureEntry* te, LLViewerTexture* te_image); + static U32 getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* imagep); + + void addPool(LLDrawPool *poolp); // Only to be used by LLDrawPool classes for splitting pools! + void removePool( LLDrawPool* poolp ); + + void allocDrawable(LLViewerObject *obj); + + void unlinkDrawable(LLDrawable*); + + static void removeMutedAVsLights(LLVOAvatar*); + + // Object related methods + void markVisible(LLDrawable *drawablep, LLCamera& camera); + void markOccluder(LLSpatialGroup* group); + + //downsample source to dest, taking the maximum depth value per pixel in source and writing to dest + // if source's depth buffer cannot be bound for reading, a scratch space depth buffer must be provided + void downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL); + + // Downsample depth buffer with gather and find local min/max depth values. Writes to a 16F RG render target. + void downsampleMinMaxDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL); + + void doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL); + void doOcclusion(LLCamera& camera); + void markNotCulled(LLSpatialGroup* group, LLCamera &camera); + void markMoved(LLDrawable *drawablep, bool damped_motion = false); + void markShift(LLDrawable *drawablep); + void markTextured(LLDrawable *drawablep); + void markGLRebuild(LLGLUpdate* glu); + void markRebuild(LLSpatialGroup* group, bool priority = false); + void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, bool priority = false); + void markPartitionMove(LLDrawable* drawablep); + void markMeshDirty(LLSpatialGroup* group); + + //get the object between start and end that's closest to start. + LLViewerObject* lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end, + bool pick_transparent, + bool pick_rigged, + S32* face_hit, // return the face hit + LLVector4a* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector4a* normal = NULL, // return the surface normal at the intersection point + LLVector4a* tangent = NULL // return the surface tangent at the intersection point + ); + + //get the closest particle to start between start and end, returns the LLVOPartGroup and particle index + LLVOPartGroup* lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection, + S32* face_hit); + + + LLViewerObject* lineSegmentIntersectInHUD(const LLVector4a& start, const LLVector4a& end, + bool pick_transparent, + S32* face_hit, // return the face hit + LLVector4a* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector4a* normal = NULL, // return the surface normal at the intersection point + LLVector4a* tangent = NULL // return the surface tangent at the intersection point + ); + + // Something about these textures has changed. Dirty them. + void dirtyPoolObjectTextures(const std::set& textures); + + void resetDrawOrders(); + + U32 addObject(LLViewerObject *obj); + + void enableShadows(const bool enable_shadows); void releaseShadowTargets(); void releaseShadowTarget(U32 index); -// void setLocalLighting(const bool local_lighting); -// bool isLocalLightingEnabled() const; - S32 setLightingDetail(S32 level); - S32 getLightingDetail() const { return mLightingDetail; } - S32 getMaxLightingDetail() const; - - void setUseVertexShaders(bool use_shaders); - bool getUseVertexShaders() const { return mVertexShadersEnabled; } - bool canUseVertexShaders(); - bool canUseWindLightShaders() const; - bool canUseWindLightShadersOnObjects() const; - bool canUseAntiAliasing() const; - - // phases - void resetFrameStats(); - - void updateMoveDampedAsync(LLDrawable* drawablep); - void updateMoveNormalAsync(LLDrawable* drawablep); - void updateMovedList(LLDrawable::drawable_vector_t& move_list); - void updateMove(); - bool visibleObjectsInFrustum(LLCamera& camera); - bool getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max); - bool getVisiblePointCloud(LLCamera& camera, LLVector3 &min, LLVector3& max, std::vector& fp, LLVector3 light_dir = LLVector3(0,0,0)); - void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0, LLPlane* plane = NULL); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane - void createObjects(F32 max_dtime); - void createObject(LLViewerObject* vobj); - void processPartitionQ(); - void updateGeom(F32 max_dtime); - void updateGL(); - void rebuildPriorityGroups(); - void rebuildGroups(); - void clearRebuildGroups(); - void clearRebuildDrawables(); - - //calculate pixel area of given box from vantage point of given camera - static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera); - static F32 calcPixelArea(const LLVector4a& center, const LLVector4a& size, LLCamera &camera); - - void stateSort(LLCamera& camera, LLCullResult& result); - void stateSort(LLSpatialGroup* group, LLCamera& camera); - void stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed = FALSE); - void stateSort(LLDrawable* drawablep, LLCamera& camera); - void postSort(LLCamera& camera); - void forAllVisibleDrawables(void (*func)(LLDrawable*)); - - void renderObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false); - void renderMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false); - - void renderGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture); - - void grabReferences(LLCullResult& result); - void clearReferences(); - - //check references will assert that there are no references in sCullResult to the provided data - void checkReferences(LLFace* face); - void checkReferences(LLDrawable* drawable); - void checkReferences(LLDrawInfo* draw_info); - void checkReferences(LLSpatialGroup* group); - - - void renderGeom(LLCamera& camera, bool forceVBOUpdate = false); - void renderGeomDeferred(LLCamera& camera); - void renderGeomPostDeferred(LLCamera& camera, bool do_occlusion=true); - void renderGeomShadow(LLCamera& camera); - void bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target = nullptr); - void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep); - - void unbindDeferredShader(LLGLSLShader& shader); - void renderDeferredLighting(LLRenderTarget* light_target); - void postDeferredGammaCorrect(LLRenderTarget* screen_target); - - void generateWaterReflection(LLCamera& camera); - void generateSunShadow(LLCamera& camera); +// void setLocalLighting(const bool local_lighting); +// bool isLocalLightingEnabled() const; + S32 setLightingDetail(S32 level); + S32 getLightingDetail() const { return mLightingDetail; } + S32 getMaxLightingDetail() const; + + void setUseVertexShaders(bool use_shaders); + bool getUseVertexShaders() const { return mVertexShadersEnabled; } + bool canUseVertexShaders(); + bool canUseWindLightShaders() const; + bool canUseWindLightShadersOnObjects() const; + bool canUseAntiAliasing() const; + + // phases + void resetFrameStats(); + + void updateMoveDampedAsync(LLDrawable* drawablep); + void updateMoveNormalAsync(LLDrawable* drawablep); + void updateMovedList(LLDrawable::drawable_vector_t& move_list); + void updateMove(); + bool visibleObjectsInFrustum(LLCamera& camera); + bool getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max); + bool getVisiblePointCloud(LLCamera& camera, LLVector3 &min, LLVector3& max, std::vector& fp, LLVector3 light_dir = LLVector3(0,0,0)); + void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0, LLPlane* plane = NULL); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane + void createObjects(F32 max_dtime); + void createObject(LLViewerObject* vobj); + void processPartitionQ(); + void updateGeom(F32 max_dtime); + void updateGL(); + void rebuildPriorityGroups(); + void rebuildGroups(); + void clearRebuildGroups(); + void clearRebuildDrawables(); + + //calculate pixel area of given box from vantage point of given camera + static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera); + static F32 calcPixelArea(const LLVector4a& center, const LLVector4a& size, LLCamera &camera); + + void stateSort(LLCamera& camera, LLCullResult& result); + void stateSort(LLSpatialGroup* group, LLCamera& camera); + void stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed = FALSE); + void stateSort(LLDrawable* drawablep, LLCamera& camera); + void postSort(LLCamera& camera); + void forAllVisibleDrawables(void (*func)(LLDrawable*)); + + void renderObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false); + void renderMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false); + + void renderGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture); + + void grabReferences(LLCullResult& result); + void clearReferences(); + + //check references will assert that there are no references in sCullResult to the provided data + void checkReferences(LLFace* face); + void checkReferences(LLDrawable* drawable); + void checkReferences(LLDrawInfo* draw_info); + void checkReferences(LLSpatialGroup* group); + + + void renderGeom(LLCamera& camera, bool forceVBOUpdate = false); + void renderGeomDeferred(LLCamera& camera); + void renderGeomPostDeferred(LLCamera& camera, bool do_occlusion=true); + void renderGeomShadow(LLCamera& camera); + void bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target = nullptr); + void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep); + + void unbindDeferredShader(LLGLSLShader& shader); + void renderDeferredLighting(LLRenderTarget* light_target); + void postDeferredGammaCorrect(LLRenderTarget* screen_target); + + void generateWaterReflection(LLCamera& camera); + void generateSunShadow(LLCamera& camera); LLRenderTarget* getShadowTarget(U32 i); - void generateHighlight(LLCamera& camera); - void renderHighlight(const LLViewerObject* obj, F32 fade); - void setHighlightObject(LLDrawable* obj) { mHighlightObject = obj; } - - - void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, bool use_shader, bool use_occlusion, U32 target_width); - void renderHighlights(); - void renderDebug(); - void renderPhysicsDisplay(); - - void rebuildPools(); // Rebuild pools - - void findReferences(LLDrawable *drawablep); // Find the lists which have references to this object - bool verify(); // Verify that all data in the pipeline is "correct" - - S32 getLightCount() const { return mLights.size(); } - - void calcNearbyLights(LLCamera& camera); - void setupHWLights(LLDrawPool* pool); - void setupAvatarLights(bool for_edit = false); - void enableLights(U32 mask); - void enableLightsStatic(); - void enableLightsDynamic(); - void enableLightsAvatar(); - void enableLightsPreview(); - void enableLightsAvatarEdit(const LLColor4& color); - void enableLightsFullbright(const LLColor4& color); - void disableLights(); - - void shiftObjects(const LLVector3 &offset); - - void setLight(LLDrawable *drawablep, bool is_light); - - bool hasRenderBatches(const U32 type) const; - LLCullResult::drawinfo_iterator beginRenderMap(U32 type); - LLCullResult::drawinfo_iterator endRenderMap(U32 type); - LLCullResult::sg_iterator beginAlphaGroups(); - LLCullResult::sg_iterator endAlphaGroups(); - - - void addTrianglesDrawn(S32 index_count, U32 render_type = LLRender::TRIANGLES); - - bool hasRenderDebugFeatureMask(const U32 mask) const { return bool(mRenderDebugFeatureMask & mask); } - bool hasRenderDebugMask(const U64 mask) const { return bool(mRenderDebugMask & mask); } - void setAllRenderDebugFeatures() { mRenderDebugFeatureMask = 0xffffffff; } - void clearAllRenderDebugFeatures() { mRenderDebugFeatureMask = 0x0; } - void setAllRenderDebugDisplays() { mRenderDebugMask = 0xffffffffffffffff; } - void clearAllRenderDebugDisplays() { mRenderDebugMask = 0x0; } - - bool hasRenderType(const U32 type) const; - bool hasAnyRenderType(const U32 type, ...) const; - - void setRenderTypeMask(U32 type, ...); - // This is equivalent to 'setRenderTypeMask' - //void orRenderTypeMask(U32 type, ...); - void andRenderTypeMask(U32 type, ...); - void clearRenderTypeMask(U32 type, ...); - void setAllRenderTypes(); - void clearAllRenderTypes(); - - void pushRenderTypeMask(); - void popRenderTypeMask(); - - void pushRenderDebugFeatureMask(); - void popRenderDebugFeatureMask(); - - static void toggleRenderType(U32 type); - - // For UI control of render features - static bool hasRenderTypeControl(U32 data); - static void toggleRenderDebug(U64 data); - static void toggleRenderDebugFeature(U32 data); - static void toggleRenderTypeControl(U32 data); - static bool toggleRenderTypeControlNegated(S32 data); - static bool toggleRenderDebugControl(U64 data); - static bool toggleRenderDebugFeatureControl(U32 data); - static void setRenderDebugFeatureControl(U32 bit, bool value); - - static void setRenderParticleBeacons(bool val); - static void toggleRenderParticleBeacons(); - static bool getRenderParticleBeacons(); - - static void setRenderSoundBeacons(bool val); - static void toggleRenderSoundBeacons(); - static bool getRenderSoundBeacons(); - - static void setRenderMOAPBeacons(bool val); - static void toggleRenderMOAPBeacons(); - static bool getRenderMOAPBeacons(); - - static void setRenderPhysicalBeacons(bool val); - static void toggleRenderPhysicalBeacons(); - static bool getRenderPhysicalBeacons(); - - static void setRenderScriptedBeacons(bool val); - static void toggleRenderScriptedBeacons(); - static bool getRenderScriptedBeacons(); - - static void setRenderScriptedTouchBeacons(bool val); - static void toggleRenderScriptedTouchBeacons(); - static bool getRenderScriptedTouchBeacons(); - - static void setRenderBeacons(bool val); - static void toggleRenderBeacons(); - static bool getRenderBeacons(); - - static void setRenderHighlights(bool val); - static void toggleRenderHighlights(); - static bool getRenderHighlights(); - static void setRenderHighlightTextureChannel(LLRender::eTexIndex channel); // sets which UV setup to display in highlight overlay - - static void updateRenderBump(); - static void updateRenderDeferred(); - static void refreshCachedSettings(); - - static void throttleNewMemoryAllocation(bool disable); - - - - void addDebugBlip(const LLVector3& position, const LLColor4& color); - - void hidePermanentObjects( std::vector& restoreList ); - void restorePermanentObjects( const std::vector& restoreList ); - void skipRenderingOfTerrain( bool flag ); - void hideObject( const LLUUID& id ); - void restoreHiddenObject( const LLUUID& id ); + void generateHighlight(LLCamera& camera); + void renderHighlight(const LLViewerObject* obj, F32 fade); + void setHighlightObject(LLDrawable* obj) { mHighlightObject = obj; } + + + void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, bool use_shader, bool use_occlusion, U32 target_width); + void renderHighlights(); + void renderDebug(); + void renderPhysicsDisplay(); + + void rebuildPools(); // Rebuild pools + + void findReferences(LLDrawable *drawablep); // Find the lists which have references to this object + bool verify(); // Verify that all data in the pipeline is "correct" + + S32 getLightCount() const { return mLights.size(); } + + void calcNearbyLights(LLCamera& camera); + void setupHWLights(LLDrawPool* pool); + void setupAvatarLights(bool for_edit = false); + void enableLights(U32 mask); + void enableLightsStatic(); + void enableLightsDynamic(); + void enableLightsAvatar(); + void enableLightsPreview(); + void enableLightsAvatarEdit(const LLColor4& color); + void enableLightsFullbright(const LLColor4& color); + void disableLights(); + + void shiftObjects(const LLVector3 &offset); + + void setLight(LLDrawable *drawablep, bool is_light); + + bool hasRenderBatches(const U32 type) const; + LLCullResult::drawinfo_iterator beginRenderMap(U32 type); + LLCullResult::drawinfo_iterator endRenderMap(U32 type); + LLCullResult::sg_iterator beginAlphaGroups(); + LLCullResult::sg_iterator endAlphaGroups(); + + + void addTrianglesDrawn(S32 index_count, U32 render_type = LLRender::TRIANGLES); + + bool hasRenderDebugFeatureMask(const U32 mask) const { return bool(mRenderDebugFeatureMask & mask); } + bool hasRenderDebugMask(const U64 mask) const { return bool(mRenderDebugMask & mask); } + void setAllRenderDebugFeatures() { mRenderDebugFeatureMask = 0xffffffff; } + void clearAllRenderDebugFeatures() { mRenderDebugFeatureMask = 0x0; } + void setAllRenderDebugDisplays() { mRenderDebugMask = 0xffffffffffffffff; } + void clearAllRenderDebugDisplays() { mRenderDebugMask = 0x0; } + + bool hasRenderType(const U32 type) const; + bool hasAnyRenderType(const U32 type, ...) const; + + void setRenderTypeMask(U32 type, ...); + // This is equivalent to 'setRenderTypeMask' + //void orRenderTypeMask(U32 type, ...); + void andRenderTypeMask(U32 type, ...); + void clearRenderTypeMask(U32 type, ...); + void setAllRenderTypes(); + void clearAllRenderTypes(); + + void pushRenderTypeMask(); + void popRenderTypeMask(); + + void pushRenderDebugFeatureMask(); + void popRenderDebugFeatureMask(); + + static void toggleRenderType(U32 type); + + // For UI control of render features + static bool hasRenderTypeControl(U32 data); + static void toggleRenderDebug(U64 data); + static void toggleRenderDebugFeature(U32 data); + static void toggleRenderTypeControl(U32 data); + static bool toggleRenderTypeControlNegated(S32 data); + static bool toggleRenderDebugControl(U64 data); + static bool toggleRenderDebugFeatureControl(U32 data); + static void setRenderDebugFeatureControl(U32 bit, bool value); + + static void setRenderParticleBeacons(bool val); + static void toggleRenderParticleBeacons(); + static bool getRenderParticleBeacons(); + + static void setRenderSoundBeacons(bool val); + static void toggleRenderSoundBeacons(); + static bool getRenderSoundBeacons(); + + static void setRenderMOAPBeacons(bool val); + static void toggleRenderMOAPBeacons(); + static bool getRenderMOAPBeacons(); + + static void setRenderPhysicalBeacons(bool val); + static void toggleRenderPhysicalBeacons(); + static bool getRenderPhysicalBeacons(); + + static void setRenderScriptedBeacons(bool val); + static void toggleRenderScriptedBeacons(); + static bool getRenderScriptedBeacons(); + + static void setRenderScriptedTouchBeacons(bool val); + static void toggleRenderScriptedTouchBeacons(); + static bool getRenderScriptedTouchBeacons(); + + static void setRenderBeacons(bool val); + static void toggleRenderBeacons(); + static bool getRenderBeacons(); + + static void setRenderHighlights(bool val); + static void toggleRenderHighlights(); + static bool getRenderHighlights(); + static void setRenderHighlightTextureChannel(LLRender::eTexIndex channel); // sets which UV setup to display in highlight overlay + + static void updateRenderBump(); + static void updateRenderDeferred(); + static void refreshCachedSettings(); + + static void throttleNewMemoryAllocation(bool disable); + + + + void addDebugBlip(const LLVector3& position, const LLColor4& color); + + void hidePermanentObjects( std::vector& restoreList ); + void restorePermanentObjects( const std::vector& restoreList ); + void skipRenderingOfTerrain( bool flag ); + void hideObject( const LLUUID& id ); + void restoreHiddenObject( const LLUUID& id ); private: - void unloadShaders(); - void addToQuickLookup( LLDrawPool* new_poolp ); - void removeFromQuickLookup( LLDrawPool* poolp ); - bool updateDrawableGeom(LLDrawable* drawable, bool priority); - void assertInitializedDoError(); - bool assertInitialized() { const bool is_init = isInit(); if (!is_init) assertInitializedDoError(); return is_init; }; - void connectRefreshCachedSettingsSafe(const std::string name); - void hideDrawable( LLDrawable *pDrawable ); - void unhideDrawable( LLDrawable *pDrawable ); + void unloadShaders(); + void addToQuickLookup( LLDrawPool* new_poolp ); + void removeFromQuickLookup( LLDrawPool* poolp ); + bool updateDrawableGeom(LLDrawable* drawable, bool priority); + void assertInitializedDoError(); + bool assertInitialized() { const bool is_init = isInit(); if (!is_init) assertInitializedDoError(); return is_init; }; + void connectRefreshCachedSettingsSafe(const std::string name); + void hideDrawable( LLDrawable *pDrawable ); + void unhideDrawable( LLDrawable *pDrawable ); public: - enum {GPU_CLASS_MAX = 3 }; - - enum LLRenderTypeMask - { - // Following are pool types (some are also object types) - RENDER_TYPE_SKY = LLDrawPool::POOL_SKY, - RENDER_TYPE_WL_SKY = LLDrawPool::POOL_WL_SKY, - RENDER_TYPE_GROUND = LLDrawPool::POOL_GROUND, - RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN, - RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE, - RENDER_TYPE_GRASS = LLDrawPool::POOL_GRASS, - RENDER_TYPE_ALPHA_MASK = LLDrawPool::POOL_ALPHA_MASK, - RENDER_TYPE_FULLBRIGHT_ALPHA_MASK = LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK, - RENDER_TYPE_FULLBRIGHT = LLDrawPool::POOL_FULLBRIGHT, - RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP, - RENDER_TYPE_MATERIALS = LLDrawPool::POOL_MATERIALS, - RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR, - RENDER_TYPE_TREE = LLDrawPool::POOL_TREE, - RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE, - RENDER_TYPE_VOIDWATER = LLDrawPool::POOL_VOIDWATER, - RENDER_TYPE_WATER = LLDrawPool::POOL_WATER, - RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA, - RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW, - RENDER_TYPE_PASS_SIMPLE = LLRenderPass::PASS_SIMPLE, - RENDER_TYPE_PASS_GRASS = LLRenderPass::PASS_GRASS, - RENDER_TYPE_PASS_FULLBRIGHT = LLRenderPass::PASS_FULLBRIGHT, - RENDER_TYPE_PASS_INVISIBLE = LLRenderPass::PASS_INVISIBLE, - RENDER_TYPE_PASS_INVISI_SHINY = LLRenderPass::PASS_INVISI_SHINY, - RENDER_TYPE_PASS_FULLBRIGHT_SHINY = LLRenderPass::PASS_FULLBRIGHT_SHINY, - RENDER_TYPE_PASS_SHINY = LLRenderPass::PASS_SHINY, - RENDER_TYPE_PASS_BUMP = LLRenderPass::PASS_BUMP, - RENDER_TYPE_PASS_POST_BUMP = LLRenderPass::PASS_POST_BUMP, - RENDER_TYPE_PASS_GLOW = LLRenderPass::PASS_GLOW, - RENDER_TYPE_PASS_ALPHA = LLRenderPass::PASS_ALPHA, - RENDER_TYPE_PASS_ALPHA_MASK = LLRenderPass::PASS_ALPHA_MASK, - RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK = LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, - RENDER_TYPE_PASS_MATERIAL = LLRenderPass::PASS_MATERIAL, - RENDER_TYPE_PASS_MATERIAL_ALPHA = LLRenderPass::PASS_MATERIAL_ALPHA, - RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK = LLRenderPass::PASS_MATERIAL_ALPHA_MASK, - RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE= LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, - RENDER_TYPE_PASS_SPECMAP = LLRenderPass::PASS_SPECMAP, - RENDER_TYPE_PASS_SPECMAP_BLEND = LLRenderPass::PASS_SPECMAP_BLEND, - RENDER_TYPE_PASS_SPECMAP_MASK = LLRenderPass::PASS_SPECMAP_MASK, - RENDER_TYPE_PASS_SPECMAP_EMISSIVE = LLRenderPass::PASS_SPECMAP_EMISSIVE, - RENDER_TYPE_PASS_NORMMAP = LLRenderPass::PASS_NORMMAP, - RENDER_TYPE_PASS_NORMMAP_BLEND = LLRenderPass::PASS_NORMMAP_BLEND, - RENDER_TYPE_PASS_NORMMAP_MASK = LLRenderPass::PASS_NORMMAP_MASK, - RENDER_TYPE_PASS_NORMMAP_EMISSIVE = LLRenderPass::PASS_NORMMAP_EMISSIVE, - RENDER_TYPE_PASS_NORMSPEC = LLRenderPass::PASS_NORMSPEC, - RENDER_TYPE_PASS_NORMSPEC_BLEND = LLRenderPass::PASS_NORMSPEC_BLEND, - RENDER_TYPE_PASS_NORMSPEC_MASK = LLRenderPass::PASS_NORMSPEC_MASK, - RENDER_TYPE_PASS_NORMSPEC_EMISSIVE = LLRenderPass::PASS_NORMSPEC_EMISSIVE, - // Following are object types (only used in drawable mRenderType) - RENDER_TYPE_HUD = LLRenderPass::NUM_RENDER_TYPES, - RENDER_TYPE_VOLUME, - RENDER_TYPE_PARTICLES, - RENDER_TYPE_CLOUDS, - RENDER_TYPE_HUD_PARTICLES, - NUM_RENDER_TYPES, - END_RENDER_TYPES = NUM_RENDER_TYPES - }; - - enum LLRenderDebugFeatureMask - { - RENDER_DEBUG_FEATURE_UI = 0x0001, - RENDER_DEBUG_FEATURE_SELECTED = 0x0002, - RENDER_DEBUG_FEATURE_HIGHLIGHTED = 0x0004, - RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES = 0x0008, -// RENDER_DEBUG_FEATURE_HW_LIGHTING = 0x0010, - RENDER_DEBUG_FEATURE_FLEXIBLE = 0x0010, - RENDER_DEBUG_FEATURE_FOG = 0x0020, - RENDER_DEBUG_FEATURE_FR_INFO = 0x0080, - RENDER_DEBUG_FEATURE_FOOT_SHADOWS = 0x0100, - }; - - enum LLRenderDebugMask: U64 - { - RENDER_DEBUG_COMPOSITION = 0x00000001, - RENDER_DEBUG_VERIFY = 0x00000002, - RENDER_DEBUG_BBOXES = 0x00000004, - RENDER_DEBUG_OCTREE = 0x00000008, - RENDER_DEBUG_WIND_VECTORS = 0x00000010, - RENDER_DEBUG_OCCLUSION = 0x00000020, - RENDER_DEBUG_POINTS = 0x00000040, - RENDER_DEBUG_TEXTURE_PRIORITY = 0x00000080, - RENDER_DEBUG_TEXTURE_AREA = 0x00000100, - RENDER_DEBUG_FACE_AREA = 0x00000200, - RENDER_DEBUG_PARTICLES = 0x00000400, - RENDER_DEBUG_GLOW = 0x00000800, // not used - RENDER_DEBUG_TEXTURE_ANIM = 0x00001000, - RENDER_DEBUG_LIGHTS = 0x00002000, - RENDER_DEBUG_BATCH_SIZE = 0x00004000, - RENDER_DEBUG_ALPHA_BINS = 0x00008000, // not used - RENDER_DEBUG_RAYCAST = 0x00010000, - RENDER_DEBUG_AVATAR_DRAW_INFO = 0x00020000, - RENDER_DEBUG_SHADOW_FRUSTA = 0x00040000, - RENDER_DEBUG_SCULPTED = 0x00080000, - RENDER_DEBUG_AVATAR_VOLUME = 0x00100000, - RENDER_DEBUG_AVATAR_JOINTS = 0x00200000, - RENDER_DEBUG_BUILD_QUEUE = 0x00400000, - RENDER_DEBUG_AGENT_TARGET = 0x00800000, - RENDER_DEBUG_UPDATE_TYPE = 0x01000000, - RENDER_DEBUG_PHYSICS_SHAPES = 0x02000000, - RENDER_DEBUG_NORMALS = 0x04000000, - RENDER_DEBUG_LOD_INFO = 0x08000000, - RENDER_DEBUG_RENDER_COMPLEXITY = 0x10000000, - RENDER_DEBUG_ATTACHMENT_BYTES = 0x20000000, // not used - RENDER_DEBUG_TEXEL_DENSITY = 0x40000000, - RENDER_DEBUG_TRIANGLE_COUNT = 0x80000000, - RENDER_DEBUG_IMPOSTORS = 0x100000000, + enum {GPU_CLASS_MAX = 3 }; + + enum LLRenderTypeMask + { + // Following are pool types (some are also object types) + RENDER_TYPE_SKY = LLDrawPool::POOL_SKY, + RENDER_TYPE_WL_SKY = LLDrawPool::POOL_WL_SKY, + RENDER_TYPE_GROUND = LLDrawPool::POOL_GROUND, + RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN, + RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE, + RENDER_TYPE_GRASS = LLDrawPool::POOL_GRASS, + RENDER_TYPE_ALPHA_MASK = LLDrawPool::POOL_ALPHA_MASK, + RENDER_TYPE_FULLBRIGHT_ALPHA_MASK = LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK, + RENDER_TYPE_FULLBRIGHT = LLDrawPool::POOL_FULLBRIGHT, + RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP, + RENDER_TYPE_MATERIALS = LLDrawPool::POOL_MATERIALS, + RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR, + RENDER_TYPE_TREE = LLDrawPool::POOL_TREE, + RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE, + RENDER_TYPE_VOIDWATER = LLDrawPool::POOL_VOIDWATER, + RENDER_TYPE_WATER = LLDrawPool::POOL_WATER, + RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA, + RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW, + RENDER_TYPE_PASS_SIMPLE = LLRenderPass::PASS_SIMPLE, + RENDER_TYPE_PASS_GRASS = LLRenderPass::PASS_GRASS, + RENDER_TYPE_PASS_FULLBRIGHT = LLRenderPass::PASS_FULLBRIGHT, + RENDER_TYPE_PASS_INVISIBLE = LLRenderPass::PASS_INVISIBLE, + RENDER_TYPE_PASS_INVISI_SHINY = LLRenderPass::PASS_INVISI_SHINY, + RENDER_TYPE_PASS_FULLBRIGHT_SHINY = LLRenderPass::PASS_FULLBRIGHT_SHINY, + RENDER_TYPE_PASS_SHINY = LLRenderPass::PASS_SHINY, + RENDER_TYPE_PASS_BUMP = LLRenderPass::PASS_BUMP, + RENDER_TYPE_PASS_POST_BUMP = LLRenderPass::PASS_POST_BUMP, + RENDER_TYPE_PASS_GLOW = LLRenderPass::PASS_GLOW, + RENDER_TYPE_PASS_ALPHA = LLRenderPass::PASS_ALPHA, + RENDER_TYPE_PASS_ALPHA_MASK = LLRenderPass::PASS_ALPHA_MASK, + RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK = LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, + RENDER_TYPE_PASS_MATERIAL = LLRenderPass::PASS_MATERIAL, + RENDER_TYPE_PASS_MATERIAL_ALPHA = LLRenderPass::PASS_MATERIAL_ALPHA, + RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK = LLRenderPass::PASS_MATERIAL_ALPHA_MASK, + RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE= LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, + RENDER_TYPE_PASS_SPECMAP = LLRenderPass::PASS_SPECMAP, + RENDER_TYPE_PASS_SPECMAP_BLEND = LLRenderPass::PASS_SPECMAP_BLEND, + RENDER_TYPE_PASS_SPECMAP_MASK = LLRenderPass::PASS_SPECMAP_MASK, + RENDER_TYPE_PASS_SPECMAP_EMISSIVE = LLRenderPass::PASS_SPECMAP_EMISSIVE, + RENDER_TYPE_PASS_NORMMAP = LLRenderPass::PASS_NORMMAP, + RENDER_TYPE_PASS_NORMMAP_BLEND = LLRenderPass::PASS_NORMMAP_BLEND, + RENDER_TYPE_PASS_NORMMAP_MASK = LLRenderPass::PASS_NORMMAP_MASK, + RENDER_TYPE_PASS_NORMMAP_EMISSIVE = LLRenderPass::PASS_NORMMAP_EMISSIVE, + RENDER_TYPE_PASS_NORMSPEC = LLRenderPass::PASS_NORMSPEC, + RENDER_TYPE_PASS_NORMSPEC_BLEND = LLRenderPass::PASS_NORMSPEC_BLEND, + RENDER_TYPE_PASS_NORMSPEC_MASK = LLRenderPass::PASS_NORMSPEC_MASK, + RENDER_TYPE_PASS_NORMSPEC_EMISSIVE = LLRenderPass::PASS_NORMSPEC_EMISSIVE, + // Following are object types (only used in drawable mRenderType) + RENDER_TYPE_HUD = LLRenderPass::NUM_RENDER_TYPES, + RENDER_TYPE_VOLUME, + RENDER_TYPE_PARTICLES, + RENDER_TYPE_CLOUDS, + RENDER_TYPE_HUD_PARTICLES, + NUM_RENDER_TYPES, + END_RENDER_TYPES = NUM_RENDER_TYPES + }; + + enum LLRenderDebugFeatureMask + { + RENDER_DEBUG_FEATURE_UI = 0x0001, + RENDER_DEBUG_FEATURE_SELECTED = 0x0002, + RENDER_DEBUG_FEATURE_HIGHLIGHTED = 0x0004, + RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES = 0x0008, +// RENDER_DEBUG_FEATURE_HW_LIGHTING = 0x0010, + RENDER_DEBUG_FEATURE_FLEXIBLE = 0x0010, + RENDER_DEBUG_FEATURE_FOG = 0x0020, + RENDER_DEBUG_FEATURE_FR_INFO = 0x0080, + RENDER_DEBUG_FEATURE_FOOT_SHADOWS = 0x0100, + }; + + enum LLRenderDebugMask: U64 + { + RENDER_DEBUG_COMPOSITION = 0x00000001, + RENDER_DEBUG_VERIFY = 0x00000002, + RENDER_DEBUG_BBOXES = 0x00000004, + RENDER_DEBUG_OCTREE = 0x00000008, + RENDER_DEBUG_WIND_VECTORS = 0x00000010, + RENDER_DEBUG_OCCLUSION = 0x00000020, + RENDER_DEBUG_POINTS = 0x00000040, + RENDER_DEBUG_TEXTURE_PRIORITY = 0x00000080, + RENDER_DEBUG_TEXTURE_AREA = 0x00000100, + RENDER_DEBUG_FACE_AREA = 0x00000200, + RENDER_DEBUG_PARTICLES = 0x00000400, + RENDER_DEBUG_GLOW = 0x00000800, // not used + RENDER_DEBUG_TEXTURE_ANIM = 0x00001000, + RENDER_DEBUG_LIGHTS = 0x00002000, + RENDER_DEBUG_BATCH_SIZE = 0x00004000, + RENDER_DEBUG_ALPHA_BINS = 0x00008000, // not used + RENDER_DEBUG_RAYCAST = 0x00010000, + RENDER_DEBUG_AVATAR_DRAW_INFO = 0x00020000, + RENDER_DEBUG_SHADOW_FRUSTA = 0x00040000, + RENDER_DEBUG_SCULPTED = 0x00080000, + RENDER_DEBUG_AVATAR_VOLUME = 0x00100000, + RENDER_DEBUG_AVATAR_JOINTS = 0x00200000, + RENDER_DEBUG_BUILD_QUEUE = 0x00400000, + RENDER_DEBUG_AGENT_TARGET = 0x00800000, + RENDER_DEBUG_UPDATE_TYPE = 0x01000000, + RENDER_DEBUG_PHYSICS_SHAPES = 0x02000000, + RENDER_DEBUG_NORMALS = 0x04000000, + RENDER_DEBUG_LOD_INFO = 0x08000000, + RENDER_DEBUG_RENDER_COMPLEXITY = 0x10000000, + RENDER_DEBUG_ATTACHMENT_BYTES = 0x20000000, // not used + RENDER_DEBUG_TEXEL_DENSITY = 0x40000000, + RENDER_DEBUG_TRIANGLE_COUNT = 0x80000000, + RENDER_DEBUG_IMPOSTORS = 0x100000000, RENDER_DEBUG_SH = 0x200000000, - }; + }; public: - - LLSpatialPartition* getSpatialPartition(LLViewerObject* vobj); - - void updateCamera(bool reset = false); - - LLVector3 mFlyCamPosition; - LLQuaternion mFlyCamRotation; - - bool mBackfaceCull; - S32 mMatrixOpCount; - S32 mTextureMatrixOps; - S32 mNumVisibleNodes; - - S32 mDebugTextureUploadCost; - S32 mDebugSculptUploadCost; - S32 mDebugMeshUploadCost; - - S32 mNumVisibleFaces; - - static S32 sCompiles; - - static bool sShowHUDAttachments; - static bool sForceOldBakedUpload; // If true will not use capabilities to upload baked textures. - static S32 sUseOcclusion; // 0 = no occlusion, 1 = read only, 2 = read/write - static bool sDelayVBUpdate; - static bool sAutoMaskAlphaDeferred; - static bool sAutoMaskAlphaNonDeferred; - static bool sDisableShaders; // if true, rendering will be done without shaders - static bool sRenderBump; - static bool sBakeSunlight; - static bool sNoAlpha; - static bool sUseTriStrips; - static bool sUseFarClip; - static bool sShadowRender; - static bool sWaterReflections; - static bool sDynamicLOD; - static bool sPickAvatar; - static bool sReflectionRender; - static bool sDistortionRender; - static bool sImpostorRender; - static bool sImpostorRenderAlphaDepthPass; - static bool sUnderWaterRender; - static bool sRenderGlow; - static bool sTextureBindTest; - static bool sRenderFrameTest; - static bool sRenderAttachedLights; - static bool sRenderAttachedParticles; - static bool sRenderDeferred; - static bool sMemAllocationThrottled; - static S32 sVisibleLightCount; - static F32 sMinRenderSize; - static bool sRenderingHUDs; + + LLSpatialPartition* getSpatialPartition(LLViewerObject* vobj); + + void updateCamera(bool reset = false); + + LLVector3 mFlyCamPosition; + LLQuaternion mFlyCamRotation; + + bool mBackfaceCull; + S32 mMatrixOpCount; + S32 mTextureMatrixOps; + S32 mNumVisibleNodes; + + S32 mDebugTextureUploadCost; + S32 mDebugSculptUploadCost; + S32 mDebugMeshUploadCost; + + S32 mNumVisibleFaces; + + static S32 sCompiles; + + static bool sShowHUDAttachments; + static bool sForceOldBakedUpload; // If true will not use capabilities to upload baked textures. + static S32 sUseOcclusion; // 0 = no occlusion, 1 = read only, 2 = read/write + static bool sDelayVBUpdate; + static bool sAutoMaskAlphaDeferred; + static bool sAutoMaskAlphaNonDeferred; + static bool sDisableShaders; // if true, rendering will be done without shaders + static bool sRenderBump; + static bool sBakeSunlight; + static bool sNoAlpha; + static bool sUseTriStrips; + static bool sUseFarClip; + static bool sShadowRender; + static bool sWaterReflections; + static bool sDynamicLOD; + static bool sPickAvatar; + static bool sReflectionRender; + static bool sDistortionRender; + static bool sImpostorRender; + static bool sImpostorRenderAlphaDepthPass; + static bool sUnderWaterRender; + static bool sRenderGlow; + static bool sTextureBindTest; + static bool sRenderFrameTest; + static bool sRenderAttachedLights; + static bool sRenderAttachedParticles; + static bool sRenderDeferred; + static bool sMemAllocationThrottled; + static S32 sVisibleLightCount; + static F32 sMinRenderSize; + static bool sRenderingHUDs; static F32 sDistortionWaterClipPlaneMargin; - static LLTrace::EventStatHandle sStatBatchSize; - - //screen texture - U32 mScreenWidth; - U32 mScreenHeight; - - LLRenderTarget mScreen; - LLRenderTarget mUIScreen; - LLRenderTarget mDeferredScreen; - LLRenderTarget mFXAABuffer; - LLRenderTarget mEdgeMap; - LLRenderTarget mDeferredDepth; - LLRenderTarget mOcclusionDepth; - LLRenderTarget mDeferredLight; - LLRenderTarget mHighlight; - LLRenderTarget mPhysicsDisplay; + static LLTrace::EventStatHandle sStatBatchSize; + + //screen texture + U32 mScreenWidth; + U32 mScreenHeight; + + LLRenderTarget mScreen; + LLRenderTarget mUIScreen; + LLRenderTarget mDeferredScreen; + LLRenderTarget mFXAABuffer; + LLRenderTarget mEdgeMap; + LLRenderTarget mDeferredDepth; + LLRenderTarget mOcclusionDepth; + LLRenderTarget mDeferredLight; + LLRenderTarget mHighlight; + LLRenderTarget mPhysicsDisplay; LLCullResult mSky; LLCullResult mReflectedObjects; LLCullResult mRefractedObjects; - //utility buffer for rendering post effects, gets abused by renderDeferredLighting - LLPointer mDeferredVB; - - //utility buffer for rendering cubes, 8 vertices are corners of a cube [-1, 1] - LLPointer mCubeVB; - - //sun shadow map - LLRenderTarget mShadow[6]; - LLRenderTarget mShadowOcclusion[6]; - - std::vector mShadowFrustPoints[4]; - LLVector4 mShadowError; - LLVector4 mShadowFOV; - LLVector3 mShadowFrustOrigin[4]; - LLCamera mShadowCamera[8]; - LLVector3 mShadowExtents[4][2]; - glh::matrix4f mSunShadowMatrix[6]; - glh::matrix4f mShadowModelview[6]; - glh::matrix4f mShadowProjection[6]; + //utility buffer for rendering post effects, gets abused by renderDeferredLighting + LLPointer mDeferredVB; + + //utility buffer for rendering cubes, 8 vertices are corners of a cube [-1, 1] + LLPointer mCubeVB; + + //sun shadow map + LLRenderTarget mShadow[6]; + LLRenderTarget mShadowOcclusion[6]; + + std::vector mShadowFrustPoints[4]; + LLVector4 mShadowError; + LLVector4 mShadowFOV; + LLVector3 mShadowFrustOrigin[4]; + LLCamera mShadowCamera[8]; + LLVector3 mShadowExtents[4][2]; + glh::matrix4f mSunShadowMatrix[6]; + glh::matrix4f mShadowModelview[6]; + glh::matrix4f mShadowProjection[6]; glh::matrix4f mReflectionModelView; - LLPointer mShadowSpotLight[2]; - F32 mSpotLightFade[2]; - LLPointer mTargetShadowSpotLight[2]; + LLPointer mShadowSpotLight[2]; + F32 mSpotLightFade[2]; + LLPointer mTargetShadowSpotLight[2]; - LLVector4 mSunClipPlanes; - LLVector4 mSunOrthoClipPlanes; - LLVector2 mScreenScale; + LLVector4 mSunClipPlanes; + LLVector4 mSunOrthoClipPlanes; + LLVector2 mScreenScale; - //water reflection texture - LLRenderTarget mWaterRef; + //water reflection texture + LLRenderTarget mWaterRef; - //water distortion texture (refraction) - LLRenderTarget mWaterDis; + //water distortion texture (refraction) + LLRenderTarget mWaterDis; - //texture for making the glow - LLRenderTarget mGlow[3]; + //texture for making the glow + LLRenderTarget mGlow[3]; - //noise map - U32 mNoiseMap; - U32 mTrueNoiseMap; - U32 mLightFunc; + //noise map + U32 mNoiseMap; + U32 mTrueNoiseMap; + U32 mLightFunc; - LLColor4 mSunDiffuse; - LLColor4 mMoonDiffuse; - LLVector4 mSunDir; - LLVector4 mMoonDir; + LLColor4 mSunDiffuse; + LLColor4 mMoonDiffuse; + LLVector4 mSunDir; + LLVector4 mMoonDir; bool mNeedsShadowTargetClear; - LLVector4 mTransformedSunDir; - LLVector4 mTransformedMoonDir; + LLVector4 mTransformedSunDir; + LLVector4 mTransformedMoonDir; - bool mInitialized; - bool mVertexShadersEnabled; - S32 mVertexShadersLoaded; // 0 = no, 1 = yes, -1 = failed + bool mInitialized; + bool mVertexShadersEnabled; + S32 mVertexShadersLoaded; // 0 = no, 1 = yes, -1 = failed - U32 mTransformFeedbackPrimitives; //number of primitives expected to be generated by transform feedback + U32 mTransformFeedbackPrimitives; //number of primitives expected to be generated by transform feedback protected: - bool mRenderTypeEnabled[NUM_RENDER_TYPES]; - std::stack mRenderTypeEnableStack; - - U32 mRenderDebugFeatureMask; - U64 mRenderDebugMask; - U64 mOldRenderDebugMask; - std::stack mRenderDebugFeatureStack; - - - ///////////////////////////////////////////// - // - // - LLDrawable::drawable_vector_t mMovedList; - LLDrawable::drawable_vector_t mMovedBridge; - LLDrawable::drawable_vector_t mShiftList; - - ///////////////////////////////////////////// - // - // - struct Light - { - Light(LLDrawable* ptr, F32 d, F32 f = 0.0f) - : drawable(ptr), - dist(d), - fade(f) - {} - LLPointer drawable; - F32 dist; - F32 fade; - struct compare - { - bool operator()(const Light& a, const Light& b) const - { - if ( a.dist < b.dist ) - return true; - else if ( a.dist > b.dist ) - return false; - else - return a.drawable < b.drawable; - } - }; - }; - typedef std::set< Light, Light::compare > light_set_t; - - LLDrawable::drawable_set_t mLights; - light_set_t mNearbyLights; // lights near camera - LLColor4 mHWLightColors[8]; - - ///////////////////////////////////////////// - // - // Different queues of drawables being processed. - // - LLDrawable::drawable_list_t mBuildQ1; // priority - LLDrawable::drawable_list_t mBuildQ2; // non-priority - LLSpatialGroup::sg_vector_t mGroupQ1; //priority - LLSpatialGroup::sg_vector_t mGroupQ2; // non-priority - - LLSpatialGroup::sg_vector_t mGroupSaveQ1; // a place to save mGroupQ1 until it is safe to unref - - LLSpatialGroup::sg_vector_t mMeshDirtyGroup; //groups that need rebuildMesh called - U32 mMeshDirtyQueryObject; - - LLDrawable::drawable_list_t mPartitionQ; //drawables that need to update their spatial partition radius - - bool mGroupQ2Locked; - bool mGroupQ1Locked; - - bool mResetVertexBuffers; //if true, clear vertex buffers on next update - - LLViewerObject::vobj_list_t mCreateQ; - - LLDrawable::drawable_set_t mRetexturedList; - - class HighlightItem - { - public: - const LLPointer mItem; - mutable F32 mFade; - - HighlightItem(LLDrawable* item) - : mItem(item), mFade(0) - { - } - - bool operator<(const HighlightItem& rhs) const - { - return mItem < rhs.mItem; - } - - bool operator==(const HighlightItem& rhs) const - { - return mItem == rhs.mItem; - } - - void incrFade(F32 val) const - { - mFade = llclamp(mFade+val, 0.f, 1.f); - } - }; - - std::set mHighlightSet; - LLPointer mHighlightObject; - - ////////////////////////////////////////////////// - // - // Draw pools are responsible for storing all rendered data, - // and performing the actual rendering of objects. - // - struct compare_pools - { - bool operator()(const LLDrawPool* a, const LLDrawPool* b) const - { - if (!a) - return true; - else if (!b) - return false; - else - { - S32 atype = a->getType(); - S32 btype = b->getType(); - if (atype < btype) - return true; - else if (atype > btype) - return false; - else - return a->getId() < b->getId(); - } - } - }; - typedef std::set pool_set_t; - pool_set_t mPools; - LLDrawPool* mLastRebuildPool; - - // For quick-lookups into mPools (mapped by texture pointer) - std::map mTerrainPools; - std::map mTreePools; - LLDrawPoolAlpha* mAlphaPool; - LLDrawPool* mSkyPool; - LLDrawPool* mTerrainPool; - LLDrawPool* mWaterPool; - LLDrawPool* mGroundPool; - LLRenderPass* mSimplePool; - LLRenderPass* mGrassPool; - LLRenderPass* mAlphaMaskPool; - LLRenderPass* mFullbrightAlphaMaskPool; - LLRenderPass* mFullbrightPool; - LLDrawPool* mInvisiblePool; - LLDrawPool* mGlowPool; - LLDrawPool* mBumpPool; - LLDrawPool* mMaterialsPool; - LLDrawPool* mWLSkyPool; - // Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar - + bool mRenderTypeEnabled[NUM_RENDER_TYPES]; + std::stack mRenderTypeEnableStack; + + U32 mRenderDebugFeatureMask; + U64 mRenderDebugMask; + U64 mOldRenderDebugMask; + std::stack mRenderDebugFeatureStack; + + + ///////////////////////////////////////////// + // + // + LLDrawable::drawable_vector_t mMovedList; + LLDrawable::drawable_vector_t mMovedBridge; + LLDrawable::drawable_vector_t mShiftList; + + ///////////////////////////////////////////// + // + // + struct Light + { + Light(LLDrawable* ptr, F32 d, F32 f = 0.0f) + : drawable(ptr), + dist(d), + fade(f) + {} + LLPointer drawable; + F32 dist; + F32 fade; + struct compare + { + bool operator()(const Light& a, const Light& b) const + { + if ( a.dist < b.dist ) + return true; + else if ( a.dist > b.dist ) + return false; + else + return a.drawable < b.drawable; + } + }; + }; + typedef std::set< Light, Light::compare > light_set_t; + + LLDrawable::drawable_set_t mLights; + light_set_t mNearbyLights; // lights near camera + LLColor4 mHWLightColors[8]; + + ///////////////////////////////////////////// + // + // Different queues of drawables being processed. + // + LLDrawable::drawable_list_t mBuildQ1; // priority + LLDrawable::drawable_list_t mBuildQ2; // non-priority + LLSpatialGroup::sg_vector_t mGroupQ1; //priority + LLSpatialGroup::sg_vector_t mGroupQ2; // non-priority + + LLSpatialGroup::sg_vector_t mGroupSaveQ1; // a place to save mGroupQ1 until it is safe to unref + + LLSpatialGroup::sg_vector_t mMeshDirtyGroup; //groups that need rebuildMesh called + U32 mMeshDirtyQueryObject; + + LLDrawable::drawable_list_t mPartitionQ; //drawables that need to update their spatial partition radius + + bool mGroupQ2Locked; + bool mGroupQ1Locked; + + bool mResetVertexBuffers; //if true, clear vertex buffers on next update + + LLViewerObject::vobj_list_t mCreateQ; + + LLDrawable::drawable_set_t mRetexturedList; + + class HighlightItem + { + public: + const LLPointer mItem; + mutable F32 mFade; + + HighlightItem(LLDrawable* item) + : mItem(item), mFade(0) + { + } + + bool operator<(const HighlightItem& rhs) const + { + return mItem < rhs.mItem; + } + + bool operator==(const HighlightItem& rhs) const + { + return mItem == rhs.mItem; + } + + void incrFade(F32 val) const + { + mFade = llclamp(mFade+val, 0.f, 1.f); + } + }; + + std::set mHighlightSet; + LLPointer mHighlightObject; + + ////////////////////////////////////////////////// + // + // Draw pools are responsible for storing all rendered data, + // and performing the actual rendering of objects. + // + struct compare_pools + { + bool operator()(const LLDrawPool* a, const LLDrawPool* b) const + { + if (!a) + return true; + else if (!b) + return false; + else + { + S32 atype = a->getType(); + S32 btype = b->getType(); + if (atype < btype) + return true; + else if (atype > btype) + return false; + else + return a->getId() < b->getId(); + } + } + }; + typedef std::set pool_set_t; + pool_set_t mPools; + LLDrawPool* mLastRebuildPool; + + // For quick-lookups into mPools (mapped by texture pointer) + std::map mTerrainPools; + std::map mTreePools; + LLDrawPoolAlpha* mAlphaPool; + LLDrawPool* mSkyPool; + LLDrawPool* mTerrainPool; + LLDrawPool* mWaterPool; + LLDrawPool* mGroundPool; + LLRenderPass* mSimplePool; + LLRenderPass* mGrassPool; + LLRenderPass* mAlphaMaskPool; + LLRenderPass* mFullbrightAlphaMaskPool; + LLRenderPass* mFullbrightPool; + LLDrawPool* mInvisiblePool; + LLDrawPool* mGlowPool; + LLDrawPool* mBumpPool; + LLDrawPool* mMaterialsPool; + LLDrawPool* mWLSkyPool; + // Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar + public: - std::vector mHighlightFaces; // highlight faces on physical objects + std::vector mHighlightFaces; // highlight faces on physical objects protected: - std::vector mSelectedFaces; - - class DebugBlip - { - public: - LLColor4 mColor; - LLVector3 mPosition; - F32 mAge; - - DebugBlip(const LLVector3& position, const LLColor4& color) - : mColor(color), mPosition(position), mAge(0.f) - { } - }; - - std::list mDebugBlips; - - LLPointer mFaceSelectImagep; - - U32 mLightMask; - U32 mLightMovingMask; - S32 mLightingDetail; - - static bool sRenderPhysicalBeacons; - static bool sRenderMOAPBeacons; - static bool sRenderScriptedTouchBeacons; - static bool sRenderScriptedBeacons; - static bool sRenderParticleBeacons; - static bool sRenderSoundBeacons; + std::vector mSelectedFaces; + + class DebugBlip + { + public: + LLColor4 mColor; + LLVector3 mPosition; + F32 mAge; + + DebugBlip(const LLVector3& position, const LLColor4& color) + : mColor(color), mPosition(position), mAge(0.f) + { } + }; + + std::list mDebugBlips; + + LLPointer mFaceSelectImagep; + + U32 mLightMask; + U32 mLightMovingMask; + S32 mLightingDetail; + + static bool sRenderPhysicalBeacons; + static bool sRenderMOAPBeacons; + static bool sRenderScriptedTouchBeacons; + static bool sRenderScriptedBeacons; + static bool sRenderParticleBeacons; + static bool sRenderSoundBeacons; public: - static bool sRenderBeacons; - static bool sRenderHighlight; - - // Determines which set of UVs to use in highlight display - // - static LLRender::eTexIndex sRenderHighlightTextureChannel; - - //debug use - static U32 sCurRenderPoolType ; - - //cached settings - static bool WindLightUseAtmosShaders; - static bool VertexShaderEnable; - static bool RenderAvatarVP; - static bool RenderDeferred; - static F32 RenderDeferredSunWash; - static U32 RenderFSAASamples; - static U32 RenderResolutionDivisor; - static bool RenderUIBuffer; - static S32 RenderShadowDetail; - static bool RenderDeferredSSAO; - static F32 RenderShadowResolutionScale; - static bool RenderLocalLights; - static bool RenderDelayCreation; - static bool RenderAnimateRes; - static bool FreezeTime; - static S32 DebugBeaconLineWidth; - static F32 RenderHighlightBrightness; - static LLColor4 RenderHighlightColor; - static F32 RenderHighlightThickness; - static bool RenderSpotLightsInNondeferred; - static LLColor4 PreviewAmbientColor; - static LLColor4 PreviewDiffuse0; - static LLColor4 PreviewSpecular0; - static LLColor4 PreviewDiffuse1; - static LLColor4 PreviewSpecular1; - static LLColor4 PreviewDiffuse2; - static LLColor4 PreviewSpecular2; - static LLVector3 PreviewDirection0; - static LLVector3 PreviewDirection1; - static LLVector3 PreviewDirection2; - static F32 RenderGlowMinLuminance; - static F32 RenderGlowMaxExtractAlpha; - static F32 RenderGlowWarmthAmount; - static LLVector3 RenderGlowLumWeights; - static LLVector3 RenderGlowWarmthWeights; - static S32 RenderGlowResolutionPow; - static S32 RenderGlowIterations; - static F32 RenderGlowWidth; - static F32 RenderGlowStrength; - static bool RenderDepthOfField; - static bool RenderDepthOfFieldInEditMode; - static F32 CameraFocusTransitionTime; - static F32 CameraFNumber; - static F32 CameraFocalLength; - static F32 CameraFieldOfView; - static F32 RenderShadowNoise; - static F32 RenderShadowBlurSize; - static F32 RenderSSAOScale; - static U32 RenderSSAOMaxScale; - static F32 RenderSSAOFactor; - static LLVector3 RenderSSAOEffect; - static F32 RenderShadowOffsetError; - static F32 RenderShadowBiasError; - static F32 RenderShadowOffset; - static F32 RenderShadowBias; - static F32 RenderSpotShadowOffset; - static F32 RenderSpotShadowBias; - static F32 RenderEdgeDepthCutoff; - static F32 RenderEdgeNormCutoff; - static LLVector3 RenderShadowGaussian; - static F32 RenderShadowBlurDistFactor; - static bool RenderDeferredAtmospheric; - static S32 RenderReflectionDetail; - static F32 RenderHighlightFadeTime; - static LLVector3 RenderShadowClipPlanes; - static LLVector3 RenderShadowOrthoClipPlanes; - static LLVector3 RenderShadowNearDist; - static F32 RenderFarClip; - static LLVector3 RenderShadowSplitExponent; - static F32 RenderShadowErrorCutoff; - static F32 RenderShadowFOVCutoff; - static bool CameraOffset; - static F32 CameraMaxCoF; - static F32 CameraDoFResScale; - static F32 RenderAutoHideSurfaceAreaLimit; + static bool sRenderBeacons; + static bool sRenderHighlight; + + // Determines which set of UVs to use in highlight display + // + static LLRender::eTexIndex sRenderHighlightTextureChannel; + + //debug use + static U32 sCurRenderPoolType ; + + //cached settings + static bool WindLightUseAtmosShaders; + static bool VertexShaderEnable; + static bool RenderAvatarVP; + static bool RenderDeferred; + static F32 RenderDeferredSunWash; + static U32 RenderFSAASamples; + static U32 RenderResolutionDivisor; + static bool RenderUIBuffer; + static S32 RenderShadowDetail; + static bool RenderDeferredSSAO; + static F32 RenderShadowResolutionScale; + static bool RenderLocalLights; + static bool RenderDelayCreation; + static bool RenderAnimateRes; + static bool FreezeTime; + static S32 DebugBeaconLineWidth; + static F32 RenderHighlightBrightness; + static LLColor4 RenderHighlightColor; + static F32 RenderHighlightThickness; + static bool RenderSpotLightsInNondeferred; + static LLColor4 PreviewAmbientColor; + static LLColor4 PreviewDiffuse0; + static LLColor4 PreviewSpecular0; + static LLColor4 PreviewDiffuse1; + static LLColor4 PreviewSpecular1; + static LLColor4 PreviewDiffuse2; + static LLColor4 PreviewSpecular2; + static LLVector3 PreviewDirection0; + static LLVector3 PreviewDirection1; + static LLVector3 PreviewDirection2; + static F32 RenderGlowMinLuminance; + static F32 RenderGlowMaxExtractAlpha; + static F32 RenderGlowWarmthAmount; + static LLVector3 RenderGlowLumWeights; + static LLVector3 RenderGlowWarmthWeights; + static S32 RenderGlowResolutionPow; + static S32 RenderGlowIterations; + static F32 RenderGlowWidth; + static F32 RenderGlowStrength; + static bool RenderDepthOfField; + static bool RenderDepthOfFieldInEditMode; + static F32 CameraFocusTransitionTime; + static F32 CameraFNumber; + static F32 CameraFocalLength; + static F32 CameraFieldOfView; + static F32 RenderShadowNoise; + static F32 RenderShadowBlurSize; + static F32 RenderSSAOScale; + static U32 RenderSSAOMaxScale; + static F32 RenderSSAOFactor; + static LLVector3 RenderSSAOEffect; + static F32 RenderShadowOffsetError; + static F32 RenderShadowBiasError; + static F32 RenderShadowOffset; + static F32 RenderShadowBias; + static F32 RenderSpotShadowOffset; + static F32 RenderSpotShadowBias; + static F32 RenderEdgeDepthCutoff; + static F32 RenderEdgeNormCutoff; + static LLVector3 RenderShadowGaussian; + static F32 RenderShadowBlurDistFactor; + static bool RenderDeferredAtmospheric; + static S32 RenderReflectionDetail; + static F32 RenderHighlightFadeTime; + static LLVector3 RenderShadowClipPlanes; + static LLVector3 RenderShadowOrthoClipPlanes; + static LLVector3 RenderShadowNearDist; + static F32 RenderFarClip; + static LLVector3 RenderShadowSplitExponent; + static F32 RenderShadowErrorCutoff; + static F32 RenderShadowFOVCutoff; + static bool CameraOffset; + static F32 CameraMaxCoF; + static F32 CameraDoFResScale; + static F32 RenderAutoHideSurfaceAreaLimit; }; void render_bbox(const LLVector3 &min, const LLVector3 &max); -- cgit v1.3 From 868cd32e5e229e503f1b5b1d5ec543fd6f76cb7f Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Tue, 12 Mar 2019 11:07:23 -0700 Subject: More tab restoration. Also fix ref to removed extra GLSL link module. 'warn-on-failure:no-tabs' --- indra/llrender/llglslshader.cpp | 5 - indra/newview/llfloatereditextdaycycle.cpp | 2 +- indra/newview/llpanelenvironment.cpp | 8 +- indra/newview/llvovolume.cpp | 9041 ++++++++++++++-------------- 4 files changed, 4524 insertions(+), 4532 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 9a4eeb59df..471d73febf 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -401,11 +401,6 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, // work-around missing mix(vec3,vec3,bvec3) mDefines["OLD_SELECT"] = "1"; #endif - - if (mExtraLinkObject) - { - attachObject(mExtraLinkObject); - } //compile new source vector< pair >::iterator fileIter = mShaderFiles.begin(); diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp index 055c8120a3..235a9b4d53 100644 --- a/indra/newview/llfloatereditextdaycycle.cpp +++ b/indra/newview/llfloatereditextdaycycle.cpp @@ -266,7 +266,7 @@ BOOL LLFloaterEditExtDayCycle::postBuild() panel->setOnDirtyFlagChanged([this](LLPanel *, bool val) { onPanelDirtyFlagChanged(val); }); } - return TRUE; + return TRUE; } void LLFloaterEditExtDayCycle::onOpen(const LLSD& key) diff --git a/indra/newview/llpanelenvironment.cpp b/indra/newview/llpanelenvironment.cpp index 9cda37d05e..ef307ad079 100644 --- a/indra/newview/llpanelenvironment.cpp +++ b/indra/newview/llpanelenvironment.cpp @@ -1064,10 +1064,10 @@ LLSettingsDropTarget::LLSettingsDropTarget(const LLSettingsDropTarget::Params& p {} BOOL LLSettingsDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) { BOOL handled = FALSE; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 641b42b56a..9c761cc4a6 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -512,153 +512,153 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, // If the media changed at all, request new media data LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " << ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL; - requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED); - } + requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED); + } else { LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " << ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL; } - } - // ...and clean up any media impls - cleanUpMediaImpls(); + } + // ...and clean up any media impls + cleanUpMediaImpls(); - return retval; + return retval; } void LLVOVolume::animateTextures() { - if (!mDead) - { - F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f; - S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot); - - if (result) - { - if (!mTexAnimMode) - { - mFaceMappingChanged = TRUE; - gPipeline.markTextured(mDrawable); - } - mTexAnimMode = result | mTextureAnimp->mMode; - - S32 start=0, end=mDrawable->getNumFaces()-1; - if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end) - { - start = end = mTextureAnimp->mFace; - } - - for (S32 i = start; i <= end; i++) - { - LLFace* facep = mDrawable->getFace(i); - if (!facep) continue; - if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; + if (!mDead) + { + F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f; + S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot); + + if (result) + { + if (!mTexAnimMode) + { + mFaceMappingChanged = TRUE; + gPipeline.markTextured(mDrawable); + } + mTexAnimMode = result | mTextureAnimp->mMode; + + S32 start=0, end=mDrawable->getNumFaces()-1; + if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end) + { + start = end = mTextureAnimp->mFace; + } + + for (S32 i = start; i <= end; i++) + { + LLFace* facep = mDrawable->getFace(i); + if (!facep) continue; + if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; - const LLTextureEntry* te = facep->getTextureEntry(); - - if (!te) - { - continue; - } - - if (!(result & LLViewerTextureAnim::ROTATE)) - { - te->getRotation(&rot); - } - if (!(result & LLViewerTextureAnim::TRANSLATE)) - { - te->getOffset(&off_s,&off_t); - } - if (!(result & LLViewerTextureAnim::SCALE)) - { - te->getScale(&scale_s, &scale_t); - } + const LLTextureEntry* te = facep->getTextureEntry(); + + if (!te) + { + continue; + } + + if (!(result & LLViewerTextureAnim::ROTATE)) + { + te->getRotation(&rot); + } + if (!(result & LLViewerTextureAnim::TRANSLATE)) + { + te->getOffset(&off_s,&off_t); + } + if (!(result & LLViewerTextureAnim::SCALE)) + { + te->getScale(&scale_s, &scale_t); + } - if (!facep->mTextureMatrix) - { - facep->mTextureMatrix = new LLMatrix4(); - } + if (!facep->mTextureMatrix) + { + facep->mTextureMatrix = new LLMatrix4(); + } - LLMatrix4& tex_mat = *facep->mTextureMatrix; - tex_mat.setIdentity(); - LLVector3 trans ; + LLMatrix4& tex_mat = *facep->mTextureMatrix; + tex_mat.setIdentity(); + LLVector3 trans ; - trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f)); - tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); + trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f)); + tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); - LLVector3 scale(scale_s, scale_t, 1.f); - LLQuaternion quat; - quat.setQuat(rot, 0, 0, -1.f); - - tex_mat.rotate(quat); + LLVector3 scale(scale_s, scale_t, 1.f); + LLQuaternion quat; + quat.setQuat(rot, 0, 0, -1.f); + + tex_mat.rotate(quat); - LLMatrix4 mat; - mat.initAll(scale, LLQuaternion(), LLVector3()); - tex_mat *= mat; - - tex_mat.translate(trans); - } - } - else - { - if (mTexAnimMode && mTextureAnimp->mRate == 0) - { - U8 start, count; + LLMatrix4 mat; + mat.initAll(scale, LLQuaternion(), LLVector3()); + tex_mat *= mat; + + tex_mat.translate(trans); + } + } + else + { + if (mTexAnimMode && mTextureAnimp->mRate == 0) + { + U8 start, count; - if (mTextureAnimp->mFace == -1) - { - start = 0; - count = getNumTEs(); - } - else - { - start = (U8) mTextureAnimp->mFace; - count = 1; - } + if (mTextureAnimp->mFace == -1) + { + start = 0; + count = getNumTEs(); + } + else + { + start = (U8) mTextureAnimp->mFace; + count = 1; + } - for (S32 i = start; i < start + count; i++) - { - if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE) - { - setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT); - } - if (mTexAnimMode & LLViewerTextureAnim::SCALE) - { - setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT); - } - if (mTexAnimMode & LLViewerTextureAnim::ROTATE) - { - setTERotation(i, mTextureAnimp->mRot); - } - } + for (S32 i = start; i < start + count; i++) + { + if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE) + { + setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT); + } + if (mTexAnimMode & LLViewerTextureAnim::SCALE) + { + setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT); + } + if (mTexAnimMode & LLViewerTextureAnim::ROTATE) + { + setTERotation(i, mTextureAnimp->mRot); + } + } - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - mTexAnimMode = 0; - } - } - } + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; + } + } + } } void LLVOVolume::updateTextures() { - const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds - if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) - { - updateTextureVirtualSize(); + const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds + if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) + { + updateTextureVirtualSize(); - if (mDrawable.notNull() && !isVisible() && !mDrawable->isActive()) - { //delete vertex buffer to free up some VRAM - LLSpatialGroup* group = mDrawable->getSpatialGroup(); - if (group && (group->mVertexBuffer.notNull() || !group->mBufferMap.empty() || !group->mDrawMap.empty())) - { - group->destroyGL(true); + if (mDrawable.notNull() && !isVisible() && !mDrawable->isActive()) + { //delete vertex buffer to free up some VRAM + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group && (group->mVertexBuffer.notNull() || !group->mBufferMap.empty() || !group->mDrawMap.empty())) + { + group->destroyGL(true); - //flag the group as having changed geometry so it gets a rebuild next time - //it becomes visible - group->setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); - } - } + //flag the group as having changed geometry so it gets a rebuild next time + //it becomes visible + group->setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); + } + } } @@ -666,458 +666,458 @@ void LLVOVolume::updateTextures() BOOL LLVOVolume::isVisible() const { - if(mDrawable.notNull() && mDrawable->isVisible()) - { - return TRUE ; - } + if(mDrawable.notNull() && mDrawable->isVisible()) + { + return TRUE ; + } - if(isAttachment()) - { - LLViewerObject* objp = (LLViewerObject*)getParent() ; - while(objp && !objp->isAvatar()) - { - objp = (LLViewerObject*)objp->getParent() ; - } + if(isAttachment()) + { + LLViewerObject* objp = (LLViewerObject*)getParent() ; + while(objp && !objp->isAvatar()) + { + objp = (LLViewerObject*)objp->getParent() ; + } - return objp && objp->mDrawable.notNull() && objp->mDrawable->isVisible() ; - } + return objp && objp->mDrawable.notNull() && objp->mDrawable->isVisible() ; + } - return FALSE ; + return FALSE ; } void LLVOVolume::updateTextureVirtualSize(bool forced) { - LL_RECORD_BLOCK_TIME(FTM_VOLUME_TEXTURES); - // Update the pixel area of all faces + LL_RECORD_BLOCK_TIME(FTM_VOLUME_TEXTURES); + // Update the pixel area of all faces - if(!forced) - { - if(!isVisible()) - { //don't load textures for non-visible faces - const S32 num_faces = mDrawable->getNumFaces(); - for (S32 i = 0; i < num_faces; i++) - { - LLFace* face = mDrawable->getFace(i); - if (face) - { - face->setPixelArea(0.f); - face->setVirtualSize(0.f); - } - } + if(!forced) + { + if(!isVisible()) + { //don't load textures for non-visible faces + const S32 num_faces = mDrawable->getNumFaces(); + for (S32 i = 0; i < num_faces; i++) + { + LLFace* face = mDrawable->getFace(i); + if (face) + { + face->setPixelArea(0.f); + face->setVirtualSize(0.f); + } + } - return ; - } + return ; + } - if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) - { - return; - } - } + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) + { + return; + } + } - static LLCachedControl dont_load_textures(gSavedSettings,"TextureDisable", false); - - if (dont_load_textures || LLAppViewer::getTextureFetch()->mDebugPause) // || !mDrawable->isVisible()) - { - return; - } + static LLCachedControl dont_load_textures(gSavedSettings,"TextureDisable", false); + + if (dont_load_textures || LLAppViewer::getTextureFetch()->mDebugPause) // || !mDrawable->isVisible()) + { + return; + } - mTextureUpdateTimer.reset(); - - F32 old_area = mPixelArea; - mPixelArea = 0.f; + mTextureUpdateTimer.reset(); + + F32 old_area = mPixelArea; + mPixelArea = 0.f; - const S32 num_faces = mDrawable->getNumFaces(); - F32 min_vsize=999999999.f, max_vsize=0.f; - LLViewerCamera* camera = LLViewerCamera::getInstance(); - for (S32 i = 0; i < num_faces; i++) - { - LLFace* face = mDrawable->getFace(i); - if (!face) continue; - const LLTextureEntry *te = face->getTextureEntry(); - LLViewerTexture *imagep = face->getTexture(); - if (!imagep || !te || - face->mExtents[0].equals3(face->mExtents[1])) - { - continue; - } - - F32 vsize; - F32 old_size = face->getVirtualSize(); + const S32 num_faces = mDrawable->getNumFaces(); + F32 min_vsize=999999999.f, max_vsize=0.f; + LLViewerCamera* camera = LLViewerCamera::getInstance(); + for (S32 i = 0; i < num_faces; i++) + { + LLFace* face = mDrawable->getFace(i); + if (!face) continue; + const LLTextureEntry *te = face->getTextureEntry(); + LLViewerTexture *imagep = face->getTexture(); + if (!imagep || !te || + face->mExtents[0].equals3(face->mExtents[1])) + { + continue; + } + + F32 vsize; + F32 old_size = face->getVirtualSize(); - if (isHUDAttachment()) - { - F32 area = (F32) camera->getScreenPixelArea(); - vsize = area; - imagep->setBoostLevel(LLGLTexture::BOOST_HUD); - face->setPixelArea(area); // treat as full screen - face->setVirtualSize(vsize); - } - else - { - vsize = face->getTextureVirtualSize(); - } + if (isHUDAttachment()) + { + F32 area = (F32) camera->getScreenPixelArea(); + vsize = area; + imagep->setBoostLevel(LLGLTexture::BOOST_HUD); + face->setPixelArea(area); // treat as full screen + face->setVirtualSize(vsize); + } + else + { + vsize = face->getTextureVirtualSize(); + } - mPixelArea = llmax(mPixelArea, face->getPixelArea()); + mPixelArea = llmax(mPixelArea, face->getPixelArea()); - if (face->mTextureMatrix != NULL) - { - if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || - (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE); - } - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) - { - if (vsize < min_vsize) min_vsize = vsize; - if (vsize > max_vsize) max_vsize = vsize; - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) - { - LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ; - if(img) - { - F32 pri = img->getDecodePriority(); - pri = llmax(pri, 0.0f); - if (pri < min_vsize) min_vsize = pri; - if (pri > max_vsize) max_vsize = pri; - } - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) - { - F32 pri = mPixelArea; - if (pri < min_vsize) min_vsize = pri; - if (pri > max_vsize) max_vsize = pri; - } - } - - if (isSculpted()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID id = sculpt_params->getSculptTexture(); - - updateSculptTexture(); - - + if (face->mTextureMatrix != NULL) + { + if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || + (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE); + } + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) + { + if (vsize < min_vsize) min_vsize = vsize; + if (vsize > max_vsize) max_vsize = vsize; + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ; + if(img) + { + F32 pri = img->getDecodePriority(); + pri = llmax(pri, 0.0f); + if (pri < min_vsize) min_vsize = pri; + if (pri > max_vsize) max_vsize = pri; + } + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) + { + F32 pri = mPixelArea; + if (pri < min_vsize) min_vsize = pri; + if (pri > max_vsize) max_vsize = pri; + } + } + + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID id = sculpt_params->getSculptTexture(); + + updateSculptTexture(); + + - if (mSculptTexture.notNull()) - { - mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), - (S32)LLGLTexture::BOOST_SCULPTED)); - mSculptTexture->setForSculpt() ; - - if(!mSculptTexture->isCachedRawImageReady()) - { - S32 lod = llmin(mLOD, 3); - F32 lodf = ((F32)(lod + 1.0f)/4.f); - F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ; - mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE); - - //if the sculpty very close to the view point, load first - { - LLVector3 lookAt = getPositionAgent() - camera->getOrigin(); - F32 dist = lookAt.normVec() ; - F32 cos_angle_to_view_dir = lookAt * camera->getXAxis() ; - mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ; - } - } - - S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture - S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ; + if (mSculptTexture.notNull()) + { + mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), + (S32)LLGLTexture::BOOST_SCULPTED)); + mSculptTexture->setForSculpt() ; + + if(!mSculptTexture->isCachedRawImageReady()) + { + S32 lod = llmin(mLOD, 3); + F32 lodf = ((F32)(lod + 1.0f)/4.f); + F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ; + mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE); + + //if the sculpty very close to the view point, load first + { + LLVector3 lookAt = getPositionAgent() - camera->getOrigin(); + F32 dist = lookAt.normVec() ; + F32 cos_angle_to_view_dir = lookAt * camera->getXAxis() ; + mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ; + } + } + + S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture + S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ; - if (texture_discard >= 0 && //texture has some data available - (texture_discard < current_discard || //texture has more data than last rebuild - current_discard < 0)) //no previous rebuild - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); - mSculptChanged = TRUE; - } + if (texture_discard >= 0 && //texture has some data available + (texture_discard < current_discard || //texture has more data than last rebuild + current_discard < 0)) //no previous rebuild + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + mSculptChanged = TRUE; + } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) - { - setDebugText(llformat("T%d C%d V%d\n%dx%d", - texture_discard, current_discard, getVolume()->getSculptLevel(), - mSculptTexture->getHeight(), mSculptTexture->getWidth())); - } - } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) + { + setDebugText(llformat("T%d C%d V%d\n%dx%d", + texture_discard, current_discard, getVolume()->getSculptLevel(), + mSculptTexture->getHeight(), mSculptTexture->getWidth())); + } + } - } + } - if (getLightTextureID().notNull()) - { - LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - LLUUID id = params->getLightTexture(); - mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM); - if (mLightTexture.notNull()) - { - F32 rad = getLightRadius(); - mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(), - LLVector3(rad,rad,rad), - *camera)); - } - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) - { - setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) - { - setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) - { - setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); - } + if (getLightTextureID().notNull()) + { + LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + LLUUID id = params->getLightTexture(); + mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM); + if (mLightTexture.notNull()) + { + F32 rad = getLightRadius(); + mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(), + LLVector3(rad,rad,rad), + *camera)); + } + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) + { + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) + { + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); + } - if (mPixelArea == 0) - { //flexi phasing issues make this happen - mPixelArea = old_area; - } + if (mPixelArea == 0) + { //flexi phasing issues make this happen + mPixelArea = old_area; + } } BOOL LLVOVolume::isActive() const { - return !mStatic; + return !mStatic; } BOOL LLVOVolume::setMaterial(const U8 material) { - BOOL res = LLViewerObject::setMaterial(material); - - return res; + BOOL res = LLViewerObject::setMaterial(material); + + return res; } void LLVOVolume::setTexture(const S32 face) { - llassert(face < getNumTEs()); - gGL.getTexUnit(0)->bind(getTEImage(face)); + llassert(face < getNumTEs()); + gGL.getTexUnit(0)->bind(getTEImage(face)); } void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped) { - if (scale != getScale()) - { - // store local radius - LLViewerObject::setScale(scale); + if (scale != getScale()) + { + // store local radius + LLViewerObject::setScale(scale); - if (mVolumeImpl) - { - mVolumeImpl->onSetScale(scale, damped); - } - - updateRadius(); + if (mVolumeImpl) + { + mVolumeImpl->onSetScale(scale, damped); + } + + updateRadius(); - //since drawable transforms do not include scale, changing volume scale - //requires an immediate rebuild of volume verts. - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION, TRUE); - } + //since drawable transforms do not include scale, changing volume scale + //requires an immediate rebuild of volume verts. + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION, TRUE); + } } LLFace* LLVOVolume::addFace(S32 f) { - const LLTextureEntry* te = getTE(f); - LLViewerTexture* imagep = getTEImage(f); - if (te->getMaterialParams().notNull()) - { - LLViewerTexture* normalp = getTENormalMap(f); - LLViewerTexture* specularp = getTESpecularMap(f); - return mDrawable->addFace(te, imagep, normalp, specularp); - } - return mDrawable->addFace(te, imagep); + const LLTextureEntry* te = getTE(f); + LLViewerTexture* imagep = getTEImage(f); + if (te->getMaterialParams().notNull()) + { + LLViewerTexture* normalp = getTENormalMap(f); + LLViewerTexture* specularp = getTESpecularMap(f); + return mDrawable->addFace(te, imagep, normalp, specularp); + } + return mDrawable->addFace(te, imagep); } LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) { - pipeline->allocDrawable(this); - - mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); + pipeline->allocDrawable(this); + + mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); - S32 max_tes_to_set = getNumTEs(); - for (S32 i = 0; i < max_tes_to_set; i++) - { - addFace(i); - } - mNumFaces = max_tes_to_set; + S32 max_tes_to_set = getNumTEs(); + for (S32 i = 0; i < max_tes_to_set; i++) + { + addFace(i); + } + mNumFaces = max_tes_to_set; - if (isAttachment()) - { - mDrawable->makeActive(); - } + if (isAttachment()) + { + mDrawable->makeActive(); + } - if (getIsLight()) - { - // Add it to the pipeline mLightSet - gPipeline.setLight(mDrawable, TRUE); - } - - updateRadius(); - bool force_update = true; // avoid non-alpha mDistance update being optimized away - mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update); + if (getIsLight()) + { + // Add it to the pipeline mLightSet + gPipeline.setLight(mDrawable, TRUE); + } + + updateRadius(); + bool force_update = true; // avoid non-alpha mDistance update being optimized away + mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update); - return mDrawable; + return mDrawable; } BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bool unique_volume) { - LLVolumeParams volume_params = params_in; + LLVolumeParams volume_params = params_in; - S32 last_lod = mVolumep.notNull() ? LLVolumeLODGroup::getVolumeDetailFromScale(mVolumep->getDetail()) : -1; - S32 lod = mLOD; + S32 last_lod = mVolumep.notNull() ? LLVolumeLODGroup::getVolumeDetailFromScale(mVolumep->getDetail()) : -1; + S32 lod = mLOD; - BOOL is404 = FALSE; - - if (isSculpted()) - { - // if it's a mesh - if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - { //meshes might not have all LODs, get the force detail to best existing LOD - if (NO_LOD != lod) - { - lod = gMeshRepo.getActualMeshLOD(volume_params, lod); - if (lod == -1) - { - is404 = TRUE; - lod = 0; - } - } - } - } + BOOL is404 = FALSE; + + if (isSculpted()) + { + // if it's a mesh + if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { //meshes might not have all LODs, get the force detail to best existing LOD + if (NO_LOD != lod) + { + lod = gMeshRepo.getActualMeshLOD(volume_params, lod); + if (lod == -1) + { + is404 = TRUE; + lod = 0; + } + } + } + } - // Check if we need to change implementations - bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE); - if (is_flexible) - { - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, false); - if (!mVolumeImpl) - { - LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); - mVolumeImpl = new LLVolumeImplFlexible(this, data); - } - } - else - { - // Mark the parameter not in use - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, false); - if (mVolumeImpl) - { - delete mVolumeImpl; - mVolumeImpl = NULL; - if (mDrawable.notNull()) - { - // Undo the damage we did to this matrix - mDrawable->updateXform(FALSE); - } - } - } - - if (is404) - { - setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI)); - //render prim proxy when mesh loading attempts give up - volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE); + // Check if we need to change implementations + bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE); + if (is_flexible) + { + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, false); + if (!mVolumeImpl) + { + LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + mVolumeImpl = new LLVolumeImplFlexible(this, data); + } + } + else + { + // Mark the parameter not in use + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, false); + if (mVolumeImpl) + { + delete mVolumeImpl; + mVolumeImpl = NULL; + if (mDrawable.notNull()) + { + // Undo the damage we did to this matrix + mDrawable->updateXform(FALSE); + } + } + } + + if (is404) + { + setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI)); + //render prim proxy when mesh loading attempts give up + volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE); - } + } - if ((LLPrimitive::setVolume(volume_params, lod, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged) - { - mFaceMappingChanged = TRUE; - - if (mVolumeImpl) - { - mVolumeImpl->onSetVolume(volume_params, mLOD); - } - - updateSculptTexture(); + if ((LLPrimitive::setVolume(volume_params, lod, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged) + { + mFaceMappingChanged = TRUE; + + if (mVolumeImpl) + { + mVolumeImpl->onSetVolume(volume_params, mLOD); + } + + updateSculptTexture(); - if (isSculpted()) - { - updateSculptTexture(); - // if it's a mesh - if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - { - if (!getVolume()->isMeshAssetLoaded()) - { - //load request not yet issued, request pipeline load this mesh - LLUUID asset_id = volume_params.getSculptID(); - S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod, last_lod); - if (available_lod != lod) - { - LLPrimitive::setVolume(volume_params, available_lod); - } - } - - } - else // otherwise is sculptie - { - if (mSculptTexture.notNull()) - { - sculpt(); - } - } - } + if (isSculpted()) + { + updateSculptTexture(); + // if it's a mesh + if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { + if (!getVolume()->isMeshAssetLoaded()) + { + //load request not yet issued, request pipeline load this mesh + LLUUID asset_id = volume_params.getSculptID(); + S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod, last_lod); + if (available_lod != lod) + { + LLPrimitive::setVolume(volume_params, available_lod); + } + } + + } + else // otherwise is sculptie + { + if (mSculptTexture.notNull()) + { + sculpt(); + } + } + } - static LLCachedControl use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false); + static LLCachedControl use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false); - bool cache_in_vram = use_transform_feedback && gTransformPositionProgram.mProgramObject && - (!mVolumeImpl || !mVolumeImpl->isVolumeUnique()); + bool cache_in_vram = use_transform_feedback && gTransformPositionProgram.mProgramObject && + (!mVolumeImpl || !mVolumeImpl->isVolumeUnique()); - if (cache_in_vram) - { //this volume might be used as source data for a transform object, put it in vram - LLVolume* volume = getVolume(); - for (S32 i = 0; i < volume->getNumFaces(); ++i) - { - const LLVolumeFace& face = volume->getVolumeFace(i); - if (face.mVertexBuffer.notNull()) - { //already cached - break; - } - volume->genTangents(i); - LLFace::cacheFaceInVRAM(face); - } - } + if (cache_in_vram) + { //this volume might be used as source data for a transform object, put it in vram + LLVolume* volume = getVolume(); + for (S32 i = 0; i < volume->getNumFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + if (face.mVertexBuffer.notNull()) + { //already cached + break; + } + volume->genTangents(i); + LLFace::cacheFaceInVRAM(face); + } + } - return TRUE; - } - else if (NO_LOD == lod) - { - LLSculptIDSize::instance().resetSizeSum(volume_params.getSculptID()); - } + return TRUE; + } + else if (NO_LOD == lod) + { + LLSculptIDSize::instance().resetSizeSum(volume_params.getSculptID()); + } - return FALSE; + return FALSE; } void LLVOVolume::updateSculptTexture() { - LLPointer old_sculpt = mSculptTexture; + LLPointer old_sculpt = mSculptTexture; - if (isSculpted() && !isMesh()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID id = sculpt_params->getSculptTexture(); - if (id.notNull()) - { - mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - } - } - else - { - mSculptTexture = NULL; - } + if (isSculpted() && !isMesh()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID id = sculpt_params->getSculptTexture(); + if (id.notNull()) + { + mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } + } + else + { + mSculptTexture = NULL; + } - if (mSculptTexture != old_sculpt) - { - if (old_sculpt.notNull()) - { - old_sculpt->removeVolume(LLRender::SCULPT_TEX, this); - } - if (mSculptTexture.notNull()) - { - mSculptTexture->addVolume(LLRender::SCULPT_TEX, this); - } - } - + if (mSculptTexture != old_sculpt) + { + if (old_sculpt.notNull()) + { + old_sculpt->removeVolume(LLRender::SCULPT_TEX, this); + } + if (mSculptTexture.notNull()) + { + mSculptTexture->addVolume(LLRender::SCULPT_TEX, this); + } + } + } void LLVOVolume::updateVisualComplexity() @@ -1136,8 +1136,8 @@ void LLVOVolume::updateVisualComplexity() void LLVOVolume::notifyMeshLoaded() { - mSculptChanged = TRUE; - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); + mSculptChanged = TRUE; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); if (getAvatar() && !isAnimatedObject()) { @@ -1152,124 +1152,124 @@ void LLVOVolume::notifyMeshLoaded() // sculpt replaces generate() for sculpted surfaces void LLVOVolume::sculpt() -{ - if (mSculptTexture.notNull()) - { - U16 sculpt_height = 0; - U16 sculpt_width = 0; - S8 sculpt_components = 0; - const U8* sculpt_data = NULL; - - S32 discard_level = mSculptTexture->getCachedRawImageLevel() ; - LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ; - - S32 max_discard = mSculptTexture->getMaxDiscardLevel(); - if (discard_level > max_discard) - { - discard_level = max_discard; // clamp to the best we can do - } - if(discard_level > MAX_DISCARD_LEVEL) - { - return; //we think data is not ready yet. - } +{ + if (mSculptTexture.notNull()) + { + U16 sculpt_height = 0; + U16 sculpt_width = 0; + S8 sculpt_components = 0; + const U8* sculpt_data = NULL; + + S32 discard_level = mSculptTexture->getCachedRawImageLevel() ; + LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ; + + S32 max_discard = mSculptTexture->getMaxDiscardLevel(); + if (discard_level > max_discard) + { + discard_level = max_discard; // clamp to the best we can do + } + if(discard_level > MAX_DISCARD_LEVEL) + { + return; //we think data is not ready yet. + } - S32 current_discard = getVolume()->getSculptLevel() ; - if(current_discard < -2) - { - static S32 low_sculpty_discard_warning_count = 1; - S32 exponent = llmax(1, llfloor( log10((F64) low_sculpty_discard_warning_count) )); - S32 interval = pow(10.0, exponent); - if ( low_sculpty_discard_warning_count < 10 || - (low_sculpty_discard_warning_count % interval) == 0) - { // Log first 10 time, then decreasing intervals afterwards otherwise this can flood the logs - LL_WARNS() << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() - << " at " << current_discard - << " is less than -2." - << " Hit this " << low_sculpty_discard_warning_count << " times" - << LL_ENDL; - } - low_sculpty_discard_warning_count++; - - // corrupted volume... don't update the sculpty - return; - } - else if (current_discard > MAX_DISCARD_LEVEL) - { - static S32 high_sculpty_discard_warning_count = 1; - S32 exponent = llmax(1, llfloor( log10((F64) high_sculpty_discard_warning_count) )); - S32 interval = pow(10.0, exponent); - if ( high_sculpty_discard_warning_count < 10 || - (high_sculpty_discard_warning_count % interval) == 0) - { // Log first 10 time, then decreasing intervals afterwards otherwise this can flood the logs - LL_WARNS() << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() - << " at " << current_discard - << " is more than than allowed max of " << MAX_DISCARD_LEVEL - << ". Hit this " << high_sculpty_discard_warning_count << " times" - << LL_ENDL; - } - high_sculpty_discard_warning_count++; + S32 current_discard = getVolume()->getSculptLevel() ; + if(current_discard < -2) + { + static S32 low_sculpty_discard_warning_count = 1; + S32 exponent = llmax(1, llfloor( log10((F64) low_sculpty_discard_warning_count) )); + S32 interval = pow(10.0, exponent); + if ( low_sculpty_discard_warning_count < 10 || + (low_sculpty_discard_warning_count % interval) == 0) + { // Log first 10 time, then decreasing intervals afterwards otherwise this can flood the logs + LL_WARNS() << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() + << " at " << current_discard + << " is less than -2." + << " Hit this " << low_sculpty_discard_warning_count << " times" + << LL_ENDL; + } + low_sculpty_discard_warning_count++; + + // corrupted volume... don't update the sculpty + return; + } + else if (current_discard > MAX_DISCARD_LEVEL) + { + static S32 high_sculpty_discard_warning_count = 1; + S32 exponent = llmax(1, llfloor( log10((F64) high_sculpty_discard_warning_count) )); + S32 interval = pow(10.0, exponent); + if ( high_sculpty_discard_warning_count < 10 || + (high_sculpty_discard_warning_count % interval) == 0) + { // Log first 10 time, then decreasing intervals afterwards otherwise this can flood the logs + LL_WARNS() << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() + << " at " << current_discard + << " is more than than allowed max of " << MAX_DISCARD_LEVEL + << ". Hit this " << high_sculpty_discard_warning_count << " times" + << LL_ENDL; + } + high_sculpty_discard_warning_count++; - // corrupted volume... don't update the sculpty - return; - } + // corrupted volume... don't update the sculpty + return; + } - if (current_discard == discard_level) // no work to do here - return; - - if(!raw_image) - { - llassert(discard_level < 0) ; + if (current_discard == discard_level) // no work to do here + return; + + if(!raw_image) + { + llassert(discard_level < 0) ; - sculpt_width = 0; - sculpt_height = 0; - sculpt_data = NULL ; + sculpt_width = 0; + sculpt_height = 0; + sculpt_data = NULL ; - if(LLViewerTextureManager::sTesterp) - { - LLViewerTextureManager::sTesterp->updateGrayTextureBinding(); - } - } - else - { - sculpt_height = raw_image->getHeight(); - sculpt_width = raw_image->getWidth(); - sculpt_components = raw_image->getComponents(); - - sculpt_data = raw_image->getData(); - - if(LLViewerTextureManager::sTesterp) - { - mSculptTexture->updateBindStatsForTester() ; - } - } - getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level, mSculptTexture->isMissingAsset()); + if(LLViewerTextureManager::sTesterp) + { + LLViewerTextureManager::sTesterp->updateGrayTextureBinding(); + } + } + else + { + sculpt_height = raw_image->getHeight(); + sculpt_width = raw_image->getWidth(); + sculpt_components = raw_image->getComponents(); + + sculpt_data = raw_image->getData(); + + if(LLViewerTextureManager::sTesterp) + { + mSculptTexture->updateBindStatsForTester() ; + } + } + getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level, mSculptTexture->isMissingAsset()); - //notify rebuild any other VOVolumes that reference this sculpty volume - for (S32 i = 0; i < mSculptTexture->getNumVolumes(LLRender::SCULPT_TEX); ++i) - { - LLVOVolume* volume = (*(mSculptTexture->getVolumeList(LLRender::SCULPT_TEX)))[i]; - if (volume != this && volume->getVolume() == getVolume()) - { - gPipeline.markRebuild(volume->mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE); - } - } - } + //notify rebuild any other VOVolumes that reference this sculpty volume + for (S32 i = 0; i < mSculptTexture->getNumVolumes(LLRender::SCULPT_TEX); ++i) + { + LLVOVolume* volume = (*(mSculptTexture->getVolumeList(LLRender::SCULPT_TEX)))[i]; + if (volume != this && volume->getVolume() == getVolume()) + { + gPipeline.markRebuild(volume->mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE); + } + } + } } -S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius, F32 lod_factor) +S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius, F32 lod_factor) { - S32 cur_detail; - if (LLPipeline::sDynamicLOD) - { - // We've got LOD in the profile, and in the twist. Use radius. - F32 tan_angle = (lod_factor*radius)/distance; - cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f)); - } - else - { - cur_detail = llclamp((S32) (sqrtf(radius)*lod_factor*4.f), 0, 3); - } - return cur_detail; + S32 cur_detail; + if (LLPipeline::sDynamicLOD) + { + // We've got LOD in the profile, and in the twist. Use radius. + F32 tan_angle = (lod_factor*radius)/distance; + cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f)); + } + else + { + cur_detail = llclamp((S32) (sqrtf(radius)*lod_factor*4.f), 0, 3); + } + return cur_detail; } std::string get_debug_object_lod_text(LLVOVolume *rootp) @@ -1314,28 +1314,28 @@ std::string get_debug_object_lod_text(LLVOVolume *rootp) BOOL LLVOVolume::calcLOD() { - if (mDrawable.isNull()) - { - return FALSE; - } + if (mDrawable.isNull()) + { + return FALSE; + } - S32 cur_detail = 0; - - F32 radius; - F32 distance; - F32 lod_factor = LLVOVolume::sLODFactor; + S32 cur_detail = 0; + + F32 radius; + F32 distance; + F32 lod_factor = LLVOVolume::sLODFactor; - if (mDrawable->isState(LLDrawable::RIGGED)) - { - LLVOAvatar* avatar = getAvatar(); - - // Not sure how this can really happen, but alas it does. Better exit here than crashing. - if( !avatar || !avatar->mDrawable ) - { - return FALSE; - } + if (mDrawable->isState(LLDrawable::RIGGED)) + { + LLVOAvatar* avatar = getAvatar(); + + // Not sure how this can really happen, but alas it does. Better exit here than crashing. + if( !avatar || !avatar->mDrawable ) + { + return FALSE; + } - distance = avatar->mDrawable->mDistanceWRTCamera; + distance = avatar->mDrawable->mDistanceWRTCamera; if (avatar->isControlAvatar()) @@ -1362,20 +1362,20 @@ BOOL LLVOVolume::calcLOD() LL_DEBUGS("DynamicBox","CalcLOD") << "avatar distance/radius uninitialized, skipping" << LL_ENDL; return FALSE; } - } - else - { - distance = mDrawable->mDistanceWRTCamera; - radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); + } + else + { + distance = mDrawable->mDistanceWRTCamera; + radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); if (distance <= 0.f || radius <= 0.f) { LL_DEBUGS("DynamicBox","CalcLOD") << "non-avatar distance/radius uninitialized, skipping" << LL_ENDL; return FALSE; } - } - - //hold onto unmodified distance for debugging - //F32 debug_distance = distance; + } + + //hold onto unmodified distance for debugging + //F32 debug_distance = distance; mLODDistance = distance; mLODRadius = radius; @@ -1391,24 +1391,24 @@ BOOL LLVOVolume::calcLOD() distance *= sDistanceFactor; - F32 rampDist = LLVOVolume::sLODFactor * 2; - - if (distance < rampDist) - { - // Boost LOD when you're REALLY close - distance *= 1.0f/rampDist; - distance *= distance; - distance *= rampDist; - } - + F32 rampDist = LLVOVolume::sLODFactor * 2; + + if (distance < rampDist) + { + // Boost LOD when you're REALLY close + distance *= 1.0f/rampDist; + distance *= distance; + distance *= rampDist; + } + - distance *= F_PI/3.f; + distance *= F_PI/3.f; - static LLCachedControl ignore_fov_zoom(gSavedSettings,"IgnoreFOVZoomForLODs"); - if(!ignore_fov_zoom) - { - lod_factor *= DEFAULT_FIELD_OF_VIEW / LLViewerCamera::getInstance()->getDefaultFOV(); - } + static LLCachedControl ignore_fov_zoom(gSavedSettings,"IgnoreFOVZoomForLODs"); + if(!ignore_fov_zoom) + { + lod_factor *= DEFAULT_FIELD_OF_VIEW / LLViewerCamera::getInstance()->getDefaultFOV(); + } mLODAdjustedDistance = distance; @@ -1431,51 +1431,51 @@ BOOL LLVOVolume::calcLOD() setDebugText(llformat("TRIS SHOWN %d EST %d", total_tris, est_max_tris)); } } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && - mDrawable->getFace(0)) - { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && + mDrawable->getFace(0)) + { // This is a debug display for LODs. Please don't put the texture index here. setDebugText(llformat("%d", cur_detail)); - } + } - if (cur_detail != mLOD) - { + if (cur_detail != mLOD) + { LL_DEBUGS("DynamicBox","CalcLOD") << "new LOD " << cur_detail << " change from " << mLOD << " distance " << distance << " radius " << radius << " rampDist " << rampDist << " drawable rigged? " << (mDrawable ? (S32) mDrawable->isState(LLDrawable::RIGGED) : (S32) -1) - << " mRiggedVolume " << (void*)getRiggedVolume() + << " mRiggedVolume " << (void*)getRiggedVolume() << " distanceWRTCamera " << (mDrawable ? mDrawable->mDistanceWRTCamera : -1.f) << LL_ENDL; - mAppAngle = ll_round((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); - mLOD = cur_detail; + mAppAngle = ll_round((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); + mLOD = cur_detail; return TRUE; - } + } - return FALSE; + return FALSE; } BOOL LLVOVolume::updateLOD() { - if (mDrawable.isNull()) - { - return FALSE; - } - - BOOL lod_changed = FALSE; - - if (!LLSculptIDSize::instance().isUnloaded(getVolume()->getParams().getSculptID())) - { - lod_changed = calcLOD(); - } - else - { - return FALSE; - } + if (mDrawable.isNull()) + { + return FALSE; + } + + BOOL lod_changed = FALSE; - if (lod_changed) - { + if (!LLSculptIDSize::instance().isUnloaded(getVolume()->getParams().getSculptID())) + { + lod_changed = calcLOD(); + } + else + { + return FALSE; + } + + if (lod_changed) + { if (debugLoggingEnabled("AnimatedObjectsLinkset")) { if (isAnimatedObject() && isRiggedMesh()) @@ -1486,153 +1486,153 @@ BOOL LLVOVolume::updateLOD() } } - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); - mLODChanged = TRUE; - } - else - { - F32 new_radius = getBinRadius(); - F32 old_radius = mDrawable->getBinRadius(); - if (new_radius < old_radius * 0.9f || new_radius > old_radius*1.1f) - { - gPipeline.markPartitionMove(mDrawable); - } - } + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + mLODChanged = TRUE; + } + else + { + F32 new_radius = getBinRadius(); + F32 old_radius = mDrawable->getBinRadius(); + if (new_radius < old_radius * 0.9f || new_radius > old_radius*1.1f) + { + gPipeline.markPartitionMove(mDrawable); + } + } - lod_changed = lod_changed || LLViewerObject::updateLOD(); - - return lod_changed; + lod_changed = lod_changed || LLViewerObject::updateLOD(); + + return lod_changed; } BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp) { - if (!LLViewerObject::setDrawableParent(parentp)) - { - // no change in drawable parent - return FALSE; - } + if (!LLViewerObject::setDrawableParent(parentp)) + { + // no change in drawable parent + return FALSE; + } - if (!mDrawable->isRoot()) - { - // rebuild vertices in parent relative space - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); + if (!mDrawable->isRoot()) + { + // rebuild vertices in parent relative space + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - if (mDrawable->isActive() && !parentp->isActive()) - { - parentp->makeActive(); - } - else if (mDrawable->isStatic() && parentp->isActive()) - { - mDrawable->makeActive(); - } - } - - return TRUE; + if (mDrawable->isActive() && !parentp->isActive()) + { + parentp->makeActive(); + } + else if (mDrawable->isStatic() && parentp->isActive()) + { + mDrawable->makeActive(); + } + } + + return TRUE; } void LLVOVolume::updateFaceFlags() { - // There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces() - for (S32 i = 0; i < getVolume()->getNumFaces() && i < mDrawable->getNumFaces(); i++) - { - LLFace *face = mDrawable->getFace(i); - if (face) - { - BOOL fullbright = getTE(i)->getFullbright(); - face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); + // There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces() + for (S32 i = 0; i < getVolume()->getNumFaces() && i < mDrawable->getNumFaces(); i++) + { + LLFace *face = mDrawable->getFace(i); + if (face) + { + BOOL fullbright = getTE(i)->getFullbright(); + face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); - if (fullbright || (mMaterial == LL_MCODE_LIGHT)) - { - face->setState(LLFace::FULLBRIGHT); - } - if (mDrawable->isLight()) - { - face->setState(LLFace::LIGHT); - } - if (isHUDAttachment()) - { - face->setState(LLFace::HUD_RENDER); - } - } - } + if (fullbright || (mMaterial == LL_MCODE_LIGHT)) + { + face->setState(LLFace::FULLBRIGHT); + } + if (mDrawable->isLight()) + { + face->setState(LLFace::LIGHT); + } + if (isHUDAttachment()) + { + face->setState(LLFace::HUD_RENDER); + } + } + } } BOOL LLVOVolume::setParent(LLViewerObject* parent) { - BOOL ret = FALSE ; + BOOL ret = FALSE ; LLViewerObject *old_parent = (LLViewerObject*) getParent(); - if (parent != old_parent) - { - ret = LLViewerObject::setParent(parent); - if (ret && mDrawable) - { - gPipeline.markMoved(mDrawable); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - } + if (parent != old_parent) + { + ret = LLViewerObject::setParent(parent); + if (ret && mDrawable) + { + gPipeline.markMoved(mDrawable); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); + } onReparent(old_parent, parent); - } + } - return ret ; + return ret ; } // NOTE: regenFaces() MUST be followed by genTriangles()! void LLVOVolume::regenFaces() { - // remove existing faces - BOOL count_changed = mNumFaces != getNumTEs(); - - if (count_changed) - { - deleteFaces(); - // add new faces - mNumFaces = getNumTEs(); - } - - for (S32 i = 0; i < mNumFaces; i++) - { - LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i); - if (!facep) continue; + // remove existing faces + BOOL count_changed = mNumFaces != getNumTEs(); + + if (count_changed) + { + deleteFaces(); + // add new faces + mNumFaces = getNumTEs(); + } + + for (S32 i = 0; i < mNumFaces; i++) + { + LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i); + if (!facep) continue; - facep->setTEOffset(i); - facep->setTexture(getTEImage(i)); - if (facep->getTextureEntry()->getMaterialParams().notNull()) - { - facep->setNormalMap(getTENormalMap(i)); - facep->setSpecularMap(getTESpecularMap(i)); - } - facep->setViewerObject(this); - - // If the face had media on it, this will have broken the link between the LLViewerMediaTexture and the face. - // Re-establish the link. - if((int)mMediaImplList.size() > i) - { - if(mMediaImplList[i]) - { - LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[i]->getMediaTextureID()) ; - if(media_tex) - { - media_tex->addMediaToFace(facep) ; - } - } - } - } - - if (!count_changed) - { - updateFaceFlags(); - } + facep->setTEOffset(i); + facep->setTexture(getTEImage(i)); + if (facep->getTextureEntry()->getMaterialParams().notNull()) + { + facep->setNormalMap(getTENormalMap(i)); + facep->setSpecularMap(getTESpecularMap(i)); + } + facep->setViewerObject(this); + + // If the face had media on it, this will have broken the link between the LLViewerMediaTexture and the face. + // Re-establish the link. + if((int)mMediaImplList.size() > i) + { + if(mMediaImplList[i]) + { + LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[i]->getMediaTextureID()) ; + if(media_tex) + { + media_tex->addMediaToFace(facep) ; + } + } + } + } + + if (!count_changed) + { + updateFaceFlags(); + } } BOOL LLVOVolume::genBBoxes(BOOL force_global) { - BOOL res = TRUE; + BOOL res = TRUE; - LLVector4a min,max; + LLVector4a min,max; - min.clear(); - max.clear(); + min.clear(); + max.clear(); - BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED); + BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED); if (getRiggedVolume()) { @@ -1644,11 +1644,11 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) updateRiggedVolume(); } - LLVolume* volume = mRiggedVolume; - if (!volume) - { - volume = getVolume(); - } + LLVolume* volume = mRiggedVolume; + if (!volume) + { + volume = getVolume(); + } bool any_valid_boxes = false; @@ -1657,45 +1657,45 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) LL_DEBUGS("RiggedBox") << "rebuilding box, volume face count " << getVolume()->getNumVolumeFaces() << " drawable face count " << mDrawable->getNumFaces() << LL_ENDL; } // There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces() - for (S32 i = 0; - i < getVolume()->getNumVolumeFaces() && i < mDrawable->getNumFaces() && i < getNumTEs(); - i++) - { - LLFace *face = mDrawable->getFace(i); - if (!face) - { - continue; - } + for (S32 i = 0; + i < getVolume()->getNumVolumeFaces() && i < mDrawable->getNumFaces() && i < getNumTEs(); + i++) + { + LLFace *face = mDrawable->getFace(i); + if (!face) + { + continue; + } BOOL face_res = face->genVolumeBBoxes(*volume, i, mRelativeXform, (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global); res &= face_res; // note that this result is never used - + // MAINT-8264 - ignore bboxes of ill-formed faces. if (!face_res) { continue; } - if (rebuild) - { + if (rebuild) + { if (getRiggedVolume()) { LL_DEBUGS("RiggedBox") << "rebuilding box, face " << i << " extents " << face->mExtents[0] << ", " << face->mExtents[1] << LL_ENDL; } - if (!any_valid_boxes) - { - min = face->mExtents[0]; - max = face->mExtents[1]; + if (!any_valid_boxes) + { + min = face->mExtents[0]; + max = face->mExtents[1]; any_valid_boxes = true; - } - else - { - min.setMin(min, face->mExtents[0]); - max.setMax(max, face->mExtents[1]); - } - } - } + } + else + { + min.setMin(min, face->mExtents[0]); + max.setMax(max, face->mExtents[1]); + } + } + } if (any_valid_boxes) { @@ -1708,7 +1708,7 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) mDrawable->setSpatialExtents(min,max); min.add(max); min.mul(0.5f); - mDrawable->setPositionGroup(min); + mDrawable->setPositionGroup(min); } updateRadius(); @@ -1718,121 +1718,121 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) { LL_DEBUGS("RiggedBox") << "genBBoxes failed to find any valid face boxes" << LL_ENDL; } - - return res; + + return res; } void LLVOVolume::preRebuild() { - if (mVolumeImpl != NULL) - { - mVolumeImpl->preRebuild(); - } + if (mVolumeImpl != NULL) + { + mVolumeImpl->preRebuild(); + } } void LLVOVolume::updateRelativeXform(bool force_identity) { - if (mVolumeImpl) - { - mVolumeImpl->updateRelativeXform(force_identity); - return; - } - - LLDrawable* drawable = mDrawable; - - if (drawable->isState(LLDrawable::RIGGED) && mRiggedVolume.notNull()) - { //rigged volume (which is in agent space) is used for generating bounding boxes etc - //inverse of render matrix should go to partition space - mRelativeXform = getRenderMatrix(); - - F32* dst = (F32*) mRelativeXformInvTrans.mMatrix; - F32* src = (F32*) mRelativeXform.mMatrix; - dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; - dst[3] = src[4]; dst[4] = src[5]; dst[5] = src[6]; - dst[6] = src[8]; dst[7] = src[9]; dst[8] = src[10]; - - mRelativeXform.invert(); - mRelativeXformInvTrans.transpose(); - } - else if (drawable->isActive() || force_identity) - { - // setup relative transforms - LLQuaternion delta_rot; - LLVector3 delta_pos, delta_scale; - - //matrix from local space to parent relative/global space - bool use_identity = force_identity || drawable->isSpatialRoot(); - delta_rot = use_identity ? LLQuaternion() : mDrawable->getRotation(); - delta_pos = use_identity ? LLVector3(0,0,0) : mDrawable->getPosition(); - delta_scale = mDrawable->getScale(); - - // Vertex transform (4x4) - LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot; - LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot; - LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot; - - mRelativeXform.initRows(LLVector4(x_axis, 0.f), - LLVector4(y_axis, 0.f), - LLVector4(z_axis, 0.f), - LLVector4(delta_pos, 1.f)); + if (mVolumeImpl) + { + mVolumeImpl->updateRelativeXform(force_identity); + return; + } + + LLDrawable* drawable = mDrawable; + + if (drawable->isState(LLDrawable::RIGGED) && mRiggedVolume.notNull()) + { //rigged volume (which is in agent space) is used for generating bounding boxes etc + //inverse of render matrix should go to partition space + mRelativeXform = getRenderMatrix(); + + F32* dst = (F32*) mRelativeXformInvTrans.mMatrix; + F32* src = (F32*) mRelativeXform.mMatrix; + dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; + dst[3] = src[4]; dst[4] = src[5]; dst[5] = src[6]; + dst[6] = src[8]; dst[7] = src[9]; dst[8] = src[10]; + + mRelativeXform.invert(); + mRelativeXformInvTrans.transpose(); + } + else if (drawable->isActive() || force_identity) + { + // setup relative transforms + LLQuaternion delta_rot; + LLVector3 delta_pos, delta_scale; + + //matrix from local space to parent relative/global space + bool use_identity = force_identity || drawable->isSpatialRoot(); + delta_rot = use_identity ? LLQuaternion() : mDrawable->getRotation(); + delta_pos = use_identity ? LLVector3(0,0,0) : mDrawable->getPosition(); + delta_scale = mDrawable->getScale(); + + // Vertex transform (4x4) + LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot; + LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot; + LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot; + + mRelativeXform.initRows(LLVector4(x_axis, 0.f), + LLVector4(y_axis, 0.f), + LLVector4(z_axis, 0.f), + LLVector4(delta_pos, 1.f)); - - // compute inverse transpose for normals - // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); - // mRelativeXformInvTrans.invert(); - // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); - // grumble - invert is NOT a matrix invert, so we do it by hand: - - LLMatrix3 rot_inverse = LLMatrix3(~delta_rot); - - LLMatrix3 scale_inverse; - scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX], - LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY], - LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]); - - - mRelativeXformInvTrans = rot_inverse * scale_inverse; + + // compute inverse transpose for normals + // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); + // mRelativeXformInvTrans.invert(); + // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); + // grumble - invert is NOT a matrix invert, so we do it by hand: + + LLMatrix3 rot_inverse = LLMatrix3(~delta_rot); + + LLMatrix3 scale_inverse; + scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX], + LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY], + LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]); + + + mRelativeXformInvTrans = rot_inverse * scale_inverse; - mRelativeXformInvTrans.transpose(); - } - else - { - LLVector3 pos = getPosition(); - LLVector3 scale = getScale(); - LLQuaternion rot = getRotation(); - - if (mParent) - { - pos *= mParent->getRotation(); - pos += mParent->getPosition(); - rot *= mParent->getRotation(); - } - - //LLViewerRegion* region = getRegion(); - //pos += region->getOriginAgent(); - - LLVector3 x_axis = LLVector3(scale.mV[VX], 0.f, 0.f) * rot; - LLVector3 y_axis = LLVector3(0.f, scale.mV[VY], 0.f) * rot; - LLVector3 z_axis = LLVector3(0.f, 0.f, scale.mV[VZ]) * rot; - - mRelativeXform.initRows(LLVector4(x_axis, 0.f), - LLVector4(y_axis, 0.f), - LLVector4(z_axis, 0.f), - LLVector4(pos, 1.f)); - - // compute inverse transpose for normals - LLMatrix3 rot_inverse = LLMatrix3(~rot); - - LLMatrix3 scale_inverse; - scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX], - LLVector3(0.0, 1.0, 0.0) / scale.mV[VY], - LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]); - - - mRelativeXformInvTrans = rot_inverse * scale_inverse; + mRelativeXformInvTrans.transpose(); + } + else + { + LLVector3 pos = getPosition(); + LLVector3 scale = getScale(); + LLQuaternion rot = getRotation(); + + if (mParent) + { + pos *= mParent->getRotation(); + pos += mParent->getPosition(); + rot *= mParent->getRotation(); + } + + //LLViewerRegion* region = getRegion(); + //pos += region->getOriginAgent(); + + LLVector3 x_axis = LLVector3(scale.mV[VX], 0.f, 0.f) * rot; + LLVector3 y_axis = LLVector3(0.f, scale.mV[VY], 0.f) * rot; + LLVector3 z_axis = LLVector3(0.f, 0.f, scale.mV[VZ]) * rot; + + mRelativeXform.initRows(LLVector4(x_axis, 0.f), + LLVector4(y_axis, 0.f), + LLVector4(z_axis, 0.f), + LLVector4(pos, 1.f)); + + // compute inverse transpose for normals + LLMatrix3 rot_inverse = LLMatrix3(~rot); + + LLMatrix3 scale_inverse; + scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX], + LLVector3(0.0, 1.0, 0.0) / scale.mV[VY], + LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]); + + + mRelativeXformInvTrans = rot_inverse * scale_inverse; - mRelativeXformInvTrans.transpose(); - } + mRelativeXformInvTrans.transpose(); + } } static LLTrace::BlockTimerStatHandle FTM_GEN_FLEX("Generate Flexies"); @@ -1841,918 +1841,918 @@ static LLTrace::BlockTimerStatHandle FTM_UPDATE_RIGGED_VOLUME("Update Rigged"); bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) { - bool regen_faces = false; + bool regen_faces = false; - LLVolume *old_volumep, *new_volumep; - F32 old_lod, new_lod; - S32 old_num_faces, new_num_faces; + LLVolume *old_volumep, *new_volumep; + F32 old_lod, new_lod; + S32 old_num_faces, new_num_faces; - old_volumep = getVolume(); - old_lod = old_volumep->getDetail(); - old_num_faces = old_volumep->getNumFaces(); - old_volumep = NULL; + old_volumep = getVolume(); + old_lod = old_volumep->getDetail(); + old_num_faces = old_volumep->getNumFaces(); + old_volumep = NULL; - { - LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME); - const LLVolumeParams &volume_params = getVolume()->getParams(); - setVolume(volume_params, 0); - } + { + LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME); + const LLVolumeParams &volume_params = getVolume()->getParams(); + setVolume(volume_params, 0); + } - new_volumep = getVolume(); - new_lod = new_volumep->getDetail(); - new_num_faces = new_volumep->getNumFaces(); - new_volumep = NULL; + new_volumep = getVolume(); + new_lod = new_volumep->getDetail(); + new_num_faces = new_volumep->getNumFaces(); + new_volumep = NULL; - if ((new_lod != old_lod) || mSculptChanged) - { + if ((new_lod != old_lod) || mSculptChanged) + { if (mDrawable->isState(LLDrawable::RIGGED)) { updateVisualComplexity(); } - compiled = TRUE; - sNumLODChanges += new_num_faces; + compiled = TRUE; + sNumLODChanges += new_num_faces; - if ((S32)getNumTEs() != getVolume()->getNumFaces()) - { - setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. - } + if ((S32)getNumTEs() != getVolume()->getNumFaces()) + { + setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. + } - drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() + drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() - { - LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); - regen_faces = new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs(); - if (regen_faces) - { - regenFaces(); - } + { + LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); + regen_faces = new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs(); + if (regen_faces) + { + regenFaces(); + } - if (mSculptChanged) - { //changes in sculpt maps can thrash an object bounding box without - //triggering a spatial group bounding box update -- force spatial group - //to update bounding boxes - LLSpatialGroup* group = mDrawable->getSpatialGroup(); - if (group) - { - group->unbound(); - } - } - } - } + if (mSculptChanged) + { //changes in sculpt maps can thrash an object bounding box without + //triggering a spatial group bounding box update -- force spatial group + //to update bounding boxes + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->unbound(); + } + } + } + } - return regen_faces; + return regen_faces; } BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_PRIMITIVES); - - if (mDrawable->isState(LLDrawable::REBUILD_RIGGED)) - { - { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_RIGGED_VOLUME); - updateRiggedVolume(); - } - genBBoxes(FALSE); - mDrawable->clearState(LLDrawable::REBUILD_RIGGED); - } + LL_RECORD_BLOCK_TIME(FTM_UPDATE_PRIMITIVES); + + if (mDrawable->isState(LLDrawable::REBUILD_RIGGED)) + { + { + LL_RECORD_BLOCK_TIME(FTM_UPDATE_RIGGED_VOLUME); + updateRiggedVolume(); + } + genBBoxes(FALSE); + mDrawable->clearState(LLDrawable::REBUILD_RIGGED); + } - if (mVolumeImpl != NULL) - { - BOOL res; - { - LL_RECORD_BLOCK_TIME(FTM_GEN_FLEX); - res = mVolumeImpl->doUpdateGeometry(drawable); - } - updateFaceFlags(); - return res; - } - - LLSpatialGroup* group = drawable->getSpatialGroup(); - if (group) - { - group->dirtyMesh(); - } + if (mVolumeImpl != NULL) + { + BOOL res; + { + LL_RECORD_BLOCK_TIME(FTM_GEN_FLEX); + res = mVolumeImpl->doUpdateGeometry(drawable); + } + updateFaceFlags(); + return res; + } + + LLSpatialGroup* group = drawable->getSpatialGroup(); + if (group) + { + group->dirtyMesh(); + } - BOOL compiled = FALSE; - - updateRelativeXform(); - - if (mDrawable.isNull()) // Not sure why this is happening, but it is... - { - return TRUE; // No update to complete - } + BOOL compiled = FALSE; + + updateRelativeXform(); + + if (mDrawable.isNull()) // Not sure why this is happening, but it is... + { + return TRUE; // No update to complete + } - if (mVolumeChanged || mFaceMappingChanged) - { - dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + if (mVolumeChanged || mFaceMappingChanged) + { + dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); - bool was_regen_faces = false; + bool was_regen_faces = false; - if (mVolumeChanged) - { - was_regen_faces = lodOrSculptChanged(drawable, compiled); - drawable->setState(LLDrawable::REBUILD_VOLUME); - } - else if (mSculptChanged || mLODChanged) - { - compiled = TRUE; - was_regen_faces = lodOrSculptChanged(drawable, compiled); - } + if (mVolumeChanged) + { + was_regen_faces = lodOrSculptChanged(drawable, compiled); + drawable->setState(LLDrawable::REBUILD_VOLUME); + } + else if (mSculptChanged || mLODChanged) + { + compiled = TRUE; + was_regen_faces = lodOrSculptChanged(drawable, compiled); + } - if (!was_regen_faces) { - LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); - regenFaces(); - } + if (!was_regen_faces) { + LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); + regenFaces(); + } - genBBoxes(FALSE); - } - else if (mLODChanged || mSculptChanged) - { - dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); - compiled = TRUE; - lodOrSculptChanged(drawable, compiled); - - if(drawable->isState(LLDrawable::REBUILD_RIGGED | LLDrawable::RIGGED)) - { - updateRiggedVolume(false); - } - genBBoxes(FALSE); - } - // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local - else - { - compiled = TRUE; - // All it did was move or we changed the texture coordinate offset - LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); - genBBoxes(FALSE); - } + genBBoxes(FALSE); + } + else if (mLODChanged || mSculptChanged) + { + dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + compiled = TRUE; + lodOrSculptChanged(drawable, compiled); + + if(drawable->isState(LLDrawable::REBUILD_RIGGED | LLDrawable::RIGGED)) + { + updateRiggedVolume(false); + } + genBBoxes(FALSE); + } + // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local + else + { + compiled = TRUE; + // All it did was move or we changed the texture coordinate offset + LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); + genBBoxes(FALSE); + } - // Update face flags - updateFaceFlags(); - - if(compiled) - { - LLPipeline::sCompiles++; - } - - mVolumeChanged = FALSE; - mLODChanged = FALSE; - mSculptChanged = FALSE; - mFaceMappingChanged = FALSE; - - return LLViewerObject::updateGeometry(drawable); + // Update face flags + updateFaceFlags(); + + if(compiled) + { + LLPipeline::sCompiles++; + } + + mVolumeChanged = FALSE; + mLODChanged = FALSE; + mSculptChanged = FALSE; + mFaceMappingChanged = FALSE; + + return LLViewerObject::updateGeometry(drawable); } void LLVOVolume::updateFaceSize(S32 idx) { - if( mDrawable->getNumFaces() <= idx ) - { - return; - } + if( mDrawable->getNumFaces() <= idx ) + { + return; + } - LLFace* facep = mDrawable->getFace(idx); - if (facep) - { - if (idx >= getVolume()->getNumVolumeFaces()) - { - facep->setSize(0,0, true); - } - else - { - const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); - facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, - true); // <--- volume faces should be padded for 16-byte alignment - - } - } + LLFace* facep = mDrawable->getFace(idx); + if (facep) + { + if (idx >= getVolume()->getNumVolumeFaces()) + { + facep->setSize(0,0, true); + } + else + { + const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); + facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, + true); // <--- volume faces should be padded for 16-byte alignment + + } + } } BOOL LLVOVolume::isRootEdit() const { - if (mParent && !((LLViewerObject*)mParent)->isAvatar()) - { - return FALSE; - } - return TRUE; + if (mParent && !((LLViewerObject*)mParent)->isAvatar()) + { + return FALSE; + } + return TRUE; } //virtual void LLVOVolume::setNumTEs(const U8 num_tes) { - const U8 old_num_tes = getNumTEs() ; - - if(old_num_tes && old_num_tes < num_tes) //new faces added - { - LLViewerObject::setNumTEs(num_tes) ; + const U8 old_num_tes = getNumTEs() ; + + if(old_num_tes && old_num_tes < num_tes) //new faces added + { + LLViewerObject::setNumTEs(num_tes) ; - if(mMediaImplList.size() >= old_num_tes && mMediaImplList[old_num_tes -1].notNull())//duplicate the last media textures if exists. - { - mMediaImplList.resize(num_tes) ; - const LLTextureEntry* te = getTE(old_num_tes - 1) ; - for(U8 i = old_num_tes; i < num_tes ; i++) - { - setTE(i, *te) ; - mMediaImplList[i] = mMediaImplList[old_num_tes -1] ; - } - mMediaImplList[old_num_tes -1]->setUpdated(TRUE) ; - } - } - else if(old_num_tes > num_tes && mMediaImplList.size() > num_tes) //old faces removed - { - U8 end = mMediaImplList.size() ; - for(U8 i = num_tes; i < end ; i++) - { - removeMediaImpl(i) ; - } - mMediaImplList.resize(num_tes) ; + if(mMediaImplList.size() >= old_num_tes && mMediaImplList[old_num_tes -1].notNull())//duplicate the last media textures if exists. + { + mMediaImplList.resize(num_tes) ; + const LLTextureEntry* te = getTE(old_num_tes - 1) ; + for(U8 i = old_num_tes; i < num_tes ; i++) + { + setTE(i, *te) ; + mMediaImplList[i] = mMediaImplList[old_num_tes -1] ; + } + mMediaImplList[old_num_tes -1]->setUpdated(TRUE) ; + } + } + else if(old_num_tes > num_tes && mMediaImplList.size() > num_tes) //old faces removed + { + U8 end = mMediaImplList.size() ; + for(U8 i = num_tes; i < end ; i++) + { + removeMediaImpl(i) ; + } + mMediaImplList.resize(num_tes) ; - LLViewerObject::setNumTEs(num_tes) ; - } - else - { - LLViewerObject::setNumTEs(num_tes) ; - } + LLViewerObject::setNumTEs(num_tes) ; + } + else + { + LLViewerObject::setNumTEs(num_tes) ; + } - return ; + return ; } //virtual void LLVOVolume::changeTEImage(S32 index, LLViewerTexture* imagep) { - BOOL changed = (mTEImages[index] != imagep); - LLViewerObject::changeTEImage(index, imagep); - if (changed) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } + BOOL changed = (mTEImages[index] != imagep); + LLViewerObject::changeTEImage(index, imagep); + if (changed) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } } void LLVOVolume::setTEImage(const U8 te, LLViewerTexture *imagep) { - BOOL changed = (mTEImages[te] != imagep); - LLViewerObject::setTEImage(te, imagep); - if (changed) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } + BOOL changed = (mTEImages[te] != imagep); + LLViewerObject::setTEImage(te, imagep); + if (changed) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } } S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid) { - S32 res = LLViewerObject::setTETexture(te, uuid); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTETexture(te, uuid); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEColor(const U8 te, const LLColor3& color) { - return setTEColor(te, LLColor4(color)); + return setTEColor(te, LLColor4(color)); } S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color) { - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS("MaterialTEs") << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; - } - else if (color != tep->getColor()) - { - F32 old_alpha = tep->getColor().mV[3]; - if (color.mV[3] != old_alpha) - { - gPipeline.markTextured(mDrawable); - //treat this alpha change as an LoD update since render batches may need to get rebuilt - mLODChanged = TRUE; - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); - } - retval = LLPrimitive::setTEColor(te, color); - if (mDrawable.notNull() && retval) - { - // These should only happen on updates which are not the initial update. - mDrawable->setState(LLDrawable::REBUILD_COLOR); - dirtyMesh(); - } - } + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS("MaterialTEs") << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + } + else if (color != tep->getColor()) + { + F32 old_alpha = tep->getColor().mV[3]; + if (color.mV[3] != old_alpha) + { + gPipeline.markTextured(mDrawable); + //treat this alpha change as an LoD update since render batches may need to get rebuilt + mLODChanged = TRUE; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + } + retval = LLPrimitive::setTEColor(te, color); + if (mDrawable.notNull() && retval) + { + // These should only happen on updates which are not the initial update. + mDrawable->setState(LLDrawable::REBUILD_COLOR); + dirtyMesh(); + } + } - return retval; + return retval; } S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap) { - S32 res = LLViewerObject::setTEBumpmap(te, bumpmap); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEBumpmap(te, bumpmap); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen) { - S32 res = LLViewerObject::setTETexGen(te, texgen); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTETexGen(te, texgen); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEMediaTexGen(const U8 te, const U8 media) { - S32 res = LLViewerObject::setTEMediaTexGen(te, media); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEMediaTexGen(te, media); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny) { - S32 res = LLViewerObject::setTEShiny(te, shiny); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEShiny(te, shiny); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright) { - S32 res = LLViewerObject::setTEFullbright(te, fullbright); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEFullbright(te, fullbright); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump) { - S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags) { - S32 res = LLViewerObject::setTEMediaFlags(te, media_flags); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEMediaFlags(te, media_flags); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEGlow(const U8 te, const F32 glow) { - S32 res = LLViewerObject::setTEGlow(te, glow); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEGlow(te, glow); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } void LLVOVolume::setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID &pMaterialID, const LLMaterialPtr pMaterialParams, U32 te) { - LLVOVolume* pVol = (LLVOVolume*)gObjectList.findObject(objectID); - if (pVol) - { - LL_DEBUGS("MaterialTEs") << "materialid " << pMaterialID.asString() << " to TE " << te << LL_ENDL; - if (te >= pVol->getNumTEs()) - return; + LLVOVolume* pVol = (LLVOVolume*)gObjectList.findObject(objectID); + if (pVol) + { + LL_DEBUGS("MaterialTEs") << "materialid " << pMaterialID.asString() << " to TE " << te << LL_ENDL; + if (te >= pVol->getNumTEs()) + return; - LLTextureEntry* texture_entry = pVol->getTE(te); - if (texture_entry && (texture_entry->getMaterialID() == pMaterialID)) - { - pVol->setTEMaterialParams(te, pMaterialParams); - } - } + LLTextureEntry* texture_entry = pVol->getTE(te); + if (texture_entry && (texture_entry->getMaterialID() == pMaterialID)) + { + pVol->setTEMaterialParams(te, pMaterialParams); + } + } } S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) { - S32 res = LLViewerObject::setTEMaterialID(te, pMaterialID); - LL_DEBUGS("MaterialTEs") << "te "<< (S32)te << " materialid " << pMaterialID.asString() << " res " << res - << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this), te) ? " selected" : " not selected" ) - << LL_ENDL; - - LL_DEBUGS("MaterialTEs") << " " << pMaterialID.asString() << LL_ENDL; - if (res) - { - LLMaterialMgr::instance().getTE(getRegion()->getRegionID(), pMaterialID, te, boost::bind(&LLVOVolume::setTEMaterialParamsCallbackTE, getID(), _1, _2, _3)); + S32 res = LLViewerObject::setTEMaterialID(te, pMaterialID); + LL_DEBUGS("MaterialTEs") << "te "<< (S32)te << " materialid " << pMaterialID.asString() << " res " << res + << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this), te) ? " selected" : " not selected" ) + << LL_ENDL; + + LL_DEBUGS("MaterialTEs") << " " << pMaterialID.asString() << LL_ENDL; + if (res) + { + LLMaterialMgr::instance().getTE(getRegion()->getRegionID(), pMaterialID, te, boost::bind(&LLVOVolume::setTEMaterialParamsCallbackTE, getID(), _1, _2, _3)); - setChanged(ALL_CHANGED); - if (!mDrawable.isNull()) - { - gPipeline.markTextured(mDrawable); - gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL); - } - mFaceMappingChanged = TRUE; - } - return res; + setChanged(ALL_CHANGED); + if (!mDrawable.isNull()) + { + gPipeline.markTextured(mDrawable); + gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL); + } + mFaceMappingChanged = TRUE; + } + return res; } bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture) { //Ok, here we have confirmation about texture creation, check our wait-list //and make changes, or return false - std::pair range = mWaitingTextureInfo.equal_range(texture->getID()); + std::pair range = mWaitingTextureInfo.equal_range(texture->getID()); - typedef std::map map_te_material; - map_te_material new_material; + typedef std::map map_te_material; + map_te_material new_material; - for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it) - { - LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te); + for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it) + { + LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te); - //here we just interesting in DIFFUSE_MAP only! - if(NULL != cur_material.get() && LLRender::DIFFUSE_MAP == range_it->second.map && GL_RGBA != texture->getPrimaryFormat()) - { //ok let's check the diffuse mode - switch(cur_material->getDiffuseAlphaMode()) - { - case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: - case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: - case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: - { //uups... we have non 32 bit texture with LLMaterial::DIFFUSE_ALPHA_MODE_* => LLMaterial::DIFFUSE_ALPHA_MODE_NONE - - LLMaterialPtr mat = NULL; - map_te_material::iterator it = new_material.find(range_it->second.te); - if(new_material.end() == it) { - mat = new LLMaterial(cur_material->asLLSD()); - new_material.insert(map_te_material::value_type(range_it->second.te, mat)); - } else { - mat = it->second; - } + //here we just interesting in DIFFUSE_MAP only! + if(NULL != cur_material.get() && LLRender::DIFFUSE_MAP == range_it->second.map && GL_RGBA != texture->getPrimaryFormat()) + { //ok let's check the diffuse mode + switch(cur_material->getDiffuseAlphaMode()) + { + case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: + case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: + case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: + { //uups... we have non 32 bit texture with LLMaterial::DIFFUSE_ALPHA_MODE_* => LLMaterial::DIFFUSE_ALPHA_MODE_NONE + + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } - mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); + mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); - } break; - } //switch - } //if - } //for + } break; + } //switch + } //if + } //for - //setup new materials - for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) - { - LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second); - LLViewerObject::setTEMaterialParams(it->first, it->second); - } + //setup new materials + for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) + { + LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second); + LLViewerObject::setTEMaterialParams(it->first, it->second); + } - //clear wait-list - mWaitingTextureInfo.erase(range.first, range.second); + //clear wait-list + mWaitingTextureInfo.erase(range.first, range.second); - return 0 != new_material.size(); + return 0 != new_material.size(); } bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture) { //Ok, here if we wait information about texture and it's missing //then depending from the texture map (diffuse, normal, or specular) //make changes in material and confirm it. If not return false. - std::pair range = mWaitingTextureInfo.equal_range(texture->getID()); - if(range.first == range.second) return false; + std::pair range = mWaitingTextureInfo.equal_range(texture->getID()); + if(range.first == range.second) return false; - typedef std::map map_te_material; - map_te_material new_material; - - for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it) - { - LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te); - if (cur_material.isNull()) - continue; + typedef std::map map_te_material; + map_te_material new_material; + + for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it) + { + LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te); + if (cur_material.isNull()) + continue; - switch(range_it->second.map) - { - case LLRender::DIFFUSE_MAP: - { - if(LLMaterial::DIFFUSE_ALPHA_MODE_NONE != cur_material->getDiffuseAlphaMode()) - { //missing texture + !LLMaterial::DIFFUSE_ALPHA_MODE_NONE => LLMaterial::DIFFUSE_ALPHA_MODE_NONE - LLMaterialPtr mat = NULL; - map_te_material::iterator it = new_material.find(range_it->second.te); - if(new_material.end() == it) { - mat = new LLMaterial(cur_material->asLLSD()); - new_material.insert(map_te_material::value_type(range_it->second.te, mat)); - } else { - mat = it->second; - } + switch(range_it->second.map) + { + case LLRender::DIFFUSE_MAP: + { + if(LLMaterial::DIFFUSE_ALPHA_MODE_NONE != cur_material->getDiffuseAlphaMode()) + { //missing texture + !LLMaterial::DIFFUSE_ALPHA_MODE_NONE => LLMaterial::DIFFUSE_ALPHA_MODE_NONE + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } - mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); - } - } break; - case LLRender::NORMAL_MAP: - { //missing texture => reset material texture id - LLMaterialPtr mat = NULL; - map_te_material::iterator it = new_material.find(range_it->second.te); - if(new_material.end() == it) { - mat = new LLMaterial(cur_material->asLLSD()); - new_material.insert(map_te_material::value_type(range_it->second.te, mat)); - } else { - mat = it->second; - } + mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); + } + } break; + case LLRender::NORMAL_MAP: + { //missing texture => reset material texture id + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } - mat->setNormalID(LLUUID::null); - } break; - case LLRender::SPECULAR_MAP: - { //missing texture => reset material texture id - LLMaterialPtr mat = NULL; - map_te_material::iterator it = new_material.find(range_it->second.te); - if(new_material.end() == it) { - mat = new LLMaterial(cur_material->asLLSD()); - new_material.insert(map_te_material::value_type(range_it->second.te, mat)); - } else { - mat = it->second; - } + mat->setNormalID(LLUUID::null); + } break; + case LLRender::SPECULAR_MAP: + { //missing texture => reset material texture id + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } - mat->setSpecularID(LLUUID::null); - } break; - case LLRender::NUM_TEXTURE_CHANNELS: - //nothing to do, make compiler happy - break; - } //switch - } //for + mat->setSpecularID(LLUUID::null); + } break; + case LLRender::NUM_TEXTURE_CHANNELS: + //nothing to do, make compiler happy + break; + } //switch + } //for - //setup new materials - for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) - { - LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), it->second); - LLViewerObject::setTEMaterialParams(it->first, it->second); - } + //setup new materials + for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) + { + LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), it->second); + LLViewerObject::setTEMaterialParams(it->first, it->second); + } - //clear wait-list - mWaitingTextureInfo.erase(range.first, range.second); + //clear wait-list + mWaitingTextureInfo.erase(range.first, range.second); - return 0 != new_material.size(); + return 0 != new_material.size(); } S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) { - LLMaterialPtr pMaterial = const_cast(pMaterialParams); + LLMaterialPtr pMaterial = const_cast(pMaterialParams); - if(pMaterialParams) - { //check all of them according to material settings + if(pMaterialParams) + { //check all of them according to material settings - LLViewerTexture *img_diffuse = getTEImage(te); - LLViewerTexture *img_normal = getTENormalMap(te); - LLViewerTexture *img_specular = getTESpecularMap(te); + LLViewerTexture *img_diffuse = getTEImage(te); + LLViewerTexture *img_normal = getTENormalMap(te); + LLViewerTexture *img_specular = getTESpecularMap(te); - llassert(NULL != img_diffuse); + llassert(NULL != img_diffuse); - LLMaterialPtr new_material = NULL; + LLMaterialPtr new_material = NULL; - //diffuse - if(NULL != img_diffuse) - { //guard - if(0 == img_diffuse->getPrimaryFormat() && !img_diffuse->isMissingAsset()) - { //ok here we don't have information about texture, let's belief and leave material settings - //but we remember this case - mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(img_diffuse->getID(), material_info(LLRender::DIFFUSE_MAP, te))); - } - else - { - bool bSetDiffuseNone = false; - if(img_diffuse->isMissingAsset()) - { - bSetDiffuseNone = true; - } - else - { - switch(pMaterialParams->getDiffuseAlphaMode()) - { - case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: - case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: - case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: - { //all of them modes available only for 32 bit textures - if(GL_RGBA != img_diffuse->getPrimaryFormat()) - { - bSetDiffuseNone = true; - } - } break; - } - } //else + //diffuse + if(NULL != img_diffuse) + { //guard + if(0 == img_diffuse->getPrimaryFormat() && !img_diffuse->isMissingAsset()) + { //ok here we don't have information about texture, let's belief and leave material settings + //but we remember this case + mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(img_diffuse->getID(), material_info(LLRender::DIFFUSE_MAP, te))); + } + else + { + bool bSetDiffuseNone = false; + if(img_diffuse->isMissingAsset()) + { + bSetDiffuseNone = true; + } + else + { + switch(pMaterialParams->getDiffuseAlphaMode()) + { + case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: + case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: + case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: + { //all of them modes available only for 32 bit textures + if(GL_RGBA != img_diffuse->getPrimaryFormat()) + { + bSetDiffuseNone = true; + } + } break; + } + } //else - if(bSetDiffuseNone) - { //upps... we should substitute this material with LLMaterial::DIFFUSE_ALPHA_MODE_NONE - new_material = new LLMaterial(pMaterialParams->asLLSD()); - new_material->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); - } - } - } + if(bSetDiffuseNone) + { //upps... we should substitute this material with LLMaterial::DIFFUSE_ALPHA_MODE_NONE + new_material = new LLMaterial(pMaterialParams->asLLSD()); + new_material->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); + } + } + } - //normal - if(LLUUID::null != pMaterialParams->getNormalID()) - { - if(img_normal && img_normal->isMissingAsset() && img_normal->getID() == pMaterialParams->getNormalID()) - { - if(!new_material) { - new_material = new LLMaterial(pMaterialParams->asLLSD()); - } - new_material->setNormalID(LLUUID::null); - } - else if(NULL == img_normal || 0 == img_normal->getPrimaryFormat()) - { //ok here we don't have information about texture, let's belief and leave material settings - //but we remember this case - mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getNormalID(), material_info(LLRender::NORMAL_MAP,te))); - } + //normal + if(LLUUID::null != pMaterialParams->getNormalID()) + { + if(img_normal && img_normal->isMissingAsset() && img_normal->getID() == pMaterialParams->getNormalID()) + { + if(!new_material) { + new_material = new LLMaterial(pMaterialParams->asLLSD()); + } + new_material->setNormalID(LLUUID::null); + } + else if(NULL == img_normal || 0 == img_normal->getPrimaryFormat()) + { //ok here we don't have information about texture, let's belief and leave material settings + //but we remember this case + mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getNormalID(), material_info(LLRender::NORMAL_MAP,te))); + } - } + } - //specular - if(LLUUID::null != pMaterialParams->getSpecularID()) - { - if(img_specular && img_specular->isMissingAsset() && img_specular->getID() == pMaterialParams->getSpecularID()) - { - if(!new_material) { - new_material = new LLMaterial(pMaterialParams->asLLSD()); - } - new_material->setSpecularID(LLUUID::null); - } - else if(NULL == img_specular || 0 == img_specular->getPrimaryFormat()) - { //ok here we don't have information about texture, let's belief and leave material settings - //but we remember this case - mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getSpecularID(), material_info(LLRender::SPECULAR_MAP, te))); - } - } + //specular + if(LLUUID::null != pMaterialParams->getSpecularID()) + { + if(img_specular && img_specular->isMissingAsset() && img_specular->getID() == pMaterialParams->getSpecularID()) + { + if(!new_material) { + new_material = new LLMaterial(pMaterialParams->asLLSD()); + } + new_material->setSpecularID(LLUUID::null); + } + else if(NULL == img_specular || 0 == img_specular->getPrimaryFormat()) + { //ok here we don't have information about texture, let's belief and leave material settings + //but we remember this case + mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getSpecularID(), material_info(LLRender::SPECULAR_MAP, te))); + } + } - if(new_material) { - pMaterial = new_material; - LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), pMaterial); - } - } + if(new_material) { + pMaterial = new_material; + LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), pMaterial); + } + } - S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial); + S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial); - LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterial) ? pMaterial->asLLSD() : LLSD("null")) << " res " << res - << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this), te) ? " selected" : " not selected" ) - << LL_ENDL; - setChanged(ALL_CHANGED); - if (!mDrawable.isNull()) - { - gPipeline.markTextured(mDrawable); - gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL); - } - mFaceMappingChanged = TRUE; - return TEM_CHANGE_TEXTURE; + LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterial) ? pMaterial->asLLSD() : LLSD("null")) << " res " << res + << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this), te) ? " selected" : " not selected" ) + << LL_ENDL; + setChanged(ALL_CHANGED); + if (!mDrawable.isNull()) + { + gPipeline.markTextured(mDrawable); + gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL); + } + mFaceMappingChanged = TRUE; + return TEM_CHANGE_TEXTURE; } S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t) { - S32 res = LLViewerObject::setTEScale(te, s, t); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEScale(te, s, t); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s) { - S32 res = LLViewerObject::setTEScaleS(te, s); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEScaleS(te, s); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t) { - S32 res = LLViewerObject::setTEScaleT(te, t); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEScaleT(te, t); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } void LLVOVolume::updateTEData() { - /*if (mDrawable.notNull()) - { - mFaceMappingChanged = TRUE; - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE); - }*/ + /*if (mDrawable.notNull()) + { + mFaceMappingChanged = TRUE; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE); + }*/ } bool LLVOVolume::hasMedia() const { - bool result = false; - const U8 numTEs = getNumTEs(); - for (U8 i = 0; i < numTEs; i++) - { - const LLTextureEntry* te = getTE(i); - if(te->hasMedia()) - { - result = true; - break; - } - } - return result; + bool result = false; + const U8 numTEs = getNumTEs(); + for (U8 i = 0; i < numTEs; i++) + { + const LLTextureEntry* te = getTE(i); + if(te->hasMedia()) + { + result = true; + break; + } + } + return result; } LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id) { - LLVolume* volume = getVolume(); - LLVector4a result; - result.clear(); + LLVolume* volume = getVolume(); + LLVector4a result; + result.clear(); - LLVector3 ret; + LLVector3 ret; - if (volume && face_id < volume->getNumVolumeFaces()) - { - const LLVolumeFace& face = volume->getVolumeFace(face_id); - for (S32 i = 0; i < (S32)face.mNumVertices; ++i) - { - result.add(face.mNormals[i]); - } + if (volume && face_id < volume->getNumVolumeFaces()) + { + const LLVolumeFace& face = volume->getVolumeFace(face_id); + for (S32 i = 0; i < (S32)face.mNumVertices; ++i) + { + result.add(face.mNormals[i]); + } - LLVector3 ret(result.getF32ptr()); - ret = volumeDirectionToAgent(ret); - ret.normVec(); - } - - return ret; + LLVector3 ret(result.getF32ptr()); + ret = volumeDirectionToAgent(ret); + ret.normVec(); + } + + return ret; } void LLVOVolume::requestMediaDataUpdate(bool isNew) { if (sObjectMediaClient) - sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew)); + sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew)); } bool LLVOVolume::isMediaDataBeingFetched() const { - // I know what I'm doing by const_casting this away: this is just - // a wrapper class that is only going to do a lookup. - return (sObjectMediaClient) ? sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast(this), false)) : false; + // I know what I'm doing by const_casting this away: this is just + // a wrapper class that is only going to do a lookup. + return (sObjectMediaClient) ? sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast(this), false)) : false; } void LLVOVolume::cleanUpMediaImpls() { - // Iterate through our TEs and remove any Impls that are no longer used - const U8 numTEs = getNumTEs(); - for (U8 i = 0; i < numTEs; i++) - { - const LLTextureEntry* te = getTE(i); - if( ! te->hasMedia()) - { - // Delete the media IMPL! - removeMediaImpl(i) ; - } - } + // Iterate through our TEs and remove any Impls that are no longer used + const U8 numTEs = getNumTEs(); + for (U8 i = 0; i < numTEs; i++) + { + const LLTextureEntry* te = getTE(i); + if( ! te->hasMedia()) + { + // Delete the media IMPL! + removeMediaImpl(i) ; + } + } } void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version) { - // media_data_array is an array of media entry maps - // media_version is the version string in the response. - U32 fetched_version = LLTextureEntry::getVersionFromMediaVersionString(media_version); + // media_data_array is an array of media entry maps + // media_version is the version string in the response. + U32 fetched_version = LLTextureEntry::getVersionFromMediaVersionString(media_version); - // Only update it if it is newer! - if ( (S32)fetched_version > mLastFetchedMediaVersion) - { - mLastFetchedMediaVersion = fetched_version; - //LL_INFOS() << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << LL_ENDL; - - LLSD::array_const_iterator iter = media_data_array.beginArray(); - LLSD::array_const_iterator end = media_data_array.endArray(); - U8 texture_index = 0; - for (; iter != end; ++iter, ++texture_index) - { - syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/); - } - } + // Only update it if it is newer! + if ( (S32)fetched_version > mLastFetchedMediaVersion) + { + mLastFetchedMediaVersion = fetched_version; + //LL_INFOS() << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << LL_ENDL; + + LLSD::array_const_iterator iter = media_data_array.beginArray(); + LLSD::array_const_iterator end = media_data_array.endArray(); + U8 texture_index = 0; + for (; iter != end; ++iter, ++texture_index) + { + syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/); + } + } } void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool merge, bool ignore_agent) { - if(mDead) - { - // If the object has been marked dead, don't process media updates. - return; - } - - LLTextureEntry *te = getTE(texture_index); - if(!te) - { - return ; - } + if(mDead) + { + // If the object has been marked dead, don't process media updates. + return; + } + + LLTextureEntry *te = getTE(texture_index); + if(!te) + { + return ; + } - LL_DEBUGS("MediaOnAPrim") << "BEFORE: texture_index = " << texture_index - << " hasMedia = " << te->hasMedia() << " : " - << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << LL_ENDL; + LL_DEBUGS("MediaOnAPrim") << "BEFORE: texture_index = " << texture_index + << " hasMedia = " << te->hasMedia() << " : " + << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << LL_ENDL; - std::string previous_url; - LLMediaEntry* mep = te->getMediaData(); - if(mep) - { - // Save the "current url" from before the update so we can tell if - // it changes. - previous_url = mep->getCurrentURL(); - } + std::string previous_url; + LLMediaEntry* mep = te->getMediaData(); + if(mep) + { + // Save the "current url" from before the update so we can tell if + // it changes. + previous_url = mep->getCurrentURL(); + } - if (merge) - { - te->mergeIntoMediaData(media_data); - } - else { - // XXX Question: what if the media data is undefined LLSD, but the - // update we got above said that we have media flags?? Here we clobber - // that, assuming the data from the service is more up-to-date. - te->updateMediaData(media_data); - } + if (merge) + { + te->mergeIntoMediaData(media_data); + } + else { + // XXX Question: what if the media data is undefined LLSD, but the + // update we got above said that we have media flags?? Here we clobber + // that, assuming the data from the service is more up-to-date. + te->updateMediaData(media_data); + } - mep = te->getMediaData(); - if(mep) - { - bool update_from_self = false; - if (!ignore_agent) - { - LLUUID updating_agent = LLTextureEntry::getAgentIDFromMediaVersionString(getMediaURL()); - update_from_self = (updating_agent == gAgent.getID()); - } - viewer_media_t media_impl = LLViewerMedia::updateMediaImpl(mep, previous_url, update_from_self); - - addMediaImpl(media_impl, texture_index) ; - } - else - { - removeMediaImpl(texture_index); - } + mep = te->getMediaData(); + if(mep) + { + bool update_from_self = false; + if (!ignore_agent) + { + LLUUID updating_agent = LLTextureEntry::getAgentIDFromMediaVersionString(getMediaURL()); + update_from_self = (updating_agent == gAgent.getID()); + } + viewer_media_t media_impl = LLViewerMedia::updateMediaImpl(mep, previous_url, update_from_self); + + addMediaImpl(media_impl, texture_index) ; + } + else + { + removeMediaImpl(texture_index); + } - LL_DEBUGS("MediaOnAPrim") << "AFTER: texture_index = " << texture_index - << " hasMedia = " << te->hasMedia() << " : " - << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << LL_ENDL; + LL_DEBUGS("MediaOnAPrim") << "AFTER: texture_index = " << texture_index + << " hasMedia = " << te->hasMedia() << " : " + << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << LL_ENDL; } void LLVOVolume::mediaNavigateBounceBack(U8 texture_index) { - // Find the media entry for this navigate - const LLMediaEntry* mep = NULL; - viewer_media_t impl = getMediaImpl(texture_index); - LLTextureEntry *te = getTE(texture_index); - if(te) - { - mep = te->getMediaData(); - } - - if (mep && impl) - { + // Find the media entry for this navigate + const LLMediaEntry* mep = NULL; + viewer_media_t impl = getMediaImpl(texture_index); + LLTextureEntry *te = getTE(texture_index); + if(te) + { + mep = te->getMediaData(); + } + + if (mep && impl) + { std::string url = mep->getCurrentURL(); - // Look for a ":", if not there, assume "http://" - if (!url.empty() && std::string::npos == url.find(':')) - { - url = "http://" + url; - } - // If the url we're trying to "bounce back" to is either empty or not - // allowed by the whitelist, try the home url. If *that* doesn't work, - // set the media as failed and unload it + // Look for a ":", if not there, assume "http://" + if (!url.empty() && std::string::npos == url.find(':')) + { + url = "http://" + url; + } + // If the url we're trying to "bounce back" to is either empty or not + // allowed by the whitelist, try the home url. If *that* doesn't work, + // set the media as failed and unload it if (url.empty() || !mep->checkCandidateUrl(url)) { url = mep->getHomeURL(); - // Look for a ":", if not there, assume "http://" - if (!url.empty() && std::string::npos == url.find(':')) - { - url = "http://" + url; - } + // Look for a ":", if not there, assume "http://" + if (!url.empty() && std::string::npos == url.find(':')) + { + url = "http://" + url; + } } if (url.empty() || !mep->checkCandidateUrl(url)) - { - // The url to navigate back to is not good, and we have nowhere else - // to go. - LL_WARNS("MediaOnAPrim") << "FAILED to bounce back URL \"" << url << "\" -- unloading impl" << LL_ENDL; - impl->setMediaFailed(true); - } - // Make sure we are not bouncing to url we came from - else if (impl->getCurrentMediaURL() != url) - { - // Okay, navigate now + { + // The url to navigate back to is not good, and we have nowhere else + // to go. + LL_WARNS("MediaOnAPrim") << "FAILED to bounce back URL \"" << url << "\" -- unloading impl" << LL_ENDL; + impl->setMediaFailed(true); + } + // Make sure we are not bouncing to url we came from + else if (impl->getCurrentMediaURL() != url) + { + // Okay, navigate now LL_INFOS("MediaOnAPrim") << "bouncing back to URL: " << url << LL_ENDL; impl->navigateTo(url, "", false, true); } @@ -2769,11 +2769,11 @@ bool LLVOVolume::hasMediaPermission(const LLMediaEntry* media_entry, MediaPermTy // - group permissions are on, and agent_id is in the group, or // - agent permissions are on, and agent_id is the owner - // *NOTE: We *used* to check for modify permissions here (i.e. permissions were - // granted if permModify() was true). However, this doesn't make sense in the - // viewer: we don't want to show controls or allow interaction if the author - // has deemed it so. See DEV-42115. - + // *NOTE: We *used* to check for modify permissions here (i.e. permissions were + // granted if permModify() was true). However, this doesn't make sense in the + // viewer: we don't want to show controls or allow interaction if the author + // has deemed it so. See DEV-42115. + U8 media_perms = (perm_type == MEDIA_PERM_INTERACT) ? media_entry->getPermsInteract() : media_entry->getPermsControl(); // World permissions @@ -2785,11 +2785,11 @@ bool LLVOVolume::hasMediaPermission(const LLMediaEntry* media_entry, MediaPermTy // Group permissions else if (0 != (media_perms & LLMediaEntry::PERM_GROUP)) { - LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(this); - if (obj_perm && gAgent.isInGroup(obj_perm->getGroup())) - { - return true; - } + LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(this); + if (obj_perm && gAgent.isInGroup(obj_perm->getGroup())) + { + return true; + } } // Owner permissions @@ -2804,710 +2804,710 @@ bool LLVOVolume::hasMediaPermission(const LLMediaEntry* media_entry, MediaPermTy void LLVOVolume::mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location) { - bool block_navigation = false; - // FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed - // to deal with multiple face indices. - int face_index = getFaceIndexWithMediaImpl(impl, -1); - - // Find the media entry for this navigate - LLMediaEntry* mep = NULL; - LLTextureEntry *te = getTE(face_index); - if(te) - { - mep = te->getMediaData(); - } - - if(mep) - { - if(!mep->checkCandidateUrl(new_location)) - { - block_navigation = true; - } - if (!block_navigation && !hasMediaPermission(mep, MEDIA_PERM_INTERACT)) - { - block_navigation = true; - } - } - else - { - LL_WARNS("MediaOnAPrim") << "Couldn't find media entry!" << LL_ENDL; - } - - if(block_navigation) - { - LL_INFOS("MediaOnAPrim") << "blocking navigate to URI " << new_location << LL_ENDL; + bool block_navigation = false; + // FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed + // to deal with multiple face indices. + int face_index = getFaceIndexWithMediaImpl(impl, -1); + + // Find the media entry for this navigate + LLMediaEntry* mep = NULL; + LLTextureEntry *te = getTE(face_index); + if(te) + { + mep = te->getMediaData(); + } + + if(mep) + { + if(!mep->checkCandidateUrl(new_location)) + { + block_navigation = true; + } + if (!block_navigation && !hasMediaPermission(mep, MEDIA_PERM_INTERACT)) + { + block_navigation = true; + } + } + else + { + LL_WARNS("MediaOnAPrim") << "Couldn't find media entry!" << LL_ENDL; + } + + if(block_navigation) + { + LL_INFOS("MediaOnAPrim") << "blocking navigate to URI " << new_location << LL_ENDL; - // "bounce back" to the current URL from the media entry - mediaNavigateBounceBack(face_index); - } - else if (sObjectMediaNavigateClient) - { - - LL_DEBUGS("MediaOnAPrim") << "broadcasting navigate with URI " << new_location << LL_ENDL; + // "bounce back" to the current URL from the media entry + mediaNavigateBounceBack(face_index); + } + else if (sObjectMediaNavigateClient) + { + + LL_DEBUGS("MediaOnAPrim") << "broadcasting navigate with URI " << new_location << LL_ENDL; - sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this, false), face_index, new_location); - } + sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this, false), face_index, new_location); + } } void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event) { - switch(event) - { - - case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED: - { - switch(impl->getNavState()) - { - case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED: - { - // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. - mediaNavigated(impl, plugin, plugin->getLocation()); - } - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS: - // This navigate didn't change the current URL. - LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: - // This is the first location changed event after the start of a server-directed nav. Don't broadcast it. - LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; - break; - - default: - // This is a subsequent location-changed due to a redirect. Don't broadcast. - LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (redirect)" << LL_ENDL; - break; - } - } - break; - - case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE: - { - switch(impl->getNavState()) - { - case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: - { - // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. - mediaNavigated(impl, plugin, plugin->getNavigateURI()); - } - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS: - // This navigate didn't change the current URL. - LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: - // This is the the navigate complete event from a server-directed nav. Don't broadcast it. - LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; - break; - - default: - // For all other states, the navigate should have been handled by LOCATION_CHANGED events already. - break; - } - } - break; - - default: - break; - } + switch(event) + { + + case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED: + { + switch(impl->getNavState()) + { + case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED: + { + // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. + mediaNavigated(impl, plugin, plugin->getLocation()); + } + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS: + // This navigate didn't change the current URL. + LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: + // This is the first location changed event after the start of a server-directed nav. Don't broadcast it. + LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; + break; + + default: + // This is a subsequent location-changed due to a redirect. Don't broadcast. + LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (redirect)" << LL_ENDL; + break; + } + } + break; + + case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE: + { + switch(impl->getNavState()) + { + case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: + { + // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. + mediaNavigated(impl, plugin, plugin->getNavigateURI()); + } + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS: + // This navigate didn't change the current URL. + LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: + // This is the the navigate complete event from a server-directed nav. Don't broadcast it. + LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; + break; + + default: + // For all other states, the navigate should have been handled by LOCATION_CHANGED events already. + break; + } + } + break; + + default: + break; + } } void LLVOVolume::sendMediaDataUpdate() { if (sObjectMediaClient) - sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this, false)); + sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this, false)); } void LLVOVolume::removeMediaImpl(S32 texture_index) { - if(mMediaImplList.size() <= (U32)texture_index || mMediaImplList[texture_index].isNull()) - { - return ; - } + if(mMediaImplList.size() <= (U32)texture_index || mMediaImplList[texture_index].isNull()) + { + return ; + } - //make the face referencing to mMediaImplList[texture_index] to point back to the old texture. - if(mDrawable && texture_index < mDrawable->getNumFaces()) - { - LLFace* facep = mDrawable->getFace(texture_index) ; - if(facep) - { - LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; - if(media_tex) - { - media_tex->removeMediaFromFace(facep) ; - } - } - } - - //check if some other face(s) of this object reference(s)to this media impl. - S32 i ; - S32 end = (S32)mMediaImplList.size() ; - for(i = 0; i < end ; i++) - { - if( i != texture_index && mMediaImplList[i] == mMediaImplList[texture_index]) - { - break ; - } - } + //make the face referencing to mMediaImplList[texture_index] to point back to the old texture. + if(mDrawable && texture_index < mDrawable->getNumFaces()) + { + LLFace* facep = mDrawable->getFace(texture_index) ; + if(facep) + { + LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; + if(media_tex) + { + media_tex->removeMediaFromFace(facep) ; + } + } + } + + //check if some other face(s) of this object reference(s)to this media impl. + S32 i ; + S32 end = (S32)mMediaImplList.size() ; + for(i = 0; i < end ; i++) + { + if( i != texture_index && mMediaImplList[i] == mMediaImplList[texture_index]) + { + break ; + } + } - if(i == end) //this object does not need this media impl. - { - mMediaImplList[texture_index]->removeObject(this) ; - } + if(i == end) //this object does not need this media impl. + { + mMediaImplList[texture_index]->removeObject(this) ; + } - mMediaImplList[texture_index] = NULL ; - return ; + mMediaImplList[texture_index] = NULL ; + return ; } void LLVOVolume::addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) { - if((S32)mMediaImplList.size() < texture_index + 1) - { - mMediaImplList.resize(texture_index + 1) ; - } - - if(mMediaImplList[texture_index].notNull()) - { - if(mMediaImplList[texture_index] == media_impl) - { - return ; - } + if((S32)mMediaImplList.size() < texture_index + 1) + { + mMediaImplList.resize(texture_index + 1) ; + } + + if(mMediaImplList[texture_index].notNull()) + { + if(mMediaImplList[texture_index] == media_impl) + { + return ; + } - removeMediaImpl(texture_index) ; - } + removeMediaImpl(texture_index) ; + } - mMediaImplList[texture_index] = media_impl; - media_impl->addObject(this) ; + mMediaImplList[texture_index] = media_impl; + media_impl->addObject(this) ; - //add the face to show the media if it is in playing - if(mDrawable) - { - LLFace* facep(NULL); - if( texture_index < mDrawable->getNumFaces() ) - { - facep = mDrawable->getFace(texture_index) ; - } + //add the face to show the media if it is in playing + if(mDrawable) + { + LLFace* facep(NULL); + if( texture_index < mDrawable->getNumFaces() ) + { + facep = mDrawable->getFace(texture_index) ; + } - if(facep) - { - LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; - if(media_tex) - { - media_tex->addMediaToFace(facep) ; - } - } - else //the face is not available now, start media on this face later. - { - media_impl->setUpdated(TRUE) ; - } - } - return ; + if(facep) + { + LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; + if(media_tex) + { + media_tex->addMediaToFace(facep) ; + } + } + else //the face is not available now, start media on this face later. + { + media_impl->setUpdated(TRUE) ; + } + } + return ; } viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const { - if(mMediaImplList.size() > face_id) - { - return mMediaImplList[face_id]; - } - return NULL; + if(mMediaImplList.size() > face_id) + { + return mMediaImplList[face_id]; + } + return NULL; } F64 LLVOVolume::getTotalMediaInterest() const { - // If this object is currently focused, this object has "high" interest - if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == getID()) - return F64_MAX; - - F64 interest = (F64)-1.0; // means not interested; - - // If this object is selected, this object has "high" interest, but since - // there can be more than one, we still add in calculated impl interest - // XXX Sadly, 'contains()' doesn't take a const :( - if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this))) - interest = F64_MAX / 2.0; + // If this object is currently focused, this object has "high" interest + if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == getID()) + return F64_MAX; + + F64 interest = (F64)-1.0; // means not interested; - int i = 0; - const int end = getNumTEs(); - for ( ; i < end; ++i) - { - const viewer_media_t &impl = getMediaImpl(i); - if (!impl.isNull()) - { - if (interest == (F64)-1.0) interest = (F64)0.0; - interest += impl->getInterest(); - } - } - return interest; + // If this object is selected, this object has "high" interest, but since + // there can be more than one, we still add in calculated impl interest + // XXX Sadly, 'contains()' doesn't take a const :( + if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this))) + interest = F64_MAX / 2.0; + + int i = 0; + const int end = getNumTEs(); + for ( ; i < end; ++i) + { + const viewer_media_t &impl = getMediaImpl(i); + if (!impl.isNull()) + { + if (interest == (F64)-1.0) interest = (F64)0.0; + interest += impl->getInterest(); + } + } + return interest; } S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id) { - S32 end = (S32)mMediaImplList.size() ; - for(S32 face_id = start_face_id + 1; face_id < end; face_id++) - { - if(mMediaImplList[face_id] == media_impl) - { - return face_id ; - } - } - return -1 ; + S32 end = (S32)mMediaImplList.size() ; + for(S32 face_id = start_face_id + 1; face_id < end; face_id++) + { + if(mMediaImplList[face_id] == media_impl) + { + return face_id ; + } + } + return -1 ; } //---------------------------------------------------------------------------- void LLVOVolume::setLightTextureID(LLUUID id) { - LLViewerTexture* old_texturep = getLightTexture(); // same as mLightTexture, but inits if nessesary - if (id.notNull()) - { - if (!hasLightTexture()) - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true); - } - else if (old_texturep) - { - old_texturep->removeVolume(LLRender::LIGHT_TEX, this); - } - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block && param_block->getLightTexture() != id) - { - param_block->setLightTexture(id); - parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); - } - LLViewerTexture* tex = getLightTexture(); - if (tex) - { - tex->addVolume(LLRender::LIGHT_TEX, this); // new texture - } - else - { - LL_WARNS() << "Can't get light texture for ID " << id.asString() << LL_ENDL; - } - } - else if (hasLightTexture()) - { - if (old_texturep) - { - old_texturep->removeVolume(LLRender::LIGHT_TEX, this); - } - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); - parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); - mLightTexture = NULL; - } + LLViewerTexture* old_texturep = getLightTexture(); // same as mLightTexture, but inits if nessesary + if (id.notNull()) + { + if (!hasLightTexture()) + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true); + } + else if (old_texturep) + { + old_texturep->removeVolume(LLRender::LIGHT_TEX, this); + } + LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block && param_block->getLightTexture() != id) + { + param_block->setLightTexture(id); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + } + LLViewerTexture* tex = getLightTexture(); + if (tex) + { + tex->addVolume(LLRender::LIGHT_TEX, this); // new texture + } + else + { + LL_WARNS() << "Can't get light texture for ID " << id.asString() << LL_ENDL; + } + } + else if (hasLightTexture()) + { + if (old_texturep) + { + old_texturep->removeVolume(LLRender::LIGHT_TEX, this); + } + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + mLightTexture = NULL; + } } void LLVOVolume::setSpotLightParams(LLVector3 params) { - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block && param_block->getParams() != params) - { - param_block->setParams(params); - parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); - } + LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block && param_block->getParams() != params) + { + param_block->setParams(params); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + } } - + void LLVOVolume::setIsLight(BOOL is_light) { - BOOL was_light = getIsLight(); - if (is_light != was_light) - { - if (is_light) - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, TRUE, true); - } - else - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, FALSE, true); - } + BOOL was_light = getIsLight(); + if (is_light != was_light) + { + if (is_light) + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, TRUE, true); + } + else + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, FALSE, true); + } - if (is_light) - { - // Add it to the pipeline mLightSet - gPipeline.setLight(mDrawable, TRUE); - } - else - { - // Not a light. Remove it from the pipeline's light set. - gPipeline.setLight(mDrawable, FALSE); - } - } + if (is_light) + { + // Add it to the pipeline mLightSet + gPipeline.setLight(mDrawable, TRUE); + } + else + { + // Not a light. Remove it from the pipeline's light set. + gPipeline.setLight(mDrawable, FALSE); + } + } } void LLVOVolume::setLightColor(const LLColor3& color) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getColor() != color) - { - param_block->setColor(LLColor4(color, param_block->getColor().mV[3])); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - } + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getColor() != color) + { + param_block->setColor(LLColor4(color, param_block->getColor().mV[3])); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + } } void LLVOVolume::setLightIntensity(F32 intensity) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getColor().mV[3] != intensity) - { - param_block->setColor(LLColor4(LLColor3(param_block->getColor()), intensity)); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getColor().mV[3] != intensity) + { + param_block->setColor(LLColor4(LLColor3(param_block->getColor()), intensity)); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } } void LLVOVolume::setLightRadius(F32 radius) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getRadius() != radius) - { - param_block->setRadius(radius); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getRadius() != radius) + { + param_block->setRadius(radius); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } } void LLVOVolume::setLightFalloff(F32 falloff) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getFalloff() != falloff) - { - param_block->setFalloff(falloff); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getFalloff() != falloff) + { + param_block->setFalloff(falloff); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } } void LLVOVolume::setLightCutoff(F32 cutoff) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getCutoff() != cutoff) - { - param_block->setCutoff(cutoff); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getCutoff() != cutoff) + { + param_block->setCutoff(cutoff); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } } //---------------------------------------------------------------------------- BOOL LLVOVolume::getIsLight() const { - return getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT); + return getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT); } LLColor3 LLVOVolume::getLightBaseColor() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return LLColor3(param_block->getColor()); - } - else - { - return LLColor3(1,1,1); - } + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return LLColor3(param_block->getColor()); + } + else + { + return LLColor3(1,1,1); + } } LLColor3 LLVOVolume::getLightColor() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return LLColor3(param_block->getColor()) * param_block->getColor().mV[3]; - } - else - { - return LLColor3(1,1,1); - } + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return LLColor3(param_block->getColor()) * param_block->getColor().mV[3]; + } + else + { + return LLColor3(1,1,1); + } } LLUUID LLVOVolume::getLightTextureID() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block) - { - return param_block->getLightTexture(); - } - } - - return LLUUID::null; + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block) + { + return param_block->getLightTexture(); + } + } + + return LLUUID::null; } LLVector3 LLVOVolume::getSpotLightParams() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block) - { - return param_block->getParams(); - } - } - - return LLVector3(); + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block) + { + return param_block->getParams(); + } + } + + return LLVector3(); } F32 LLVOVolume::getSpotLightPriority() const { - return mSpotLightPriority; + return mSpotLightPriority; } void LLVOVolume::updateSpotLightPriority() { - LLVector3 pos = mDrawable->getPositionAgent(); - LLVector3 at(0,0,-1); - at *= getRenderRotation(); + LLVector3 pos = mDrawable->getPositionAgent(); + LLVector3 at(0,0,-1); + at *= getRenderRotation(); - F32 r = getLightRadius()*0.5f; + F32 r = getLightRadius()*0.5f; - pos += at * r; + pos += at * r; - at = LLViewerCamera::getInstance()->getAtAxis(); + at = LLViewerCamera::getInstance()->getAtAxis(); - pos -= at * r; - - mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); + pos -= at * r; + + mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); - if (mLightTexture.notNull()) - { - mLightTexture->addTextureStats(mSpotLightPriority); - mLightTexture->setBoostLevel(LLGLTexture::BOOST_CLOUDS); - } + if (mLightTexture.notNull()) + { + mLightTexture->addTextureStats(mSpotLightPriority); + mLightTexture->setBoostLevel(LLGLTexture::BOOST_CLOUDS); + } } bool LLVOVolume::isLightSpotlight() const { - LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (params && getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - return params->isLightSpotlight(); - } - return false; + LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (params && getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + return params->isLightSpotlight(); + } + return false; } LLViewerTexture* LLVOVolume::getLightTexture() { - LLUUID id = getLightTextureID(); + LLUUID id = getLightTextureID(); - if (id.notNull()) - { - if (mLightTexture.isNull() || id != mLightTexture->getID()) - { - mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM); - } - } - else - { - mLightTexture = NULL; - } + if (id.notNull()) + { + if (mLightTexture.isNull() || id != mLightTexture->getID()) + { + mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM); + } + } + else + { + mLightTexture = NULL; + } - return mLightTexture; + return mLightTexture; } F32 LLVOVolume::getLightIntensity() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getColor().mV[3]; - } - else - { - return 1.f; - } + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getColor().mV[3]; + } + else + { + return 1.f; + } } F32 LLVOVolume::getLightRadius() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getRadius(); - } - else - { - return 0.f; - } + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getRadius(); + } + else + { + return 0.f; + } } F32 LLVOVolume::getLightFalloff() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getFalloff(); - } - else - { - return 0.f; - } + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getFalloff(); + } + else + { + return 0.f; + } } F32 LLVOVolume::getLightCutoff() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getCutoff(); - } - else - { - return 0.f; - } + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getCutoff(); + } + else + { + return 0.f; + } } U32 LLVOVolume::getVolumeInterfaceID() const { - if (mVolumeImpl) - { - return mVolumeImpl->getID(); - } + if (mVolumeImpl) + { + return mVolumeImpl->getID(); + } - return 0; + return 0; } BOOL LLVOVolume::isFlexible() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE)) - { - LLVolume* volume = getVolume(); - if (volume && volume->getParams().getPathParams().getCurveType() != LL_PCODE_PATH_FLEXIBLE) - { - LLVolumeParams volume_params = getVolume()->getParams(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); - } - return TRUE; - } - else - { - return FALSE; - } + if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE)) + { + LLVolume* volume = getVolume(); + if (volume && volume->getParams().getPathParams().getCurveType() != LL_PCODE_PATH_FLEXIBLE) + { + LLVolumeParams volume_params = getVolume()->getParams(); + U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); + volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); + } + return TRUE; + } + else + { + return FALSE; + } } BOOL LLVOVolume::isSculpted() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) - { - return TRUE; - } - - return FALSE; + if (getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + { + return TRUE; + } + + return FALSE; } BOOL LLVOVolume::isMesh() const { - if (isSculpted()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - U8 sculpt_type = sculpt_params->getSculptType(); + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + U8 sculpt_type = sculpt_params->getSculptType(); - if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - // mesh is a mesh - { - return TRUE; - } - } + if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + // mesh is a mesh + { + return TRUE; + } + } - return FALSE; + return FALSE; } BOOL LLVOVolume::hasLightTexture() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - return TRUE; - } + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + return TRUE; + } - return FALSE; + return FALSE; } BOOL LLVOVolume::isVolumeGlobal() const { - if (mVolumeImpl) - { - return mVolumeImpl->isVolumeGlobal() ? TRUE : FALSE; - } - else if (mRiggedVolume.notNull()) - { - return TRUE; - } + if (mVolumeImpl) + { + return mVolumeImpl->isVolumeGlobal() ? TRUE : FALSE; + } + else if (mRiggedVolume.notNull()) + { + return TRUE; + } - return FALSE; + return FALSE; } BOOL LLVOVolume::canBeFlexible() const { - U8 path = getVolume()->getParams().getPathParams().getCurveType(); - return (path == LL_PCODE_PATH_FLEXIBLE || path == LL_PCODE_PATH_LINE); + U8 path = getVolume()->getParams().getPathParams().getCurveType(); + return (path == LL_PCODE_PATH_FLEXIBLE || path == LL_PCODE_PATH_LINE); } BOOL LLVOVolume::setIsFlexible(BOOL is_flexible) { - BOOL res = FALSE; - BOOL was_flexible = isFlexible(); - LLVolumeParams volume_params; - if (is_flexible) - { - if (!was_flexible) - { - volume_params = getVolume()->getParams(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); - res = TRUE; - setFlags(FLAGS_USE_PHYSICS, FALSE); - setFlags(FLAGS_PHANTOM, TRUE); - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, true); - if (mDrawable) - { - mDrawable->makeActive(); - } - } - } - else - { - if (was_flexible) - { - volume_params = getVolume()->getParams(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - volume_params.setType(profile_and_hole, LL_PCODE_PATH_LINE); - res = TRUE; - setFlags(FLAGS_PHANTOM, FALSE); - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, true); - } - } - if (res) - { - res = setVolume(volume_params, 1); - if (res) - { - markForUpdate(TRUE); - } - } - return res; + BOOL res = FALSE; + BOOL was_flexible = isFlexible(); + LLVolumeParams volume_params; + if (is_flexible) + { + if (!was_flexible) + { + volume_params = getVolume()->getParams(); + U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); + volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); + res = TRUE; + setFlags(FLAGS_USE_PHYSICS, FALSE); + setFlags(FLAGS_PHANTOM, TRUE); + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, true); + if (mDrawable) + { + mDrawable->makeActive(); + } + } + } + else + { + if (was_flexible) + { + volume_params = getVolume()->getParams(); + U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); + volume_params.setType(profile_and_hole, LL_PCODE_PATH_LINE); + res = TRUE; + setFlags(FLAGS_PHANTOM, FALSE); + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, true); + } + } + if (res) + { + res = setVolume(volume_params, 1); + if (res) + { + markForUpdate(TRUE); + } + } + return res; } const LLMeshSkinInfo* LLVOVolume::getSkinInfo() const @@ -3531,16 +3531,16 @@ BOOL LLVOVolume::isRiggedMesh() const //---------------------------------------------------------------------------- U32 LLVOVolume::getExtendedMeshFlags() const { - const LLExtendedMeshParams *param_block = + const LLExtendedMeshParams *param_block = (const LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH); - if (param_block) - { - return param_block->getFlags(); - } - else - { - return 0; - } + if (param_block) + { + return param_block->getFlags(); + } + else + { + return 0; + } } void LLVOVolume::onSetExtendedMeshFlags(U32 flags) @@ -3549,7 +3549,7 @@ void LLVOVolume::onSetExtendedMeshFlags(U32 flags) // The isAnySelected() check was needed at one point to prevent // graphics problems. These are now believed to be fixed so the // check has been disabled. - if (/*!getRootEdit()->isAnySelected() &&*/ mDrawable.notNull()) + if (/*!getRootEdit()->isAnySelected() &&*/ mDrawable.notNull()) { // Need to trigger rebuildGeom(), which is where control avatars get created/removed getRootEdit()->recursiveMarkForUpdate(TRUE); @@ -3716,83 +3716,83 @@ void LLVOVolume::updateRiggingInfo() void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point) { - LLVolume *volume = getVolume(); + LLVolume *volume = getVolume(); - if (volume) - { - LLVector3 view_vector; - view_vector = view_point; - - //transform view vector into volume space - view_vector -= getRenderPosition(); - //mDrawable->mDistanceWRTCamera = view_vector.length(); - LLQuaternion worldRot = getRenderRotation(); - view_vector = view_vector * ~worldRot; - if (!isVolumeGlobal()) - { - LLVector3 objScale = getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - view_vector.scaleVec(invObjScale); - } - - updateRelativeXform(); - LLMatrix4 trans_mat = mRelativeXform; - if (mDrawable->isStatic()) - { - trans_mat.translate(getRegion()->getOriginAgent()); - } + if (volume) + { + LLVector3 view_vector; + view_vector = view_point; + + //transform view vector into volume space + view_vector -= getRenderPosition(); + //mDrawable->mDistanceWRTCamera = view_vector.length(); + LLQuaternion worldRot = getRenderRotation(); + view_vector = view_vector * ~worldRot; + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + view_vector.scaleVec(invObjScale); + } + + updateRelativeXform(); + LLMatrix4 trans_mat = mRelativeXform; + if (mDrawable->isStatic()) + { + trans_mat.translate(getRegion()->getOriginAgent()); + } - volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, view_vector, trans_mat, mRelativeXformInvTrans, nodep->getTESelectMask()); + volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, view_vector, trans_mat, mRelativeXformInvTrans, nodep->getTESelectMask()); - nodep->mSilhouetteExists = TRUE; - } + nodep->mSilhouetteExists = TRUE; + } } void LLVOVolume::deleteFaces() { - S32 face_count = mNumFaces; - if (mDrawable.notNull()) - { - mDrawable->deleteFaces(0, face_count); - } + S32 face_count = mNumFaces; + if (mDrawable.notNull()) + { + mDrawable->deleteFaces(0, face_count); + } - mNumFaces = 0; + mNumFaces = 0; } void LLVOVolume::updateRadius() { - if (mDrawable.isNull()) - { - return; - } - - mVObjRadius = getScale().length(); - mDrawable->setRadius(mVObjRadius); + if (mDrawable.isNull()) + { + return; + } + + mVObjRadius = getScale().length(); + mDrawable->setRadius(mVObjRadius); } BOOL LLVOVolume::isAttachment() const { - return mAttachmentState != 0 ; + return mAttachmentState != 0 ; } BOOL LLVOVolume::isHUDAttachment() const { - // *NOTE: we assume hud attachment points are in defined range - // since this range is constant for backwards compatibility - // reasons this is probably a reasonable assumption to make - S32 attachment_id = ATTACHMENT_ID_FROM_STATE(mAttachmentState); - return ( attachment_id >= 31 && attachment_id <= 38 ); + // *NOTE: we assume hud attachment points are in defined range + // since this range is constant for backwards compatibility + // reasons this is probably a reasonable assumption to make + S32 attachment_id = ATTACHMENT_ID_FROM_STATE(mAttachmentState); + return ( attachment_id >= 31 && attachment_id <= 38 ); } const LLMatrix4 LLVOVolume::getRenderMatrix() const { - if (mDrawable->isActive() && !mDrawable->isRoot()) - { - return mDrawable->getParent()->getWorldMatrix(); - } - return mDrawable->getWorldMatrix(); + if (mDrawable->isActive() && !mDrawable->isRoot()) + { + return mDrawable->getParent()->getWorldMatrix(); + } + return mDrawable->getWorldMatrix(); } // Returns a base cost and adds textures to passed in set. @@ -3808,62 +3808,62 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const * the official viewer for consideration. *****************************************************************/ - // Get access to params we'll need at various points. - // Skip if this is object doesn't have a volume (e.g. is an avatar). - BOOL has_volume = (getVolume() != NULL); - LLVolumeParams volume_params; - LLPathParams path_params; - LLProfileParams profile_params; - - U32 num_triangles = 0; - - // per-prim costs - static const U32 ARC_PARTICLE_COST = 1; // determined experimentally - static const U32 ARC_PARTICLE_MAX = 2048; // default values - static const U32 ARC_TEXTURE_COST = 16; // multiplier for texture resolution - performance tested - static const U32 ARC_LIGHT_COST = 500; // static cost for light-producing prims - static const U32 ARC_MEDIA_FACE_COST = 1500; // static cost per media-enabled face - - - // per-prim multipliers - static const F32 ARC_GLOW_MULT = 1.5f; // tested based on performance - static const F32 ARC_BUMP_MULT = 1.25f; // tested based on performance - static const F32 ARC_FLEXI_MULT = 5; // tested based on performance - static const F32 ARC_SHINY_MULT = 1.6f; // tested based on performance - static const F32 ARC_INVISI_COST = 1.2f; // tested based on performance - static const F32 ARC_WEIGHTED_MESH = 1.2f; // tested based on performance - - static const F32 ARC_PLANAR_COST = 1.0f; // tested based on performance to have negligible impact - static const F32 ARC_ANIM_TEX_COST = 4.f; // tested based on performance - static const F32 ARC_ALPHA_COST = 4.f; // 4x max - based on performance - - F32 shame = 0; - - U32 invisi = 0; - U32 shiny = 0; - U32 glow = 0; - U32 alpha = 0; - U32 flexi = 0; - U32 animtex = 0; - U32 particles = 0; - U32 bump = 0; - U32 planar = 0; - U32 weighted_mesh = 0; - U32 produces_light = 0; - U32 media_faces = 0; - - const LLDrawable* drawablep = mDrawable; - U32 num_faces = drawablep->getNumFaces(); - - if (has_volume) - { - volume_params = getVolume()->getParams(); - path_params = volume_params.getPathParams(); - profile_params = volume_params.getProfileParams(); + // Get access to params we'll need at various points. + // Skip if this is object doesn't have a volume (e.g. is an avatar). + BOOL has_volume = (getVolume() != NULL); + LLVolumeParams volume_params; + LLPathParams path_params; + LLProfileParams profile_params; + + U32 num_triangles = 0; + + // per-prim costs + static const U32 ARC_PARTICLE_COST = 1; // determined experimentally + static const U32 ARC_PARTICLE_MAX = 2048; // default values + static const U32 ARC_TEXTURE_COST = 16; // multiplier for texture resolution - performance tested + static const U32 ARC_LIGHT_COST = 500; // static cost for light-producing prims + static const U32 ARC_MEDIA_FACE_COST = 1500; // static cost per media-enabled face + + + // per-prim multipliers + static const F32 ARC_GLOW_MULT = 1.5f; // tested based on performance + static const F32 ARC_BUMP_MULT = 1.25f; // tested based on performance + static const F32 ARC_FLEXI_MULT = 5; // tested based on performance + static const F32 ARC_SHINY_MULT = 1.6f; // tested based on performance + static const F32 ARC_INVISI_COST = 1.2f; // tested based on performance + static const F32 ARC_WEIGHTED_MESH = 1.2f; // tested based on performance + + static const F32 ARC_PLANAR_COST = 1.0f; // tested based on performance to have negligible impact + static const F32 ARC_ANIM_TEX_COST = 4.f; // tested based on performance + static const F32 ARC_ALPHA_COST = 4.f; // 4x max - based on performance + + F32 shame = 0; + + U32 invisi = 0; + U32 shiny = 0; + U32 glow = 0; + U32 alpha = 0; + U32 flexi = 0; + U32 animtex = 0; + U32 particles = 0; + U32 bump = 0; + U32 planar = 0; + U32 weighted_mesh = 0; + U32 produces_light = 0; + U32 media_faces = 0; + + const LLDrawable* drawablep = mDrawable; + U32 num_faces = drawablep->getNumFaces(); + + if (has_volume) + { + volume_params = getVolume()->getParams(); + path_params = volume_params.getPathParams(); + profile_params = volume_params.getProfileParams(); LLMeshCostData costs; - if (getCostData(costs)) - { + if (getCostData(costs)) + { if (isAnimatedObject() && isRiggedMesh()) { // Scaling here is to make animated object vs @@ -3876,195 +3876,195 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const F32 radius = getScale().length()*0.5f; num_triangles = costs.getRadiusWeightedTris(radius); } - } - } + } + } - if (num_triangles <= 0) - { - num_triangles = 4; - } + if (num_triangles <= 0) + { + num_triangles = 4; + } - if (isSculpted()) - { - if (isMesh()) - { - // base cost is dependent on mesh complexity - // note that 3 is the highest LOD as of the time of this coding. - S32 size = gMeshRepo.getMeshSize(volume_params.getSculptID(), getLOD()); - if ( size > 0) - { - if (isRiggedMesh()) - { - // weighted attachment - 1 point for every 3 bytes - weighted_mesh = 1; - } - } - else - { - // something went wrong - user should know their content isn't render-free - return 0; - } - } - else - { - const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID sculpt_id = sculpt_params->getSculptTexture(); - if (textures.find(sculpt_id) == textures.end()) - { - LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(sculpt_id); - if (texture) - { - S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (texture->getFullHeight() / 128.f + texture->getFullWidth() / 128.f)); - textures.insert(texture_cost_t::value_type(sculpt_id, texture_cost)); - } - } - } - } + if (isSculpted()) + { + if (isMesh()) + { + // base cost is dependent on mesh complexity + // note that 3 is the highest LOD as of the time of this coding. + S32 size = gMeshRepo.getMeshSize(volume_params.getSculptID(), getLOD()); + if ( size > 0) + { + if (isRiggedMesh()) + { + // weighted attachment - 1 point for every 3 bytes + weighted_mesh = 1; + } + } + else + { + // something went wrong - user should know their content isn't render-free + return 0; + } + } + else + { + const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID sculpt_id = sculpt_params->getSculptTexture(); + if (textures.find(sculpt_id) == textures.end()) + { + LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(sculpt_id); + if (texture) + { + S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (texture->getFullHeight() / 128.f + texture->getFullWidth() / 128.f)); + textures.insert(texture_cost_t::value_type(sculpt_id, texture_cost)); + } + } + } + } - if (isFlexible()) - { - flexi = 1; - } - if (isParticleSource()) - { - particles = 1; - } + if (isFlexible()) + { + flexi = 1; + } + if (isParticleSource()) + { + particles = 1; + } - if (getIsLight()) - { - produces_light = 1; - } + if (getIsLight()) + { + produces_light = 1; + } - for (S32 i = 0; i < num_faces; ++i) - { - const LLFace* face = drawablep->getFace(i); - if (!face) continue; - const LLTextureEntry* te = face->getTextureEntry(); - const LLViewerTexture* img = face->getTexture(); + for (S32 i = 0; i < num_faces; ++i) + { + const LLFace* face = drawablep->getFace(i); + if (!face) continue; + const LLTextureEntry* te = face->getTextureEntry(); + const LLViewerTexture* img = face->getTexture(); - if (img) - { - if (textures.find(img->getID()) == textures.end()) - { - S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (img->getFullHeight() / 128.f + img->getFullWidth() / 128.f)); - textures.insert(texture_cost_t::value_type(img->getID(), texture_cost)); - } - } + if (img) + { + if (textures.find(img->getID()) == textures.end()) + { + S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (img->getFullHeight() / 128.f + img->getFullWidth() / 128.f)); + textures.insert(texture_cost_t::value_type(img->getID(), texture_cost)); + } + } - if (face->getPoolType() == LLDrawPool::POOL_ALPHA) - { - alpha = 1; - } - else if (img && img->getPrimaryFormat() == GL_ALPHA) - { - invisi = 1; - } - if (face->hasMedia()) - { - media_faces++; - } + if (face->getPoolType() == LLDrawPool::POOL_ALPHA) + { + alpha = 1; + } + else if (img && img->getPrimaryFormat() == GL_ALPHA) + { + invisi = 1; + } + if (face->hasMedia()) + { + media_faces++; + } - if (te) - { - if (te->getBumpmap()) - { - // bump is a multiplier, don't add per-face - bump = 1; - } - if (te->getShiny()) - { - // shiny is a multiplier, don't add per-face - shiny = 1; - } - if (te->getGlow() > 0.f) - { - // glow is a multiplier, don't add per-face - glow = 1; - } - if (face->mTextureMatrix != NULL) - { - animtex = 1; - } - if (te->getTexGen()) - { - planar = 1; - } - } - } + if (te) + { + if (te->getBumpmap()) + { + // bump is a multiplier, don't add per-face + bump = 1; + } + if (te->getShiny()) + { + // shiny is a multiplier, don't add per-face + shiny = 1; + } + if (te->getGlow() > 0.f) + { + // glow is a multiplier, don't add per-face + glow = 1; + } + if (face->mTextureMatrix != NULL) + { + animtex = 1; + } + if (te->getTexGen()) + { + planar = 1; + } + } + } - // shame currently has the "base" cost of 1 point per 15 triangles, min 2. - shame = num_triangles * 5.f; - shame = shame < 2.f ? 2.f : shame; + // shame currently has the "base" cost of 1 point per 15 triangles, min 2. + shame = num_triangles * 5.f; + shame = shame < 2.f ? 2.f : shame; - // multiply by per-face modifiers - if (planar) - { - shame *= planar * ARC_PLANAR_COST; - } + // multiply by per-face modifiers + if (planar) + { + shame *= planar * ARC_PLANAR_COST; + } - if (animtex) - { - shame *= animtex * ARC_ANIM_TEX_COST; - } + if (animtex) + { + shame *= animtex * ARC_ANIM_TEX_COST; + } - if (alpha) - { - shame *= alpha * ARC_ALPHA_COST; - } + if (alpha) + { + shame *= alpha * ARC_ALPHA_COST; + } - if(invisi) - { - shame *= invisi * ARC_INVISI_COST; - } + if(invisi) + { + shame *= invisi * ARC_INVISI_COST; + } - if (glow) - { - shame *= glow * ARC_GLOW_MULT; - } + if (glow) + { + shame *= glow * ARC_GLOW_MULT; + } - if (bump) - { - shame *= bump * ARC_BUMP_MULT; - } + if (bump) + { + shame *= bump * ARC_BUMP_MULT; + } - if (shiny) - { - shame *= shiny * ARC_SHINY_MULT; - } + if (shiny) + { + shame *= shiny * ARC_SHINY_MULT; + } - // multiply shame by multipliers - if (weighted_mesh) - { - shame *= weighted_mesh * ARC_WEIGHTED_MESH; - } + // multiply shame by multipliers + if (weighted_mesh) + { + shame *= weighted_mesh * ARC_WEIGHTED_MESH; + } - if (flexi) - { - shame *= flexi * ARC_FLEXI_MULT; - } + if (flexi) + { + shame *= flexi * ARC_FLEXI_MULT; + } - // add additional costs - if (particles) - { - const LLPartSysData *part_sys_data = &(mPartSourcep->mPartSysData); - const LLPartData *part_data = &(part_sys_data->mPartData); - U32 num_particles = (U32)(part_sys_data->mBurstPartCount * llceil( part_data->mMaxAge / part_sys_data->mBurstRate)); - num_particles = num_particles > ARC_PARTICLE_MAX ? ARC_PARTICLE_MAX : num_particles; - F32 part_size = (llmax(part_data->mStartScale[0], part_data->mEndScale[0]) + llmax(part_data->mStartScale[1], part_data->mEndScale[1])) / 2.f; - shame += num_particles * part_size * ARC_PARTICLE_COST; - } + // add additional costs + if (particles) + { + const LLPartSysData *part_sys_data = &(mPartSourcep->mPartSysData); + const LLPartData *part_data = &(part_sys_data->mPartData); + U32 num_particles = (U32)(part_sys_data->mBurstPartCount * llceil( part_data->mMaxAge / part_sys_data->mBurstRate)); + num_particles = num_particles > ARC_PARTICLE_MAX ? ARC_PARTICLE_MAX : num_particles; + F32 part_size = (llmax(part_data->mStartScale[0], part_data->mEndScale[0]) + llmax(part_data->mStartScale[1], part_data->mEndScale[1])) / 2.f; + shame += num_particles * part_size * ARC_PARTICLE_COST; + } - if (produces_light) - { - shame += ARC_LIGHT_COST; - } + if (produces_light) + { + shame += ARC_LIGHT_COST; + } - if (media_faces) - { - shame += media_faces * ARC_MEDIA_FACE_COST; - } + if (media_faces) + { + shame += media_faces * ARC_MEDIA_FACE_COST; + } // Streaming cost for animated objects includes a fixed cost // per linkset. Add a corresponding charge here translated into @@ -4074,35 +4074,35 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const shame += (ANIMATED_OBJECT_BASE_COST/0.06) * 5.0f; } - if (shame > mRenderComplexity_current) - { - mRenderComplexity_current = (S32)shame; - } + if (shame > mRenderComplexity_current) + { + mRenderComplexity_current = (S32)shame; + } - return (U32)shame; + return (U32)shame; } F32 LLVOVolume::getEstTrianglesMax() const { - if (isMesh() && getVolume()) - { - return gMeshRepo.getEstTrianglesMax(getVolume()->getParams().getSculptID()); - } + if (isMesh() && getVolume()) + { + return gMeshRepo.getEstTrianglesMax(getVolume()->getParams().getSculptID()); + } return 0.f; } F32 LLVOVolume::getEstTrianglesStreamingCost() const { - if (isMesh() && getVolume()) - { - return gMeshRepo.getEstTrianglesStreamingCost(getVolume()->getParams().getSculptID()); - } + if (isMesh() && getVolume()) + { + return gMeshRepo.getEstTrianglesStreamingCost(getVolume()->getParams().getSculptID()); + } return 0.f; } F32 LLVOVolume::getStreamingCost() const { - F32 radius = getScale().length()*0.5f; + F32 radius = getScale().length()*0.5f; F32 linkset_base_cost = 0.f; LLMeshCostData costs; @@ -4144,87 +4144,87 @@ bool LLVOVolume::getCostData(LLMeshCostData& costs) const } else { - LLVolume* volume = getVolume(); - S32 counts[4]; - LLVolume::getLoDTriangleCounts(volume->getParams(), counts); + LLVolume* volume = getVolume(); + S32 counts[4]; + LLVolume::getLoDTriangleCounts(volume->getParams(), counts); - LLSD header; - header["lowest_lod"]["size"] = counts[0] * 10; - header["low_lod"]["size"] = counts[1] * 10; - header["medium_lod"]["size"] = counts[2] * 10; - header["high_lod"]["size"] = counts[3] * 10; + LLSD header; + header["lowest_lod"]["size"] = counts[0] * 10; + header["low_lod"]["size"] = counts[1] * 10; + header["medium_lod"]["size"] = counts[2] * 10; + header["high_lod"]["size"] = counts[3] * 10; - return gMeshRepo.getCostData(header, costs); + return gMeshRepo.getCostData(header, costs); } } //static void LLVOVolume::updateRenderComplexity() { - mRenderComplexity_last = mRenderComplexity_current; - mRenderComplexity_current = 0; + mRenderComplexity_last = mRenderComplexity_current; + mRenderComplexity_current = 0; } U32 LLVOVolume::getTriangleCount(S32* vcount) const { - U32 count = 0; - LLVolume* volume = getVolume(); - if (volume) - { - count = volume->getNumTriangles(vcount); - } + U32 count = 0; + LLVolume* volume = getVolume(); + if (volume) + { + count = volume->getNumTriangles(vcount); + } - return count; + return count; } U32 LLVOVolume::getHighLODTriangleCount() { - U32 ret = 0; + U32 ret = 0; - LLVolume* volume = getVolume(); + LLVolume* volume = getVolume(); - if (!isSculpted()) - { - LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); - ret = ref->getNumTriangles(); - LLPrimitive::getVolumeManager()->unrefVolume(ref); - } - else if (isMesh()) - { - LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); - if (!ref->isMeshAssetLoaded() || ref->getNumVolumeFaces() == 0) - { - gMeshRepo.loadMesh(this, volume->getParams(), LLModel::LOD_HIGH); - } - ret = ref->getNumTriangles(); - LLPrimitive::getVolumeManager()->unrefVolume(ref); - } - else - { //default sculpts have a constant number of triangles - ret = 31*2*31; //31 rows of 31 columns of quads for a 32x32 vertex patch - } + if (!isSculpted()) + { + LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); + ret = ref->getNumTriangles(); + LLPrimitive::getVolumeManager()->unrefVolume(ref); + } + else if (isMesh()) + { + LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); + if (!ref->isMeshAssetLoaded() || ref->getNumVolumeFaces() == 0) + { + gMeshRepo.loadMesh(this, volume->getParams(), LLModel::LOD_HIGH); + } + ret = ref->getNumTriangles(); + LLPrimitive::getVolumeManager()->unrefVolume(ref); + } + else + { //default sculpts have a constant number of triangles + ret = 31*2*31; //31 rows of 31 columns of quads for a 32x32 vertex patch + } - return ret; + return ret; } //static void LLVOVolume::preUpdateGeom() { - sNumLODChanges = 0; + sNumLODChanges = 0; } void LLVOVolume::parameterChanged(U16 param_type, bool local_origin) { - LLViewerObject::parameterChanged(param_type, local_origin); + LLViewerObject::parameterChanged(param_type, local_origin); } void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin) { - LLViewerObject::parameterChanged(param_type, data, in_use, local_origin); - if (mVolumeImpl) - { - mVolumeImpl->onParameterChanged(param_type, data, in_use, local_origin); - } + LLViewerObject::parameterChanged(param_type, data, in_use, local_origin); + if (mVolumeImpl) + { + mVolumeImpl->onParameterChanged(param_type, data, in_use, local_origin); + } if (!local_origin && param_type == LLNetworkData::PARAMS_EXTENDED_MESH) { U32 extended_mesh_flags = getExtendedMeshFlags(); @@ -4240,19 +4240,19 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u onSetExtendedMeshFlags(extended_mesh_flags); } } - if (mDrawable.notNull()) - { - BOOL is_light = getIsLight(); - if (is_light != mDrawable->isState(LLDrawable::LIGHT)) - { - gPipeline.setLight(mDrawable, is_light); - } - } + if (mDrawable.notNull()) + { + BOOL is_light = getIsLight(); + if (is_light != mDrawable->isState(LLDrawable::LIGHT)) + { + gPipeline.setLight(mDrawable, is_light); + } + } } void LLVOVolume::setSelected(BOOL sel) { - LLViewerObject::setSelected(sel); + LLViewerObject::setSelected(sel); if (isAnimatedObject()) { getRootEdit()->recursiveMarkForUpdate(TRUE); @@ -4267,110 +4267,110 @@ void LLVOVolume::setSelected(BOOL sel) } void LLVOVolume::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) -{ +{ } F32 LLVOVolume::getBinRadius() { - F32 radius; - - F32 scale = 1.f; + F32 radius; + + F32 scale = 1.f; - S32 size_factor = llmax(gSavedSettings.getS32("OctreeStaticObjectSizeFactor"), 1); - S32 attachment_size_factor = llmax(gSavedSettings.getS32("OctreeAttachmentSizeFactor"), 1); - LLVector3 distance_factor = gSavedSettings.getVector3("OctreeDistanceFactor"); - LLVector3 alpha_distance_factor = gSavedSettings.getVector3("OctreeAlphaDistanceFactor"); - const LLVector4a* ext = mDrawable->getSpatialExtents(); - - BOOL shrink_wrap = mDrawable->isAnimating(); - BOOL alpha_wrap = FALSE; + S32 size_factor = llmax(gSavedSettings.getS32("OctreeStaticObjectSizeFactor"), 1); + S32 attachment_size_factor = llmax(gSavedSettings.getS32("OctreeAttachmentSizeFactor"), 1); + LLVector3 distance_factor = gSavedSettings.getVector3("OctreeDistanceFactor"); + LLVector3 alpha_distance_factor = gSavedSettings.getVector3("OctreeAlphaDistanceFactor"); + const LLVector4a* ext = mDrawable->getSpatialExtents(); + + BOOL shrink_wrap = mDrawable->isAnimating(); + BOOL alpha_wrap = FALSE; - if (!isHUDAttachment()) - { - for (S32 i = 0; i < mDrawable->getNumFaces(); i++) - { - LLFace* face = mDrawable->getFace(i); - if (!face) continue; - if (face->getPoolType() == LLDrawPool::POOL_ALPHA && - !face->canRenderAsMask()) - { - alpha_wrap = TRUE; - break; - } - } - } - else - { - shrink_wrap = FALSE; - } + if (!isHUDAttachment()) + { + for (S32 i = 0; i < mDrawable->getNumFaces(); i++) + { + LLFace* face = mDrawable->getFace(i); + if (!face) continue; + if (face->getPoolType() == LLDrawPool::POOL_ALPHA && + !face->canRenderAsMask()) + { + alpha_wrap = TRUE; + break; + } + } + } + else + { + shrink_wrap = FALSE; + } - if (alpha_wrap) - { - LLVector3 bounds = getScale(); - radius = llmin(bounds.mV[1], bounds.mV[2]); - radius = llmin(radius, bounds.mV[0]); - radius *= 0.5f; - radius *= 1.f+mDrawable->mDistanceWRTCamera*alpha_distance_factor[1]; - radius += mDrawable->mDistanceWRTCamera*alpha_distance_factor[0]; - } - else if (shrink_wrap) - { - LLVector4a rad; - rad.setSub(ext[1], ext[0]); - - radius = rad.getLength3().getF32()*0.5f; - } - else if (mDrawable->isStatic()) - { - F32 szf = size_factor; + if (alpha_wrap) + { + LLVector3 bounds = getScale(); + radius = llmin(bounds.mV[1], bounds.mV[2]); + radius = llmin(radius, bounds.mV[0]); + radius *= 0.5f; + radius *= 1.f+mDrawable->mDistanceWRTCamera*alpha_distance_factor[1]; + radius += mDrawable->mDistanceWRTCamera*alpha_distance_factor[0]; + } + else if (shrink_wrap) + { + LLVector4a rad; + rad.setSub(ext[1], ext[0]); + + radius = rad.getLength3().getF32()*0.5f; + } + else if (mDrawable->isStatic()) + { + F32 szf = size_factor; - radius = llmax(mDrawable->getRadius(), szf); - - radius = powf(radius, 1.f+szf/radius); + radius = llmax(mDrawable->getRadius(), szf); + + radius = powf(radius, 1.f+szf/radius); - radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1]; - radius += mDrawable->mDistanceWRTCamera * distance_factor[0]; - } - else if (mDrawable->getVObj()->isAttachment()) - { - radius = llmax((S32) mDrawable->getRadius(),1)*attachment_size_factor; - } - else - { - radius = mDrawable->getRadius(); - radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1]; - radius += mDrawable->mDistanceWRTCamera * distance_factor[0]; - } + radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1]; + radius += mDrawable->mDistanceWRTCamera * distance_factor[0]; + } + else if (mDrawable->getVObj()->isAttachment()) + { + radius = llmax((S32) mDrawable->getRadius(),1)*attachment_size_factor; + } + else + { + radius = mDrawable->getRadius(); + radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1]; + radius += mDrawable->mDistanceWRTCamera * distance_factor[0]; + } - return llclamp(radius*scale, 0.5f, 256.f); + return llclamp(radius*scale, 0.5f, 256.f); } const LLVector3 LLVOVolume::getPivotPositionAgent() const { - if (mVolumeImpl) - { - return mVolumeImpl->getPivotPosition(); - } - return LLViewerObject::getPivotPositionAgent(); + if (mVolumeImpl) + { + return mVolumeImpl->getPivotPosition(); + } + return LLViewerObject::getPivotPositionAgent(); } void LLVOVolume::onShift(const LLVector4a &shift_vector) { - if (mVolumeImpl) - { - mVolumeImpl->onShift(shift_vector); - } + if (mVolumeImpl) + { + mVolumeImpl->onShift(shift_vector); + } - updateRelativeXform(); + updateRelativeXform(); } const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const { - if (mVolumeImpl) - { - return mVolumeImpl->getWorldMatrix(xform); - } - return xform->getWorldMatrix(); + if (mVolumeImpl) + { + return mVolumeImpl->getWorldMatrix(xform); + } + return xform->getWorldMatrix(); } void LLVOVolume::markForUpdate(BOOL priority) @@ -4391,256 +4391,256 @@ void LLVOVolume::markForUpdate(BOOL priority) LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const { - LLVector3 ret = pos - getRenderPosition(); - ret = ret * ~getRenderRotation(); - if (!isVolumeGlobal()) - { - LLVector3 objScale = getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - ret.scaleVec(invObjScale); - } - - return ret; + LLVector3 ret = pos - getRenderPosition(); + ret = ret * ~getRenderRotation(); + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + ret.scaleVec(invObjScale); + } + + return ret; } LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const { - LLVector3 ret = dir * ~getRenderRotation(); - - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - ret.scaleVec(objScale); + LLVector3 ret = dir * ~getRenderRotation(); + + LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); + ret.scaleVec(objScale); - return ret; + return ret; } LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const { - LLVector3 ret = dir; - if (!isVolumeGlobal()) - { - LLVector3 objScale = getScale(); - ret.scaleVec(objScale); - } + LLVector3 ret = dir; + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + ret.scaleVec(objScale); + } - ret = ret * getRenderRotation(); - ret += getRenderPosition(); - - return ret; + ret = ret * getRenderRotation(); + ret += getRenderPosition(); + + return ret; } LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const { - LLVector3 ret = dir; - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - ret.scaleVec(invObjScale); - ret = ret * getRenderRotation(); + LLVector3 ret = dir; + LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + ret.scaleVec(invObjScale); + ret = ret * getRenderRotation(); - return ret; + return ret; } BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp, - LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) - + LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) + { - if (!mbCanSelect - || mDrawable->isDead() - || !gPipeline.hasRenderType(mDrawable->getRenderType())) - { - return FALSE; - } + if (!mbCanSelect + || mDrawable->isDead() + || !gPipeline.hasRenderType(mDrawable->getRenderType())) + { + return FALSE; + } - BOOL ret = FALSE; + BOOL ret = FALSE; - LLVolume* volume = getVolume(); + LLVolume* volume = getVolume(); - bool transform = true; + bool transform = true; - if (mDrawable->isState(LLDrawable::RIGGED)) - { - if ((pick_rigged) || (getAvatar() && (getAvatar()->isSelf()) && (LLFloater::isVisible(gFloaterTools)))) - { - updateRiggedVolume(true); - volume = mRiggedVolume; - transform = false; - } - else - { //cannot pick rigged attachments on other avatars or when not in build mode - return FALSE; - } - } - - if (volume) - { - LLVector4a local_start = start; - LLVector4a local_end = end; - - if (transform) - { - LLVector3 v_start(start.getF32ptr()); - LLVector3 v_end(end.getF32ptr()); - - v_start = agentPositionToVolume(v_start); - v_end = agentPositionToVolume(v_end); + if (mDrawable->isState(LLDrawable::RIGGED)) + { + if ((pick_rigged) || (getAvatar() && (getAvatar()->isSelf()) && (LLFloater::isVisible(gFloaterTools)))) + { + updateRiggedVolume(true); + volume = mRiggedVolume; + transform = false; + } + else + { //cannot pick rigged attachments on other avatars or when not in build mode + return FALSE; + } + } + + if (volume) + { + LLVector4a local_start = start; + LLVector4a local_end = end; + + if (transform) + { + LLVector3 v_start(start.getF32ptr()); + LLVector3 v_end(end.getF32ptr()); + + v_start = agentPositionToVolume(v_start); + v_end = agentPositionToVolume(v_end); - local_start.load3(v_start.mV); - local_end.load3(v_end.mV); - } - - LLVector4a p; - LLVector4a n; - LLVector2 tc; - LLVector4a tn; + local_start.load3(v_start.mV); + local_end.load3(v_end.mV); + } + + LLVector4a p; + LLVector4a n; + LLVector2 tc; + LLVector4a tn; - if (intersection != NULL) - { - p = *intersection; - } + if (intersection != NULL) + { + p = *intersection; + } - if (tex_coord != NULL) - { - tc = *tex_coord; - } + if (tex_coord != NULL) + { + tc = *tex_coord; + } - if (normal != NULL) - { - n = *normal; - } + if (normal != NULL) + { + n = *normal; + } - if (tangent != NULL) - { - tn = *tangent; - } + if (tangent != NULL) + { + tn = *tangent; + } - S32 face_hit = -1; + S32 face_hit = -1; - S32 start_face, end_face; - if (face == -1) - { - start_face = 0; - end_face = volume->getNumVolumeFaces(); - } - else - { - start_face = face; - end_face = face+1; - } - pick_transparent |= isHiglightedOrBeacon(); - bool special_cursor = specialHoverCursor(); - for (S32 i = start_face; i < end_face; ++i) - { - if (!special_cursor && !pick_transparent && getTE(i) && getTE(i)->getColor().mV[3] == 0.f) - { //don't attempt to pick completely transparent faces unless - //pick_transparent is true - continue; - } + S32 start_face, end_face; + if (face == -1) + { + start_face = 0; + end_face = volume->getNumVolumeFaces(); + } + else + { + start_face = face; + end_face = face+1; + } + pick_transparent |= isHiglightedOrBeacon(); + bool special_cursor = specialHoverCursor(); + for (S32 i = start_face; i < end_face; ++i) + { + if (!special_cursor && !pick_transparent && getTE(i) && getTE(i)->getColor().mV[3] == 0.f) + { //don't attempt to pick completely transparent faces unless + //pick_transparent is true + continue; + } - face_hit = volume->lineSegmentIntersect(local_start, local_end, i, - &p, &tc, &n, &tn); - - if (face_hit >= 0 && mDrawable->getNumFaces() > face_hit) - { - LLFace* face = mDrawable->getFace(face_hit); + face_hit = volume->lineSegmentIntersect(local_start, local_end, i, + &p, &tc, &n, &tn); + + if (face_hit >= 0 && mDrawable->getNumFaces() > face_hit) + { + LLFace* face = mDrawable->getFace(face_hit); - bool ignore_alpha = false; + bool ignore_alpha = false; - const LLTextureEntry* te = face->getTextureEntry(); - if (te) - { - LLMaterial* mat = te->getMaterialParams(); - if (mat) - { - U8 mode = mat->getDiffuseAlphaMode(); + const LLTextureEntry* te = face->getTextureEntry(); + if (te) + { + LLMaterial* mat = te->getMaterialParams(); + if (mat) + { + U8 mode = mat->getDiffuseAlphaMode(); - if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE || - mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE) - { - ignore_alpha = true; - } - } - } + if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE || + mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE) + { + ignore_alpha = true; + } + } + } - if (face && - (ignore_alpha || - pick_transparent || - !face->getTexture() || - !face->getTexture()->hasGLTexture() || - face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)))) - { - local_end = p; - if (face_hitp != NULL) - { - *face_hitp = face_hit; - } - - if (intersection != NULL) - { - if (transform) - { - LLVector3 v_p(p.getF32ptr()); - - intersection->load3(volumePositionToAgent(v_p).mV); // must map back to agent space - } - else - { - *intersection = p; - } - } + if (face && + (ignore_alpha || + pick_transparent || + !face->getTexture() || + !face->getTexture()->hasGLTexture() || + face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)))) + { + local_end = p; + if (face_hitp != NULL) + { + *face_hitp = face_hit; + } + + if (intersection != NULL) + { + if (transform) + { + LLVector3 v_p(p.getF32ptr()); + + intersection->load3(volumePositionToAgent(v_p).mV); // must map back to agent space + } + else + { + *intersection = p; + } + } - if (normal != NULL) - { - if (transform) - { - LLVector3 v_n(n.getF32ptr()); - normal->load3(volumeDirectionToAgent(v_n).mV); - } - else - { - *normal = n; - } - (*normal).normalize3fast(); - } + if (normal != NULL) + { + if (transform) + { + LLVector3 v_n(n.getF32ptr()); + normal->load3(volumeDirectionToAgent(v_n).mV); + } + else + { + *normal = n; + } + (*normal).normalize3fast(); + } - if (tangent != NULL) - { - if (transform) - { - LLVector3 v_tn(tn.getF32ptr()); - - LLVector4a trans_tangent; - trans_tangent.load3(volumeDirectionToAgent(v_tn).mV); - - LLVector4Logical mask; - mask.clear(); - mask.setElement<3>(); - - tangent->setSelectWithMask(mask, tn, trans_tangent); - } - else - { - *tangent = tn; - } - (*tangent).normalize3fast(); - } + if (tangent != NULL) + { + if (transform) + { + LLVector3 v_tn(tn.getF32ptr()); + + LLVector4a trans_tangent; + trans_tangent.load3(volumeDirectionToAgent(v_tn).mV); + + LLVector4Logical mask; + mask.clear(); + mask.setElement<3>(); + + tangent->setSelectWithMask(mask, tn, trans_tangent); + } + else + { + *tangent = tn; + } + (*tangent).normalize3fast(); + } - if (tex_coord != NULL) - { - *tex_coord = tc; - } - - ret = TRUE; - } - } - } - } - - return ret; + if (tex_coord != NULL) + { + *tex_coord = tc; + } + + ret = TRUE; + } + } + } + } + + return ret; } bool LLVOVolume::treatAsRigged() { - return isSelected() && + return isSelected() && (isAttachment() || isAnimatedObject()) && mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED); @@ -4648,53 +4648,53 @@ bool LLVOVolume::treatAsRigged() LLRiggedVolume* LLVOVolume::getRiggedVolume() { - return mRiggedVolume; + return mRiggedVolume; } void LLVOVolume::clearRiggedVolume() { - if (mRiggedVolume.notNull()) - { - mRiggedVolume = NULL; - updateRelativeXform(); - } + if (mRiggedVolume.notNull()) + { + mRiggedVolume = NULL; + updateRelativeXform(); + } } void LLVOVolume::updateRiggedVolume(bool force_update) { - //Update mRiggedVolume to match current animation frame of avatar. - //Also update position/size in octree. + //Update mRiggedVolume to match current animation frame of avatar. + //Also update position/size in octree. - if ((!force_update) && (!treatAsRigged())) - { - clearRiggedVolume(); - - return; - } + if ((!force_update) && (!treatAsRigged())) + { + clearRiggedVolume(); + + return; + } - LLVolume* volume = getVolume(); - const LLMeshSkinInfo* skin = getSkinInfo(); - if (!skin) - { - clearRiggedVolume(); - return; - } + LLVolume* volume = getVolume(); + const LLMeshSkinInfo* skin = getSkinInfo(); + if (!skin) + { + clearRiggedVolume(); + return; + } - LLVOAvatar* avatar = getAvatar(); - if (!avatar) - { - clearRiggedVolume(); - return; - } + LLVOAvatar* avatar = getAvatar(); + if (!avatar) + { + clearRiggedVolume(); + return; + } - if (!mRiggedVolume) - { - LLVolumeParams p; - mRiggedVolume = new LLRiggedVolume(p); - updateRelativeXform(); - } + if (!mRiggedVolume) + { + LLVolumeParams p; + mRiggedVolume = new LLRiggedVolume(p); + updateRelativeXform(); + } - mRiggedVolume->update(skin, avatar, volume); + mRiggedVolume->update(skin, avatar, volume); } static LLTrace::BlockTimerStatHandle FTM_SKIN_RIGGED("Skin"); @@ -4702,128 +4702,128 @@ static LLTrace::BlockTimerStatHandle FTM_RIGGED_OCTREE("Octree"); void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume) { - bool copy = false; - if (volume->getNumVolumeFaces() != getNumVolumeFaces()) - { - copy = true; - } + bool copy = false; + if (volume->getNumVolumeFaces() != getNumVolumeFaces()) + { + copy = true; + } - for (S32 i = 0; i < volume->getNumVolumeFaces() && !copy; ++i) - { - const LLVolumeFace& src_face = volume->getVolumeFace(i); - const LLVolumeFace& dst_face = getVolumeFace(i); + for (S32 i = 0; i < volume->getNumVolumeFaces() && !copy; ++i) + { + const LLVolumeFace& src_face = volume->getVolumeFace(i); + const LLVolumeFace& dst_face = getVolumeFace(i); - if (src_face.mNumIndices != dst_face.mNumIndices || - src_face.mNumVertices != dst_face.mNumVertices) - { - copy = true; - } - } + if (src_face.mNumIndices != dst_face.mNumIndices || + src_face.mNumVertices != dst_face.mNumVertices) + { + copy = true; + } + } - if (copy) - { - copyVolumeFaces(volume); - } + if (copy) + { + copyVolumeFaces(volume); + } else { bool is_paused = avatar && avatar->areAnimationsPaused(); - if (is_paused) - { + if (is_paused) + { S32 frames_paused = LLFrameTimer::getFrameCount() - avatar->getMotionController().getPausedFrame(); if (frames_paused > 2) { return; } - } + } } - //build matrix palette - static const size_t kMaxJoints = LL_MAX_JOINTS_PER_MESH_OBJECT; + //build matrix palette + static const size_t kMaxJoints = LL_MAX_JOINTS_PER_MESH_OBJECT; - LLMatrix4a mat[kMaxJoints]; - U32 maxJoints = LLSkinningUtil::getMeshJointCount(skin); + LLMatrix4a mat[kMaxJoints]; + U32 maxJoints = LLSkinningUtil::getMeshJointCount(skin); LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, maxJoints, skin, avatar); S32 rigged_vert_count = 0; S32 rigged_face_count = 0; LLVector4a box_min, box_max; - for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) - { - const LLVolumeFace& vol_face = volume->getVolumeFace(i); - - LLVolumeFace& dst_face = mVolumeFaces[i]; - - LLVector4a* weight = vol_face.mWeights; + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& vol_face = volume->getVolumeFace(i); + + LLVolumeFace& dst_face = mVolumeFaces[i]; + + LLVector4a* weight = vol_face.mWeights; - if ( weight ) - { + if ( weight ) + { LLSkinningUtil::checkSkinWeights(weight, dst_face.mNumVertices, skin); - LLMatrix4a bind_shape_matrix; - bind_shape_matrix.loadu(skin->mBindShapeMatrix); + LLMatrix4a bind_shape_matrix; + bind_shape_matrix.loadu(skin->mBindShapeMatrix); - LLVector4a* pos = dst_face.mPositions; + LLVector4a* pos = dst_face.mPositions; - if (pos && dst_face.mExtents) - { - LL_RECORD_BLOCK_TIME(FTM_SKIN_RIGGED); + if (pos && dst_face.mExtents) + { + LL_RECORD_BLOCK_TIME(FTM_SKIN_RIGGED); U32 max_joints = LLSkinningUtil::getMaxJointCount(); rigged_vert_count += dst_face.mNumVertices; rigged_face_count++; - for (U32 j = 0; j < dst_face.mNumVertices; ++j) - { - LLMatrix4a final_mat; + for (U32 j = 0; j < dst_face.mNumVertices; ++j) + { + LLMatrix4a final_mat; LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); - - LLVector4a& v = vol_face.mPositions[j]; - LLVector4a t; - LLVector4a dst; - bind_shape_matrix.affineTransform(v, t); - final_mat.affineTransform(t, dst); - pos[j] = dst; - } + + LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + } - //update bounding box - // VFExtents change - LLVector4a& min = dst_face.mExtents[0]; - LLVector4a& max = dst_face.mExtents[1]; + //update bounding box + // VFExtents change + LLVector4a& min = dst_face.mExtents[0]; + LLVector4a& max = dst_face.mExtents[1]; - min = pos[0]; - max = pos[1]; + min = pos[0]; + max = pos[1]; if (i==0) { box_min = min; box_max = max; } - for (U32 j = 1; j < dst_face.mNumVertices; ++j) - { - min.setMin(min, pos[j]); - max.setMax(max, pos[j]); - } + for (U32 j = 1; j < dst_face.mNumVertices; ++j) + { + min.setMin(min, pos[j]); + max.setMax(max, pos[j]); + } box_min.setMin(min,box_min); box_max.setMax(max,box_max); - dst_face.mCenter->setAdd(dst_face.mExtents[0], dst_face.mExtents[1]); - dst_face.mCenter->mul(0.5f); - - } + dst_face.mCenter->setAdd(dst_face.mExtents[0], dst_face.mExtents[1]); + dst_face.mCenter->mul(0.5f); - { - LL_RECORD_BLOCK_TIME(FTM_RIGGED_OCTREE); - delete dst_face.mOctree; - dst_face.mOctree = NULL; + } - LLVector4a size; - size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]); - size.splat(size.getLength3().getF32()*0.5f); - - dst_face.createOctree(1.f); - } - } - } + { + LL_RECORD_BLOCK_TIME(FTM_RIGGED_OCTREE); + delete dst_face.mOctree; + dst_face.mOctree = NULL; + + LLVector4a size; + size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]); + size.splat(size.getLength3().getF32()*0.5f); + + dst_face.createOctree(1.f); + } + } + } mExtraDebugText = llformat("rigged %d/%d - box (%f %f %f) (%f %f %f)", rigged_face_count, rigged_vert_count, box_min[0], box_min[1], box_min[2], @@ -4832,63 +4832,63 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons U32 LLVOVolume::getPartitionType() const { - if (isHUDAttachment()) - { - return LLViewerRegion::PARTITION_HUD; - } + if (isHUDAttachment()) + { + return LLViewerRegion::PARTITION_HUD; + } - return LLViewerRegion::PARTITION_VOLUME; + return LLViewerRegion::PARTITION_VOLUME; } LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp) : LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB, regionp), LLVolumeGeometryManager() { - mLODPeriod = 32; - mDepthMask = FALSE; - mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; - mPartitionType = LLViewerRegion::PARTITION_VOLUME; - mSlopRatio = 0.25f; - mBufferUsage = GL_DYNAMIC_DRAW_ARB; + mLODPeriod = 32; + mDepthMask = FALSE; + mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; + mPartitionType = LLViewerRegion::PARTITION_VOLUME; + mSlopRatio = 0.25f; + mBufferUsage = GL_DYNAMIC_DRAW_ARB; } LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep, LLViewerRegion* regionp) : LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK, regionp), LLVolumeGeometryManager() { - mDepthMask = FALSE; - mLODPeriod = 32; - mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; - mPartitionType = LLViewerRegion::PARTITION_BRIDGE; - - mBufferUsage = GL_DYNAMIC_DRAW_ARB; + mDepthMask = FALSE; + mLODPeriod = 32; + mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; + mPartitionType = LLViewerRegion::PARTITION_BRIDGE; + + mBufferUsage = GL_DYNAMIC_DRAW_ARB; - mSlopRatio = 0.25f; + mSlopRatio = 0.25f; } bool can_batch_texture(LLFace* facep) { - if (facep->getTextureEntry()->getBumpmap()) - { //bump maps aren't worked into texture batching yet - return false; - } + if (facep->getTextureEntry()->getBumpmap()) + { //bump maps aren't worked into texture batching yet + return false; + } - if (facep->getTextureEntry()->getMaterialParams().notNull()) - { //materials don't work with texture batching yet - return false; - } + if (facep->getTextureEntry()->getMaterialParams().notNull()) + { //materials don't work with texture batching yet + return false; + } - if (facep->getTexture() && facep->getTexture()->getPrimaryFormat() == GL_ALPHA) - { //can't batch invisiprims - return false; - } + if (facep->getTexture() && facep->getTexture()->getPrimaryFormat() == GL_ALPHA) + { //can't batch invisiprims + return false; + } - if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) - { //texture animation breaks batches - return false; - } - - return true; + if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) + { //texture animation breaks batches + return false; + } + + return true; } const static U32 MAX_FACE_COUNT = 4096U; @@ -4902,285 +4902,285 @@ LLFace** LLVolumeGeometryManager::sNormSpecFaces = NULL; LLFace** LLVolumeGeometryManager::sAlphaFaces = NULL; LLVolumeGeometryManager::LLVolumeGeometryManager() - : LLGeometryManager() + : LLGeometryManager() { - llassert(sInstanceCount >= 0); - if (sInstanceCount == 0) - { - allocateFaces(MAX_FACE_COUNT); - } + llassert(sInstanceCount >= 0); + if (sInstanceCount == 0) + { + allocateFaces(MAX_FACE_COUNT); + } - ++sInstanceCount; + ++sInstanceCount; } LLVolumeGeometryManager::~LLVolumeGeometryManager() { - llassert(sInstanceCount > 0); - --sInstanceCount; + llassert(sInstanceCount > 0); + --sInstanceCount; - if (sInstanceCount <= 0) - { - freeFaces(); - sInstanceCount = 0; - } + if (sInstanceCount <= 0) + { + freeFaces(); + sInstanceCount = 0; + } } void LLVolumeGeometryManager::allocateFaces(U32 pMaxFaceCount) { - sFullbrightFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sBumpFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sSimpleFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sNormFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sSpecFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sNormSpecFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sAlphaFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sFullbrightFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sBumpFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sSimpleFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sNormFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sSpecFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sNormSpecFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sAlphaFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); } void LLVolumeGeometryManager::freeFaces() { - ll_aligned_free<64>(sFullbrightFaces); - ll_aligned_free<64>(sBumpFaces); - ll_aligned_free<64>(sSimpleFaces); - ll_aligned_free<64>(sNormFaces); - ll_aligned_free<64>(sSpecFaces); - ll_aligned_free<64>(sNormSpecFaces); - ll_aligned_free<64>(sAlphaFaces); + ll_aligned_free<64>(sFullbrightFaces); + ll_aligned_free<64>(sBumpFaces); + ll_aligned_free<64>(sSimpleFaces); + ll_aligned_free<64>(sNormFaces); + ll_aligned_free<64>(sSpecFaces); + ll_aligned_free<64>(sNormSpecFaces); + ll_aligned_free<64>(sAlphaFaces); - sFullbrightFaces = NULL; - sBumpFaces = NULL; - sSimpleFaces = NULL; - sNormFaces = NULL; - sSpecFaces = NULL; - sNormSpecFaces = NULL; - sAlphaFaces = NULL; + sFullbrightFaces = NULL; + sBumpFaces = NULL; + sSimpleFaces = NULL; + sNormFaces = NULL; + sSpecFaces = NULL; + sNormSpecFaces = NULL; + sAlphaFaces = NULL; } static LLTrace::BlockTimerStatHandle FTM_REGISTER_FACE("Register Face"); void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) { - LL_RECORD_BLOCK_TIME(FTM_REGISTER_FACE); - if (type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT)) - { - LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL; - } + LL_RECORD_BLOCK_TIME(FTM_REGISTER_FACE); + if (type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT)) + { + LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL; + } - bool selected = facep->getViewerObject()->isSelected(); + bool selected = facep->getViewerObject()->isSelected(); - if (selected && LLSelectMgr::getInstance()->mHideSelectedObjects) - { - return; - } + if (selected && LLSelectMgr::getInstance()->mHideSelectedObjects) + { + return; + } - //add face to drawmap - LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[type]; + //add face to drawmap + LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[type]; - S32 idx = draw_vec.size()-1; + S32 idx = draw_vec.size()-1; - BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) || - (type == LLRenderPass::PASS_INVISIBLE) || - (type == LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK) || - (type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)) || - (facep->getTextureEntry()->getFullbright()); - - if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_NORMAL)) - { - LL_WARNS() << "Non fullbright face has no normals!" << LL_ENDL; - return; - } + BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) || + (type == LLRenderPass::PASS_INVISIBLE) || + (type == LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK) || + (type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)) || + (facep->getTextureEntry()->getFullbright()); + + if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_NORMAL)) + { + LL_WARNS() << "Non fullbright face has no normals!" << LL_ENDL; + return; + } - const LLMatrix4* tex_mat = NULL; - if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) - { - tex_mat = facep->mTextureMatrix; - } + const LLMatrix4* tex_mat = NULL; + if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) + { + tex_mat = facep->mTextureMatrix; + } - const LLMatrix4* model_mat = NULL; + const LLMatrix4* model_mat = NULL; - LLDrawable* drawable = facep->getDrawable(); - - if (drawable->isState(LLDrawable::ANIMATED_CHILD)) - { - model_mat = &drawable->getWorldMatrix(); - } - else if (drawable->isActive()) - { - model_mat = &drawable->getRenderMatrix(); - } - else - { - model_mat = &(drawable->getRegion()->mRenderMatrix); - } + LLDrawable* drawable = facep->getDrawable(); + + if (drawable->isState(LLDrawable::ANIMATED_CHILD)) + { + model_mat = &drawable->getWorldMatrix(); + } + else if (drawable->isActive()) + { + model_mat = &drawable->getRenderMatrix(); + } + else + { + model_mat = &(drawable->getRegion()->mRenderMatrix); + } - //drawable->getVObj()->setDebugText(llformat("%d", drawable->isState(LLDrawable::ANIMATED_CHILD))); + //drawable->getVObj()->setDebugText(llformat("%d", drawable->isState(LLDrawable::ANIMATED_CHILD))); - U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0; - U8 shiny = facep->getTextureEntry()->getShiny(); - - LLViewerTexture* tex = facep->getTexture(); + U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0; + U8 shiny = facep->getTextureEntry()->getShiny(); + + LLViewerTexture* tex = facep->getTexture(); - U8 index = facep->getTextureIndex(); + U8 index = facep->getTextureIndex(); - LLMaterial* mat = facep->getTextureEntry()->getMaterialParams().get(); - LLMaterialID mat_id = facep->getTextureEntry()->getMaterialID(); + LLMaterial* mat = facep->getTextureEntry()->getMaterialParams().get(); + LLMaterialID mat_id = facep->getTextureEntry()->getMaterialID(); - bool batchable = false; + bool batchable = false; - U32 shader_mask = 0xFFFFFFFF; //no shader + U32 shader_mask = 0xFFFFFFFF; //no shader - if (mat) - { - if (type == LLRenderPass::PASS_ALPHA) - { - shader_mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND); - } - else - { - shader_mask = mat->getShaderMask(); - } - } + if (mat) + { + if (type == LLRenderPass::PASS_ALPHA) + { + shader_mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND); + } + else + { + shader_mask = mat->getShaderMask(); + } + } - if (index < 255 && idx >= 0) - { - if (mat || draw_vec[idx]->mMaterial) - { //can't batch textures when materials are present (yet) - batchable = false; - } - else if (index < draw_vec[idx]->mTextureList.size()) - { - if (draw_vec[idx]->mTextureList[index].isNull()) - { - batchable = true; - draw_vec[idx]->mTextureList[index] = tex; - } - else if (draw_vec[idx]->mTextureList[index] == tex) - { //this face's texture index can be used with this batch - batchable = true; - } - } - else - { //texture list can be expanded to fit this texture index - batchable = true; - } - } + if (index < 255 && idx >= 0) + { + if (mat || draw_vec[idx]->mMaterial) + { //can't batch textures when materials are present (yet) + batchable = false; + } + else if (index < draw_vec[idx]->mTextureList.size()) + { + if (draw_vec[idx]->mTextureList[index].isNull()) + { + batchable = true; + draw_vec[idx]->mTextureList[index] = tex; + } + else if (draw_vec[idx]->mTextureList[index] == tex) + { //this face's texture index can be used with this batch + batchable = true; + } + } + else + { //texture list can be expanded to fit this texture index + batchable = true; + } + } - if (idx >= 0 && - draw_vec[idx]->mVertexBuffer == facep->getVertexBuffer() && - draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && - (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex || batchable) && + if (idx >= 0 && + draw_vec[idx]->mVertexBuffer == facep->getVertexBuffer() && + draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && + (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex || batchable) && #if LL_DARWIN - draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && - draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && + draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && + draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && #endif - draw_vec[idx]->mMaterial == mat && - draw_vec[idx]->mMaterialID == mat_id && - draw_vec[idx]->mFullbright == fullbright && - draw_vec[idx]->mBump == bump && - (!mat || (draw_vec[idx]->mShiny == shiny)) && // need to break batches when a material is shared, but legacy settings are different - draw_vec[idx]->mTextureMatrix == tex_mat && - draw_vec[idx]->mModelMatrix == model_mat && - draw_vec[idx]->mShaderMask == shader_mask && - draw_vec[idx]->mSelected == selected) - { - draw_vec[idx]->mCount += facep->getIndicesCount(); - draw_vec[idx]->mEnd += facep->getGeomCount(); - draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize()); + draw_vec[idx]->mMaterial == mat && + draw_vec[idx]->mMaterialID == mat_id && + draw_vec[idx]->mFullbright == fullbright && + draw_vec[idx]->mBump == bump && + (!mat || (draw_vec[idx]->mShiny == shiny)) && // need to break batches when a material is shared, but legacy settings are different + draw_vec[idx]->mTextureMatrix == tex_mat && + draw_vec[idx]->mModelMatrix == model_mat && + draw_vec[idx]->mShaderMask == shader_mask && + draw_vec[idx]->mSelected == selected) + { + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mEnd += facep->getGeomCount(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize()); - if (index < 255 && index >= draw_vec[idx]->mTextureList.size()) - { - draw_vec[idx]->mTextureList.resize(index+1); - draw_vec[idx]->mTextureList[index] = tex; - } - draw_vec[idx]->validate(); - update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]); - update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[1]); - } - else - { - U32 start = facep->getGeomIndex(); - U32 end = start + facep->getGeomCount()-1; - U32 offset = facep->getIndicesStart(); - U32 count = facep->getIndicesCount(); - LLPointer draw_info = new LLDrawInfo(start,end,count,offset, tex, - facep->getVertexBuffer(), selected, fullbright, bump); - draw_info->mGroup = group; - draw_info->mVSize = facep->getVirtualSize(); - draw_vec.push_back(draw_info); - draw_info->mTextureMatrix = tex_mat; - draw_info->mModelMatrix = model_mat; - - draw_info->mBump = bump; - draw_info->mShiny = shiny; + if (index < 255 && index >= draw_vec[idx]->mTextureList.size()) + { + draw_vec[idx]->mTextureList.resize(index+1); + draw_vec[idx]->mTextureList[index] = tex; + } + draw_vec[idx]->validate(); + update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]); + update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[1]); + } + else + { + U32 start = facep->getGeomIndex(); + U32 end = start + facep->getGeomCount()-1; + U32 offset = facep->getIndicesStart(); + U32 count = facep->getIndicesCount(); + LLPointer draw_info = new LLDrawInfo(start,end,count,offset, tex, + facep->getVertexBuffer(), selected, fullbright, bump); + draw_info->mGroup = group; + draw_info->mVSize = facep->getVirtualSize(); + draw_vec.push_back(draw_info); + draw_info->mTextureMatrix = tex_mat; + draw_info->mModelMatrix = model_mat; + + draw_info->mBump = bump; + draw_info->mShiny = shiny; - static const float alpha[4] = - { - 0.00f, - 0.25f, - 0.5f, - 0.75f - }; - float spec = alpha[shiny & TEM_SHINY_MASK]; - LLVector4 specColor(spec, spec, spec, spec); - draw_info->mSpecColor = specColor; - draw_info->mEnvIntensity = spec; - draw_info->mSpecularMap = NULL; - draw_info->mMaterial = mat; - draw_info->mShaderMask = shader_mask; - - if (mat) - { - draw_info->mMaterialID = mat_id; + static const float alpha[4] = + { + 0.00f, + 0.25f, + 0.5f, + 0.75f + }; + float spec = alpha[shiny & TEM_SHINY_MASK]; + LLVector4 specColor(spec, spec, spec, spec); + draw_info->mSpecColor = specColor; + draw_info->mEnvIntensity = spec; + draw_info->mSpecularMap = NULL; + draw_info->mMaterial = mat; + draw_info->mShaderMask = shader_mask; + + if (mat) + { + draw_info->mMaterialID = mat_id; - // We have a material. Update our draw info accordingly. - - if (!mat->getSpecularID().isNull()) - { - LLVector4 specColor; - specColor.mV[0] = mat->getSpecularLightColor().mV[0] * (1.f / 255.f); - specColor.mV[1] = mat->getSpecularLightColor().mV[1] * (1.f / 255.f); - specColor.mV[2] = mat->getSpecularLightColor().mV[2] * (1.f / 255.f); - specColor.mV[3] = mat->getSpecularLightExponent() * (1.f / 255.f); - draw_info->mSpecColor = specColor; - draw_info->mEnvIntensity = mat->getEnvironmentIntensity() * (1.f / 255.f); - draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTEOffset()); - } + // We have a material. Update our draw info accordingly. + + if (!mat->getSpecularID().isNull()) + { + LLVector4 specColor; + specColor.mV[0] = mat->getSpecularLightColor().mV[0] * (1.f / 255.f); + specColor.mV[1] = mat->getSpecularLightColor().mV[1] * (1.f / 255.f); + specColor.mV[2] = mat->getSpecularLightColor().mV[2] * (1.f / 255.f); + specColor.mV[3] = mat->getSpecularLightExponent() * (1.f / 255.f); + draw_info->mSpecColor = specColor; + draw_info->mEnvIntensity = mat->getEnvironmentIntensity() * (1.f / 255.f); + draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTEOffset()); + } - draw_info->mAlphaMaskCutoff = mat->getAlphaMaskCutoff() * (1.f / 255.f); - draw_info->mDiffuseAlphaMode = mat->getDiffuseAlphaMode(); - draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTEOffset()); - } - else - { - if (type == LLRenderPass::PASS_GRASS) - { - draw_info->mAlphaMaskCutoff = 0.5f; - } - else - { - draw_info->mAlphaMaskCutoff = 0.33f; - } - } - - if (type == LLRenderPass::PASS_ALPHA) - { //for alpha sorting - facep->setDrawInfo(draw_info); - } - draw_info->mExtents[0] = facep->mExtents[0]; - draw_info->mExtents[1] = facep->mExtents[1]; + draw_info->mAlphaMaskCutoff = mat->getAlphaMaskCutoff() * (1.f / 255.f); + draw_info->mDiffuseAlphaMode = mat->getDiffuseAlphaMode(); + draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTEOffset()); + } + else + { + if (type == LLRenderPass::PASS_GRASS) + { + draw_info->mAlphaMaskCutoff = 0.5f; + } + else + { + draw_info->mAlphaMaskCutoff = 0.33f; + } + } + + if (type == LLRenderPass::PASS_ALPHA) + { //for alpha sorting + facep->setDrawInfo(draw_info); + } + draw_info->mExtents[0] = facep->mExtents[0]; + draw_info->mExtents[1] = facep->mExtents[1]; - if (LLPipeline::sUseTriStrips) - { - draw_info->mDrawMode = LLRender::TRIANGLE_STRIP; - } + if (LLPipeline::sUseTriStrips) + { + draw_info->mDrawMode = LLRender::TRIANGLE_STRIP; + } - if (index < 255) - { //initialize texture list for texture batching - draw_info->mTextureList.resize(index+1); - draw_info->mTextureList[index] = tex; - } - draw_info->validate(); - } + if (index < 255) + { //initialize texture list for texture batching + draw_info->mTextureList.resize(index+1); + draw_info->mTextureList[index] = tex; + } + draw_info->validate(); + } } void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) @@ -5194,219 +5194,219 @@ static LLTrace::BlockTimerStatHandle FTM_REBUILD_VOLUME_GEN_DRAW_INFO("Gen Draw static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) { - LLVOAvatar* avatar = vobj->getAvatar(); - - if (avatar) - { - LLDrawable* drawable = avatar->mDrawable; - if (drawable && drawable->getNumFaces() > 0) - { - LLFace* face = drawable->getFace(0); - if (face) - { - LLDrawPool* drawpool = face->getPool(); - if (drawpool) - { - if (drawpool->getType() == LLDrawPool::POOL_AVATAR) - { - return (LLDrawPoolAvatar*) drawpool; - } - } - } - } - } + LLVOAvatar* avatar = vobj->getAvatar(); + + if (avatar) + { + LLDrawable* drawable = avatar->mDrawable; + if (drawable && drawable->getNumFaces() > 0) + { + LLFace* face = drawable->getFace(0); + if (face) + { + LLDrawPool* drawpool = face->getPool(); + if (drawpool) + { + if (drawpool->getType() == LLDrawPool::POOL_AVATAR) + { + return (LLDrawPoolAvatar*) drawpool; + } + } + } + } + } - return NULL; + return NULL; } void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value) { - static LLCachedControl render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U); + static LLCachedControl render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U); - if (0 != render_auto_mute_byte_limit) - { - //for unload - LLSculptIDSize::container_BY_SIZE_view::iterator - itL = LLSculptIDSize::instance().getSizeInfo().get().lower_bound(render_auto_mute_byte_limit), - itU = LLSculptIDSize::instance().getSizeInfo().get().end(); + if (0 != render_auto_mute_byte_limit) + { + //for unload + LLSculptIDSize::container_BY_SIZE_view::iterator + itL = LLSculptIDSize::instance().getSizeInfo().get().lower_bound(render_auto_mute_byte_limit), + itU = LLSculptIDSize::instance().getSizeInfo().get().end(); - for (; itL != itU; ++itL) - { - const LLSculptIDSize::Info &nfo = *itL; - LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); - if (pVVol - && !pVVol->isDead() - && pVVol->isAttachment() - && !pVVol->getAvatar()->isSelf() - && LLVOVolume::NO_LOD != pVVol->getLOD() - ) - { - //postponed - pVVol->markForUnload(); - LLSculptIDSize::instance().addToUnloaded(nfo.getSculptId()); - } - } + for (; itL != itU; ++itL) + { + const LLSculptIDSize::Info &nfo = *itL; + LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); + if (pVVol + && !pVVol->isDead() + && pVVol->isAttachment() + && !pVVol->getAvatar()->isSelf() + && LLVOVolume::NO_LOD != pVVol->getLOD() + ) + { + //postponed + pVVol->markForUnload(); + LLSculptIDSize::instance().addToUnloaded(nfo.getSculptId()); + } + } - //for load if it was unload - itL = LLSculptIDSize::instance().getSizeInfo().get().begin(); - itU = LLSculptIDSize::instance().getSizeInfo().get().upper_bound(render_auto_mute_byte_limit); + //for load if it was unload + itL = LLSculptIDSize::instance().getSizeInfo().get().begin(); + itU = LLSculptIDSize::instance().getSizeInfo().get().upper_bound(render_auto_mute_byte_limit); - for (; itL != itU; ++itL) - { - const LLSculptIDSize::Info &nfo = *itL; - LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); - if (pVVol - && !pVVol->isDead() - && pVVol->isAttachment() - && !pVVol->getAvatar()->isSelf() - && LLVOVolume::NO_LOD == pVVol->getLOD() - ) - { - LLSculptIDSize::instance().remFromUnloaded(nfo.getSculptId()); - pVVol->updateLOD(); - pVVol->markForUpdate(TRUE); - } - } - } - else - { - LLSculptIDSize::instance().clearUnloaded(); + for (; itL != itU; ++itL) + { + const LLSculptIDSize::Info &nfo = *itL; + LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); + if (pVVol + && !pVVol->isDead() + && pVVol->isAttachment() + && !pVVol->getAvatar()->isSelf() + && LLVOVolume::NO_LOD == pVVol->getLOD() + ) + { + LLSculptIDSize::instance().remFromUnloaded(nfo.getSculptId()); + pVVol->updateLOD(); + pVVol->markForUpdate(TRUE); + } + } + } + else + { + LLSculptIDSize::instance().clearUnloaded(); - LLSculptIDSize::container_BY_SIZE_view::iterator - itL = LLSculptIDSize::instance().getSizeInfo().get().begin(), - itU = LLSculptIDSize::instance().getSizeInfo().get().end(); + LLSculptIDSize::container_BY_SIZE_view::iterator + itL = LLSculptIDSize::instance().getSizeInfo().get().begin(), + itU = LLSculptIDSize::instance().getSizeInfo().get().end(); - for (; itL != itU; ++itL) - { - const LLSculptIDSize::Info &nfo = *itL; - LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); - if (pVVol - && !pVVol->isDead() - && pVVol->isAttachment() - && !pVVol->getAvatar()->isSelf() - && LLVOVolume::NO_LOD == pVVol->getLOD() - ) - { - pVVol->updateLOD(); - pVVol->markForUpdate(TRUE); - } - } - } + for (; itL != itU; ++itL) + { + const LLSculptIDSize::Info &nfo = *itL; + LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); + if (pVVol + && !pVVol->isDead() + && pVVol->isAttachment() + && !pVVol->getAvatar()->isSelf() + && LLVOVolume::NO_LOD == pVVol->getLOD() + ) + { + pVVol->updateLOD(); + pVVol->markForUpdate(TRUE); + } + } + } } void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { - if (group->changeLOD()) - { - group->mLastUpdateDistance = group->mDistance; - } + if (group->changeLOD()) + { + group->mLastUpdateDistance = group->mDistance; + } - group->mLastUpdateViewAngle = group->mViewAngle; + group->mLastUpdateViewAngle = group->mViewAngle; - if (!group->hasState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY)) - { - if (group->hasState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate) - { - rebuildMesh(group); - } - return; - } + if (!group->hasState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY)) + { + if (group->hasState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate) + { + rebuildMesh(group); + } + return; + } - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB); - group->mBuilt = 1.f; - - LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); + group->mBuilt = 1.f; + + LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); LLViewerObject *vobj = NULL; LLVOVolume *vol_obj = NULL; - if (bridge) - { + if (bridge) + { vobj = bridge->mDrawable->getVObj(); vol_obj = dynamic_cast(vobj); - } + } if (vol_obj) { vol_obj->updateVisualComplexity(); } - group->mGeometryBytes = 0; - group->mSurfaceArea = 0; - - //cache object box size since it might be used for determining visibility - const LLVector4a* bounds = group->getObjectBounds(); - group->mObjectBoxSize = bounds[1].getLength3().getF32(); + group->mGeometryBytes = 0; + group->mSurfaceArea = 0; + + //cache object box size since it might be used for determining visibility + const LLVector4a* bounds = group->getObjectBounds(); + group->mObjectBoxSize = bounds[1].getLength3().getF32(); - group->clearDrawMap(); + group->clearDrawMap(); - mFaceList.clear(); + mFaceList.clear(); - U32 fullbright_count = 0; - U32 bump_count = 0; - U32 simple_count = 0; - U32 alpha_count = 0; - U32 norm_count = 0; - U32 spec_count = 0; - U32 normspec_count = 0; + U32 fullbright_count = 0; + U32 bump_count = 0; + U32 simple_count = 0; + U32 alpha_count = 0; + U32 norm_count = 0; + U32 spec_count = 0; + U32 normspec_count = 0; - U32 useage = group->getSpatialPartition()->mBufferUsage; + U32 useage = group->getSpatialPartition()->mBufferUsage; - U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); - U32 max_total = (gSavedSettings.getS32("RenderMaxNodeSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); - max_vertices = llmin(max_vertices, (U32) 65535); + U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); + U32 max_total = (gSavedSettings.getS32("RenderMaxNodeSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); + max_vertices = llmin(max_vertices, (U32) 65535); - U32 cur_total = 0; + U32 cur_total = 0; - bool emissive = false; + bool emissive = false; - //Determine if we've received skininfo that contains an - //alternate bind matrix - if it does then apply the translational component - //to the joints of the avatar. + //Determine if we've received skininfo that contains an + //alternate bind matrix - if it does then apply the translational component + //to the joints of the avatar. #if 0 - bool pelvisGotSet = false; + bool pelvisGotSet = false; #endif - { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_FACE_LIST); + { + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_FACE_LIST); - //get all the faces into a list - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); + //get all the faces into a list + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - - if (!drawablep || drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) - { - continue; - } - - if (drawablep->isAnimating()) - { //fall back to stream draw for animating verts - useage = GL_STREAM_DRAW_ARB; - } - - LLVOVolume* vobj = drawablep->getVOVolume(); + { + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + + if (!drawablep || drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) + { + continue; + } + + if (drawablep->isAnimating()) + { //fall back to stream draw for animating verts + useage = GL_STREAM_DRAW_ARB; + } + + LLVOVolume* vobj = drawablep->getVOVolume(); - if (!vobj) - { - continue; - } + if (!vobj) + { + continue; + } std::string vobj_name = llformat("Vol%p", vobj); - if (vobj->isMesh() && - ((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled())) - { - continue; - } + if (vobj->isMesh() && + ((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled())) + { + continue; + } - LLVolume* volume = vobj->getVolume(); - if (volume) - { - const LLVector3& scale = vobj->getScale(); - group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); - } + LLVolume* volume = vobj->getVolume(); + if (volume) + { + const LLVector3& scale = vobj->getScale(); + group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); + } bool is_mesh = vobj->isMesh(); F32 est_tris = vobj->getEstTrianglesMax(); @@ -5426,11 +5426,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) << " frame " << LLFrameTimer::getFrameCount() << LL_ENDL; - llassert_always(vobj); - vobj->updateTextureVirtualSize(true); - vobj->preRebuild(); + llassert_always(vobj); + vobj->updateTextureVirtualSize(true); + vobj->preRebuild(); - drawablep->clearState(LLDrawable::HAS_ALPHA); + drawablep->clearState(LLDrawable::HAS_ALPHA); if (vobj->isRiggedMesh() && ((vobj->isAnimatedObject() && vobj->getControlAvatar()) || @@ -5440,503 +5440,500 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } // Standard rigged mesh attachments: - bool rigged = !vobj->isAnimatedObject() && vobj->isRiggedMesh() && vobj->isAttachment(); + bool rigged = !vobj->isAnimatedObject() && vobj->isRiggedMesh() && vobj->isAttachment(); // Animated objects. Have to check for isRiggedMesh() to // exclude static objects in animated object linksets. - rigged = rigged || (vobj->isAnimatedObject() && vobj->isRiggedMesh() && + rigged = rigged || (vobj->isAnimatedObject() && vobj->isRiggedMesh() && vobj->getControlAvatar() && vobj->getControlAvatar()->mPlaying); - bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); - bool any_rigged_face = false; + bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); + bool any_rigged_face = false; - //for each face - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - LLFace* facep = drawablep->getFace(i); - if (!facep) - { - continue; - } + //for each face + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + LLFace* facep = drawablep->getFace(i); + if (!facep) + { + continue; + } - //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render - // batch, it will recover its vertex buffer reference from the spatial group - facep->setVertexBuffer(NULL); - - //sum up face verts and indices - drawablep->updateFaceSize(i); - - if (rigged) - { - if (!facep->isState(LLFace::RIGGED)) - { //completely reset vertex buffer - facep->clearVertexBuffer(); - } - - facep->setState(LLFace::RIGGED); - any_rigged_face = true; - - //get drawpool of avatar with rigged face - LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); - - if (pool) - { - //remove face from old pool if it exists - LLDrawPool* old_pool = facep->getPool(); - if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) - { - ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); - } - - //add face to new pool - LLViewerTexture* tex = facep->getTexture(); - - const LLTextureEntry* te = facep->getTextureEntry(); - llassert(te != nullptr); - if (te) - { - U32 type = gPipeline.getPoolTypeFromTE(te, tex); - - if (te->getGlow()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); - } - - LLMaterial* mat = te->getMaterialParams().get(); - - if (mat && LLPipeline::sRenderDeferred) - { - U8 alpha_mode = mat->getDiffuseAlphaMode(); - - bool is_alpha = type == LLDrawPool::POOL_ALPHA && - (alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND || - te->getColor().mV[3] < 0.999f); - - if (is_alpha) - { //this face needs alpha blending, override alpha mode - alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; - } - - if (!is_alpha || te->getColor().mV[3] > 0.f) // //only add the face if it will actually be visible - { - U32 mask = mat->getShaderMask(alpha_mode); - pool->addRiggedFace(facep, mask); - } - } - else if (mat) - { - bool fullbright = te->getFullbright(); - bool is_alpha = type == LLDrawPool::POOL_ALPHA; - U8 mode = mat->getDiffuseAlphaMode(); - bool can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || - mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; - - if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && te->getColor().mV[3] >= 0.999f) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); - } - else if (is_alpha || (te->getColor().mV[3] < 0.999f)) - { - if (te->getColor().mV[3] > 0.f) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA : LLDrawPoolAvatar::RIGGED_ALPHA); - } - } - else if (gPipeline.canUseVertexShaders() - && LLPipeline::sRenderBump - && te->getShiny() - && can_be_shiny) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY : LLDrawPoolAvatar::RIGGED_SHINY); - } - else - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); - } - } - else - { - if (type == LLDrawPool::POOL_ALPHA) - { - if (te->getColor().mV[3] > 0.f) - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); - } - } - } - else if (te->getShiny()) - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); - } - else - { - if (LLPipeline::sRenderDeferred) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); - } - } - } - else - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); - } - } - - - if (LLPipeline::sRenderDeferred) - { - if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) - { - if (te->getBumpmap()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); - } - } - } - } - } - } + //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render + // batch, it will recover its vertex buffer reference from the spatial group + facep->setVertexBuffer(NULL); + + //sum up face verts and indices + drawablep->updateFaceSize(i); + + if (rigged) + { + if (!facep->isState(LLFace::RIGGED)) + { //completely reset vertex buffer + facep->clearVertexBuffer(); + } + + facep->setState(LLFace::RIGGED); + any_rigged_face = true; + + //get drawpool of avatar with rigged face + LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); + + if (pool) + { + const LLTextureEntry* te = facep->getTextureEntry(); + + //remove face from old pool if it exists + LLDrawPool* old_pool = facep->getPool(); + if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) + { + ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); + } + + //add face to new pool + LLViewerTexture* tex = facep->getTexture(); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + + + if (te->getGlow()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); + } + + LLMaterial* mat = te->getMaterialParams().get(); + + if (mat && LLPipeline::sRenderDeferred) + { + U8 alpha_mode = mat->getDiffuseAlphaMode(); + + bool is_alpha = type == LLDrawPool::POOL_ALPHA && + (alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND || + te->getColor().mV[3] < 0.999f); + + if (is_alpha) + { //this face needs alpha blending, override alpha mode + alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; + } + + if (!is_alpha || te->getColor().mV[3] > 0.f) // //only add the face if it will actually be visible + { + U32 mask = mat->getShaderMask(alpha_mode); + pool->addRiggedFace(facep, mask); + } + } + else if (mat) + { + bool fullbright = te->getFullbright(); + bool is_alpha = type == LLDrawPool::POOL_ALPHA; + U8 mode = mat->getDiffuseAlphaMode(); + bool can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || + mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; + + if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && te->getColor().mV[3] >= 0.999f) + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); + } + else if (is_alpha || (te->getColor().mV[3] < 0.999f)) + { + if (te->getColor().mV[3] > 0.f) + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA : LLDrawPoolAvatar::RIGGED_ALPHA); + } + } + else if (gPipeline.canUseVertexShaders() + && LLPipeline::sRenderBump + && te->getShiny() + && can_be_shiny) + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY : LLDrawPoolAvatar::RIGGED_SHINY); + } + else + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); + } + } + else + { + if (type == LLDrawPool::POOL_ALPHA) + { + if (te->getColor().mV[3] > 0.f) + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); + } + } + } + else if (te->getShiny()) + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); + } + else + { + if (LLPipeline::sRenderDeferred) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); + } + } + } + else + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + } + + + if (LLPipeline::sRenderDeferred) + { + if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) + { + if (te->getBumpmap()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); + } + } + } + } + } - continue; - } - else - { - if (facep->isState(LLFace::RIGGED)) - { //face is not rigged but used to be, remove from rigged face pool - LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); - if (pool) - { - pool->removeRiggedFace(facep); - } - facep->clearState(LLFace::RIGGED); - } - } + continue; + } + else + { + if (facep->isState(LLFace::RIGGED)) + { //face is not rigged but used to be, remove from rigged face pool + LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); + if (pool) + { + pool->removeRiggedFace(facep); + } + facep->clearState(LLFace::RIGGED); + } + } - if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) - { - facep->clearVertexBuffer(); - continue; - } + if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) + { + facep->clearVertexBuffer(); + continue; + } - cur_total += facep->getGeomCount(); + cur_total += facep->getGeomCount(); - if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) - { - const LLTextureEntry* te = facep->getTextureEntry(); - LLViewerTexture* tex = facep->getTexture(); + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) + { + const LLTextureEntry* te = facep->getTextureEntry(); + LLViewerTexture* tex = facep->getTexture(); - if (te->getGlow() >= 1.f/255.f) - { - emissive = true; - } + if (te->getGlow() >= 1.f/255.f) + { + emissive = true; + } - if (facep->isState(LLFace::TEXTURE_ANIM)) - { - if (!vobj->mTexAnimMode) - { - facep->clearState(LLFace::TEXTURE_ANIM); - } - } + if (facep->isState(LLFace::TEXTURE_ANIM)) + { + if (!vobj->mTexAnimMode) + { + facep->clearState(LLFace::TEXTURE_ANIM); + } + } - BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); - U32 type = gPipeline.getPoolTypeFromTE(te, tex); - if (type != LLDrawPool::POOL_ALPHA && force_simple) - { - type = LLDrawPool::POOL_SIMPLE; - } - facep->setPoolType(type); + BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + if (type != LLDrawPool::POOL_ALPHA && force_simple) + { + type = LLDrawPool::POOL_SIMPLE; + } + facep->setPoolType(type); - if (vobj->isHUDAttachment()) - { - facep->setState(LLFace::FULLBRIGHT); - } + if (vobj->isHUDAttachment()) + { + facep->setState(LLFace::FULLBRIGHT); + } - if (vobj->mTextureAnimp && vobj->mTexAnimMode) - { - if (vobj->mTextureAnimp->mFace <= -1) - { - S32 face; - for (face = 0; face < vobj->getNumTEs(); face++) - { - LLFace * facep = drawablep->getFace(face); - if (facep) - { - facep->setState(LLFace::TEXTURE_ANIM); - } - } - } - else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) - { - LLFace * facep = drawablep->getFace(vobj->mTextureAnimp->mFace); - if (facep) - { - facep->setState(LLFace::TEXTURE_ANIM); - } - } - } + if (vobj->mTextureAnimp && vobj->mTexAnimMode) + { + if (vobj->mTextureAnimp->mFace <= -1) + { + S32 face; + for (face = 0; face < vobj->getNumTEs(); face++) + { + LLFace * facep = drawablep->getFace(face); + if (facep) + { + facep->setState(LLFace::TEXTURE_ANIM); + } + } + } + else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) + { + LLFace * facep = drawablep->getFace(vobj->mTextureAnimp->mFace); + if (facep) + { + facep->setState(LLFace::TEXTURE_ANIM); + } + } + } - if (type == LLDrawPool::POOL_ALPHA) - { - if (facep->canRenderAsMask()) - { //can be treated as alpha mask - if (simple_count < MAX_FACE_COUNT) - { - sSimpleFaces[simple_count++] = facep; - } - } - else - { - if (te->getColor().mV[3] > 0.f) - { //only treat as alpha in the pipeline if < 100% transparent - drawablep->setState(LLDrawable::HAS_ALPHA); - } - if (alpha_count < MAX_FACE_COUNT) - { - sAlphaFaces[alpha_count++] = facep; - } - } - } - else - { - if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) - { - facep->mLastUpdateTime = gFrameTimeSeconds; - } - - if (gPipeline.canUseWindLightShadersOnObjects() - && LLPipeline::sRenderBump) - { - if (LLPipeline::sRenderDeferred && te->getMaterialParams().notNull() && !te->getMaterialID().isNull()) - { - LLMaterial* mat = te->getMaterialParams().get(); - if (mat->getNormalID().notNull()) - { - if (mat->getSpecularID().notNull()) - { //has normal and specular maps (needs texcoord1, texcoord2, and tangent) - if (normspec_count < MAX_FACE_COUNT) - { - sNormSpecFaces[normspec_count++] = facep; - } - } - else - { //has normal map (needs texcoord1 and tangent) - if (norm_count < MAX_FACE_COUNT) - { - sNormFaces[norm_count++] = facep; - } - } - } - else if (mat->getSpecularID().notNull()) - { //has specular map but no normal map, needs texcoord2 - if (spec_count < MAX_FACE_COUNT) - { - sSpecFaces[spec_count++] = facep; - } - } - else - { //has neither specular map nor normal map, only needs texcoord0 - if (simple_count < MAX_FACE_COUNT) - { - sSimpleFaces[simple_count++] = facep; - } - } - } - else if (te->getBumpmap()) - { //needs normal + tangent - if (bump_count < MAX_FACE_COUNT) - { - sBumpFaces[bump_count++] = facep; - } - } - else if (te->getShiny() || !te->getFullbright()) - { //needs normal - if (simple_count < MAX_FACE_COUNT) - { - sSimpleFaces[simple_count++] = facep; - } - } - else - { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); - if (fullbright_count < MAX_FACE_COUNT) - { - sFullbrightFaces[fullbright_count++] = facep; - } - } - } - else - { - if (te->getBumpmap() && LLPipeline::sRenderBump) - { //needs normal + tangent - if (bump_count < MAX_FACE_COUNT) - { - sBumpFaces[bump_count++] = facep; - } - } - else if ((te->getShiny() && LLPipeline::sRenderBump) || - !(te->getFullbright() || bake_sunlight)) - { //needs normal - if (simple_count < MAX_FACE_COUNT) - { - sSimpleFaces[simple_count++] = facep; - } - } - else - { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); - if (fullbright_count < MAX_FACE_COUNT) - { - sFullbrightFaces[fullbright_count++] = facep; - } - } - } - } - } - else - { //face has no renderable geometry - facep->clearVertexBuffer(); - } - } - - if (any_rigged_face) - { - if (!drawablep->isState(LLDrawable::RIGGED)) - { - drawablep->setState(LLDrawable::RIGGED); + if (type == LLDrawPool::POOL_ALPHA) + { + if (facep->canRenderAsMask()) + { //can be treated as alpha mask + if (simple_count < MAX_FACE_COUNT) + { + sSimpleFaces[simple_count++] = facep; + } + } + else + { + if (te->getColor().mV[3] > 0.f) + { //only treat as alpha in the pipeline if < 100% transparent + drawablep->setState(LLDrawable::HAS_ALPHA); + } + if (alpha_count < MAX_FACE_COUNT) + { + sAlphaFaces[alpha_count++] = facep; + } + } + } + else + { + if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) + { + facep->mLastUpdateTime = gFrameTimeSeconds; + } + + if (gPipeline.canUseWindLightShadersOnObjects() + && LLPipeline::sRenderBump) + { + if (LLPipeline::sRenderDeferred && te->getMaterialParams().notNull() && !te->getMaterialID().isNull()) + { + LLMaterial* mat = te->getMaterialParams().get(); + if (mat->getNormalID().notNull()) + { + if (mat->getSpecularID().notNull()) + { //has normal and specular maps (needs texcoord1, texcoord2, and tangent) + if (normspec_count < MAX_FACE_COUNT) + { + sNormSpecFaces[normspec_count++] = facep; + } + } + else + { //has normal map (needs texcoord1 and tangent) + if (norm_count < MAX_FACE_COUNT) + { + sNormFaces[norm_count++] = facep; + } + } + } + else if (mat->getSpecularID().notNull()) + { //has specular map but no normal map, needs texcoord2 + if (spec_count < MAX_FACE_COUNT) + { + sSpecFaces[spec_count++] = facep; + } + } + else + { //has neither specular map nor normal map, only needs texcoord0 + if (simple_count < MAX_FACE_COUNT) + { + sSimpleFaces[simple_count++] = facep; + } + } + } + else if (te->getBumpmap()) + { //needs normal + tangent + if (bump_count < MAX_FACE_COUNT) + { + sBumpFaces[bump_count++] = facep; + } + } + else if (te->getShiny() || !te->getFullbright()) + { //needs normal + if (simple_count < MAX_FACE_COUNT) + { + sSimpleFaces[simple_count++] = facep; + } + } + else + { //doesn't need normal + facep->setState(LLFace::FULLBRIGHT); + if (fullbright_count < MAX_FACE_COUNT) + { + sFullbrightFaces[fullbright_count++] = facep; + } + } + } + else + { + if (te->getBumpmap() && LLPipeline::sRenderBump) + { //needs normal + tangent + if (bump_count < MAX_FACE_COUNT) + { + sBumpFaces[bump_count++] = facep; + } + } + else if ((te->getShiny() && LLPipeline::sRenderBump) || + !(te->getFullbright() || bake_sunlight)) + { //needs normal + if (simple_count < MAX_FACE_COUNT) + { + sSimpleFaces[simple_count++] = facep; + } + } + else + { //doesn't need normal + facep->setState(LLFace::FULLBRIGHT); + if (fullbright_count < MAX_FACE_COUNT) + { + sFullbrightFaces[fullbright_count++] = facep; + } + } + } + } + } + else + { //face has no renderable geometry + facep->clearVertexBuffer(); + } + } + + if (any_rigged_face) + { + if (!drawablep->isState(LLDrawable::RIGGED)) + { + drawablep->setState(LLDrawable::RIGGED); - //first time this is drawable is being marked as rigged, - // do another LoD update to use avatar bounding box - vobj->updateLOD(); - } - } - else - { - drawablep->clearState(LLDrawable::RIGGED); + //first time this is drawable is being marked as rigged, + // do another LoD update to use avatar bounding box + vobj->updateLOD(); + } + } + else + { + drawablep->clearState(LLDrawable::RIGGED); vobj->updateRiggedVolume(); - } - } - } + } + } + } - group->mBufferUsage = useage; - - //PROCESS NON-ALPHA FACES - U32 simple_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; - U32 alpha_mask = simple_mask | 0x80000000; //hack to give alpha verts their own VBO - U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; - U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; - - U32 norm_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TANGENT; - U32 normspec_mask = norm_mask | LLVertexBuffer::MAP_TEXCOORD2; - U32 spec_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD2; - - if (emissive) - { //emissive faces are present, include emissive byte to preserve batching - simple_mask = simple_mask | LLVertexBuffer::MAP_EMISSIVE; - alpha_mask = alpha_mask | LLVertexBuffer::MAP_EMISSIVE; - bump_mask = bump_mask | LLVertexBuffer::MAP_EMISSIVE; - fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_EMISSIVE; - norm_mask = norm_mask | LLVertexBuffer::MAP_EMISSIVE; - normspec_mask = normspec_mask | LLVertexBuffer::MAP_EMISSIVE; - spec_mask = spec_mask | LLVertexBuffer::MAP_EMISSIVE; - } + group->mBufferUsage = useage; + + //PROCESS NON-ALPHA FACES + U32 simple_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + U32 alpha_mask = simple_mask | 0x80000000; //hack to give alpha verts their own VBO + U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + + U32 norm_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TANGENT; + U32 normspec_mask = norm_mask | LLVertexBuffer::MAP_TEXCOORD2; + U32 spec_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD2; + + if (emissive) + { //emissive faces are present, include emissive byte to preserve batching + simple_mask = simple_mask | LLVertexBuffer::MAP_EMISSIVE; + alpha_mask = alpha_mask | LLVertexBuffer::MAP_EMISSIVE; + bump_mask = bump_mask | LLVertexBuffer::MAP_EMISSIVE; + fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_EMISSIVE; + norm_mask = norm_mask | LLVertexBuffer::MAP_EMISSIVE; + normspec_mask = normspec_mask | LLVertexBuffer::MAP_EMISSIVE; + spec_mask = spec_mask | LLVertexBuffer::MAP_EMISSIVE; + } - BOOL batch_textures = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1; + BOOL batch_textures = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1; - if (batch_textures) - { - bump_mask = bump_mask | LLVertexBuffer::MAP_TANGENT; - simple_mask = simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX; - alpha_mask = alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2; - fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX; - } + if (batch_textures) + { + bump_mask = bump_mask | LLVertexBuffer::MAP_TANGENT; + simple_mask = simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX; + alpha_mask = alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2; + fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX; + } - group->mGeometryBytes = 0; + group->mGeometryBytes = 0; - U32 geometryBytes = 0; + U32 geometryBytes = 0; - geometryBytes += genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE); - geometryBytes += genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures); - geometryBytes += genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures); - geometryBytes += genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE); - geometryBytes += genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE); - geometryBytes += genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE); - geometryBytes += genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE); + geometryBytes += genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE); + geometryBytes += genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures); + geometryBytes += genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures); + geometryBytes += genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE); + geometryBytes += genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE); + geometryBytes += genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE); + geometryBytes += genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE); - group->mGeometryBytes = geometryBytes; + group->mGeometryBytes = geometryBytes; - if (!LLPipeline::sDelayVBUpdate) - { - //drawables have been rebuilt, clear rebuild status - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - if(drawablep) - { + if (!LLPipeline::sDelayVBUpdate) + { + //drawables have been rebuilt, clear rebuild status + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) + { + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + if(drawablep) + { drawablep->clearState(LLDrawable::REBUILD_ALL); } } - } + } - group->mLastUpdateTime = gFrameTimeSeconds; - group->mBuilt = 1.f; - group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY); + group->mLastUpdateTime = gFrameTimeSeconds; + group->mBuilt = 1.f; + group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY); - if (LLPipeline::sDelayVBUpdate) - { - group->setState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); - } + if (LLPipeline::sDelayVBUpdate) + { + group->setState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); + } - mFaceList.clear(); + mFaceList.clear(); } static LLTrace::BlockTimerStatHandle FTM_REBUILD_MESH_FLUSH("Flush Mesh"); void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) { - llassert(group); - if (group && group->hasState(LLSpatialGroup::MESH_DIRTY) && !group->hasState(LLSpatialGroup::GEOM_DIRTY)) - { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB); - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers + llassert(group); + if (group && group->hasState(LLSpatialGroup::MESH_DIRTY) && !group->hasState(LLSpatialGroup::GEOM_DIRTY)) + { + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers - group->mBuilt = 1.f; - - S32 num_mapped_vertex_buffer = LLVertexBuffer::sMappedCount ; + group->mBuilt = 1.f; + + S32 num_mapped_vertex_buffer = LLVertexBuffer::sMappedCount ; - const U32 MAX_BUFFER_COUNT = 4096; - LLVertexBuffer* locked_buffer[MAX_BUFFER_COUNT]; - - U32 buffer_count = 0; + const U32 MAX_BUFFER_COUNT = 4096; + LLVertexBuffer* locked_buffer[MAX_BUFFER_COUNT]; + + U32 buffer_count = 0; - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) + { + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) - { - LLVOVolume* vobj = drawablep->getVOVolume(); + if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) + { + LLVOVolume* vobj = drawablep->getVOVolume(); if (debugLoggingEnabled("AnimatedObjectsLinkset")) { if (vobj->isAnimatedObject() && vobj->isRiggedMesh()) @@ -5946,128 +5943,128 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " rebuildMesh, tris " << est_tris << LL_ENDL; } } - if (vobj->isNoLOD()) continue; + if (vobj->isNoLOD()) continue; - vobj->preRebuild(); + vobj->preRebuild(); - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { - vobj->updateRelativeXform(true); - } + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(true); + } - LLVolume* volume = vobj->getVolume(); - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) - { - LLFace* face = drawablep->getFace(i); - if (face) - { - LLVertexBuffer* buff = face->getVertexBuffer(); - if (buff) - { - llassert(!face->isState(LLFace::RIGGED)); - - if (!face->getGeometryVolume(*volume, face->getTEOffset(), - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex())) - { //something's gone wrong with the vertex buffer accounting, rebuild this group - group->dirtyGeom(); - gPipeline.markRebuild(group, TRUE); - } - - - if (buff->isLocked() && buffer_count < MAX_BUFFER_COUNT) - { - locked_buffer[buffer_count++] = buff; - } - } - } - } + LLVolume* volume = vobj->getVolume(); + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + LLFace* face = drawablep->getFace(i); + if (face) + { + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff) + { + llassert(!face->isState(LLFace::RIGGED)); + + if (!face->getGeometryVolume(*volume, face->getTEOffset(), + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex())) + { //something's gone wrong with the vertex buffer accounting, rebuild this group + group->dirtyGeom(); + gPipeline.markRebuild(group, TRUE); + } + + + if (buff->isLocked() && buffer_count < MAX_BUFFER_COUNT) + { + locked_buffer[buffer_count++] = buff; + } + } + } + } - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { - vobj->updateRelativeXform(); - } + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(); + } - - drawablep->clearState(LLDrawable::REBUILD_ALL); - } - } - - { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_MESH_FLUSH); - for (LLVertexBuffer** iter = locked_buffer, ** end_iter = locked_buffer+buffer_count; iter != end_iter; ++iter) - { - (*iter)->flush(); - } + + drawablep->clearState(LLDrawable::REBUILD_ALL); + } + } + + { + LL_RECORD_BLOCK_TIME(FTM_REBUILD_MESH_FLUSH); + for (LLVertexBuffer** iter = locked_buffer, ** end_iter = locked_buffer+buffer_count; iter != end_iter; ++iter) + { + (*iter)->flush(); + } - // don't forget alpha - if(group != NULL && - !group->mVertexBuffer.isNull() && - group->mVertexBuffer->isLocked()) - { - group->mVertexBuffer->flush(); - } - } + // don't forget alpha + if(group != NULL && + !group->mVertexBuffer.isNull() && + group->mVertexBuffer->isLocked()) + { + group->mVertexBuffer->flush(); + } + } - //if not all buffers are unmapped - if(num_mapped_vertex_buffer != LLVertexBuffer::sMappedCount) - { - LL_WARNS() << "Not all mapped vertex buffers are unmapped!" << LL_ENDL ; - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - if(!drawablep) - { - continue; - } - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) - { - LLFace* face = drawablep->getFace(i); - if (face) - { - LLVertexBuffer* buff = face->getVertexBuffer(); - if (buff && buff->isLocked()) - { - buff->flush(); - } - } - } - } - } + //if not all buffers are unmapped + if(num_mapped_vertex_buffer != LLVertexBuffer::sMappedCount) + { + LL_WARNS() << "Not all mapped vertex buffers are unmapped!" << LL_ENDL ; + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) + { + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + if(!drawablep) + { + continue; + } + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + LLFace* face = drawablep->getFace(i); + if (face) + { + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff && buff->isLocked()) + { + buff->flush(); + } + } + } + } + } - group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); - } + group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); + } -// llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO)); +// llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO)); } struct CompareBatchBreakerModified { - bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) - { - const LLTextureEntry* lte = lhs->getTextureEntry(); - const LLTextureEntry* rte = rhs->getTextureEntry(); + bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) + { + const LLTextureEntry* lte = lhs->getTextureEntry(); + const LLTextureEntry* rte = rhs->getTextureEntry(); - if (lte->getBumpmap() != rte->getBumpmap()) - { - return lte->getBumpmap() < rte->getBumpmap(); - } - else if (lte->getFullbright() != rte->getFullbright()) - { - return lte->getFullbright() < rte->getFullbright(); - } - else if (LLPipeline::sRenderDeferred && lte->getMaterialParams() != rte->getMaterialParams()) - { - return lte->getMaterialParams() < rte->getMaterialParams(); - } - else if (LLPipeline::sRenderDeferred && (lte->getMaterialParams() == rte->getMaterialParams()) && (lte->getShiny() != rte->getShiny())) - { - return lte->getShiny() < rte->getShiny(); - } - else - { - return lhs->getTexture() < rhs->getTexture(); - } - } + if (lte->getBumpmap() != rte->getBumpmap()) + { + return lte->getBumpmap() < rte->getBumpmap(); + } + else if (lte->getFullbright() != rte->getFullbright()) + { + return lte->getFullbright() < rte->getFullbright(); + } + else if (LLPipeline::sRenderDeferred && lte->getMaterialParams() != rte->getMaterialParams()) + { + return lte->getMaterialParams() < rte->getMaterialParams(); + } + else if (LLPipeline::sRenderDeferred && (lte->getMaterialParams() == rte->getMaterialParams()) && (lte->getShiny() != rte->getShiny())) + { + return lte->getShiny() < rte->getShiny(); + } + else + { + return lhs->getTexture() < rhs->getTexture(); + } + } }; static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_SORT("Draw Info Face Sort"); @@ -6082,679 +6079,679 @@ static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL no_materials) { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); - U32 geometryBytes = 0; - U32 buffer_usage = group->mBufferUsage; - - static LLCachedControl use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false); + U32 geometryBytes = 0; + U32 buffer_usage = group->mBufferUsage; + + static LLCachedControl use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false); - if (use_transform_feedback && - gTransformPositionProgram.mProgramObject && //transform shaders are loaded - buffer_usage == GL_DYNAMIC_DRAW_ARB && //target buffer is in VRAM - !(mask & LLVertexBuffer::MAP_WEIGHT4)) //TODO: add support for weights - { - buffer_usage = GL_DYNAMIC_COPY_ARB; - } + if (use_transform_feedback && + gTransformPositionProgram.mProgramObject && //transform shaders are loaded + buffer_usage == GL_DYNAMIC_DRAW_ARB && //target buffer is in VRAM + !(mask & LLVertexBuffer::MAP_WEIGHT4)) //TODO: add support for weights + { + buffer_usage = GL_DYNAMIC_COPY_ARB; + } #if LL_DARWIN - // HACK from Leslie: - // Disable VBO usage for alpha on Mac OS X because it kills the framerate - // due to implicit calls to glTexSubImage that are beyond our control. - // (this works because the only calls here that sort by distance are alpha) - if (distance_sort) - { - buffer_usage = 0x0; - } + // HACK from Leslie: + // Disable VBO usage for alpha on Mac OS X because it kills the framerate + // due to implicit calls to glTexSubImage that are beyond our control. + // (this works because the only calls here that sort by distance are alpha) + if (distance_sort) + { + buffer_usage = 0x0; + } #endif - - //calculate maximum number of vertices to store in a single buffer - U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); - max_vertices = llmin(max_vertices, (U32) 65535); + + //calculate maximum number of vertices to store in a single buffer + U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); + max_vertices = llmin(max_vertices, (U32) 65535); - { - LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_SORT); - if (!distance_sort) - { - //sort faces by things that break batches - std::sort(faces, faces+face_count, CompareBatchBreakerModified()); - } - else - { - //sort faces by distance - std::sort(faces, faces+face_count, LLFace::CompareDistanceGreater()); - } - } - - bool hud_group = group->isHUDGroup() ; - LLFace** face_iter = faces; - LLFace** end_faces = faces+face_count; - - LLSpatialGroup::buffer_map_t buffer_map; + { + LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_SORT); + if (!distance_sort) + { + //sort faces by things that break batches + std::sort(faces, faces+face_count, CompareBatchBreakerModified()); + } + else + { + //sort faces by distance + std::sort(faces, faces+face_count, LLFace::CompareDistanceGreater()); + } + } + + bool hud_group = group->isHUDGroup() ; + LLFace** face_iter = faces; + LLFace** end_faces = faces+face_count; + + LLSpatialGroup::buffer_map_t buffer_map; - LLViewerTexture* last_tex = NULL; - S32 buffer_index = 0; + LLViewerTexture* last_tex = NULL; + S32 buffer_index = 0; - if (distance_sort) - { - buffer_index = -1; - } + if (distance_sort) + { + buffer_index = -1; + } - S32 texture_index_channels = 1; - - if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) - { - texture_index_channels = LLGLSLShader::sIndexedTextureChannels-1; //always reserve one for shiny for now just for simplicity; - } + S32 texture_index_channels = 1; + + if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) + { + texture_index_channels = LLGLSLShader::sIndexedTextureChannels-1; //always reserve one for shiny for now just for simplicity; + } - if (LLPipeline::sRenderDeferred && distance_sort) - { - texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels; - } + if (LLPipeline::sRenderDeferred && distance_sort) + { + texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels; + } - texture_index_channels = llmin(texture_index_channels, (S32) gSavedSettings.getU32("RenderMaxTextureIndex")); - - //NEVER use more than 16 texture index channels (workaround for prevalent driver bug) - texture_index_channels = llmin(texture_index_channels, 16); + texture_index_channels = llmin(texture_index_channels, (S32) gSavedSettings.getU32("RenderMaxTextureIndex")); + + //NEVER use more than 16 texture index channels (workaround for prevalent driver bug) + texture_index_channels = llmin(texture_index_channels, 16); - bool flexi = false; + bool flexi = false; - while (face_iter != end_faces) - { - //pull off next face - LLFace* facep = *face_iter; - LLViewerTexture* tex = facep->getTexture(); - LLMaterialPtr mat = facep->getTextureEntry()->getMaterialParams(); + while (face_iter != end_faces) + { + //pull off next face + LLFace* facep = *face_iter; + LLViewerTexture* tex = facep->getTexture(); + LLMaterialPtr mat = facep->getTextureEntry()->getMaterialParams(); - if (distance_sort) - { - tex = NULL; - } + if (distance_sort) + { + tex = NULL; + } - if (last_tex == tex) - { - buffer_index++; - } - else - { - last_tex = tex; - buffer_index = 0; - } + if (last_tex == tex) + { + buffer_index++; + } + else + { + last_tex = tex; + buffer_index = 0; + } - bool bake_sunlight = LLPipeline::sBakeSunlight && facep->getDrawable()->isStatic(); + bool bake_sunlight = LLPipeline::sBakeSunlight && facep->getDrawable()->isStatic(); - U32 index_count = facep->getIndicesCount(); - U32 geom_count = facep->getGeomCount(); + U32 index_count = facep->getIndicesCount(); + U32 geom_count = facep->getGeomCount(); - flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); + flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); - //sum up vertices needed for this render batch - LLFace** i = face_iter; - ++i; - - const U32 MAX_TEXTURE_COUNT = 32; - LLViewerTexture* texture_list[MAX_TEXTURE_COUNT]; - - U32 texture_count = 0; + //sum up vertices needed for this render batch + LLFace** i = face_iter; + ++i; + + const U32 MAX_TEXTURE_COUNT = 32; + LLViewerTexture* texture_list[MAX_TEXTURE_COUNT]; + + U32 texture_count = 0; - { - LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_FACE_SIZE); - if (batch_textures) - { - U8 cur_tex = 0; - facep->setTextureIndex(cur_tex); - if (texture_count < MAX_TEXTURE_COUNT) - { - texture_list[texture_count++] = tex; - } + { + LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_FACE_SIZE); + if (batch_textures) + { + U8 cur_tex = 0; + facep->setTextureIndex(cur_tex); + if (texture_count < MAX_TEXTURE_COUNT) + { + texture_list[texture_count++] = tex; + } - if (can_batch_texture(facep)) - { //populate texture_list with any textures that can be batched - //move i to the next unbatchable face - while (i != end_faces) - { - facep = *i; - - if (!can_batch_texture(facep)) - { //face is bump mapped or has an animated texture matrix -- can't - //batch more than 1 texture at a time - facep->setTextureIndex(0); - break; - } - - if (facep->getTexture() != tex) - { - if (distance_sort) - { //textures might be out of order, see if texture exists in current batch - bool found = false; - for (U32 tex_idx = 0; tex_idx < texture_count; ++tex_idx) - { - if (facep->getTexture() == texture_list[tex_idx]) - { - cur_tex = tex_idx; - found = true; - break; - } - } - - if (!found) - { - cur_tex = texture_count; - } - } - else - { - cur_tex++; - } - - if (cur_tex >= texture_index_channels) - { //cut batches when index channels are depleted - break; - } - - tex = facep->getTexture(); - - if (texture_count < MAX_TEXTURE_COUNT) - { - texture_list[texture_count++] = tex; - } - } - - if (geom_count + facep->getGeomCount() > max_vertices) - { //cut batches on geom count too big - break; - } - - ++i; - - flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); - - index_count += facep->getIndicesCount(); - geom_count += facep->getGeomCount(); - - facep->setTextureIndex(cur_tex); - } - } - else - { - facep->setTextureIndex(0); - } + if (can_batch_texture(facep)) + { //populate texture_list with any textures that can be batched + //move i to the next unbatchable face + while (i != end_faces) + { + facep = *i; + + if (!can_batch_texture(facep)) + { //face is bump mapped or has an animated texture matrix -- can't + //batch more than 1 texture at a time + facep->setTextureIndex(0); + break; + } + + if (facep->getTexture() != tex) + { + if (distance_sort) + { //textures might be out of order, see if texture exists in current batch + bool found = false; + for (U32 tex_idx = 0; tex_idx < texture_count; ++tex_idx) + { + if (facep->getTexture() == texture_list[tex_idx]) + { + cur_tex = tex_idx; + found = true; + break; + } + } + + if (!found) + { + cur_tex = texture_count; + } + } + else + { + cur_tex++; + } + + if (cur_tex >= texture_index_channels) + { //cut batches when index channels are depleted + break; + } + + tex = facep->getTexture(); + + if (texture_count < MAX_TEXTURE_COUNT) + { + texture_list[texture_count++] = tex; + } + } + + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut batches on geom count too big + break; + } + + ++i; + + flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); + + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); + + facep->setTextureIndex(cur_tex); + } + } + else + { + facep->setTextureIndex(0); + } - tex = texture_list[0]; - } - else - { - while (i != end_faces && - (LLPipeline::sTextureBindTest || - (distance_sort || - ((*i)->getTexture() == tex && - ((*i)->getTextureEntry()->getMaterialParams() == mat))))) - { - facep = *i; - + tex = texture_list[0]; + } + else + { + while (i != end_faces && + (LLPipeline::sTextureBindTest || + (distance_sort || + ((*i)->getTexture() == tex && + ((*i)->getTextureEntry()->getMaterialParams() == mat))))) + { + facep = *i; + - //face has no texture index - facep->mDrawInfo = NULL; - facep->setTextureIndex(255); + //face has no texture index + facep->mDrawInfo = NULL; + facep->setTextureIndex(255); - if (geom_count + facep->getGeomCount() > max_vertices) - { //cut batches on geom count too big - break; - } + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut batches on geom count too big + break; + } - ++i; - index_count += facep->getIndicesCount(); - geom_count += facep->getGeomCount(); + ++i; + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); - flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); - } - } - } + flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); + } + } + } - if (flexi && buffer_usage && buffer_usage != GL_STREAM_DRAW_ARB) - { - buffer_usage = GL_STREAM_DRAW_ARB; - } + if (flexi && buffer_usage && buffer_usage != GL_STREAM_DRAW_ARB) + { + buffer_usage = GL_STREAM_DRAW_ARB; + } - //create vertex buffer - LLPointer buffer; + //create vertex buffer + LLPointer buffer; - { - LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_ALLOCATE); - buffer = createVertexBuffer(mask, buffer_usage); - if(!buffer->allocateBuffer(geom_count, index_count, TRUE)) - { - LL_WARNS() << "Failed to allocate group Vertex Buffer to " - << geom_count << " vertices and " - << index_count << " indices" << LL_ENDL; - buffer = NULL; - } - } + { + LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_ALLOCATE); + buffer = createVertexBuffer(mask, buffer_usage); + if(!buffer->allocateBuffer(geom_count, index_count, TRUE)) + { + LL_WARNS() << "Failed to allocate group Vertex Buffer to " + << geom_count << " vertices and " + << index_count << " indices" << LL_ENDL; + buffer = NULL; + } + } - if (buffer) - { - geometryBytes += buffer->getSize() + buffer->getIndicesSize(); - buffer_map[mask][*face_iter].push_back(buffer); - } + if (buffer) + { + geometryBytes += buffer->getSize() + buffer->getIndicesSize(); + buffer_map[mask][*face_iter].push_back(buffer); + } - //add face geometry + //add face geometry - U32 indices_index = 0; - U16 index_offset = 0; + U32 indices_index = 0; + U16 index_offset = 0; - while (face_iter < i) - { - //update face indices for new buffer - facep = *face_iter; - if (buffer.isNull()) - { - // Bulk allocation failed - facep->setVertexBuffer(buffer); - facep->setSize(0, 0); // mark as no geometry - ++face_iter; - continue; - } - facep->setIndicesIndex(indices_index); - facep->setGeomIndex(index_offset); - facep->setVertexBuffer(buffer); - - if (batch_textures && facep->getTextureIndex() == 255) - { - LL_ERRS() << "Invalid texture index." << LL_ENDL; - } - - { - //for debugging, set last time face was updated vs moved - facep->updateRebuildFlags(); + while (face_iter < i) + { + //update face indices for new buffer + facep = *face_iter; + if (buffer.isNull()) + { + // Bulk allocation failed + facep->setVertexBuffer(buffer); + facep->setSize(0, 0); // mark as no geometry + ++face_iter; + continue; + } + facep->setIndicesIndex(indices_index); + facep->setGeomIndex(index_offset); + facep->setVertexBuffer(buffer); + + if (batch_textures && facep->getTextureIndex() == 255) + { + LL_ERRS() << "Invalid texture index." << LL_ENDL; + } + + { + //for debugging, set last time face was updated vs moved + facep->updateRebuildFlags(); - if (!LLPipeline::sDelayVBUpdate) - { //copy face geometry into vertex buffer - LLDrawable* drawablep = facep->getDrawable(); - LLVOVolume* vobj = drawablep->getVOVolume(); - LLVolume* volume = vobj->getVolume(); + if (!LLPipeline::sDelayVBUpdate) + { //copy face geometry into vertex buffer + LLDrawable* drawablep = facep->getDrawable(); + LLVOVolume* vobj = drawablep->getVOVolume(); + LLVolume* volume = vobj->getVolume(); - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { - vobj->updateRelativeXform(true); - } + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(true); + } - U32 te_idx = facep->getTEOffset(); + U32 te_idx = facep->getTEOffset(); - llassert(!facep->isState(LLFace::RIGGED)); + llassert(!facep->isState(LLFace::RIGGED)); - if (!facep->getGeometryVolume(*volume, te_idx, - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true)) - { - LL_WARNS() << "Failed to get geometry for face!" << LL_ENDL; - } + if (!facep->getGeometryVolume(*volume, te_idx, + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true)) + { + LL_WARNS() << "Failed to get geometry for face!" << LL_ENDL; + } - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { - vobj->updateRelativeXform(false); - } - } - } + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(false); + } + } + } - index_offset += facep->getGeomCount(); - indices_index += facep->getIndicesCount(); + index_offset += facep->getGeomCount(); + indices_index += facep->getIndicesCount(); - //append face to appropriate render batch + //append face to appropriate render batch - BOOL force_simple = facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA; - BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); - if ((mask & LLVertexBuffer::MAP_NORMAL) == 0) - { //paranoia check to make sure GL doesn't try to read non-existant normals - fullbright = TRUE; - } + BOOL force_simple = facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA; + BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); + if ((mask & LLVertexBuffer::MAP_NORMAL) == 0) + { //paranoia check to make sure GL doesn't try to read non-existant normals + fullbright = TRUE; + } - if (hud_group) - { //all hud attachments are fullbright - fullbright = TRUE; - } + if (hud_group) + { //all hud attachments are fullbright + fullbright = TRUE; + } - const LLTextureEntry* te = facep->getTextureEntry(); - tex = facep->getTexture(); + const LLTextureEntry* te = facep->getTextureEntry(); + tex = facep->getTexture(); - BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE; - - LLMaterial* mat = te->getMaterialParams().get(); + BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE; + + LLMaterial* mat = te->getMaterialParams().get(); - bool can_be_shiny = true; - if (mat) - { - U8 mode = mat->getDiffuseAlphaMode(); - can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || - mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; - } + bool can_be_shiny = true; + if (mat) + { + U8 mode = mat->getDiffuseAlphaMode(); + can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || + mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; + } - bool use_legacy_bump = te->getBumpmap() && (te->getBumpmap() < 18) && (!mat || mat->getNormalID().isNull()); - bool opaque = te->getColor().mV[3] >= 0.999f; + bool use_legacy_bump = te->getBumpmap() && (te->getBumpmap() < 18) && (!mat || mat->getNormalID().isNull()); + bool opaque = te->getColor().mV[3] >= 0.999f; - if (mat && LLPipeline::sRenderDeferred && !hud_group) - { - bool material_pass = false; + if (mat && LLPipeline::sRenderDeferred && !hud_group) + { + bool material_pass = false; - // do NOT use 'fullbright' for this logic or you risk sending - // things without normals down the materials pipeline and will - // render poorly if not crash NORSPEC-240,314 - // - if (te->getFullbright()) - { - if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { - if (opaque) - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); - } - else - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - } - else if (is_alpha) - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - else - { - if (mat->getEnvironmentIntensity() > 0 || - te->getShiny() > 0) - { - material_pass = true; - } - else - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); - } - } - } - else if (no_materials) - { - registerFace(group, facep, LLRenderPass::PASS_SIMPLE); - } - else if (te->getColor().mV[3] < 0.999f) - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - else if (use_legacy_bump) - { - // we have a material AND legacy bump settings, but no normal map - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - else - { - material_pass = true; - } + // do NOT use 'fullbright' for this logic or you risk sending + // things without normals down the materials pipeline and will + // render poorly if not crash NORSPEC-240,314 + // + if (te->getFullbright()) + { + if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { + if (opaque) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + } + else if (is_alpha) + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + else + { + if (mat->getEnvironmentIntensity() > 0 || + te->getShiny() > 0) + { + material_pass = true; + } + else + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + } + } + } + else if (no_materials) + { + registerFace(group, facep, LLRenderPass::PASS_SIMPLE); + } + else if (te->getColor().mV[3] < 0.999f) + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + else if (use_legacy_bump) + { + // we have a material AND legacy bump settings, but no normal map + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + else + { + material_pass = true; + } - if (material_pass) - { - static const U32 pass[] = - { - LLRenderPass::PASS_MATERIAL, - LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_MATERIAL_ALPHA, - LLRenderPass::PASS_MATERIAL_ALPHA_MASK, - LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, - LLRenderPass::PASS_SPECMAP, - LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_SPECMAP_BLEND, - LLRenderPass::PASS_SPECMAP_MASK, - LLRenderPass::PASS_SPECMAP_EMISSIVE, - LLRenderPass::PASS_NORMMAP, - LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMMAP_BLEND, - LLRenderPass::PASS_NORMMAP_MASK, - LLRenderPass::PASS_NORMMAP_EMISSIVE, - LLRenderPass::PASS_NORMSPEC, - LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMSPEC_BLEND, - LLRenderPass::PASS_NORMSPEC_MASK, - LLRenderPass::PASS_NORMSPEC_EMISSIVE, - }; - - U32 mask = mat->getShaderMask(); - - llassert(mask < sizeof(pass)/sizeof(U32)); - - mask = llmin(mask, (U32)(sizeof(pass)/sizeof(U32)-1)); - - registerFace(group, facep, pass[mask]); - } - } - else if (mat) - { - U8 mode = mat->getDiffuseAlphaMode(); - if (te->getColor().mV[3] < 0.999f) - { - mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; - } + if (material_pass) + { + static const U32 pass[] = + { + LLRenderPass::PASS_MATERIAL, + LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_MATERIAL_ALPHA, + LLRenderPass::PASS_MATERIAL_ALPHA_MASK, + LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, + LLRenderPass::PASS_SPECMAP, + LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_SPECMAP_BLEND, + LLRenderPass::PASS_SPECMAP_MASK, + LLRenderPass::PASS_SPECMAP_EMISSIVE, + LLRenderPass::PASS_NORMMAP, + LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMMAP_BLEND, + LLRenderPass::PASS_NORMMAP_MASK, + LLRenderPass::PASS_NORMMAP_EMISSIVE, + LLRenderPass::PASS_NORMSPEC, + LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMSPEC_BLEND, + LLRenderPass::PASS_NORMSPEC_MASK, + LLRenderPass::PASS_NORMSPEC_EMISSIVE, + }; + + U32 mask = mat->getShaderMask(); + + llassert(mask < sizeof(pass)/sizeof(U32)); + + mask = llmin(mask, (U32)(sizeof(pass)/sizeof(U32)-1)); + + registerFace(group, facep, pass[mask]); + } + } + else if (mat) + { + U8 mode = mat->getDiffuseAlphaMode(); + if (te->getColor().mV[3] < 0.999f) + { + mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; + } - if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { - registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK : LLRenderPass::PASS_ALPHA_MASK); - } - else if (is_alpha || (te->getColor().mV[3] < 0.999f)) - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - else if (gPipeline.canUseVertexShaders() - && LLPipeline::sRenderBump - && te->getShiny() - && can_be_shiny) - { - registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_SHINY : LLRenderPass::PASS_SHINY); - } - else - { - registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT : LLRenderPass::PASS_SIMPLE); - } - } - else if (is_alpha) - { - // can we safely treat this as an alpha mask? - if (facep->getFaceColor().mV[3] <= 0.f) - { //100% transparent, don't render unless we're highlighting transparent - registerFace(group, facep, LLRenderPass::PASS_ALPHA_INVISIBLE); - } - else if (facep->canRenderAsMask()) - { - if (te->getFullbright() || LLPipeline::sNoAlpha) - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); - } - else - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); - } - } - else - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - } - else if (gPipeline.canUseVertexShaders() - && LLPipeline::sRenderBump - && te->getShiny() - && can_be_shiny) - { //shiny - if (tex->getPrimaryFormat() == GL_ALPHA) - { //invisiprim+shiny - registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); - } - else if (LLPipeline::sRenderDeferred && !hud_group) - { //deferred rendering - if (te->getFullbright()) - { //register in post deferred fullbright shiny pass - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); - if (te->getBumpmap()) - { //register in post deferred bump pass - registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); - } - } - else if (use_legacy_bump) - { //register in deferred bump pass - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - else - { //register in deferred simple pass (deferred simple includes shiny) - llassert(mask & LLVertexBuffer::MAP_NORMAL); - registerFace(group, facep, LLRenderPass::PASS_SIMPLE); - } - } - else if (fullbright) - { //not deferred, register in standard fullbright shiny pass - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); - } - else - { //not deferred or fullbright, register in standard shiny pass - registerFace(group, facep, LLRenderPass::PASS_SHINY); - } - } - else - { //not alpha and not shiny - if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) - { //invisiprim - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); - } - else if (fullbright || bake_sunlight) - { //fullbright - if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); - } - else - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); - } - if (LLPipeline::sRenderDeferred && !hud_group && LLPipeline::sRenderBump && use_legacy_bump) - { //if this is the deferred render and a bump map is present, register in post deferred bump - registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); - } - } - else - { - if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && use_legacy_bump) - { //non-shiny or fullbright deferred bump - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - else - { //all around simple - llassert(mask & LLVertexBuffer::MAP_NORMAL); - if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { //material alpha mask can be respected in non-deferred - registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); - } - else - { - registerFace(group, facep, LLRenderPass::PASS_SIMPLE); - } - } - } - - - if (!gPipeline.canUseVertexShaders() && - !is_alpha && - te->getShiny() && - LLPipeline::sRenderBump) - { //shiny as an extra pass when shaders are disabled - registerFace(group, facep, LLRenderPass::PASS_SHINY); - } - } - - //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 - if (!is_alpha && (hud_group || !LLPipeline::sRenderDeferred)) - { - llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); - facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); - - if (!force_simple && LLPipeline::sRenderBump && use_legacy_bump) - { - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - } + if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { + registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK : LLRenderPass::PASS_ALPHA_MASK); + } + else if (is_alpha || (te->getColor().mV[3] < 0.999f)) + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + else if (gPipeline.canUseVertexShaders() + && LLPipeline::sRenderBump + && te->getShiny() + && can_be_shiny) + { + registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_SHINY : LLRenderPass::PASS_SHINY); + } + else + { + registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT : LLRenderPass::PASS_SIMPLE); + } + } + else if (is_alpha) + { + // can we safely treat this as an alpha mask? + if (facep->getFaceColor().mV[3] <= 0.f) + { //100% transparent, don't render unless we're highlighting transparent + registerFace(group, facep, LLRenderPass::PASS_ALPHA_INVISIBLE); + } + else if (facep->canRenderAsMask()) + { + if (te->getFullbright() || LLPipeline::sNoAlpha) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); + } + } + else + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + } + else if (gPipeline.canUseVertexShaders() + && LLPipeline::sRenderBump + && te->getShiny() + && can_be_shiny) + { //shiny + if (tex->getPrimaryFormat() == GL_ALPHA) + { //invisiprim+shiny + registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } + else if (LLPipeline::sRenderDeferred && !hud_group) + { //deferred rendering + if (te->getFullbright()) + { //register in post deferred fullbright shiny pass + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); + if (te->getBumpmap()) + { //register in post deferred bump pass + registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); + } + } + else if (use_legacy_bump) + { //register in deferred bump pass + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + else + { //register in deferred simple pass (deferred simple includes shiny) + llassert(mask & LLVertexBuffer::MAP_NORMAL); + registerFace(group, facep, LLRenderPass::PASS_SIMPLE); + } + } + else if (fullbright) + { //not deferred, register in standard fullbright shiny pass + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); + } + else + { //not deferred or fullbright, register in standard shiny pass + registerFace(group, facep, LLRenderPass::PASS_SHINY); + } + } + else + { //not alpha and not shiny + if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) + { //invisiprim + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } + else if (fullbright || bake_sunlight) + { //fullbright + if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + } + if (LLPipeline::sRenderDeferred && !hud_group && LLPipeline::sRenderBump && use_legacy_bump) + { //if this is the deferred render and a bump map is present, register in post deferred bump + registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); + } + } + else + { + if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && use_legacy_bump) + { //non-shiny or fullbright deferred bump + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + else + { //all around simple + llassert(mask & LLVertexBuffer::MAP_NORMAL); + if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { //material alpha mask can be respected in non-deferred + registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_SIMPLE); + } + } + } + + + if (!gPipeline.canUseVertexShaders() && + !is_alpha && + te->getShiny() && + LLPipeline::sRenderBump) + { //shiny as an extra pass when shaders are disabled + registerFace(group, facep, LLRenderPass::PASS_SHINY); + } + } + + //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 + if (!is_alpha && (hud_group || !LLPipeline::sRenderDeferred)) + { + llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); + facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); + + if (!force_simple && LLPipeline::sRenderBump && use_legacy_bump) + { + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + } - if (!is_alpha && LLPipeline::sRenderGlow && te->getGlow() > 0.f) - { - registerFace(group, facep, LLRenderPass::PASS_GLOW); - } - - ++face_iter; - } + if (!is_alpha && LLPipeline::sRenderGlow && te->getGlow() > 0.f) + { + registerFace(group, facep, LLRenderPass::PASS_GLOW); + } + + ++face_iter; + } - if (buffer) - { - buffer->flush(); - } - } + if (buffer) + { + buffer->flush(); + } + } - group->mBufferMap[mask].clear(); - for (LLSpatialGroup::buffer_texture_map_t::iterator i = buffer_map[mask].begin(); i != buffer_map[mask].end(); ++i) - { - group->mBufferMap[mask][i->first] = i->second; - } + group->mBufferMap[mask].clear(); + for (LLSpatialGroup::buffer_texture_map_t::iterator i = buffer_map[mask].begin(); i != buffer_map[mask].end(); ++i) + { + group->mBufferMap[mask][i->first] = i->second; + } - return geometryBytes; + return geometryBytes; } void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count) -{ - //initialize to default usage for this partition - U32 usage = group->getSpatialPartition()->mBufferUsage; - - //clear off any old faces - mFaceList.clear(); +{ + //initialize to default usage for this partition + U32 usage = group->getSpatialPartition()->mBufferUsage; + + //clear off any old faces + mFaceList.clear(); - //for each drawable + //for each drawable - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - - if (!drawablep || drawablep->isDead()) - { - continue; - } - - if (drawablep->isAnimating()) - { //fall back to stream draw for animating verts - usage = GL_STREAM_DRAW_ARB; - } + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) + { + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + + if (!drawablep || drawablep->isDead()) + { + continue; + } + + if (drawablep->isAnimating()) + { //fall back to stream draw for animating verts + usage = GL_STREAM_DRAW_ARB; + } - //for each face - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - //sum up face verts and indices - drawablep->updateFaceSize(i); - LLFace* facep = drawablep->getFace(i); - if (facep) - { - if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA && - facep->getGeomCount() + vertex_count <= 65536) - { - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); - - //remember face (for sorting) - mFaceList.push_back(facep); - } - else - { - facep->clearVertexBuffer(); - } - } - } - } - - group->mBufferUsage = usage; + //for each face + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + //sum up face verts and indices + drawablep->updateFaceSize(i); + LLFace* facep = drawablep->getFace(i); + if (facep) + { + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA && + facep->getGeomCount() + vertex_count <= 65536) + { + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + + //remember face (for sorting) + mFaceList.push_back(facep); + } + else + { + facep->clearVertexBuffer(); + } + } + } + } + + group->mBufferUsage = usage; } LLHUDPartition::LLHUDPartition(LLViewerRegion* regionp) : LLBridgePartition(regionp) { - mPartitionType = LLViewerRegion::PARTITION_HUD; - mDrawableType = LLPipeline::RENDER_TYPE_HUD; - mSlopRatio = 0.f; - mLODPeriod = 1; + mPartitionType = LLViewerRegion::PARTITION_HUD; + mDrawableType = LLPipeline::RENDER_TYPE_HUD; + mSlopRatio = 0.f; + mLODPeriod = 1; } void LLHUDPartition::shift(const LLVector4a &offset) { - //HUD objects don't shift with region crossing. That would be silly. + //HUD objects don't shift with region crossing. That would be silly. } -- cgit v1.3 From 898c9f44218353b3bf71b78ffce02662b4927625 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Wed, 13 Mar 2019 13:21:48 -0700 Subject: Mods to make merge with viewer-release have less whitespace-only change and fix diffs between EEP and VR. --- indra/llcommon/llassettype.cpp | 53 +- indra/llcommon/lllivefile.cpp | 1 - indra/llcorehttp/tests/test_refcounted.hpp | 5 +- indra/llmath/llquaternion.cpp | 1 + indra/llmath/llquaternion.h | 1 - indra/llmath/llvolume.cpp | 1 - indra/llmath/tests/m3math_test.cpp | 2 +- indra/llrender/CMakeLists.txt | 6 +- indra/llrender/llgl.cpp | 4 +- indra/llrender/llglslshader.cpp | 2 +- indra/llrender/llglslshader.h | 1 + indra/llrender/llgltexture.cpp | 182 +- indra/llrender/llimagegl.cpp | 1 + indra/newview/lldrawpoolavatar.cpp | 5 +- indra/newview/lldrawpoolwater.h | 2 - indra/newview/lldrawpoolwlsky.cpp | 23 - indra/newview/lldrawpoolwlsky.h | 22 +- indra/newview/llmeshrepository.cpp | 2 +- indra/newview/llviewerdisplay.cpp | 2 +- indra/newview/llviewermenu.cpp | 23 +- indra/newview/llviewershadermgr.cpp | 4441 ++++---- indra/newview/llviewershadermgr.h | 5 - indra/newview/llviewertexture.cpp | 28 +- indra/newview/llviewerwindow.cpp | 2 +- indra/newview/llvovolume.cpp | 2 +- indra/newview/llvowlsky.cpp | 2 +- indra/newview/llvowlsky.h | 6 +- indra/newview/llweb.cpp | 11 +- indra/newview/pipeline.cpp | 15359 +++++++++++++-------------- indra/newview/pipeline.h | 19 +- 30 files changed, 10034 insertions(+), 10180 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 13c08694f0..e6cc06e8d0 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -70,33 +70,32 @@ LLAssetDictionary::LLAssetDictionary() { // DESCRIPTION TYPE NAME HUMAN NAME CAN LINK? CAN FETCH? CAN KNOW? // |--------------------|-----------|-------------------|-----------|-----------|---------| - addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", true, false, true)); - addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", true, true, true)); - addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", true, false, false)); - addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", true, true, true)); - addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", true, false, false)); - addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", true, true, true)); - addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", true, false, false)); - addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", true, false, true)); - addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", true, false, false)); - addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", true, false, false)); - addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", true, false, false)); - addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", true, false, false)); - addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", true, true, true)); - addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", true, false, false)); - addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", true, false, false)); - addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", true, false, false)); - addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", true, true, true)); - addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", true, true, true)); - addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", false, false, false)); - - addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "sym link", false, false, true)); - addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "sym folder link", false, false, true)); - addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false)); - addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false)); - addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false)); - addEntry(LLAssetType::AT_SETTINGS, new AssetEntry("SETTINGS", "settings", "settings blob", true, true, true)); - + addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", true, false, true)); + addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", true, true, true)); + addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", true, false, false)); + addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", true, true, true)); + addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", true, false, false)); + addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", true, true, true)); + addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", true, false, false)); + addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", true, false, true)); + addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", true, false, false)); + addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", true, false, false)); + addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", true, false, false)); + addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", true, false, false)); + addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", true, true, true)); + addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", true, false, false)); + addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", true, false, false)); + addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", true, false, false)); + addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", true, true, true)); + addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", true, true, true)); + addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", false, false, false)); + + addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "sym link", false, false, true)); + addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "sym folder link", false, false, true)); + addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false)); + addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false)); + addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false)); + addEntry(LLAssetType::AT_SETTINGS, new AssetEntry("SETTINGS", "settings", "settings blob", true, true, true)); addEntry(LLAssetType::AT_UNKNOWN, new AssetEntry("UNKNOWN", "invalid", NULL, false, false, false)); addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE)); diff --git a/indra/llcommon/lllivefile.cpp b/indra/llcommon/lllivefile.cpp index 4b73ff691a..ea485c2d86 100644 --- a/indra/llcommon/lllivefile.cpp +++ b/indra/llcommon/lllivefile.cpp @@ -150,7 +150,6 @@ bool LLLiveFile::checkAndReload() } else { - LL_WARNS() << "Failed to load live file " << filename() << LL_ENDL; changed = false; } } diff --git a/indra/llcorehttp/tests/test_refcounted.hpp b/indra/llcorehttp/tests/test_refcounted.hpp index 6a516f60c0..5dff143e5d 100644 --- a/indra/llcorehttp/tests/test_refcounted.hpp +++ b/indra/llcorehttp/tests/test_refcounted.hpp @@ -30,7 +30,7 @@ #include "test_allocator.h" -#if WANT_TESTS_WITH_RACES_THAT_HANG +#if 0 // disable all of this because it's hanging win64 builds? using namespace LLCoreInt; namespace tut @@ -153,6 +153,5 @@ namespace tut ensure(mMemTotal == (GetMemTotal() - sizeof(RefCounted))); } } -#endif - +#endif // if 0 #endif // TEST_LLCOREINT_REF_COUNTED_H_ diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp index a8d9eba2a0..57a976b57a 100644 --- a/indra/llmath/llquaternion.cpp +++ b/indra/llmath/llquaternion.cpp @@ -103,6 +103,7 @@ LLQuaternion::LLQuaternion(const LLVector3 &x_axis, *this = mat.quaternion(); normalize(); } + LLQuaternion::LLQuaternion(const LLSD &sd) { setValue(sd); diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h index e2cdad548b..51ce163b4e 100644 --- a/indra/llmath/llquaternion.h +++ b/indra/llmath/llquaternion.h @@ -191,7 +191,6 @@ inline void LLQuaternion::setValue(const LLSD& sd) mQ[3] = sd[3].asReal(); } - // checker inline BOOL LLQuaternion::isFinite() const { diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 0e1748b337..605032e0a8 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2204,7 +2204,6 @@ BOOL LLVolume::generate() { rot_mat.rotate(*profile++, tmp); dst->setAdd(tmp,offset); - ++dst; } } diff --git a/indra/llmath/tests/m3math_test.cpp b/indra/llmath/tests/m3math_test.cpp index 2a0fe76aa7..1ca2b005d9 100644 --- a/indra/llmath/tests/m3math_test.cpp +++ b/indra/llmath/tests/m3math_test.cpp @@ -77,7 +77,7 @@ namespace tut template<> template<> void m3math_test_object_t::test<2>() { - LLMatrix3 llmat3_obj; + LLMatrix3 llmat3_obj(30, 1, 2, 3); llmat3_obj.setZero(); ensure("LLMatrix3::setZero failed", 0.f == llmat3_obj.setZero().mMatrix[0][0] && diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 0a81c1c6dd..589cf86745 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -107,8 +107,7 @@ if (BUILD_HEADLESS) ${LLXML_LIBRARIES} ${LLVFS_LIBRARIES} ${LLWINDOW_HEADLESS_LIBRARIES} - ${OPENGL_HEADLESS_LIBRARIES} - ) + ${OPENGL_HEADLESS_LIBRARIES}) endif (BUILD_HEADLESS) @@ -131,6 +130,5 @@ target_link_libraries(llrender ${LLVFS_LIBRARIES} ${LLWINDOW_LIBRARIES} ${FREETYPE_LIBRARIES} - ${OPENGL_LIBRARIES} - ) + ${OPENGL_LIBRARIES}) diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index b6300578e6..54a41c9d23 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1353,8 +1353,8 @@ void LLGLManager::initExtensions() // nSight doesn't support use of ARB funcs that have been normalized in the API if (!LLRender::sNsightDebugSupport) { - glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocationARB"); - glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocationARB"); + glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocationARB"); + glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocationARB"); } else { diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 471d73febf..8f3a56e1cf 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -401,7 +401,7 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, // work-around missing mix(vec3,vec3,bvec3) mDefines["OLD_SELECT"] = "1"; #endif - + //compile new source vector< pair >::iterator fileIter = mShaderFiles.begin(); for ( ; fileIter != mShaderFiles.end(); fileIter++ ) diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 830bad2aef..c1ce3d3aad 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -229,4 +229,5 @@ extern LLGLSLShader gSolidColorProgram; //Alpha mask shader (declared here so llappearance can access properly) extern LLGLSLShader gAlphaMaskProgram; + #endif diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index e9a39d8acb..ad501687ed 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -30,20 +30,20 @@ // static S32 LLGLTexture::getTotalNumOfCategories() { - return MAX_GL_IMAGE_CATEGORY - (BOOST_HIGH - BOOST_SCULPTED) + 2; + return MAX_GL_IMAGE_CATEGORY - (BOOST_HIGH - BOOST_SCULPTED) + 2 ; } // static //index starts from zero. S32 LLGLTexture::getIndexFromCategory(S32 category) { - return (category < BOOST_HIGH) ? category : category - (BOOST_HIGH - BOOST_SCULPTED) + 1; + return (category < BOOST_HIGH) ? category : category - (BOOST_HIGH - BOOST_SCULPTED) + 1 ; } //static S32 LLGLTexture::getCategoryFromIndex(S32 index) { - return (index < BOOST_HIGH) ? index : index + (BOOST_HIGH - BOOST_SCULPTED) - 1; + return (index < BOOST_HIGH) ? index : index + (BOOST_HIGH - BOOST_SCULPTED) - 1 ; } LLGLTexture::LLGLTexture(BOOL usemipmaps) @@ -55,19 +55,19 @@ LLGLTexture::LLGLTexture(BOOL usemipmaps) LLGLTexture::LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) { init(); - mFullWidth = width; - mFullHeight = height; + mFullWidth = width ; + mFullHeight = height ; mUseMipMaps = usemipmaps; - mComponents = components; + mComponents = components ; setTexelsPerImage(); } LLGLTexture::LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) { init(); - mUseMipMaps = usemipmaps; + mUseMipMaps = usemipmaps ; // Create an empty image of the specified size and width - mGLTexturep = new LLImageGL(raw, usemipmaps); + mGLTexturep = new LLImageGL(raw, usemipmaps) ; } LLGLTexture::~LLGLTexture() @@ -81,13 +81,13 @@ void LLGLTexture::init() mFullWidth = 0; mFullHeight = 0; - mTexelsPerImage = 0; - mUseMipMaps = FALSE; - mComponents = 0; + mTexelsPerImage = 0 ; + mUseMipMaps = FALSE ; + mComponents = 0 ; - mTextureState = NO_DELETE; + mTextureState = NO_DELETE ; mDontDiscard = FALSE; - mNeedsGLTexture = FALSE; + mNeedsGLTexture = FALSE ; } void LLGLTexture::cleanup() @@ -111,181 +111,181 @@ void LLGLTexture::setBoostLevel(S32 level) { if(mBoostLevel != level) { - mBoostLevel = level; + mBoostLevel = level ; if(mBoostLevel != LLGLTexture::BOOST_NONE && mBoostLevel != LLGLTexture::BOOST_ICON) { - setNoDelete(); + setNoDelete() ; } } } void LLGLTexture::forceActive() { - mTextureState = ACTIVE; + mTextureState = ACTIVE ; } void LLGLTexture::setActive() { if(mTextureState != NO_DELETE) { - mTextureState = ACTIVE; + mTextureState = ACTIVE ; } } //set the texture to stay in memory void LLGLTexture::setNoDelete() { - mTextureState = NO_DELETE; + mTextureState = NO_DELETE ; } void LLGLTexture::generateGLTexture() { if(mGLTexturep.isNull()) { - mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps); + mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ; } } LLImageGL* LLGLTexture::getGLTexture() const { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep; + return mGLTexturep ; } BOOL LLGLTexture::createGLTexture() { if(mGLTexturep.isNull()) { - generateGLTexture(); + generateGLTexture() ; } - return mGLTexturep->createGLTexture(); + return mGLTexturep->createGLTexture() ; } BOOL LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category) { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category); + BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category) ; if(ret) { - mFullWidth = mGLTexturep->getCurrentWidth(); - mFullHeight = mGLTexturep->getCurrentHeight(); - mComponents = mGLTexturep->getComponents(); + mFullWidth = mGLTexturep->getCurrentWidth() ; + mFullHeight = mGLTexturep->getCurrentHeight() ; + mComponents = mGLTexturep->getComponents() ; setTexelsPerImage(); } - return ret; + return ret ; } void LLGLTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes) { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes); + mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ; } void LLGLTexture::setAddressMode(LLTexUnit::eTextureAddressMode mode) { - llassert(mGLTexturep.notNull()); - mGLTexturep->setAddressMode(mode); + llassert(mGLTexturep.notNull()) ; + mGLTexturep->setAddressMode(mode) ; } void LLGLTexture::setFilteringOption(LLTexUnit::eTextureFilterOptions option) { - llassert(mGLTexturep.notNull()); - mGLTexturep->setFilteringOption(option); + llassert(mGLTexturep.notNull()) ; + mGLTexturep->setFilteringOption(option) ; } //virtual S32 LLGLTexture::getWidth(S32 discard_level) const { - llassert(mGLTexturep.notNull()); - return mGLTexturep->getWidth(discard_level); + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getWidth(discard_level) ; } //virtual S32 LLGLTexture::getHeight(S32 discard_level) const { - llassert(mGLTexturep.notNull()); - return mGLTexturep->getHeight(discard_level); + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getHeight(discard_level) ; } S32 LLGLTexture::getMaxDiscardLevel() const { - llassert(mGLTexturep.notNull()); - return mGLTexturep->getMaxDiscardLevel(); + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getMaxDiscardLevel() ; } S32 LLGLTexture::getDiscardLevel() const { - llassert(mGLTexturep.notNull()); - return mGLTexturep->getDiscardLevel(); + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getDiscardLevel() ; } S8 LLGLTexture::getComponents() const { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getComponents(); + return mGLTexturep->getComponents() ; } LLGLuint LLGLTexture::getTexName() const { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getTexName(); + return mGLTexturep->getTexName() ; } BOOL LLGLTexture::hasGLTexture() const { if(mGLTexturep.notNull()) { - return mGLTexturep->getHasGLTexture(); + return mGLTexturep->getHasGLTexture() ; } - return FALSE; + return FALSE ; } BOOL LLGLTexture::getBoundRecently() const { if(mGLTexturep.notNull()) { - return mGLTexturep->getBoundRecently(); + return mGLTexturep->getBoundRecently() ; } - return FALSE; + return FALSE ; } LLTexUnit::eTextureType LLGLTexture::getTarget(void) const { - llassert(mGLTexturep.notNull()); - return mGLTexturep->getTarget(); + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getTarget() ; } BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height) { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height); + return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height) ; } BOOL LLGLTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height); + return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height) ; } void LLGLTexture::setGLTextureCreated (bool initialized) { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - mGLTexturep->setGLTextureCreated (initialized); + mGLTexturep->setGLTextureCreated (initialized) ; } void LLGLTexture::setCategory(S32 category) { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - mGLTexturep->setCategory(category); + mGLTexturep->setCategory(category) ; } void LLGLTexture::setTexName(LLGLuint texName) @@ -302,107 +302,107 @@ void LLGLTexture::setTarget(const LLGLenum target, const LLTexUnit::eTextureType LLTexUnit::eTextureAddressMode LLGLTexture::getAddressMode(void) const { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getAddressMode(); + return mGLTexturep->getAddressMode() ; } S32Bytes LLGLTexture::getTextureMemory() const { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->mTextureMemory; + return mGLTexturep->mTextureMemory ; } LLGLenum LLGLTexture::getPrimaryFormat() const { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getPrimaryFormat(); + return mGLTexturep->getPrimaryFormat() ; } BOOL LLGLTexture::getIsAlphaMask() const { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getIsAlphaMask(); + return mGLTexturep->getIsAlphaMask() ; } BOOL LLGLTexture::getMask(const LLVector2 &tc) { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getMask(tc); + return mGLTexturep->getMask(tc) ; } F32 LLGLTexture::getTimePassedSinceLastBound() { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getTimePassedSinceLastBound(); + return mGLTexturep->getTimePassedSinceLastBound() ; } BOOL LLGLTexture::getMissed() const { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getMissed(); + return mGLTexturep->getMissed() ; } BOOL LLGLTexture::isJustBound() const { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->isJustBound(); + return mGLTexturep->isJustBound() ; } void LLGLTexture::forceUpdateBindStats(void) const { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->forceUpdateBindStats(); + return mGLTexturep->forceUpdateBindStats() ; } U32 LLGLTexture::getTexelsInAtlas() const { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getTexelsInAtlas(); + return mGLTexturep->getTexelsInAtlas() ; } U32 LLGLTexture::getTexelsInGLTexture() const { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getTexelsInGLTexture(); + return mGLTexturep->getTexelsInGLTexture() ; } BOOL LLGLTexture::isGLTextureCreated() const { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->isGLTextureCreated(); + return mGLTexturep->isGLTextureCreated() ; } S32 LLGLTexture::getDiscardLevelInAtlas() const { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getDiscardLevelInAtlas(); + return mGLTexturep->getDiscardLevelInAtlas() ; } void LLGLTexture::destroyGLTexture() { if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture()) { - mGLTexturep->destroyGLTexture(); - mTextureState = DELETED; + mGLTexturep->destroyGLTexture() ; + mTextureState = DELETED ; } } void LLGLTexture::setTexelsPerImage() { - U32 fullwidth = llmin(mFullWidth, (U32)MAX_IMAGE_SIZE_DEFAULT); - U32 fullheight = llmin(mFullHeight, (U32)MAX_IMAGE_SIZE_DEFAULT); + U32 fullwidth = llmin(mFullWidth,U32(MAX_IMAGE_SIZE_DEFAULT)); + U32 fullheight = llmin(mFullHeight,U32(MAX_IMAGE_SIZE_DEFAULT)); mTexelsPerImage = (U32)fullwidth * fullheight; } diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 25ec493fa2..7d8f512c93 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -352,6 +352,7 @@ BOOL LLImageGL::create(LLPointer& dest, const LLImageRaw* imageraw, B } //---------------------------------------------------------------------------- + LLImageGL::LLImageGL(BOOL usemipmaps) : LLTrace::MemTrackable("LLImageGL"), mSaveData(0), mExternalTexture(FALSE) diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index e96e7cbe6c..f0a0851b2e 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -493,7 +493,7 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) } LLVOAvatar *avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); - if (avatarp->isDead() || avatarp->mIsDummy || avatarp->mDrawable.isNull()) + if (avatarp->isDead() || avatarp->isUIAvatar() || avatarp->mDrawable.isNull()) { return; } @@ -1820,7 +1820,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { - if (avatar->isSelf() && !gAgent.needsRenderAvatar()) + if (!avatar->shouldRenderRigged()) { return; } @@ -2208,7 +2208,6 @@ void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type) { LL_ERRS() << "Invalid rigged face type." << LL_ENDL; } - if (facep->getRiggedIndex(type) != -1) { LL_ERRS() << "Tried to add a rigged face that's referenced elsewhere." << LL_ENDL; diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h index f94baefc41..d436557e1c 100644 --- a/indra/newview/lldrawpoolwater.h +++ b/indra/newview/lldrawpoolwater.h @@ -47,8 +47,6 @@ public: static BOOL sSkipScreenCopy; static BOOL sNeedsReflectionUpdate; static BOOL sNeedsDistortionUpdate; -// static LLVector3 sLightDir; -// static LLColor4 sWaterFogColor; static F32 sWaterFogEnd; enum diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index 8a739d91f8..dd450dcb70 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -124,29 +124,6 @@ void LLDrawPoolWLSky::endDeferredPass(S32 pass) moon_shader = nullptr; } -S32 LLDrawPoolWLSky::getNumShadowPasses() { return 0; } - -void LLDrawPoolWLSky::beginShadowPass(S32 pass) -{ - //cloud_shadow_shader = LLPipeline::sRenderDeferred ? &gDeferredWLCloudShadowProgram : &gWLCloudShadowProgram; -} - -void LLDrawPoolWLSky::endShadowPass(S32 pass) -{ - cloud_shadow_shader = nullptr; -} - -void LLDrawPoolWLSky::renderShadow(S32 pass) -{ - if (cloud_shadow_shader) - { - const F32 camHeightLocal = LLEnvironment::instance().getCamHeight(); - LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin(); - - renderSkyClouds(origin, camHeightLocal, cloud_shadow_shader); - } -} - void LLDrawPoolWLSky::renderFsSky(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader * shader) const { gSky.mVOWLSkyp->drawFsSky(); diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h index b05f0f8605..3acfda4eee 100644 --- a/indra/newview/lldrawpoolwlsky.h +++ b/indra/newview/lldrawpoolwlsky.h @@ -34,14 +34,12 @@ class LLGLSLShader; class LLDrawPoolWLSky : public LLDrawPool { public: - static const U32 SKY_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX - | LLVertexBuffer::MAP_TEXCOORD0; - static const U32 STAR_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX - | LLVertexBuffer::MAP_COLOR - | LLVertexBuffer::MAP_TEXCOORD0; + static const U32 SKY_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0; + static const U32 STAR_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0; static const U32 ADV_ATMO_SKY_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0; - LLDrawPoolWLSky(void); /*virtual*/ ~LLDrawPoolWLSky(); @@ -52,22 +50,10 @@ public: /*virtual*/ void endDeferredPass(S32 pass); /*virtual*/ void renderDeferred(S32 pass); - - /*virtual*/ S32 getNumPostDeferredPasses() { return 0; } - /*virtual*/ void beginPostDeferredPass(S32 pass) {} - /*virtual*/ void endPostDeferredPass(S32 pass) {} - /*virtual*/ void renderPostDeferred(S32 pass) {} - /*virtual*/ LLViewerTexture *getDebugTexture(); /*virtual*/ void beginRenderPass( S32 pass ); /*virtual*/ void endRenderPass( S32 pass ); /*virtual*/ S32 getNumPasses() { return 1; } - - /*virtual*/ S32 getNumShadowPasses(); - /*virtual*/ void beginShadowPass(S32 pass); - /*virtual*/ void endShadowPass(S32 pass); - /*virtual*/ void renderShadow(S32 pass); - /*virtual*/ void render(S32 pass = 0); /*virtual*/ void prerender(); /*virtual*/ U32 getVertexDataMask() { return SKY_VERTEX_DATA_MASK; } diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index c934cd2980..e38bd8846d 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -2663,7 +2663,7 @@ void LLMeshUploadThread::requestWholeModelFee() { ms_sleep(sleep_time); sleep_time = llmin(250U, sleep_time + sleep_time); - mHttpRequest->update(0); + mHttpRequest->update(0); } if (isDiscarded()) { diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 3d3826064f..2e5807cab9 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1036,7 +1036,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI"); if (!for_snapshot) - { + { render_ui(); swap(); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c9b13f92d3..68a91968ea 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1211,20 +1211,6 @@ class LLAdvancedSelectedTextureInfo : public view_listener_t } }; -//////////////////////////// -// TOGGLE SH LIGHTING VIS // -//////////////////////////// - -class LLAdvancedToggleDebugSH : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_SH); - gSavedSettings.setBOOL("RenderDebugSH", gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SH)); - return true; - } -}; - ////////////////////// // TOGGLE WIREFRAME // ////////////////////// @@ -6115,7 +6101,12 @@ class LLAvatarResetSkeleton: public view_listener_t { bool handleEvent(const LLSD& userdata) { - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + LLVOAvatar* avatar = NULL; + LLViewerObject *obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (obj) + { + avatar = obj->getAvatar(); + } if(avatar) { avatar->resetSkeleton(false); @@ -8658,6 +8649,7 @@ class LLWorldEnableEnvPreset : public view_listener_t } }; + /// Post-Process callbacks class LLWorldPostProcess : public view_listener_t { @@ -8998,7 +8990,6 @@ void initialize_menus() commit.add("Advanced.SelectedMaterialInfo", boost::bind(&handle_selected_material_info)); view_listener_t::addMenu(new LLAdvancedToggleWireframe(), "Advanced.ToggleWireframe"); view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe"); - view_listener_t::addMenu(new LLAdvancedToggleDebugSH(), "Advanced.ToggleDebugSH"); // Develop > Render view_listener_t::addMenu(new LLAdvancedEnableObjectObjectOcclusion(), "Advanced.EnableObjectObjectOcclusion"); view_listener_t::addMenu(new LLAdvancedEnableRenderFBO(), "Advanced.EnableRenderFBO"); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index e30ff42b4f..d1dd932a36 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -63,188 +63,184 @@ using std::pair; using std::make_pair; using std::string; -BOOL LLViewerShaderMgr::sInitialized = FALSE; -bool LLViewerShaderMgr::sSkipReload = false; +BOOL LLViewerShaderMgr::sInitialized = FALSE; +bool LLViewerShaderMgr::sSkipReload = false; -LLVector4 gShinyOrigin; +LLVector4 gShinyOrigin; //transform shaders -LLGLSLShader gTransformPositionProgram; -LLGLSLShader gTransformTexCoordProgram; -LLGLSLShader gTransformNormalProgram; -LLGLSLShader gTransformColorProgram; -LLGLSLShader gTransformTangentProgram; +LLGLSLShader gTransformPositionProgram; +LLGLSLShader gTransformTexCoordProgram; +LLGLSLShader gTransformNormalProgram; +LLGLSLShader gTransformColorProgram; +LLGLSLShader gTransformTangentProgram; //utility shaders -LLGLSLShader gOcclusionProgram; -LLGLSLShader gOcclusionCubeProgram; -LLGLSLShader gCustomAlphaProgram; -LLGLSLShader gGlowCombineProgram; -LLGLSLShader gSplatTextureRectProgram; -LLGLSLShader gGlowCombineFXAAProgram; -LLGLSLShader gTwoTextureAddProgram; -LLGLSLShader gTwoTextureCompareProgram; -LLGLSLShader gOneTextureFilterProgram; -LLGLSLShader gOneTextureNoColorProgram; -LLGLSLShader gDebugProgram; -LLGLSLShader gClipProgram; -LLGLSLShader gDownsampleDepthProgram; -LLGLSLShader gDownsampleDepthRectProgram; -LLGLSLShader gDownsampleMinMaxDepthRectProgram; -LLGLSLShader gInscatterRectProgram; -LLGLSLShader gAlphaMaskProgram; -LLGLSLShader gBenchmarkProgram; +LLGLSLShader gOcclusionProgram; +LLGLSLShader gOcclusionCubeProgram; +LLGLSLShader gCustomAlphaProgram; +LLGLSLShader gGlowCombineProgram; +LLGLSLShader gSplatTextureRectProgram; +LLGLSLShader gGlowCombineFXAAProgram; +LLGLSLShader gTwoTextureAddProgram; +LLGLSLShader gTwoTextureCompareProgram; +LLGLSLShader gOneTextureFilterProgram; +LLGLSLShader gOneTextureNoColorProgram; +LLGLSLShader gDebugProgram; +LLGLSLShader gClipProgram; +LLGLSLShader gDownsampleDepthProgram; +LLGLSLShader gDownsampleDepthRectProgram; +LLGLSLShader gAlphaMaskProgram; +LLGLSLShader gBenchmarkProgram; //object shaders -LLGLSLShader gObjectSimpleProgram; -LLGLSLShader gObjectSimpleImpostorProgram; -LLGLSLShader gObjectPreviewProgram; -LLGLSLShader gObjectSimpleWaterProgram; -LLGLSLShader gObjectSimpleAlphaMaskProgram; -LLGLSLShader gObjectSimpleWaterAlphaMaskProgram; -LLGLSLShader gObjectFullbrightProgram; -LLGLSLShader gObjectFullbrightWaterProgram; -LLGLSLShader gObjectEmissiveProgram; -LLGLSLShader gObjectEmissiveWaterProgram; -LLGLSLShader gObjectFullbrightAlphaMaskProgram; -LLGLSLShader gObjectFullbrightWaterAlphaMaskProgram; -LLGLSLShader gObjectFullbrightShinyProgram; -LLGLSLShader gObjectFullbrightShinyWaterProgram; -LLGLSLShader gObjectShinyProgram; -LLGLSLShader gObjectShinyWaterProgram; -LLGLSLShader gObjectBumpProgram; -LLGLSLShader gTreeProgram; -LLGLSLShader gTreeWaterProgram; -LLGLSLShader gObjectFullbrightNoColorProgram; -LLGLSLShader gObjectFullbrightNoColorWaterProgram; - -LLGLSLShader gObjectSimpleNonIndexedProgram; -LLGLSLShader gObjectSimpleNonIndexedTexGenProgram; -LLGLSLShader gObjectSimpleNonIndexedTexGenWaterProgram; -LLGLSLShader gObjectSimpleNonIndexedWaterProgram; -LLGLSLShader gObjectAlphaMaskNonIndexedProgram; -LLGLSLShader gObjectAlphaMaskNonIndexedWaterProgram; -LLGLSLShader gObjectAlphaMaskNoColorProgram; -LLGLSLShader gObjectAlphaMaskNoColorWaterProgram; -LLGLSLShader gObjectFullbrightNonIndexedProgram; -LLGLSLShader gObjectFullbrightNonIndexedWaterProgram; -LLGLSLShader gObjectEmissiveNonIndexedProgram; -LLGLSLShader gObjectEmissiveNonIndexedWaterProgram; -LLGLSLShader gObjectFullbrightShinyNonIndexedProgram; -LLGLSLShader gObjectFullbrightShinyNonIndexedWaterProgram; -LLGLSLShader gObjectShinyNonIndexedProgram; -LLGLSLShader gObjectShinyNonIndexedWaterProgram; +LLGLSLShader gObjectSimpleProgram; +LLGLSLShader gObjectSimpleImpostorProgram; +LLGLSLShader gObjectPreviewProgram; +LLGLSLShader gObjectSimpleWaterProgram; +LLGLSLShader gObjectSimpleAlphaMaskProgram; +LLGLSLShader gObjectSimpleWaterAlphaMaskProgram; +LLGLSLShader gObjectFullbrightProgram; +LLGLSLShader gObjectFullbrightWaterProgram; +LLGLSLShader gObjectEmissiveProgram; +LLGLSLShader gObjectEmissiveWaterProgram; +LLGLSLShader gObjectFullbrightAlphaMaskProgram; +LLGLSLShader gObjectFullbrightWaterAlphaMaskProgram; +LLGLSLShader gObjectFullbrightShinyProgram; +LLGLSLShader gObjectFullbrightShinyWaterProgram; +LLGLSLShader gObjectShinyProgram; +LLGLSLShader gObjectShinyWaterProgram; +LLGLSLShader gObjectBumpProgram; +LLGLSLShader gTreeProgram; +LLGLSLShader gTreeWaterProgram; +LLGLSLShader gObjectFullbrightNoColorProgram; +LLGLSLShader gObjectFullbrightNoColorWaterProgram; + +LLGLSLShader gObjectSimpleNonIndexedProgram; +LLGLSLShader gObjectSimpleNonIndexedTexGenProgram; +LLGLSLShader gObjectSimpleNonIndexedTexGenWaterProgram; +LLGLSLShader gObjectSimpleNonIndexedWaterProgram; +LLGLSLShader gObjectAlphaMaskNonIndexedProgram; +LLGLSLShader gObjectAlphaMaskNonIndexedWaterProgram; +LLGLSLShader gObjectAlphaMaskNoColorProgram; +LLGLSLShader gObjectAlphaMaskNoColorWaterProgram; +LLGLSLShader gObjectFullbrightNonIndexedProgram; +LLGLSLShader gObjectFullbrightNonIndexedWaterProgram; +LLGLSLShader gObjectEmissiveNonIndexedProgram; +LLGLSLShader gObjectEmissiveNonIndexedWaterProgram; +LLGLSLShader gObjectFullbrightShinyNonIndexedProgram; +LLGLSLShader gObjectFullbrightShinyNonIndexedWaterProgram; +LLGLSLShader gObjectShinyNonIndexedProgram; +LLGLSLShader gObjectShinyNonIndexedWaterProgram; //object hardware skinning shaders -LLGLSLShader gSkinnedObjectSimpleProgram; -LLGLSLShader gSkinnedObjectFullbrightProgram; -LLGLSLShader gSkinnedObjectEmissiveProgram; -LLGLSLShader gSkinnedObjectFullbrightShinyProgram; -LLGLSLShader gSkinnedObjectShinySimpleProgram; - -LLGLSLShader gSkinnedObjectSimpleWaterProgram; -LLGLSLShader gSkinnedObjectFullbrightWaterProgram; -LLGLSLShader gSkinnedObjectEmissiveWaterProgram; -LLGLSLShader gSkinnedObjectFullbrightShinyWaterProgram; -LLGLSLShader gSkinnedObjectShinySimpleWaterProgram; +LLGLSLShader gSkinnedObjectSimpleProgram; +LLGLSLShader gSkinnedObjectFullbrightProgram; +LLGLSLShader gSkinnedObjectEmissiveProgram; +LLGLSLShader gSkinnedObjectFullbrightShinyProgram; +LLGLSLShader gSkinnedObjectShinySimpleProgram; + +LLGLSLShader gSkinnedObjectSimpleWaterProgram; +LLGLSLShader gSkinnedObjectFullbrightWaterProgram; +LLGLSLShader gSkinnedObjectEmissiveWaterProgram; +LLGLSLShader gSkinnedObjectFullbrightShinyWaterProgram; +LLGLSLShader gSkinnedObjectShinySimpleWaterProgram; //environment shaders -LLGLSLShader gTerrainProgram; -LLGLSLShader gTerrainWaterProgram; -LLGLSLShader gWaterProgram; +LLGLSLShader gTerrainProgram; +LLGLSLShader gTerrainWaterProgram; +LLGLSLShader gWaterProgram; LLGLSLShader gWaterEdgeProgram; -LLGLSLShader gUnderWaterProgram; +LLGLSLShader gUnderWaterProgram; //interface shaders -LLGLSLShader gHighlightProgram; -LLGLSLShader gHighlightNormalProgram; -LLGLSLShader gHighlightSpecularProgram; +LLGLSLShader gHighlightProgram; +LLGLSLShader gHighlightNormalProgram; +LLGLSLShader gHighlightSpecularProgram; -LLGLSLShader gPathfindingProgram; -LLGLSLShader gPathfindingNoNormalsProgram; +LLGLSLShader gPathfindingProgram; +LLGLSLShader gPathfindingNoNormalsProgram; //avatar shader handles -LLGLSLShader gAvatarProgram; -LLGLSLShader gAvatarWaterProgram; -LLGLSLShader gAvatarEyeballProgram; -LLGLSLShader gAvatarPickProgram; -LLGLSLShader gImpostorProgram; +LLGLSLShader gAvatarProgram; +LLGLSLShader gAvatarWaterProgram; +LLGLSLShader gAvatarEyeballProgram; +LLGLSLShader gAvatarPickProgram; +LLGLSLShader gImpostorProgram; // WindLight shader handles -LLGLSLShader gWLSkyProgram; -LLGLSLShader gWLCloudProgram; -LLGLSLShader gWLCloudShadowProgram; +LLGLSLShader gWLSkyProgram; +LLGLSLShader gWLCloudProgram; LLGLSLShader gWLSunProgram; LLGLSLShader gWLMoonProgram; // Effects Shaders -LLGLSLShader gGlowProgram; -LLGLSLShader gGlowExtractProgram; -LLGLSLShader gPostColorFilterProgram; -LLGLSLShader gPostNightVisionProgram; +LLGLSLShader gGlowProgram; +LLGLSLShader gGlowExtractProgram; +LLGLSLShader gPostColorFilterProgram; +LLGLSLShader gPostNightVisionProgram; // Deferred rendering shaders -LLGLSLShader gDeferredImpostorProgram; -LLGLSLShader gDeferredWaterProgram; -LLGLSLShader gDeferredUnderWaterProgram; -LLGLSLShader gDeferredDiffuseProgram; -LLGLSLShader gDeferredDiffuseAlphaMaskProgram; -LLGLSLShader gDeferredNonIndexedDiffuseProgram; -LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram; -LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram; -LLGLSLShader gDeferredSkinnedDiffuseProgram; -LLGLSLShader gDeferredSkinnedBumpProgram; -LLGLSLShader gDeferredSkinnedAlphaProgram; -LLGLSLShader gDeferredBumpProgram; -LLGLSLShader gDeferredTerrainProgram; +LLGLSLShader gDeferredImpostorProgram; +LLGLSLShader gDeferredWaterProgram; +LLGLSLShader gDeferredUnderWaterProgram; +LLGLSLShader gDeferredDiffuseProgram; +LLGLSLShader gDeferredDiffuseAlphaMaskProgram; +LLGLSLShader gDeferredNonIndexedDiffuseProgram; +LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram; +LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram; +LLGLSLShader gDeferredSkinnedDiffuseProgram; +LLGLSLShader gDeferredSkinnedBumpProgram; +LLGLSLShader gDeferredSkinnedAlphaProgram; +LLGLSLShader gDeferredBumpProgram; +LLGLSLShader gDeferredTerrainProgram; LLGLSLShader gDeferredTerrainWaterProgram; -LLGLSLShader gDeferredTreeProgram; -LLGLSLShader gDeferredTreeShadowProgram; -LLGLSLShader gDeferredAvatarProgram; -LLGLSLShader gDeferredAvatarAlphaProgram; -LLGLSLShader gDeferredLightProgram; -LLGLSLShader gDeferredMultiLightProgram[16]; -LLGLSLShader gDeferredSpotLightProgram; -LLGLSLShader gDeferredMultiSpotLightProgram; -LLGLSLShader gDeferredSunProgram; -LLGLSLShader gDeferredBlurLightProgram; -LLGLSLShader gDeferredSoftenProgram; -LLGLSLShader gDeferredSoftenWaterProgram; -LLGLSLShader gDeferredShadowProgram; -LLGLSLShader gDeferredShadowCubeProgram; -LLGLSLShader gDeferredShadowAlphaMaskProgram; -LLGLSLShader gDeferredAvatarShadowProgram; -LLGLSLShader gDeferredAttachmentShadowProgram; -LLGLSLShader gDeferredAlphaProgram; -LLGLSLShader gDeferredAlphaImpostorProgram; -LLGLSLShader gDeferredAlphaWaterProgram; -LLGLSLShader gDeferredAvatarEyesProgram; -LLGLSLShader gDeferredFullbrightProgram; -LLGLSLShader gDeferredFullbrightAlphaMaskProgram; -LLGLSLShader gDeferredFullbrightWaterProgram; -LLGLSLShader gDeferredFullbrightAlphaMaskWaterProgram; -LLGLSLShader gDeferredEmissiveProgram; -LLGLSLShader gDeferredPostProgram; -LLGLSLShader gDeferredCoFProgram; -LLGLSLShader gDeferredDoFCombineProgram; -LLGLSLShader gDeferredPostGammaCorrectProgram; -LLGLSLShader gFXAAProgram; -LLGLSLShader gDeferredPostNoDoFProgram; -LLGLSLShader gDeferredWLSkyProgram; -LLGLSLShader gDeferredWLCloudProgram; -LLGLSLShader gDeferredWLCloudShadowProgram; -LLGLSLShader gDeferredWLSunProgram; -LLGLSLShader gDeferredWLMoonProgram; -LLGLSLShader gDeferredStarProgram; -LLGLSLShader gDeferredFullbrightShinyProgram; -LLGLSLShader gDeferredSkinnedFullbrightShinyProgram; -LLGLSLShader gDeferredSkinnedFullbrightProgram; -LLGLSLShader gNormalMapGenProgram; +LLGLSLShader gDeferredTreeProgram; +LLGLSLShader gDeferredTreeShadowProgram; +LLGLSLShader gDeferredAvatarProgram; +LLGLSLShader gDeferredAvatarAlphaProgram; +LLGLSLShader gDeferredLightProgram; +LLGLSLShader gDeferredMultiLightProgram[16]; +LLGLSLShader gDeferredSpotLightProgram; +LLGLSLShader gDeferredMultiSpotLightProgram; +LLGLSLShader gDeferredSunProgram; +LLGLSLShader gDeferredBlurLightProgram; +LLGLSLShader gDeferredSoftenProgram; +LLGLSLShader gDeferredSoftenWaterProgram; +LLGLSLShader gDeferredShadowProgram; +LLGLSLShader gDeferredShadowCubeProgram; +LLGLSLShader gDeferredShadowAlphaMaskProgram; +LLGLSLShader gDeferredAvatarShadowProgram; +LLGLSLShader gDeferredAttachmentShadowProgram; +LLGLSLShader gDeferredAlphaProgram; +LLGLSLShader gDeferredAlphaImpostorProgram; +LLGLSLShader gDeferredAlphaWaterProgram; +LLGLSLShader gDeferredAvatarEyesProgram; +LLGLSLShader gDeferredFullbrightProgram; +LLGLSLShader gDeferredFullbrightAlphaMaskProgram; +LLGLSLShader gDeferredFullbrightWaterProgram; +LLGLSLShader gDeferredFullbrightAlphaMaskWaterProgram; +LLGLSLShader gDeferredEmissiveProgram; +LLGLSLShader gDeferredPostProgram; +LLGLSLShader gDeferredCoFProgram; +LLGLSLShader gDeferredDoFCombineProgram; +LLGLSLShader gDeferredPostGammaCorrectProgram; +LLGLSLShader gFXAAProgram; +LLGLSLShader gDeferredPostNoDoFProgram; +LLGLSLShader gDeferredWLSkyProgram; +LLGLSLShader gDeferredWLCloudProgram; +LLGLSLShader gDeferredWLSunProgram; +LLGLSLShader gDeferredWLMoonProgram; +LLGLSLShader gDeferredStarProgram; +LLGLSLShader gDeferredFullbrightShinyProgram; +LLGLSLShader gDeferredSkinnedFullbrightShinyProgram; +LLGLSLShader gDeferredSkinnedFullbrightProgram; +LLGLSLShader gNormalMapGenProgram; // Deferred materials shaders -LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2]; -LLGLSLShader gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2]; +LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2]; +LLGLSLShader gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2]; LLViewerShaderMgr::LLViewerShaderMgr() : mShaderLevel(SHADER_COUNT, 0), @@ -254,7 +250,6 @@ LLViewerShaderMgr::LLViewerShaderMgr() : //ONLY shaders that need WL Param management should be added here mShaderList.push_back(&gWLSkyProgram); mShaderList.push_back(&gWLCloudProgram); - mShaderList.push_back(&gWLCloudShadowProgram); mShaderList.push_back(&gWLSunProgram); mShaderList.push_back(&gWLMoonProgram); mShaderList.push_back(&gAvatarProgram); @@ -335,7 +330,6 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gDeferredAvatarAlphaProgram); mShaderList.push_back(&gDeferredWLSkyProgram); mShaderList.push_back(&gDeferredWLCloudProgram); - mShaderList.push_back(&gDeferredWLCloudShadowProgram); mShaderList.push_back(&gDeferredWLMoonProgram); mShaderList.push_back(&gDeferredWLSunProgram); } @@ -349,32 +343,32 @@ LLViewerShaderMgr::~LLViewerShaderMgr() // static LLViewerShaderMgr * LLViewerShaderMgr::instance() { - if(NULL == sInstance) - { - sInstance = new LLViewerShaderMgr(); - } + if(NULL == sInstance) + { + sInstance = new LLViewerShaderMgr(); + } - return static_cast(sInstance); + return static_cast(sInstance); } // static void LLViewerShaderMgr::releaseInstance() { - if (sInstance != NULL) - { - delete sInstance; - sInstance = NULL; - } + if (sInstance != NULL) + { + delete sInstance; + sInstance = NULL; + } } void LLViewerShaderMgr::initAttribsAndUniforms(void) { - if (mReservedAttribs.empty()) - { - LLShaderMgr::initAttribsAndUniforms(); - } + if (mReservedAttribs.empty()) + { + LLShaderMgr::initAttribsAndUniforms(); + } } - + //============================================================================ // Set Levels @@ -389,76 +383,76 @@ S32 LLViewerShaderMgr::getShaderLevel(S32 type) void LLViewerShaderMgr::setShaders() { - //setShaders might be called redundantly by gSavedSettings, so return on reentrance - static bool reentrance = false; - - if (!gPipeline.mInitialized || !sInitialized || reentrance || sSkipReload) - { - return; - } - - LLGLSLShader::sIndexedTextureChannels = llmax(llmin(gGLManager.mNumTextureImageUnits, (S32) gSavedSettings.getU32("RenderMaxTextureIndex")), 1); - - //NEVER use more than 16 texture channels (work around for prevalent driver bug) - LLGLSLShader::sIndexedTextureChannels = llmin(LLGLSLShader::sIndexedTextureChannels, 16); - - if (gGLManager.mGLSLVersionMajor < 1 || - (gGLManager.mGLSLVersionMajor == 1 && gGLManager.mGLSLVersionMinor <= 20)) - { //NEVER use indexed texture rendering when GLSL version is 1.20 or earlier - LLGLSLShader::sIndexedTextureChannels = 1; - } - - reentrance = true; - - if (LLRender::sGLCoreProfile) - { - if (!gSavedSettings.getBOOL("VertexShaderEnable")) - { //vertex shaders MUST be enabled to use core profile - gSavedSettings.setBOOL("VertexShaderEnable", TRUE); - } - } - - //setup preprocessor definitions - LLShaderMgr::instance()->mDefinitions["NUM_TEX_UNITS"] = llformat("%d", gGLManager.mNumTextureImageUnits); - - // Make sure the compiled shader map is cleared before we recompile shaders. - mShaderObjects.clear(); - - initAttribsAndUniforms(); - gPipeline.releaseGLBuffers(); - - if (gSavedSettings.getBOOL("VertexShaderEnable")) - { - LLPipeline::sWaterReflections = gGLManager.mHasCubeMap; - LLPipeline::sRenderGlow = gSavedSettings.getBOOL("RenderGlow"); - LLPipeline::updateRenderDeferred(); - } - else - { - LLPipeline::sRenderGlow = FALSE; - LLPipeline::sWaterReflections = FALSE; - } - - //hack to reset buffers that change behavior with shaders - gPipeline.resetVertexBuffers(); - - if (gViewerWindow) - { - gViewerWindow->setCursor(UI_CURSOR_WAIT); - } - - // Lighting - gPipeline.setLightingDetail(-1); - - // Shaders - LL_INFOS("ShaderLoading") << "\n~~~~~~~~~~~~~~~~~~\n Loading Shaders:\n~~~~~~~~~~~~~~~~~~" << LL_ENDL; - LL_INFOS("ShaderLoading") << llformat("Using GLSL %d.%d", gGLManager.mGLSLVersionMajor, gGLManager.mGLSLVersionMinor) << LL_ENDL; - - for (S32 i = 0; i < SHADER_COUNT; i++) - { - mShaderLevel[i] = 0; - } - mMaxAvatarShaderLevel = 0; + //setShaders might be called redundantly by gSavedSettings, so return on reentrance + static bool reentrance = false; + + if (!gPipeline.mInitialized || !sInitialized || reentrance || sSkipReload) + { + return; + } + + LLGLSLShader::sIndexedTextureChannels = llmax(llmin(gGLManager.mNumTextureImageUnits, (S32) gSavedSettings.getU32("RenderMaxTextureIndex")), 1); + + //NEVER use more than 16 texture channels (work around for prevalent driver bug) + LLGLSLShader::sIndexedTextureChannels = llmin(LLGLSLShader::sIndexedTextureChannels, 16); + + if (gGLManager.mGLSLVersionMajor < 1 || + (gGLManager.mGLSLVersionMajor == 1 && gGLManager.mGLSLVersionMinor <= 20)) + { //NEVER use indexed texture rendering when GLSL version is 1.20 or earlier + LLGLSLShader::sIndexedTextureChannels = 1; + } + + reentrance = true; + + if (LLRender::sGLCoreProfile) + { + if (!gSavedSettings.getBOOL("VertexShaderEnable")) + { //vertex shaders MUST be enabled to use core profile + gSavedSettings.setBOOL("VertexShaderEnable", TRUE); + } + } + + //setup preprocessor definitions + LLShaderMgr::instance()->mDefinitions["NUM_TEX_UNITS"] = llformat("%d", gGLManager.mNumTextureImageUnits); + + // Make sure the compiled shader map is cleared before we recompile shaders. + mShaderObjects.clear(); + + initAttribsAndUniforms(); + gPipeline.releaseGLBuffers(); + + if (gSavedSettings.getBOOL("VertexShaderEnable")) + { + LLPipeline::sWaterReflections = gGLManager.mHasCubeMap; + LLPipeline::sRenderGlow = gSavedSettings.getBOOL("RenderGlow"); + LLPipeline::updateRenderDeferred(); + } + else + { + LLPipeline::sRenderGlow = FALSE; + LLPipeline::sWaterReflections = FALSE; + } + + //hack to reset buffers that change behavior with shaders + gPipeline.resetVertexBuffers(); + + if (gViewerWindow) + { + gViewerWindow->setCursor(UI_CURSOR_WAIT); + } + + // Lighting + gPipeline.setLightingDetail(-1); + + // Shaders + LL_INFOS("ShaderLoading") << "\n~~~~~~~~~~~~~~~~~~\n Loading Shaders:\n~~~~~~~~~~~~~~~~~~" << LL_ENDL; + LL_INFOS("ShaderLoading") << llformat("Using GLSL %d.%d", gGLManager.mGLSLVersionMajor, gGLManager.mGLSLVersionMinor) << LL_ENDL; + + for (S32 i = 0; i < SHADER_COUNT; i++) + { + mShaderLevel[i] = 0; + } + mMaxAvatarShaderLevel = 0; LLGLSLShader::sNoFixedFunction = false; LLVertexBuffer::unbind(); @@ -762,122 +756,119 @@ void LLViewerShaderMgr::setShaders() void LLViewerShaderMgr::unloadShaders() { - gOcclusionProgram.unload(); - gOcclusionCubeProgram.unload(); - gDebugProgram.unload(); - gClipProgram.unload(); - gDownsampleDepthProgram.unload(); - gDownsampleDepthRectProgram.unload(); - gDownsampleMinMaxDepthRectProgram.unload(); - gInscatterRectProgram.unload(); - gBenchmarkProgram.unload(); - gAlphaMaskProgram.unload(); - gUIProgram.unload(); - gPathfindingProgram.unload(); - gPathfindingNoNormalsProgram.unload(); - gCustomAlphaProgram.unload(); - gGlowCombineProgram.unload(); - gSplatTextureRectProgram.unload(); - gGlowCombineFXAAProgram.unload(); - gTwoTextureAddProgram.unload(); - gTwoTextureCompareProgram.unload(); - gOneTextureFilterProgram.unload(); - gOneTextureNoColorProgram.unload(); - gSolidColorProgram.unload(); - - gObjectFullbrightNoColorProgram.unload(); - gObjectFullbrightNoColorWaterProgram.unload(); - gObjectSimpleProgram.unload(); - gObjectSimpleImpostorProgram.unload(); - gObjectPreviewProgram.unload(); - gImpostorProgram.unload(); - gObjectSimpleAlphaMaskProgram.unload(); - gObjectBumpProgram.unload(); - gObjectSimpleWaterProgram.unload(); - gObjectSimpleWaterAlphaMaskProgram.unload(); - gObjectFullbrightProgram.unload(); - gObjectFullbrightWaterProgram.unload(); - gObjectEmissiveProgram.unload(); - gObjectEmissiveWaterProgram.unload(); - gObjectFullbrightAlphaMaskProgram.unload(); - gObjectFullbrightWaterAlphaMaskProgram.unload(); - - gObjectShinyProgram.unload(); - gObjectFullbrightShinyProgram.unload(); - gObjectFullbrightShinyWaterProgram.unload(); - gObjectShinyWaterProgram.unload(); - - gObjectSimpleNonIndexedProgram.unload(); - gObjectSimpleNonIndexedTexGenProgram.unload(); - gObjectSimpleNonIndexedTexGenWaterProgram.unload(); - gObjectSimpleNonIndexedWaterProgram.unload(); - gObjectAlphaMaskNonIndexedProgram.unload(); - gObjectAlphaMaskNonIndexedWaterProgram.unload(); - gObjectAlphaMaskNoColorProgram.unload(); - gObjectAlphaMaskNoColorWaterProgram.unload(); - gObjectFullbrightNonIndexedProgram.unload(); - gObjectFullbrightNonIndexedWaterProgram.unload(); - gObjectEmissiveNonIndexedProgram.unload(); - gObjectEmissiveNonIndexedWaterProgram.unload(); - gTreeProgram.unload(); - gTreeWaterProgram.unload(); - - gObjectShinyNonIndexedProgram.unload(); - gObjectFullbrightShinyNonIndexedProgram.unload(); - gObjectFullbrightShinyNonIndexedWaterProgram.unload(); - gObjectShinyNonIndexedWaterProgram.unload(); - - gSkinnedObjectSimpleProgram.unload(); - gSkinnedObjectFullbrightProgram.unload(); - gSkinnedObjectEmissiveProgram.unload(); - gSkinnedObjectFullbrightShinyProgram.unload(); - gSkinnedObjectShinySimpleProgram.unload(); - - gSkinnedObjectSimpleWaterProgram.unload(); - gSkinnedObjectFullbrightWaterProgram.unload(); - gSkinnedObjectEmissiveWaterProgram.unload(); - gSkinnedObjectFullbrightShinyWaterProgram.unload(); - gSkinnedObjectShinySimpleWaterProgram.unload(); - - - gWaterProgram.unload(); + gOcclusionProgram.unload(); + gOcclusionCubeProgram.unload(); + gDebugProgram.unload(); + gClipProgram.unload(); + gDownsampleDepthProgram.unload(); + gDownsampleDepthRectProgram.unload(); + gBenchmarkProgram.unload(); + gAlphaMaskProgram.unload(); + gUIProgram.unload(); + gPathfindingProgram.unload(); + gPathfindingNoNormalsProgram.unload(); + gCustomAlphaProgram.unload(); + gGlowCombineProgram.unload(); + gSplatTextureRectProgram.unload(); + gGlowCombineFXAAProgram.unload(); + gTwoTextureAddProgram.unload(); + gTwoTextureCompareProgram.unload(); + gOneTextureFilterProgram.unload(); + gOneTextureNoColorProgram.unload(); + gSolidColorProgram.unload(); + + gObjectFullbrightNoColorProgram.unload(); + gObjectFullbrightNoColorWaterProgram.unload(); + gObjectSimpleProgram.unload(); + gObjectSimpleImpostorProgram.unload(); + gObjectPreviewProgram.unload(); + gImpostorProgram.unload(); + gObjectSimpleAlphaMaskProgram.unload(); + gObjectBumpProgram.unload(); + gObjectSimpleWaterProgram.unload(); + gObjectSimpleWaterAlphaMaskProgram.unload(); + gObjectFullbrightProgram.unload(); + gObjectFullbrightWaterProgram.unload(); + gObjectEmissiveProgram.unload(); + gObjectEmissiveWaterProgram.unload(); + gObjectFullbrightAlphaMaskProgram.unload(); + gObjectFullbrightWaterAlphaMaskProgram.unload(); + + gObjectShinyProgram.unload(); + gObjectFullbrightShinyProgram.unload(); + gObjectFullbrightShinyWaterProgram.unload(); + gObjectShinyWaterProgram.unload(); + + gObjectSimpleNonIndexedProgram.unload(); + gObjectSimpleNonIndexedTexGenProgram.unload(); + gObjectSimpleNonIndexedTexGenWaterProgram.unload(); + gObjectSimpleNonIndexedWaterProgram.unload(); + gObjectAlphaMaskNonIndexedProgram.unload(); + gObjectAlphaMaskNonIndexedWaterProgram.unload(); + gObjectAlphaMaskNoColorProgram.unload(); + gObjectAlphaMaskNoColorWaterProgram.unload(); + gObjectFullbrightNonIndexedProgram.unload(); + gObjectFullbrightNonIndexedWaterProgram.unload(); + gObjectEmissiveNonIndexedProgram.unload(); + gObjectEmissiveNonIndexedWaterProgram.unload(); + gTreeProgram.unload(); + gTreeWaterProgram.unload(); + + gObjectShinyNonIndexedProgram.unload(); + gObjectFullbrightShinyNonIndexedProgram.unload(); + gObjectFullbrightShinyNonIndexedWaterProgram.unload(); + gObjectShinyNonIndexedWaterProgram.unload(); + + gSkinnedObjectSimpleProgram.unload(); + gSkinnedObjectFullbrightProgram.unload(); + gSkinnedObjectEmissiveProgram.unload(); + gSkinnedObjectFullbrightShinyProgram.unload(); + gSkinnedObjectShinySimpleProgram.unload(); + + gSkinnedObjectSimpleWaterProgram.unload(); + gSkinnedObjectFullbrightWaterProgram.unload(); + gSkinnedObjectEmissiveWaterProgram.unload(); + gSkinnedObjectFullbrightShinyWaterProgram.unload(); + gSkinnedObjectShinySimpleWaterProgram.unload(); + + + gWaterProgram.unload(); gWaterEdgeProgram.unload(); - gUnderWaterProgram.unload(); - gTerrainProgram.unload(); - gTerrainWaterProgram.unload(); - gGlowProgram.unload(); - gGlowExtractProgram.unload(); - gAvatarProgram.unload(); - gAvatarWaterProgram.unload(); - gAvatarEyeballProgram.unload(); - gAvatarPickProgram.unload(); - gHighlightProgram.unload(); - gHighlightNormalProgram.unload(); - gHighlightSpecularProgram.unload(); - - gWLSkyProgram.unload(); - gWLCloudProgram.unload(); - gWLCloudShadowProgram.unload(); + gUnderWaterProgram.unload(); + gTerrainProgram.unload(); + gTerrainWaterProgram.unload(); + gGlowProgram.unload(); + gGlowExtractProgram.unload(); + gAvatarProgram.unload(); + gAvatarWaterProgram.unload(); + gAvatarEyeballProgram.unload(); + gAvatarPickProgram.unload(); + gHighlightProgram.unload(); + gHighlightNormalProgram.unload(); + gHighlightSpecularProgram.unload(); + + gWLSkyProgram.unload(); + gWLCloudProgram.unload(); gWLSunProgram.unload(); gWLMoonProgram.unload(); - gPostColorFilterProgram.unload(); - gPostNightVisionProgram.unload(); + gPostColorFilterProgram.unload(); + gPostNightVisionProgram.unload(); - gDeferredDiffuseProgram.unload(); - gDeferredDiffuseAlphaMaskProgram.unload(); - gDeferredNonIndexedDiffuseAlphaMaskProgram.unload(); - gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.unload(); - gDeferredNonIndexedDiffuseProgram.unload(); - gDeferredSkinnedDiffuseProgram.unload(); - gDeferredSkinnedBumpProgram.unload(); - gDeferredSkinnedAlphaProgram.unload(); + gDeferredDiffuseProgram.unload(); + gDeferredDiffuseAlphaMaskProgram.unload(); + gDeferredNonIndexedDiffuseAlphaMaskProgram.unload(); + gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.unload(); + gDeferredNonIndexedDiffuseProgram.unload(); + gDeferredSkinnedDiffuseProgram.unload(); + gDeferredSkinnedBumpProgram.unload(); + gDeferredSkinnedAlphaProgram.unload(); - gTransformPositionProgram.unload(); - gTransformTexCoordProgram.unload(); - gTransformNormalProgram.unload(); - gTransformColorProgram.unload(); - gTransformTangentProgram.unload(); + gTransformPositionProgram.unload(); + gTransformTexCoordProgram.unload(); + gTransformNormalProgram.unload(); + gTransformColorProgram.unload(); + gTransformTangentProgram.unload(); mShaderLevel[SHADER_LIGHTING] = 0; mShaderLevel[SHADER_OBJECT] = 0; @@ -889,45 +880,45 @@ void LLViewerShaderMgr::unloadShaders() mShaderLevel[SHADER_WINDLIGHT] = 0; mShaderLevel[SHADER_TRANSFORM] = 0; - gPipeline.mVertexShadersLoaded = 0; + gPipeline.mVertexShadersLoaded = 0; } BOOL LLViewerShaderMgr::loadBasicShaders() { - // Load basic dependency shaders first - // All of these have to load for any shaders to function - - S32 sum_lights_class = 3; - - // class one cards will get the lower sum lights - // class zero we're not going to think about - // since a class zero card COULD be a ridiculous new card - // and old cards should have the features masked - if(LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_1) - { - sum_lights_class = 2; - } - - // If we have sun and moon only checked, then only sum those lights. - if (gPipeline.getLightingDetail() == 0) - { - sum_lights_class = 1; - } + // Load basic dependency shaders first + // All of these have to load for any shaders to function + + S32 sum_lights_class = 3; + + // class one cards will get the lower sum lights + // class zero we're not going to think about + // since a class zero card COULD be a ridiculous new card + // and old cards should have the features masked + if(LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_1) + { + sum_lights_class = 2; + } + + // If we have sun and moon only checked, then only sum those lights. + if (gPipeline.getLightingDetail() == 0) + { + sum_lights_class = 1; + } #if LL_DARWIN - // Work around driver crashes on older Macs when using deferred rendering - // NORSPEC-59 - // - if (gGLManager.mIsMobileGF) - sum_lights_class = 3; + // Work around driver crashes on older Macs when using deferred rendering + // NORSPEC-59 + // + if (gGLManager.mIsMobileGF) + sum_lights_class = 3; #endif - - // Use the feature table to mask out the max light level to use. Also make sure it's at least 1. - S32 max_light_class = gSavedSettings.getS32("RenderShaderLightingMaxLevel"); - sum_lights_class = llclamp(sum_lights_class, 1, max_light_class); + + // Use the feature table to mask out the max light level to use. Also make sure it's at least 1. + S32 max_light_class = gSavedSettings.getS32("RenderShaderLightingMaxLevel"); + sum_lights_class = llclamp(sum_lights_class, 1, max_light_class); - // Load the Basic Vertex Shaders at the appropriate level. - // (in order of shader function call depth for reference purposes, deepest level first) + // Load the Basic Vertex Shaders at the appropriate level. + // (in order of shader function call depth for reference purposes, deepest level first) vector< pair > shaders; shaders.push_back( make_pair( "windlight/atmosphericsVarsV.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); @@ -948,9 +939,9 @@ BOOL LLViewerShaderMgr::loadBasicShaders() } shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) ); - boost::unordered_map attribs; - attribs["MAX_JOINTS_PER_MESH_OBJECT"] = - boost::lexical_cast(LLSkinningUtil::getMaxJointCount()); + boost::unordered_map attribs; + attribs["MAX_JOINTS_PER_MESH_OBJECT"] = + boost::lexical_cast(LLSkinningUtil::getMaxJointCount()); // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. for (U32 i = 0; i < shaders.size(); i++) @@ -963,16 +954,16 @@ BOOL LLViewerShaderMgr::loadBasicShaders() } } - // Load the Basic Fragment Shaders at the appropriate level. - // (in order of shader function call depth for reference purposes, deepest level first) + // Load the Basic Fragment Shaders at the appropriate level. + // (in order of shader function call depth for reference purposes, deepest level first) - shaders.clear(); - S32 ch = 1; + shaders.clear(); + S32 ch = 1; - if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) - { //use indexed texture rendering for GLSL >= 1.30 - ch = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); - } + if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) + { //use indexed texture rendering for GLSL >= 1.30 + ch = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); + } std::vector index_channels; index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); @@ -1022,18 +1013,18 @@ BOOL LLViewerShaderMgr::loadBasicShaders() } } - return TRUE; + return TRUE; } BOOL LLViewerShaderMgr::loadShadersEnvironment() { - BOOL success = TRUE; + BOOL success = TRUE; - if (mShaderLevel[SHADER_ENVIRONMENT] == 0) - { - gTerrainProgram.unload(); - return TRUE; - } + if (mShaderLevel[SHADER_ENVIRONMENT] == 0) + { + gTerrainProgram.unload(); + return TRUE; + } if (success) { @@ -1055,50 +1046,50 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment() llassert(success); } - if (!success) - { - mShaderLevel[SHADER_ENVIRONMENT] = 0; - return FALSE; - } - - LLWorld::getInstance()->updateWaterObjects(); - - return TRUE; + if (!success) + { + mShaderLevel[SHADER_ENVIRONMENT] = 0; + return FALSE; + } + + LLWorld::getInstance()->updateWaterObjects(); + + return TRUE; } BOOL LLViewerShaderMgr::loadShadersWater() { - BOOL success = TRUE; - BOOL terrainWaterSuccess = TRUE; - - if (mShaderLevel[SHADER_WATER] == 0) - { - gWaterProgram.unload(); - gWaterEdgeProgram.unload(); - gUnderWaterProgram.unload(); - gTerrainWaterProgram.unload(); - return TRUE; - } - - if (success) - { - // load water shader - gWaterProgram.mName = "Water Shader"; - gWaterProgram.mFeatures.calculatesAtmospherics = true; - gWaterProgram.mFeatures.hasGamma = true; - gWaterProgram.mFeatures.hasTransport = true; - gWaterProgram.mShaderFiles.clear(); - gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB)); - gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER_ARB)); + BOOL success = TRUE; + BOOL terrainWaterSuccess = TRUE; + + if (mShaderLevel[SHADER_WATER] == 0) + { + gWaterProgram.unload(); + gWaterEdgeProgram.unload(); + gUnderWaterProgram.unload(); + gTerrainWaterProgram.unload(); + return TRUE; + } + + if (success) + { + // load water shader + gWaterProgram.mName = "Water Shader"; + gWaterProgram.mFeatures.calculatesAtmospherics = true; + gWaterProgram.mFeatures.hasGamma = true; + gWaterProgram.mFeatures.hasTransport = true; + gWaterProgram.mShaderFiles.clear(); + gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB)); + gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER_ARB)); gWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gWaterProgram.mShaderLevel = mShaderLevel[SHADER_WATER]; + gWaterProgram.mShaderLevel = mShaderLevel[SHADER_WATER]; success = gWaterProgram.createShader(NULL, NULL); - llassert(success); - } + llassert(success); + } - if (success) - { - // load water shader + if (success) + { + // load water shader gWaterEdgeProgram.mName = "Water Edge Shader"; gWaterEdgeProgram.mFeatures.calculatesAtmospherics = true; gWaterEdgeProgram.mFeatures.hasGamma = true; @@ -1111,10 +1102,10 @@ BOOL LLViewerShaderMgr::loadShadersWater() gWaterEdgeProgram.mShaderLevel = mShaderLevel[SHADER_WATER]; success = gWaterEdgeProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { + if (success) + { //load under water vertex shader gUnderWaterProgram.mName = "Underwater Shader"; gUnderWaterProgram.mFeatures.calculatesAtmospherics = true; @@ -1186,35 +1177,35 @@ BOOL LLViewerShaderMgr::loadShadersEffects() return TRUE; } - if (success) - { - gGlowProgram.mName = "Glow Shader (Post)"; - gGlowProgram.mShaderFiles.clear(); - gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowV.glsl", GL_VERTEX_SHADER_ARB)); - gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowF.glsl", GL_FRAGMENT_SHADER_ARB)); - gGlowProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT]; - success = gGlowProgram.createShader(NULL, NULL); - if (!success) - { - LLPipeline::sRenderGlow = FALSE; - } - } - - if (success) - { - gGlowExtractProgram.mName = "Glow Extract Shader (Post)"; - gGlowExtractProgram.mShaderFiles.clear(); - gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractV.glsl", GL_VERTEX_SHADER_ARB)); - gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractF.glsl", GL_FRAGMENT_SHADER_ARB)); - gGlowExtractProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT]; - success = gGlowExtractProgram.createShader(NULL, NULL); - if (!success) - { - LLPipeline::sRenderGlow = FALSE; - } - } - - return success; + if (success) + { + gGlowProgram.mName = "Glow Shader (Post)"; + gGlowProgram.mShaderFiles.clear(); + gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowV.glsl", GL_VERTEX_SHADER_ARB)); + gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowF.glsl", GL_FRAGMENT_SHADER_ARB)); + gGlowProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT]; + success = gGlowProgram.createShader(NULL, NULL); + if (!success) + { + LLPipeline::sRenderGlow = FALSE; + } + } + + if (success) + { + gGlowExtractProgram.mName = "Glow Extract Shader (Post)"; + gGlowExtractProgram.mShaderFiles.clear(); + gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractV.glsl", GL_VERTEX_SHADER_ARB)); + gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractF.glsl", GL_FRAGMENT_SHADER_ARB)); + gGlowExtractProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT]; + success = gGlowExtractProgram.createShader(NULL, NULL); + if (!success) + { + LLPipeline::sRenderGlow = FALSE; + } + } + + return success; } @@ -1222,116 +1213,113 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { bool use_sun_shadow = mShaderLevel[SHADER_DEFERRED] > 1; - if (mShaderLevel[SHADER_DEFERRED] == 0) - { - gDeferredTreeProgram.unload(); - gDeferredTreeShadowProgram.unload(); - gDeferredDiffuseProgram.unload(); - gDeferredDiffuseAlphaMaskProgram.unload(); - gDeferredNonIndexedDiffuseAlphaMaskProgram.unload(); - gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.unload(); - gDeferredNonIndexedDiffuseProgram.unload(); - gDeferredSkinnedDiffuseProgram.unload(); - gDeferredSkinnedBumpProgram.unload(); - gDeferredSkinnedAlphaProgram.unload(); - gDeferredBumpProgram.unload(); - gDeferredImpostorProgram.unload(); - gDeferredTerrainProgram.unload(); - gDeferredTerrainWaterProgram.unload(); - gDeferredLightProgram.unload(); - for (U32 i = 0; i < LL_DEFERRED_MULTI_LIGHT_COUNT; ++i) - { - gDeferredMultiLightProgram[i].unload(); - } - gDeferredSpotLightProgram.unload(); - gDeferredMultiSpotLightProgram.unload(); - gDeferredSunProgram.unload(); - gDeferredBlurLightProgram.unload(); - gDeferredSoftenProgram.unload(); - gDeferredSoftenWaterProgram.unload(); - gDeferredShadowProgram.unload(); - gDeferredShadowCubeProgram.unload(); - gDeferredShadowAlphaMaskProgram.unload(); - gDeferredAvatarShadowProgram.unload(); - gDeferredAttachmentShadowProgram.unload(); - gDeferredAvatarProgram.unload(); - gDeferredAvatarAlphaProgram.unload(); - gDeferredAlphaProgram.unload(); - gDeferredAlphaWaterProgram.unload(); - gDeferredFullbrightProgram.unload(); - gDeferredFullbrightAlphaMaskProgram.unload(); - gDeferredFullbrightWaterProgram.unload(); - gDeferredFullbrightAlphaMaskWaterProgram.unload(); - gDeferredEmissiveProgram.unload(); - gDeferredAvatarEyesProgram.unload(); - gDeferredPostProgram.unload(); - gDeferredCoFProgram.unload(); - gDeferredDoFCombineProgram.unload(); - gDeferredPostGammaCorrectProgram.unload(); - gFXAAProgram.unload(); - gDeferredWaterProgram.unload(); - gDeferredUnderWaterProgram.unload(); - gDeferredWLSkyProgram.unload(); - gDeferredWLCloudProgram.unload(); - gDeferredWLCloudShadowProgram.unload(); + if (mShaderLevel[SHADER_DEFERRED] == 0) + { + gDeferredTreeProgram.unload(); + gDeferredTreeShadowProgram.unload(); + gDeferredDiffuseProgram.unload(); + gDeferredDiffuseAlphaMaskProgram.unload(); + gDeferredNonIndexedDiffuseAlphaMaskProgram.unload(); + gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.unload(); + gDeferredNonIndexedDiffuseProgram.unload(); + gDeferredSkinnedDiffuseProgram.unload(); + gDeferredSkinnedBumpProgram.unload(); + gDeferredSkinnedAlphaProgram.unload(); + gDeferredBumpProgram.unload(); + gDeferredImpostorProgram.unload(); + gDeferredTerrainProgram.unload(); + gDeferredTerrainWaterProgram.unload(); + gDeferredLightProgram.unload(); + for (U32 i = 0; i < LL_DEFERRED_MULTI_LIGHT_COUNT; ++i) + { + gDeferredMultiLightProgram[i].unload(); + } + gDeferredSpotLightProgram.unload(); + gDeferredMultiSpotLightProgram.unload(); + gDeferredSunProgram.unload(); + gDeferredBlurLightProgram.unload(); + gDeferredSoftenProgram.unload(); + gDeferredSoftenWaterProgram.unload(); + gDeferredShadowProgram.unload(); + gDeferredShadowCubeProgram.unload(); + gDeferredShadowAlphaMaskProgram.unload(); + gDeferredAvatarShadowProgram.unload(); + gDeferredAttachmentShadowProgram.unload(); + gDeferredAvatarProgram.unload(); + gDeferredAvatarAlphaProgram.unload(); + gDeferredAlphaProgram.unload(); + gDeferredAlphaWaterProgram.unload(); + gDeferredFullbrightProgram.unload(); + gDeferredFullbrightAlphaMaskProgram.unload(); + gDeferredFullbrightWaterProgram.unload(); + gDeferredFullbrightAlphaMaskWaterProgram.unload(); + gDeferredEmissiveProgram.unload(); + gDeferredAvatarEyesProgram.unload(); + gDeferredPostProgram.unload(); + gDeferredCoFProgram.unload(); + gDeferredDoFCombineProgram.unload(); + gDeferredPostGammaCorrectProgram.unload(); + gFXAAProgram.unload(); + gDeferredWaterProgram.unload(); + gDeferredUnderWaterProgram.unload(); + gDeferredWLSkyProgram.unload(); + gDeferredWLCloudProgram.unload(); gDeferredWLSunProgram.unload(); gDeferredWLMoonProgram.unload(); - gDeferredStarProgram.unload(); - gDeferredFullbrightShinyProgram.unload(); - gDeferredSkinnedFullbrightShinyProgram.unload(); - gDeferredSkinnedFullbrightProgram.unload(); - - gNormalMapGenProgram.unload(); - for (U32 i = 0; i < LLMaterial::SHADER_COUNT*2; ++i) - { - gDeferredMaterialProgram[i].unload(); - gDeferredMaterialWaterProgram[i].unload(); - } - return TRUE; - } - - BOOL success = TRUE; - - if (success) - { - gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader"; + gDeferredStarProgram.unload(); + gDeferredFullbrightShinyProgram.unload(); + gDeferredSkinnedFullbrightShinyProgram.unload(); + gDeferredSkinnedFullbrightProgram.unload(); + + gNormalMapGenProgram.unload(); + for (U32 i = 0; i < LLMaterial::SHADER_COUNT*2; ++i) + { + gDeferredMaterialProgram[i].unload(); + gDeferredMaterialWaterProgram[i].unload(); + } + return TRUE; + } + + BOOL success = TRUE; + + if (success) + { + gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader"; gDeferredDiffuseProgram.mFeatures.encodesNormal = true; - gDeferredDiffuseProgram.mShaderFiles.clear(); - gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredDiffuseProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - gDeferredDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredDiffuseProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Alpha Mask Shader"; + gDeferredDiffuseProgram.mShaderFiles.clear(); + gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredDiffuseProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + gDeferredDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredDiffuseProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Alpha Mask Shader"; gDeferredDiffuseAlphaMaskProgram.mFeatures.encodesNormal = true; - gDeferredDiffuseAlphaMaskProgram.mShaderFiles.clear(); - gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredDiffuseAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredDiffuseAlphaMaskProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredNonIndexedDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader"; - gDeferredNonIndexedDiffuseAlphaMaskProgram.mFeatures.encodesNormal = true; - gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.clear(); - gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredNonIndexedDiffuseAlphaMaskProgram.createShader(NULL, NULL); + gDeferredDiffuseAlphaMaskProgram.mShaderFiles.clear(); + gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredDiffuseAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredDiffuseAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredNonIndexedDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader"; + gDeferredNonIndexedDiffuseAlphaMaskProgram.mFeatures.encodesNormal = true; + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.clear(); + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredNonIndexedDiffuseAlphaMaskProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { + if (success) + { gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader"; gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mFeatures.encodesNormal = true; gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.clear(); @@ -1340,22 +1328,22 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { - gDeferredNonIndexedDiffuseProgram.mName = "Non Indexed Deferred Diffuse Shader"; + if (success) + { + gDeferredNonIndexedDiffuseProgram.mName = "Non Indexed Deferred Diffuse Shader"; + gDeferredNonIndexedDiffuseProgram.mShaderFiles.clear(); gDeferredNonIndexedDiffuseProgram.mFeatures.encodesNormal = true; - gDeferredNonIndexedDiffuseProgram.mShaderFiles.clear(); - gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredNonIndexedDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredNonIndexedDiffuseProgram.createShader(NULL, NULL); + gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredNonIndexedDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredNonIndexedDiffuseProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { + if (success) + { gDeferredSkinnedDiffuseProgram.mName = "Deferred Skinned Diffuse Shader"; gDeferredSkinnedDiffuseProgram.mFeatures.hasObjectSkinning = true; gDeferredSkinnedDiffuseProgram.mFeatures.encodesNormal = true; @@ -1365,23 +1353,23 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSkinnedDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredSkinnedDiffuseProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { - gDeferredSkinnedBumpProgram.mName = "Deferred Skinned Bump Shader"; - gDeferredSkinnedBumpProgram.mFeatures.hasObjectSkinning = true; + if (success) + { + gDeferredSkinnedBumpProgram.mName = "Deferred Skinned Bump Shader"; + gDeferredSkinnedBumpProgram.mFeatures.hasObjectSkinning = true; gDeferredSkinnedBumpProgram.mFeatures.encodesNormal = true; - gDeferredSkinnedBumpProgram.mShaderFiles.clear(); - gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSkinnedBumpProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredSkinnedBumpProgram.createShader(NULL, NULL); + gDeferredSkinnedBumpProgram.mShaderFiles.clear(); + gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSkinnedBumpProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredSkinnedBumpProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { + if (success) + { gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader"; gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true; gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = false; @@ -1415,10 +1403,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() // Hack to include uniforms for lighting without linking in lighting file gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true; gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true; - } + } - if (success) - { + if (success) + { gDeferredBumpProgram.mName = "Deferred Bump Shader"; gDeferredBumpProgram.mFeatures.encodesNormal = true; gDeferredBumpProgram.mShaderFiles.clear(); @@ -1429,28 +1417,28 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() llassert(success); } - gDeferredMaterialProgram[1].mFeatures.hasLighting = false; - gDeferredMaterialProgram[5].mFeatures.hasLighting = false; - gDeferredMaterialProgram[9].mFeatures.hasLighting = false; - gDeferredMaterialProgram[13].mFeatures.hasLighting = false; - gDeferredMaterialProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; - gDeferredMaterialProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; - gDeferredMaterialProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; - gDeferredMaterialProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; - - gDeferredMaterialWaterProgram[1].mFeatures.hasLighting = false; - gDeferredMaterialWaterProgram[5].mFeatures.hasLighting = false; - gDeferredMaterialWaterProgram[9].mFeatures.hasLighting = false; - gDeferredMaterialWaterProgram[13].mFeatures.hasLighting = false; - gDeferredMaterialWaterProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; - gDeferredMaterialWaterProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; - gDeferredMaterialWaterProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; - gDeferredMaterialWaterProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; - - for (U32 i = 0; i < LLMaterial::SHADER_COUNT*2; ++i) - { - if (success) - { + gDeferredMaterialProgram[1].mFeatures.hasLighting = false; + gDeferredMaterialProgram[5].mFeatures.hasLighting = false; + gDeferredMaterialProgram[9].mFeatures.hasLighting = false; + gDeferredMaterialProgram[13].mFeatures.hasLighting = false; + gDeferredMaterialProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + + gDeferredMaterialWaterProgram[1].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[5].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[9].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[13].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialWaterProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + + for (U32 i = 0; i < LLMaterial::SHADER_COUNT*2; ++i) + { + if (success) + { mShaderList.push_back(&gDeferredMaterialProgram[i]); gDeferredMaterialProgram[i].mName = llformat("Deferred Material Shader %d", i); @@ -1501,10 +1489,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredMaterialProgram[i].createShader(NULL, NULL); llassert(success); - } + } - if (success) - { + if (success) + { mShaderList.push_back(&gDeferredMaterialWaterProgram[i]); gDeferredMaterialWaterProgram[i].mName = llformat("Deferred Underwater Material Shader %d", i); @@ -1562,136 +1550,135 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredMaterialWaterProgram[i].createShader(NULL, NULL);//&mWLUniforms); llassert(success); - } - } - - gDeferredMaterialProgram[1].mFeatures.hasLighting = true; - gDeferredMaterialProgram[5].mFeatures.hasLighting = true; - gDeferredMaterialProgram[9].mFeatures.hasLighting = true; - gDeferredMaterialProgram[13].mFeatures.hasLighting = true; - gDeferredMaterialProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; - gDeferredMaterialProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; - gDeferredMaterialProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; - gDeferredMaterialProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; - - gDeferredMaterialWaterProgram[1].mFeatures.hasLighting = true; - gDeferredMaterialWaterProgram[5].mFeatures.hasLighting = true; - gDeferredMaterialWaterProgram[9].mFeatures.hasLighting = true; - gDeferredMaterialWaterProgram[13].mFeatures.hasLighting = true; - gDeferredMaterialWaterProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; - gDeferredMaterialWaterProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; - gDeferredMaterialWaterProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; - gDeferredMaterialWaterProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; - - - if (success) - { - gDeferredTreeProgram.mName = "Deferred Tree Shader"; - gDeferredTreeProgram.mShaderFiles.clear(); + } + } + + gDeferredMaterialProgram[1].mFeatures.hasLighting = true; + gDeferredMaterialProgram[5].mFeatures.hasLighting = true; + gDeferredMaterialProgram[9].mFeatures.hasLighting = true; + gDeferredMaterialProgram[13].mFeatures.hasLighting = true; + gDeferredMaterialProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + + gDeferredMaterialWaterProgram[1].mFeatures.hasLighting = true; + gDeferredMaterialWaterProgram[5].mFeatures.hasLighting = true; + gDeferredMaterialWaterProgram[9].mFeatures.hasLighting = true; + gDeferredMaterialWaterProgram[13].mFeatures.hasLighting = true; + gDeferredMaterialWaterProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialWaterProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialWaterProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialWaterProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + + + if (success) + { + gDeferredTreeProgram.mName = "Deferred Tree Shader"; + gDeferredTreeProgram.mShaderFiles.clear(); gDeferredTreeProgram.mFeatures.encodesNormal = true; - gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredTreeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredTreeProgram.createShader(NULL, NULL); + gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredTreeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredTreeProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredTreeShadowProgram.mName = "Deferred Tree Shadow Shader"; + gDeferredTreeShadowProgram.mShaderFiles.clear(); + gDeferredTreeShadowProgram.mFeatures.isDeferred = true; + gDeferredTreeShadowProgram.mFeatures.hasShadows = true; + gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredTreeShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredTreeShadowProgram.createShader(NULL, NULL); llassert(success); - } - - if (success) - { - gDeferredTreeShadowProgram.mName = "Deferred Tree Shadow Shader"; - gDeferredTreeShadowProgram.mShaderFiles.clear(); - gDeferredTreeShadowProgram.mFeatures.isDeferred = true; - gDeferredTreeShadowProgram.mFeatures.hasShadows = true; - gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredTreeShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredTreeShadowProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredImpostorProgram.mName = "Deferred Impostor Shader"; - gDeferredImpostorProgram.mFeatures.hasSrgb = true; - gDeferredImpostorProgram.mFeatures.encodesNormal = true; - //gDeferredImpostorProgram.mFeatures.isDeferred = true; - gDeferredImpostorProgram.mShaderFiles.clear(); - gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorV.glsl", GL_VERTEX_SHADER_ARB)); + } + + if (success) + { + gDeferredImpostorProgram.mName = "Deferred Impostor Shader"; + gDeferredImpostorProgram.mFeatures.hasSrgb = true; + gDeferredImpostorProgram.mFeatures.encodesNormal = true; + //gDeferredImpostorProgram.mFeatures.isDeferred = true; + gDeferredImpostorProgram.mShaderFiles.clear(); + gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredImpostorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredImpostorProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { - gDeferredLightProgram.mName = "Deferred Light Shader"; - gDeferredLightProgram.mFeatures.isDeferred = true; - gDeferredLightProgram.mFeatures.hasShadows = true; + if (success) + { + gDeferredLightProgram.mName = "Deferred Light Shader"; + gDeferredLightProgram.mFeatures.isDeferred = true; + gDeferredLightProgram.mFeatures.hasShadows = true; - gDeferredLightProgram.mShaderFiles.clear(); - gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredLightProgram.mShaderFiles.clear(); + gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredLightProgram.createShader(NULL, NULL); + success = gDeferredLightProgram.createShader(NULL, NULL); llassert(success); - } - - for (U32 i = 0; i < LL_DEFERRED_MULTI_LIGHT_COUNT; i++) - { - if (success) - { - gDeferredMultiLightProgram[i].mName = llformat("Deferred MultiLight Shader %d", i); - gDeferredMultiLightProgram[i].mFeatures.isDeferred = true; - gDeferredMultiLightProgram[i].mFeatures.hasShadows = true; - - gDeferredMultiLightProgram[i].mShaderFiles.clear(); - gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredMultiLightProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - gDeferredMultiLightProgram[i].addPermutation("LIGHT_COUNT", llformat("%d", i+1)); - success = gDeferredMultiLightProgram[i].createShader(NULL, NULL); + } + + for (U32 i = 0; i < LL_DEFERRED_MULTI_LIGHT_COUNT; i++) + { + if (success) + { + gDeferredMultiLightProgram[i].mName = llformat("Deferred MultiLight Shader %d", i); + gDeferredMultiLightProgram[i].mFeatures.isDeferred = true; + gDeferredMultiLightProgram[i].mFeatures.hasShadows = true; + + gDeferredMultiLightProgram[i].mShaderFiles.clear(); + gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredMultiLightProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredMultiLightProgram[i].addPermutation("LIGHT_COUNT", llformat("%d", i+1)); + success = gDeferredMultiLightProgram[i].createShader(NULL, NULL); llassert(success); - } - } - - if (success) - { - gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader"; - gDeferredSpotLightProgram.mShaderFiles.clear(); - gDeferredSpotLightProgram.mFeatures.hasSrgb = true; - gDeferredSpotLightProgram.mFeatures.isDeferred = true; - gDeferredSpotLightProgram.mFeatures.hasShadows = true; - - gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/spotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - - success = gDeferredSpotLightProgram.createShader(NULL, NULL); + } + } + + if (success) + { + gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader"; + gDeferredSpotLightProgram.mShaderFiles.clear(); + gDeferredSpotLightProgram.mFeatures.hasSrgb = true; + gDeferredSpotLightProgram.mFeatures.isDeferred = true; + gDeferredSpotLightProgram.mFeatures.hasShadows = true; + + gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/spotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + + success = gDeferredSpotLightProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { - gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader"; - gDeferredMultiSpotLightProgram.mFeatures.hasSrgb = true; - gDeferredMultiSpotLightProgram.mFeatures.isDeferred = true; - gDeferredMultiSpotLightProgram.mFeatures.hasShadows = true; + if (success) + { + gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader"; + gDeferredMultiSpotLightProgram.mFeatures.hasSrgb = true; + gDeferredMultiSpotLightProgram.mFeatures.isDeferred = true; + gDeferredMultiSpotLightProgram.mFeatures.hasShadows = true; - gDeferredMultiSpotLightProgram.mShaderFiles.clear(); - gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredMultiSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredMultiSpotLightProgram.mShaderFiles.clear(); + gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredMultiSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL); + success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { - std::string fragment; - std::string vertex = "deferred/sunLightV.glsl"; + if (success) + { + std::string fragment; + std::string vertex = "deferred/sunLightV.glsl"; bool use_ao = gSavedSettings.getBOOL("RenderDeferredSSAO"); @@ -1713,40 +1700,41 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSunProgram.mFeatures.hasShadows = true; gDeferredSunProgram.mFeatures.hasAmbientOcclusion = use_ao; - gDeferredSunProgram.mShaderFiles.clear(); - gDeferredSunProgram.mShaderFiles.push_back(make_pair(vertex, GL_VERTEX_SHADER_ARB)); - gDeferredSunProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB)); - gDeferredSunProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredSunProgram.mName = "Deferred Sun Shader"; + gDeferredSunProgram.mShaderFiles.clear(); + gDeferredSunProgram.mShaderFiles.push_back(make_pair(vertex, GL_VERTEX_SHADER_ARB)); + gDeferredSunProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB)); + gDeferredSunProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredSunProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { - gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader"; - gDeferredBlurLightProgram.mFeatures.isDeferred = true; + if (success) + { + gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader"; + gDeferredBlurLightProgram.mFeatures.isDeferred = true; - gDeferredBlurLightProgram.mShaderFiles.clear(); - gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredBlurLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredBlurLightProgram.mShaderFiles.clear(); + gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredBlurLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredBlurLightProgram.createShader(NULL, NULL); + success = gDeferredBlurLightProgram.createShader(NULL, NULL); llassert(success); - } - - if (success) - { - gDeferredAlphaProgram.mName = "Deferred Alpha Shader"; - - gDeferredAlphaProgram.mFeatures.calculatesLighting = false; - gDeferredAlphaProgram.mFeatures.hasLighting = false; - gDeferredAlphaProgram.mFeatures.isAlphaLighting = true; - gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels - gDeferredAlphaProgram.mFeatures.hasSrgb = true; - gDeferredAlphaProgram.mFeatures.encodesNormal = true; - gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true; + } + + if (success) + { + gDeferredAlphaProgram.mName = "Deferred Alpha Shader"; + + gDeferredAlphaProgram.mFeatures.calculatesLighting = false; + gDeferredAlphaProgram.mFeatures.hasLighting = false; + gDeferredAlphaProgram.mFeatures.isAlphaLighting = true; + gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels + gDeferredAlphaProgram.mFeatures.hasSrgb = true; + gDeferredAlphaProgram.mFeatures.encodesNormal = true; + gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true; gDeferredAlphaProgram.mFeatures.hasAtmospherics = true; gDeferredAlphaProgram.mFeatures.hasGamma = true; gDeferredAlphaProgram.mFeatures.hasTransport = true; @@ -1787,14 +1775,13 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredAlphaImpostorProgram.mName = "Deferred Alpha Impostor Shader"; - gDeferredAlphaImpostorProgram.mFeatures.calculatesLighting = false; - gDeferredAlphaImpostorProgram.mFeatures.hasLighting = false; - gDeferredAlphaImpostorProgram.mFeatures.isAlphaLighting = true; - gDeferredAlphaImpostorProgram.mFeatures.hasSrgb = true; + gDeferredAlphaImpostorProgram.mFeatures.calculatesLighting = false; + gDeferredAlphaImpostorProgram.mFeatures.hasLighting = false; + gDeferredAlphaImpostorProgram.mFeatures.isAlphaLighting = true; + gDeferredAlphaImpostorProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of gDeferredAlphaImpostorProgram.mFeatures.hasSrgb = true; gDeferredAlphaImpostorProgram.mFeatures.encodesNormal = true; gDeferredAlphaImpostorProgram.mFeatures.hasShadows = use_sun_shadow; - gDeferredAlphaImpostorProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels if (mShaderLevel[SHADER_DEFERRED] < 1) { gDeferredAlphaImpostorProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; @@ -2414,25 +2401,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredWLCloudProgram.createShader(NULL, NULL); llassert(success); - } - - if (success && (mShaderLevel[SHADER_DEFERRED] > 2)) - { - gDeferredWLCloudShadowProgram.mName = "Deferred Cloud Shadow Program"; - gDeferredWLCloudShadowProgram.mShaderFiles.clear(); - gDeferredWLCloudShadowProgram.mFeatures.calculatesAtmospherics = true; - gDeferredWLCloudShadowProgram.mFeatures.hasTransport = true; - gDeferredWLCloudShadowProgram.mFeatures.hasGamma = true; - gDeferredWLCloudShadowProgram.mFeatures.hasSrgb = true; - gDeferredWLCloudShadowProgram.mFeatures.isDeferred = true; - gDeferredWLCloudShadowProgram.mFeatures.hasShadows = true; - gDeferredWLCloudShadowProgram.mShaderFiles.push_back(make_pair("deferred/cloudShadowV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredWLCloudShadowProgram.mShaderFiles.push_back(make_pair("deferred/cloudShadowF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredWLCloudShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - gDeferredWLCloudShadowProgram.mShaderGroup = LLGLSLShader::SG_SKY; - success = gDeferredWLCloudShadowProgram.createShader(NULL, NULL); - llassert(success); - } + } if (success) { @@ -2467,1396 +2436,1376 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredWLMoonProgram.mShaderFiles.push_back(make_pair("deferred/moonF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredWLMoonProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredWLMoonProgram.mShaderGroup = LLGLSLShader::SG_SKY; - success = gDeferredWLMoonProgram.createShader(NULL, NULL); + success = gDeferredWLMoonProgram.createShader(NULL, NULL); llassert(success); - } - - if (success) - { - gDeferredStarProgram.mName = "Deferred Star Program"; - gDeferredStarProgram.mShaderFiles.clear(); - gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredStarProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - gDeferredStarProgram.mShaderGroup = LLGLSLShader::SG_SKY; - success = gDeferredStarProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredStarProgram.mName = "Deferred Star Program"; + gDeferredStarProgram.mShaderFiles.clear(); + gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredStarProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredStarProgram.mShaderGroup = LLGLSLShader::SG_SKY; + success = gDeferredStarProgram.createShader(NULL, NULL); llassert(success); - } - - if (success) - { - gNormalMapGenProgram.mName = "Normal Map Generation Program"; - gNormalMapGenProgram.mFeatures.isDeferred = true; - gNormalMapGenProgram.mShaderFiles.clear(); - gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenV.glsl", GL_VERTEX_SHADER_ARB)); - gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenF.glsl", GL_FRAGMENT_SHADER_ARB)); - gNormalMapGenProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - gNormalMapGenProgram.mShaderGroup = LLGLSLShader::SG_SKY; - success = gNormalMapGenProgram.createShader(NULL, NULL); - } - - return success; + } + + if (success) + { + gNormalMapGenProgram.mName = "Normal Map Generation Program"; + gNormalMapGenProgram.mShaderFiles.clear(); + gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenV.glsl", GL_VERTEX_SHADER_ARB)); + gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenF.glsl", GL_FRAGMENT_SHADER_ARB)); + gNormalMapGenProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gNormalMapGenProgram.mShaderGroup = LLGLSLShader::SG_SKY; + success = gNormalMapGenProgram.createShader(NULL, NULL); + } + + return success; } BOOL LLViewerShaderMgr::loadShadersObject() { - BOOL success = TRUE; - - if (mShaderLevel[SHADER_OBJECT] == 0) - { - gObjectShinyProgram.unload(); - gObjectFullbrightShinyProgram.unload(); - gObjectFullbrightShinyWaterProgram.unload(); - gObjectShinyWaterProgram.unload(); - gObjectFullbrightNoColorProgram.unload(); - gObjectFullbrightNoColorWaterProgram.unload(); - gObjectSimpleProgram.unload(); - gObjectSimpleImpostorProgram.unload(); - gObjectPreviewProgram.unload(); - gImpostorProgram.unload(); - gObjectSimpleAlphaMaskProgram.unload(); - gObjectBumpProgram.unload(); - gObjectSimpleWaterProgram.unload(); - gObjectSimpleWaterAlphaMaskProgram.unload(); - gObjectEmissiveProgram.unload(); - gObjectEmissiveWaterProgram.unload(); - gObjectFullbrightProgram.unload(); - gObjectFullbrightAlphaMaskProgram.unload(); - gObjectFullbrightWaterProgram.unload(); - gObjectFullbrightWaterAlphaMaskProgram.unload(); - gObjectShinyNonIndexedProgram.unload(); - gObjectFullbrightShinyNonIndexedProgram.unload(); - gObjectFullbrightShinyNonIndexedWaterProgram.unload(); - gObjectShinyNonIndexedWaterProgram.unload(); - gObjectSimpleNonIndexedTexGenProgram.unload(); - gObjectSimpleNonIndexedTexGenWaterProgram.unload(); - gObjectSimpleNonIndexedWaterProgram.unload(); - gObjectAlphaMaskNonIndexedProgram.unload(); - gObjectAlphaMaskNonIndexedWaterProgram.unload(); - gObjectAlphaMaskNoColorProgram.unload(); - gObjectAlphaMaskNoColorWaterProgram.unload(); - gObjectFullbrightNonIndexedProgram.unload(); - gObjectFullbrightNonIndexedWaterProgram.unload(); - gObjectEmissiveNonIndexedProgram.unload(); - gObjectEmissiveNonIndexedWaterProgram.unload(); - gSkinnedObjectSimpleProgram.unload(); - gSkinnedObjectFullbrightProgram.unload(); - gSkinnedObjectEmissiveProgram.unload(); - gSkinnedObjectFullbrightShinyProgram.unload(); - gSkinnedObjectShinySimpleProgram.unload(); - gSkinnedObjectSimpleWaterProgram.unload(); - gSkinnedObjectFullbrightWaterProgram.unload(); - gSkinnedObjectEmissiveWaterProgram.unload(); - gSkinnedObjectFullbrightShinyWaterProgram.unload(); - gSkinnedObjectShinySimpleWaterProgram.unload(); - gTreeProgram.unload(); - gTreeWaterProgram.unload(); + BOOL success = TRUE; + + if (mShaderLevel[SHADER_OBJECT] == 0) + { + gObjectShinyProgram.unload(); + gObjectFullbrightShinyProgram.unload(); + gObjectFullbrightShinyWaterProgram.unload(); + gObjectShinyWaterProgram.unload(); + gObjectFullbrightNoColorProgram.unload(); + gObjectFullbrightNoColorWaterProgram.unload(); + gObjectSimpleProgram.unload(); + gObjectSimpleImpostorProgram.unload(); + gObjectPreviewProgram.unload(); + gImpostorProgram.unload(); + gObjectSimpleAlphaMaskProgram.unload(); + gObjectBumpProgram.unload(); + gObjectSimpleWaterProgram.unload(); + gObjectSimpleWaterAlphaMaskProgram.unload(); + gObjectEmissiveProgram.unload(); + gObjectEmissiveWaterProgram.unload(); + gObjectFullbrightProgram.unload(); + gObjectFullbrightAlphaMaskProgram.unload(); + gObjectFullbrightWaterProgram.unload(); + gObjectFullbrightWaterAlphaMaskProgram.unload(); + gObjectShinyNonIndexedProgram.unload(); + gObjectFullbrightShinyNonIndexedProgram.unload(); + gObjectFullbrightShinyNonIndexedWaterProgram.unload(); + gObjectShinyNonIndexedWaterProgram.unload(); + gObjectSimpleNonIndexedTexGenProgram.unload(); + gObjectSimpleNonIndexedTexGenWaterProgram.unload(); + gObjectSimpleNonIndexedWaterProgram.unload(); + gObjectAlphaMaskNonIndexedProgram.unload(); + gObjectAlphaMaskNonIndexedWaterProgram.unload(); + gObjectAlphaMaskNoColorProgram.unload(); + gObjectAlphaMaskNoColorWaterProgram.unload(); + gObjectFullbrightNonIndexedProgram.unload(); + gObjectFullbrightNonIndexedWaterProgram.unload(); + gObjectEmissiveNonIndexedProgram.unload(); + gObjectEmissiveNonIndexedWaterProgram.unload(); + gSkinnedObjectSimpleProgram.unload(); + gSkinnedObjectFullbrightProgram.unload(); + gSkinnedObjectEmissiveProgram.unload(); + gSkinnedObjectFullbrightShinyProgram.unload(); + gSkinnedObjectShinySimpleProgram.unload(); + gSkinnedObjectSimpleWaterProgram.unload(); + gSkinnedObjectFullbrightWaterProgram.unload(); + gSkinnedObjectEmissiveWaterProgram.unload(); + gSkinnedObjectFullbrightShinyWaterProgram.unload(); + gSkinnedObjectShinySimpleWaterProgram.unload(); + gTreeProgram.unload(); + gTreeWaterProgram.unload(); + + return TRUE; + } + + if (success) + { + gObjectSimpleNonIndexedProgram.mName = "Non indexed Shader"; + gObjectSimpleNonIndexedProgram.mFeatures.calculatesLighting = true; + gObjectSimpleNonIndexedProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleNonIndexedProgram.mFeatures.hasGamma = true; + gObjectSimpleNonIndexedProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleNonIndexedProgram.mFeatures.hasLighting = true; + gObjectSimpleNonIndexedProgram.mFeatures.disableTextureIndex = true; + gObjectSimpleNonIndexedProgram.mShaderFiles.clear(); + gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectSimpleNonIndexedProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectSimpleNonIndexedTexGenProgram.mName = "Non indexed tex-gen Shader"; + gObjectSimpleNonIndexedTexGenProgram.mFeatures.calculatesLighting = true; + gObjectSimpleNonIndexedTexGenProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleNonIndexedTexGenProgram.mFeatures.hasGamma = true; + gObjectSimpleNonIndexedTexGenProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleNonIndexedTexGenProgram.mFeatures.hasLighting = true; + gObjectSimpleNonIndexedTexGenProgram.mFeatures.disableTextureIndex = true; + gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.clear(); + gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.push_back(make_pair("objects/simpleTexGenV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleNonIndexedTexGenProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectSimpleNonIndexedTexGenProgram.createShader(NULL, NULL); + } + + + if (success) + { + gObjectSimpleNonIndexedWaterProgram.mName = "Non indexed Water Shader"; + gObjectSimpleNonIndexedWaterProgram.mFeatures.calculatesLighting = true; + gObjectSimpleNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleNonIndexedWaterProgram.mFeatures.hasWaterFog = true; + gObjectSimpleNonIndexedWaterProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleNonIndexedWaterProgram.mFeatures.hasLighting = true; + gObjectSimpleNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; + gObjectSimpleNonIndexedWaterProgram.mShaderFiles.clear(); + gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectSimpleNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectSimpleNonIndexedWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectSimpleNonIndexedTexGenWaterProgram.mName = "Non indexed tex-gen Water Shader"; + gObjectSimpleNonIndexedTexGenWaterProgram.mFeatures.calculatesLighting = true; + gObjectSimpleNonIndexedTexGenWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleNonIndexedTexGenWaterProgram.mFeatures.hasWaterFog = true; + gObjectSimpleNonIndexedTexGenWaterProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleNonIndexedTexGenWaterProgram.mFeatures.hasLighting = true; + gObjectSimpleNonIndexedTexGenWaterProgram.mFeatures.disableTextureIndex = true; + gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.clear(); + gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleTexGenV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleNonIndexedTexGenWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectSimpleNonIndexedTexGenWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectSimpleNonIndexedTexGenWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectAlphaMaskNonIndexedProgram.mName = "Non indexed alpha mask Shader"; + gObjectAlphaMaskNonIndexedProgram.mFeatures.calculatesLighting = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.calculatesAtmospherics = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.hasGamma = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.hasAtmospherics = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.hasLighting = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.disableTextureIndex = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.hasAlphaMask = true; + gObjectAlphaMaskNonIndexedProgram.mShaderFiles.clear(); + gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleNonIndexedV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectAlphaMaskNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectAlphaMaskNonIndexedProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectAlphaMaskNonIndexedWaterProgram.mName = "Non indexed alpha mask Water Shader"; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.calculatesLighting = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasWaterFog = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasAtmospherics = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasLighting = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasAlphaMask = true; + gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.clear(); + gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleNonIndexedV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectAlphaMaskNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectAlphaMaskNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectAlphaMaskNonIndexedWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectAlphaMaskNoColorProgram.mName = "No color alpha mask Shader"; + gObjectAlphaMaskNoColorProgram.mFeatures.calculatesLighting = true; + gObjectAlphaMaskNoColorProgram.mFeatures.calculatesAtmospherics = true; + gObjectAlphaMaskNoColorProgram.mFeatures.hasGamma = true; + gObjectAlphaMaskNoColorProgram.mFeatures.hasAtmospherics = true; + gObjectAlphaMaskNoColorProgram.mFeatures.hasLighting = true; + gObjectAlphaMaskNoColorProgram.mFeatures.disableTextureIndex = true; + gObjectAlphaMaskNoColorProgram.mFeatures.hasAlphaMask = true; + gObjectAlphaMaskNoColorProgram.mShaderFiles.clear(); + gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectAlphaMaskNoColorProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectAlphaMaskNoColorWaterProgram.mName = "No color alpha mask Water Shader"; + gObjectAlphaMaskNoColorWaterProgram.mFeatures.calculatesLighting = true; + gObjectAlphaMaskNoColorWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectAlphaMaskNoColorWaterProgram.mFeatures.hasWaterFog = true; + gObjectAlphaMaskNoColorWaterProgram.mFeatures.hasAtmospherics = true; + gObjectAlphaMaskNoColorWaterProgram.mFeatures.hasLighting = true; + gObjectAlphaMaskNoColorWaterProgram.mFeatures.disableTextureIndex = true; + gObjectAlphaMaskNoColorWaterProgram.mFeatures.hasAlphaMask = true; + gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.clear(); + gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectAlphaMaskNoColorWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectAlphaMaskNoColorWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectAlphaMaskNoColorWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gTreeProgram.mName = "Tree Shader"; + gTreeProgram.mFeatures.calculatesLighting = true; + gTreeProgram.mFeatures.calculatesAtmospherics = true; + gTreeProgram.mFeatures.hasGamma = true; + gTreeProgram.mFeatures.hasAtmospherics = true; + gTreeProgram.mFeatures.hasLighting = true; + gTreeProgram.mFeatures.disableTextureIndex = true; + gTreeProgram.mFeatures.hasAlphaMask = true; + gTreeProgram.mShaderFiles.clear(); + gTreeProgram.mShaderFiles.push_back(make_pair("objects/treeV.glsl", GL_VERTEX_SHADER_ARB)); + gTreeProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gTreeProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gTreeProgram.createShader(NULL, NULL); + } + + if (success) + { + gTreeWaterProgram.mName = "Tree Water Shader"; + gTreeWaterProgram.mFeatures.calculatesLighting = true; + gTreeWaterProgram.mFeatures.calculatesAtmospherics = true; + gTreeWaterProgram.mFeatures.hasWaterFog = true; + gTreeWaterProgram.mFeatures.hasAtmospherics = true; + gTreeWaterProgram.mFeatures.hasLighting = true; + gTreeWaterProgram.mFeatures.disableTextureIndex = true; + gTreeWaterProgram.mFeatures.hasAlphaMask = true; + gTreeWaterProgram.mShaderFiles.clear(); + gTreeWaterProgram.mShaderFiles.push_back(make_pair("objects/treeV.glsl", GL_VERTEX_SHADER_ARB)); + gTreeWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gTreeWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gTreeWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gTreeWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightNonIndexedProgram.mName = "Non Indexed Fullbright Shader"; + gObjectFullbrightNonIndexedProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightNonIndexedProgram.mFeatures.hasGamma = true; + gObjectFullbrightNonIndexedProgram.mFeatures.hasTransport = true; + gObjectFullbrightNonIndexedProgram.mFeatures.isFullbright = true; + gObjectFullbrightNonIndexedProgram.mFeatures.disableTextureIndex = true; + gObjectFullbrightNonIndexedProgram.mShaderFiles.clear(); + gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectFullbrightNonIndexedProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightNonIndexedWaterProgram.mName = "Non Indexed Fullbright Water Shader"; + gObjectFullbrightNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightNonIndexedWaterProgram.mFeatures.isFullbright = true; + gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasWaterFog = true; + gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasTransport = true; + gObjectFullbrightNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; + gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasSrgb = true; + gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.clear(); + gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectFullbrightNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectFullbrightNonIndexedWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectEmissiveNonIndexedProgram.mName = "Non Indexed Emissive Shader"; + gObjectEmissiveNonIndexedProgram.mFeatures.calculatesAtmospherics = true; + gObjectEmissiveNonIndexedProgram.mFeatures.hasGamma = true; + gObjectEmissiveNonIndexedProgram.mFeatures.hasTransport = true; + gObjectEmissiveNonIndexedProgram.mFeatures.isFullbright = true; + gObjectEmissiveNonIndexedProgram.mFeatures.disableTextureIndex = true; + gObjectEmissiveNonIndexedProgram.mFeatures.hasSrgb = true; + gObjectEmissiveNonIndexedProgram.mShaderFiles.clear(); + gObjectEmissiveNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectEmissiveNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectEmissiveNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectEmissiveNonIndexedProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectEmissiveNonIndexedWaterProgram.mName = "Non Indexed Emissive Water Shader"; + gObjectEmissiveNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectEmissiveNonIndexedWaterProgram.mFeatures.isFullbright = true; + gObjectEmissiveNonIndexedWaterProgram.mFeatures.hasWaterFog = true; + gObjectEmissiveNonIndexedWaterProgram.mFeatures.hasTransport = true; + gObjectEmissiveNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; + gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.clear(); + gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectEmissiveNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectEmissiveNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectEmissiveNonIndexedWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightNoColorProgram.mName = "Non Indexed no color Fullbright Shader"; + gObjectFullbrightNoColorProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightNoColorProgram.mFeatures.hasGamma = true; + gObjectFullbrightNoColorProgram.mFeatures.hasTransport = true; + gObjectFullbrightNoColorProgram.mFeatures.isFullbright = true; + gObjectFullbrightNoColorProgram.mFeatures.hasSrgb = true; + gObjectFullbrightNoColorProgram.mFeatures.disableTextureIndex = true; + gObjectFullbrightNoColorProgram.mShaderFiles.clear(); + gObjectFullbrightNoColorProgram.mShaderFiles.push_back(make_pair("objects/fullbrightNoColorV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightNoColorProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightNoColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectFullbrightNoColorProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightNoColorWaterProgram.mName = "Non Indexed no color Fullbright Water Shader"; + gObjectFullbrightNoColorWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightNoColorWaterProgram.mFeatures.isFullbright = true; + gObjectFullbrightNoColorWaterProgram.mFeatures.hasWaterFog = true; + gObjectFullbrightNoColorWaterProgram.mFeatures.hasTransport = true; + gObjectFullbrightNoColorWaterProgram.mFeatures.disableTextureIndex = true; + gObjectFullbrightNoColorWaterProgram.mShaderFiles.clear(); + gObjectFullbrightNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightNoColorV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightNoColorWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectFullbrightNoColorWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectFullbrightNoColorWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectShinyNonIndexedProgram.mName = "Non Indexed Shiny Shader"; + gObjectShinyNonIndexedProgram.mFeatures.calculatesAtmospherics = true; + gObjectShinyNonIndexedProgram.mFeatures.calculatesLighting = true; + gObjectShinyNonIndexedProgram.mFeatures.hasGamma = true; + gObjectShinyNonIndexedProgram.mFeatures.hasAtmospherics = true; + gObjectShinyNonIndexedProgram.mFeatures.isShiny = true; + gObjectShinyNonIndexedProgram.mFeatures.disableTextureIndex = true; + gObjectShinyNonIndexedProgram.mShaderFiles.clear(); + gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectShinyNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectShinyNonIndexedProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectShinyNonIndexedWaterProgram.mName = "Non Indexed Shiny Water Shader"; + gObjectShinyNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectShinyNonIndexedWaterProgram.mFeatures.calculatesLighting = true; + gObjectShinyNonIndexedWaterProgram.mFeatures.isShiny = true; + gObjectShinyNonIndexedWaterProgram.mFeatures.hasWaterFog = true; + gObjectShinyNonIndexedWaterProgram.mFeatures.hasAtmospherics = true; + gObjectShinyNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; + gObjectShinyNonIndexedWaterProgram.mShaderFiles.clear(); + gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectShinyNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectShinyNonIndexedWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightShinyNonIndexedProgram.mName = "Non Indexed Fullbright Shiny Shader"; + gObjectFullbrightShinyNonIndexedProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightShinyNonIndexedProgram.mFeatures.isFullbright = true; + gObjectFullbrightShinyNonIndexedProgram.mFeatures.isShiny = true; + gObjectFullbrightShinyNonIndexedProgram.mFeatures.hasGamma = true; + gObjectFullbrightShinyNonIndexedProgram.mFeatures.hasTransport = true; + gObjectFullbrightShinyNonIndexedProgram.mFeatures.disableTextureIndex = true; + gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.clear(); + gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightShinyNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectFullbrightShinyNonIndexedProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightShinyNonIndexedWaterProgram.mName = "Non Indexed Fullbright Shiny Water Shader"; + gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.isFullbright = true; + gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.isShiny = true; + gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasGamma = true; + gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasTransport = true; + gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasWaterFog = true; + gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; + gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.clear(); + gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightShinyNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectFullbrightShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectFullbrightShinyNonIndexedWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gImpostorProgram.mName = "Impostor Shader"; + gImpostorProgram.mFeatures.disableTextureIndex = true; + gImpostorProgram.mFeatures.hasSrgb = true; + gImpostorProgram.mShaderFiles.clear(); + gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorV.glsl", GL_VERTEX_SHADER_ARB)); + gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorF.glsl", GL_FRAGMENT_SHADER_ARB)); + gImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gImpostorProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectPreviewProgram.mName = "Simple Shader"; + gObjectPreviewProgram.mFeatures.calculatesLighting = false; + gObjectPreviewProgram.mFeatures.calculatesAtmospherics = false; + gObjectPreviewProgram.mFeatures.hasGamma = false; + gObjectPreviewProgram.mFeatures.hasAtmospherics = false; + gObjectPreviewProgram.mFeatures.hasLighting = false; + gObjectPreviewProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectPreviewProgram.mFeatures.disableTextureIndex = true; + gObjectPreviewProgram.mShaderFiles.clear(); + gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectPreviewProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectPreviewProgram.createShader(NULL, NULL); + gObjectPreviewProgram.mFeatures.hasLighting = true; + } + + if (success) + { + gObjectSimpleProgram.mName = "Simple Shader"; + gObjectSimpleProgram.mFeatures.calculatesLighting = true; + gObjectSimpleProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleProgram.mFeatures.hasGamma = true; + gObjectSimpleProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleProgram.mFeatures.hasLighting = true; + gObjectSimpleProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectSimpleProgram.mShaderFiles.clear(); + gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectSimpleProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectSimpleImpostorProgram.mName = "Simple Impostor Shader"; + gObjectSimpleImpostorProgram.mFeatures.calculatesLighting = true; + gObjectSimpleImpostorProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleImpostorProgram.mFeatures.hasGamma = true; + gObjectSimpleImpostorProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleImpostorProgram.mFeatures.hasLighting = true; + gObjectSimpleImpostorProgram.mFeatures.mIndexedTextureChannels = 0; + // force alpha mask version of lighting so we can weed out + // transparent pixels from impostor temp buffer + // + gObjectSimpleImpostorProgram.mFeatures.hasAlphaMask = true; + gObjectSimpleImpostorProgram.mShaderFiles.clear(); + gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + + success = gObjectSimpleImpostorProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectSimpleWaterProgram.mName = "Simple Water Shader"; + gObjectSimpleWaterProgram.mFeatures.calculatesLighting = true; + gObjectSimpleWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleWaterProgram.mFeatures.hasWaterFog = true; + gObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleWaterProgram.mFeatures.hasLighting = true; + gObjectSimpleWaterProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectSimpleWaterProgram.mShaderFiles.clear(); + gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectSimpleWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectBumpProgram.mName = "Bump Shader"; + /*gObjectBumpProgram.mFeatures.calculatesLighting = true; + gObjectBumpProgram.mFeatures.calculatesAtmospherics = true; + gObjectBumpProgram.mFeatures.hasGamma = true; + gObjectBumpProgram.mFeatures.hasAtmospherics = true; + gObjectBumpProgram.mFeatures.hasLighting = true; + gObjectBumpProgram.mFeatures.mIndexedTextureChannels = 0;*/ + gObjectBumpProgram.mFeatures.encodesNormal = true; + gObjectBumpProgram.mShaderFiles.clear(); + gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectBumpProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectBumpProgram.createShader(NULL, NULL); + if (success) + { //lldrawpoolbump assumes "texture0" has channel 0 and "texture1" has channel 1 + gObjectBumpProgram.bind(); + gObjectBumpProgram.uniform1i(sTexture0, 0); + gObjectBumpProgram.uniform1i(sTexture1, 1); + gObjectBumpProgram.unbind(); + } + } + + + if (success) + { + gObjectSimpleAlphaMaskProgram.mName = "Simple Alpha Mask Shader"; + gObjectSimpleAlphaMaskProgram.mFeatures.calculatesLighting = true; + gObjectSimpleAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleAlphaMaskProgram.mFeatures.hasGamma = true; + gObjectSimpleAlphaMaskProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleAlphaMaskProgram.mFeatures.hasLighting = true; + gObjectSimpleAlphaMaskProgram.mFeatures.hasAlphaMask = true; + gObjectSimpleAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectSimpleAlphaMaskProgram.mShaderFiles.clear(); + gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectSimpleAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectSimpleWaterAlphaMaskProgram.mName = "Simple Water Alpha Mask Shader"; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.calculatesLighting = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasWaterFog = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasLighting = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasAlphaMask = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.clear(); + gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectSimpleWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectSimpleWaterAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightProgram.mName = "Fullbright Shader"; + gObjectFullbrightProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightProgram.mFeatures.hasGamma = true; + gObjectFullbrightProgram.mFeatures.hasTransport = true; + gObjectFullbrightProgram.mFeatures.isFullbright = true; + gObjectFullbrightProgram.mFeatures.hasSrgb = true; + gObjectFullbrightProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectFullbrightProgram.mShaderFiles.clear(); + gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectFullbrightProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightWaterProgram.mName = "Fullbright Water Shader"; + gObjectFullbrightWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightWaterProgram.mFeatures.isFullbright = true; + gObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true; + gObjectFullbrightWaterProgram.mFeatures.hasTransport = true; + gObjectFullbrightWaterProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectFullbrightWaterProgram.mShaderFiles.clear(); + gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectFullbrightWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectEmissiveProgram.mName = "Emissive Shader"; + gObjectEmissiveProgram.mFeatures.calculatesAtmospherics = true; + gObjectEmissiveProgram.mFeatures.hasGamma = true; + gObjectEmissiveProgram.mFeatures.hasTransport = true; + gObjectEmissiveProgram.mFeatures.isFullbright = true; + gObjectEmissiveProgram.mFeatures.hasSrgb = true; + gObjectEmissiveProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectEmissiveProgram.mShaderFiles.clear(); + gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectEmissiveProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectEmissiveWaterProgram.mName = "Emissive Water Shader"; + gObjectEmissiveWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectEmissiveWaterProgram.mFeatures.isFullbright = true; + gObjectEmissiveWaterProgram.mFeatures.hasWaterFog = true; + gObjectEmissiveWaterProgram.mFeatures.hasTransport = true; + gObjectEmissiveWaterProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectEmissiveWaterProgram.mShaderFiles.clear(); + gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectEmissiveWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectEmissiveWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightAlphaMaskProgram.mName = "Fullbright Alpha Mask Shader"; + gObjectFullbrightAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.hasGamma = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.hasTransport = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.isFullbright = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.hasAlphaMask = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.hasSrgb = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectFullbrightAlphaMaskProgram.mShaderFiles.clear(); + gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectFullbrightAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightWaterAlphaMaskProgram.mName = "Fullbright Water Shader"; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.isFullbright = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasWaterFog = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasTransport = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasAlphaMask = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.clear(); + gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectFullbrightWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectFullbrightWaterAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectShinyProgram.mName = "Shiny Shader"; + gObjectShinyProgram.mFeatures.calculatesAtmospherics = true; + gObjectShinyProgram.mFeatures.calculatesLighting = true; + gObjectShinyProgram.mFeatures.hasGamma = true; + gObjectShinyProgram.mFeatures.hasAtmospherics = true; + gObjectShinyProgram.mFeatures.isShiny = true; + gObjectShinyProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectShinyProgram.mShaderFiles.clear(); + gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); + + gObjectShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectShinyProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectShinyWaterProgram.mName = "Shiny Water Shader"; + gObjectShinyWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectShinyWaterProgram.mFeatures.calculatesLighting = true; + gObjectShinyWaterProgram.mFeatures.isShiny = true; + gObjectShinyWaterProgram.mFeatures.hasWaterFog = true; + gObjectShinyWaterProgram.mFeatures.hasAtmospherics = true; + gObjectShinyWaterProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectShinyWaterProgram.mShaderFiles.clear(); + gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectShinyWaterProgram.createShader(NULL, NULL); + } - return TRUE; - } + if (success) + { + gObjectFullbrightShinyProgram.mName = "Fullbright Shiny Shader"; + gObjectFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightShinyProgram.mFeatures.isFullbright = true; + gObjectFullbrightShinyProgram.mFeatures.isShiny = true; + gObjectFullbrightShinyProgram.mFeatures.hasGamma = true; + gObjectFullbrightShinyProgram.mFeatures.hasTransport = true; + gObjectFullbrightShinyProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectFullbrightShinyProgram.mShaderFiles.clear(); + gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectFullbrightShinyProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightShinyWaterProgram.mName = "Fullbright Shiny Water Shader"; + gObjectFullbrightShinyWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightShinyWaterProgram.mFeatures.isFullbright = true; + gObjectFullbrightShinyWaterProgram.mFeatures.isShiny = true; + gObjectFullbrightShinyWaterProgram.mFeatures.hasGamma = true; + gObjectFullbrightShinyWaterProgram.mFeatures.hasTransport = true; + gObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true; + gObjectFullbrightShinyWaterProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectFullbrightShinyWaterProgram.mShaderFiles.clear(); + gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + gObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectFullbrightShinyWaterProgram.createShader(NULL, NULL); + } + + if (mShaderLevel[SHADER_AVATAR] > 0) + { //load hardware skinned attachment shaders + if (success) + { + gSkinnedObjectSimpleProgram.mName = "Skinned Simple Shader"; + gSkinnedObjectSimpleProgram.mFeatures.calculatesLighting = true; + gSkinnedObjectSimpleProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectSimpleProgram.mFeatures.hasGamma = true; + gSkinnedObjectSimpleProgram.mFeatures.hasAtmospherics = true; + gSkinnedObjectSimpleProgram.mFeatures.hasLighting = true; + gSkinnedObjectSimpleProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectSimpleProgram.mFeatures.hasAlphaMask = true; + gSkinnedObjectSimpleProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectSimpleProgram.mShaderFiles.clear(); + gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectSimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectSimpleProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectFullbrightProgram.mName = "Skinned Fullbright Shader"; + gSkinnedObjectFullbrightProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectFullbrightProgram.mFeatures.hasGamma = true; + gSkinnedObjectFullbrightProgram.mFeatures.hasTransport = true; + gSkinnedObjectFullbrightProgram.mFeatures.isFullbright = true; + gSkinnedObjectFullbrightProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectFullbrightProgram.mFeatures.hasAlphaMask = true; + gSkinnedObjectFullbrightProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectFullbrightProgram.mFeatures.hasSrgb = true; + gSkinnedObjectFullbrightProgram.mShaderFiles.clear(); + gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectFullbrightProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectEmissiveProgram.mName = "Skinned Emissive Shader"; + gSkinnedObjectEmissiveProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectEmissiveProgram.mFeatures.hasGamma = true; + gSkinnedObjectEmissiveProgram.mFeatures.hasTransport = true; + gSkinnedObjectEmissiveProgram.mFeatures.isFullbright = true; + gSkinnedObjectEmissiveProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectEmissiveProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectEmissiveProgram.mFeatures.hasSrgb = true; + gSkinnedObjectEmissiveProgram.mShaderFiles.clear(); + gSkinnedObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectEmissiveProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectEmissiveWaterProgram.mName = "Skinned Emissive Water Shader"; + gSkinnedObjectEmissiveWaterProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectEmissiveWaterProgram.mFeatures.hasGamma = true; + gSkinnedObjectEmissiveWaterProgram.mFeatures.hasTransport = true; + gSkinnedObjectEmissiveWaterProgram.mFeatures.isFullbright = true; + gSkinnedObjectEmissiveWaterProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectEmissiveWaterProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectEmissiveWaterProgram.mFeatures.hasWaterFog = true; + gSkinnedObjectEmissiveWaterProgram.mShaderFiles.clear(); + gSkinnedObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectEmissiveWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectFullbrightShinyProgram.mName = "Skinned Fullbright Shiny Shader"; + gSkinnedObjectFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.hasGamma = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.hasTransport = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.isShiny = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.isFullbright = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.hasAlphaMask = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectFullbrightShinyProgram.mShaderFiles.clear(); + gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectFullbrightShinyProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectShinySimpleProgram.mName = "Skinned Shiny Simple Shader"; + gSkinnedObjectShinySimpleProgram.mFeatures.calculatesLighting = true; + gSkinnedObjectShinySimpleProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectShinySimpleProgram.mFeatures.hasGamma = true; + gSkinnedObjectShinySimpleProgram.mFeatures.hasAtmospherics = true; + gSkinnedObjectShinySimpleProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectShinySimpleProgram.mFeatures.hasAlphaMask = true; + gSkinnedObjectShinySimpleProgram.mFeatures.isShiny = true; + gSkinnedObjectShinySimpleProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectShinySimpleProgram.mShaderFiles.clear(); + gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectShinySimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectShinySimpleProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectSimpleWaterProgram.mName = "Skinned Simple Water Shader"; + gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesLighting = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasGamma = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasLighting = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasWaterFog = true; + gSkinnedObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasAlphaMask = true; + gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear(); + gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectSimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectSimpleWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectFullbrightWaterProgram.mName = "Skinned Fullbright Water Shader"; + gSkinnedObjectFullbrightWaterProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.hasGamma = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.hasTransport = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.isFullbright = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.hasAlphaMask = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gSkinnedObjectFullbrightWaterProgram.mShaderFiles.clear(); + gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectFullbrightWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectFullbrightShinyWaterProgram.mName = "Skinned Fullbright Shiny Water Shader"; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasGamma = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasTransport = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.isShiny = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.isFullbright = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasAlphaMask = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.clear(); + gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectFullbrightShinyWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectShinySimpleWaterProgram.mName = "Skinned Shiny Simple Water Shader"; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.calculatesLighting = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasGamma = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasAtmospherics = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasAlphaMask = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.isShiny = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasWaterFog = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectShinySimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.clear(); + gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectShinySimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectShinySimpleWaterProgram.createShader(NULL, NULL); + } + } + + if( !success ) + { + mShaderLevel[SHADER_OBJECT] = 0; + return FALSE; + } + + return TRUE; +} - if (success) - { - gObjectSimpleNonIndexedProgram.mName = "Non indexed Shader"; - gObjectSimpleNonIndexedProgram.mFeatures.calculatesLighting = true; - gObjectSimpleNonIndexedProgram.mFeatures.calculatesAtmospherics = true; - gObjectSimpleNonIndexedProgram.mFeatures.hasGamma = true; - gObjectSimpleNonIndexedProgram.mFeatures.hasAtmospherics = true; - gObjectSimpleNonIndexedProgram.mFeatures.hasLighting = true; - gObjectSimpleNonIndexedProgram.mFeatures.disableTextureIndex = true; - gObjectSimpleNonIndexedProgram.mShaderFiles.clear(); - gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectSimpleNonIndexedProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectSimpleNonIndexedTexGenProgram.mName = "Non indexed tex-gen Shader"; - gObjectSimpleNonIndexedTexGenProgram.mFeatures.calculatesLighting = true; - gObjectSimpleNonIndexedTexGenProgram.mFeatures.calculatesAtmospherics = true; - gObjectSimpleNonIndexedTexGenProgram.mFeatures.hasGamma = true; - gObjectSimpleNonIndexedTexGenProgram.mFeatures.hasAtmospherics = true; - gObjectSimpleNonIndexedTexGenProgram.mFeatures.hasLighting = true; - gObjectSimpleNonIndexedTexGenProgram.mFeatures.disableTextureIndex = true; - gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.clear(); - gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.push_back(make_pair("objects/simpleTexGenV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleNonIndexedTexGenProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectSimpleNonIndexedTexGenProgram.createShader(NULL, NULL); - } - +BOOL LLViewerShaderMgr::loadShadersAvatar() +{ + BOOL success = TRUE; + + if (mShaderLevel[SHADER_AVATAR] == 0) + { + gAvatarProgram.unload(); + gAvatarWaterProgram.unload(); + gAvatarEyeballProgram.unload(); + gAvatarPickProgram.unload(); + return TRUE; + } + + if (success) + { + gAvatarProgram.mName = "Avatar Shader"; + gAvatarProgram.mFeatures.hasSkinning = true; + gAvatarProgram.mFeatures.calculatesAtmospherics = true; + gAvatarProgram.mFeatures.calculatesLighting = true; + gAvatarProgram.mFeatures.hasGamma = true; + gAvatarProgram.mFeatures.hasAtmospherics = true; + gAvatarProgram.mFeatures.hasLighting = true; + gAvatarProgram.mFeatures.hasAlphaMask = true; + gAvatarProgram.mFeatures.disableTextureIndex = true; + gAvatarProgram.mShaderFiles.clear(); + gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB)); + gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarF.glsl", GL_FRAGMENT_SHADER_ARB)); + gAvatarProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR]; + success = gAvatarProgram.createShader(NULL, NULL); + + if (success) + { + gAvatarWaterProgram.mName = "Avatar Water Shader"; + gAvatarWaterProgram.mFeatures.hasSkinning = true; + gAvatarWaterProgram.mFeatures.calculatesAtmospherics = true; + gAvatarWaterProgram.mFeatures.calculatesLighting = true; + gAvatarWaterProgram.mFeatures.hasWaterFog = true; + gAvatarWaterProgram.mFeatures.hasAtmospherics = true; + gAvatarWaterProgram.mFeatures.hasLighting = true; + gAvatarWaterProgram.mFeatures.hasAlphaMask = true; + gAvatarWaterProgram.mFeatures.disableTextureIndex = true; + gAvatarWaterProgram.mShaderFiles.clear(); + gAvatarWaterProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB)); + gAvatarWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + // Note: no cloth under water: + gAvatarWaterProgram.mShaderLevel = llmin(mShaderLevel[SHADER_AVATAR], 1); + gAvatarWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gAvatarWaterProgram.createShader(NULL, NULL); + } + + /// Keep track of avatar levels + if (gAvatarProgram.mShaderLevel != mShaderLevel[SHADER_AVATAR]) + { + mMaxAvatarShaderLevel = mShaderLevel[SHADER_AVATAR] = gAvatarProgram.mShaderLevel; + } + } + + if (success) + { + gAvatarPickProgram.mName = "Avatar Pick Shader"; + gAvatarPickProgram.mFeatures.hasSkinning = true; + gAvatarPickProgram.mFeatures.disableTextureIndex = true; + gAvatarPickProgram.mShaderFiles.clear(); + gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarV.glsl", GL_VERTEX_SHADER_ARB)); + gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarF.glsl", GL_FRAGMENT_SHADER_ARB)); + gAvatarPickProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR]; + success = gAvatarPickProgram.createShader(NULL, NULL); + } + + if (success) + { + gAvatarEyeballProgram.mName = "Avatar Eyeball Program"; + gAvatarEyeballProgram.mFeatures.calculatesLighting = true; + gAvatarEyeballProgram.mFeatures.isSpecular = true; + gAvatarEyeballProgram.mFeatures.calculatesAtmospherics = true; + gAvatarEyeballProgram.mFeatures.hasGamma = true; + gAvatarEyeballProgram.mFeatures.hasAtmospherics = true; + gAvatarEyeballProgram.mFeatures.hasLighting = true; + gAvatarEyeballProgram.mFeatures.hasAlphaMask = true; + gAvatarEyeballProgram.mFeatures.disableTextureIndex = true; + gAvatarEyeballProgram.mShaderFiles.clear(); + gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER_ARB)); + gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballF.glsl", GL_FRAGMENT_SHADER_ARB)); + gAvatarEyeballProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR]; + success = gAvatarEyeballProgram.createShader(NULL, NULL); + } + + if( !success ) + { + mShaderLevel[SHADER_AVATAR] = 0; + mMaxAvatarShaderLevel = 0; + return FALSE; + } + + return TRUE; +} - if (success) - { - gObjectSimpleNonIndexedWaterProgram.mName = "Non indexed Water Shader"; - gObjectSimpleNonIndexedWaterProgram.mFeatures.calculatesLighting = true; - gObjectSimpleNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectSimpleNonIndexedWaterProgram.mFeatures.hasWaterFog = true; - gObjectSimpleNonIndexedWaterProgram.mFeatures.hasAtmospherics = true; - gObjectSimpleNonIndexedWaterProgram.mFeatures.hasLighting = true; - gObjectSimpleNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; - gObjectSimpleNonIndexedWaterProgram.mShaderFiles.clear(); - gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectSimpleNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectSimpleNonIndexedWaterProgram.createShader(NULL, NULL); - } +BOOL LLViewerShaderMgr::loadShadersInterface() +{ + BOOL success = TRUE; + + if (mShaderLevel[SHADER_INTERFACE] == 0) + { + gHighlightProgram.unload(); + return TRUE; + } + + if (success) + { + gHighlightProgram.mName = "Highlight Shader"; + gHighlightProgram.mShaderFiles.clear(); + gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER_ARB)); + gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gHighlightProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gHighlightProgram.createShader(NULL, NULL); + } + + if (success) + { + gHighlightNormalProgram.mName = "Highlight Normals Shader"; + gHighlightNormalProgram.mShaderFiles.clear(); + gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightNormV.glsl", GL_VERTEX_SHADER_ARB)); + gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gHighlightNormalProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gHighlightNormalProgram.createShader(NULL, NULL); + } + + if (success) + { + gHighlightSpecularProgram.mName = "Highlight Spec Shader"; + gHighlightSpecularProgram.mShaderFiles.clear(); + gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightSpecV.glsl", GL_VERTEX_SHADER_ARB)); + gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gHighlightSpecularProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gHighlightSpecularProgram.createShader(NULL, NULL); + } + + if (success) + { + gUIProgram.mName = "UI Shader"; + gUIProgram.mShaderFiles.clear(); + gUIProgram.mShaderFiles.push_back(make_pair("interface/uiV.glsl", GL_VERTEX_SHADER_ARB)); + gUIProgram.mShaderFiles.push_back(make_pair("interface/uiF.glsl", GL_FRAGMENT_SHADER_ARB)); + gUIProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gUIProgram.createShader(NULL, NULL); + } + + if (success) + { + gPathfindingProgram.mName = "Pathfinding Shader"; + gPathfindingProgram.mShaderFiles.clear(); + gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingV.glsl", GL_VERTEX_SHADER_ARB)); + gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER_ARB)); + gPathfindingProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gPathfindingProgram.createShader(NULL, NULL); + } + + if (success) + { + gPathfindingNoNormalsProgram.mName = "PathfindingNoNormals Shader"; + gPathfindingNoNormalsProgram.mShaderFiles.clear(); + gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingNoNormalV.glsl", GL_VERTEX_SHADER_ARB)); + gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER_ARB)); + gPathfindingNoNormalsProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gPathfindingNoNormalsProgram.createShader(NULL, NULL); + } + + if (success) + { + gCustomAlphaProgram.mName = "Custom Alpha Shader"; + gCustomAlphaProgram.mShaderFiles.clear(); + gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaV.glsl", GL_VERTEX_SHADER_ARB)); + gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gCustomAlphaProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gCustomAlphaProgram.createShader(NULL, NULL); + } + + if (success) + { + gSplatTextureRectProgram.mName = "Splat Texture Rect Shader"; + gSplatTextureRectProgram.mShaderFiles.clear(); + gSplatTextureRectProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectV.glsl", GL_VERTEX_SHADER_ARB)); + gSplatTextureRectProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSplatTextureRectProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gSplatTextureRectProgram.createShader(NULL, NULL); + if (success) + { + gSplatTextureRectProgram.bind(); + gSplatTextureRectProgram.uniform1i(sScreenMap, 0); + gSplatTextureRectProgram.unbind(); + } + } + + if (success) + { + gGlowCombineProgram.mName = "Glow Combine Shader"; + gGlowCombineProgram.mShaderFiles.clear(); + gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineV.glsl", GL_VERTEX_SHADER_ARB)); + gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineF.glsl", GL_FRAGMENT_SHADER_ARB)); + gGlowCombineProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gGlowCombineProgram.createShader(NULL, NULL); + if (success) + { + gGlowCombineProgram.bind(); + gGlowCombineProgram.uniform1i(sGlowMap, 0); + gGlowCombineProgram.uniform1i(sScreenMap, 1); + gGlowCombineProgram.unbind(); + } + } + + if (success) + { + gGlowCombineFXAAProgram.mName = "Glow CombineFXAA Shader"; + gGlowCombineFXAAProgram.mShaderFiles.clear(); + gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAV.glsl", GL_VERTEX_SHADER_ARB)); + gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAF.glsl", GL_FRAGMENT_SHADER_ARB)); + gGlowCombineFXAAProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gGlowCombineFXAAProgram.createShader(NULL, NULL); + if (success) + { + gGlowCombineFXAAProgram.bind(); + gGlowCombineFXAAProgram.uniform1i(sGlowMap, 0); + gGlowCombineFXAAProgram.uniform1i(sScreenMap, 1); + gGlowCombineFXAAProgram.unbind(); + } + } + + + if (success) + { + gTwoTextureAddProgram.mName = "Two Texture Add Shader"; + gTwoTextureAddProgram.mShaderFiles.clear(); + gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddV.glsl", GL_VERTEX_SHADER_ARB)); + gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddF.glsl", GL_FRAGMENT_SHADER_ARB)); + gTwoTextureAddProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gTwoTextureAddProgram.createShader(NULL, NULL); + if (success) + { + gTwoTextureAddProgram.bind(); + gTwoTextureAddProgram.uniform1i(sTex0, 0); + gTwoTextureAddProgram.uniform1i(sTex1, 1); + } + } - if (success) - { - gObjectSimpleNonIndexedTexGenWaterProgram.mName = "Non indexed tex-gen Water Shader"; - gObjectSimpleNonIndexedTexGenWaterProgram.mFeatures.calculatesLighting = true; - gObjectSimpleNonIndexedTexGenWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectSimpleNonIndexedTexGenWaterProgram.mFeatures.hasWaterFog = true; - gObjectSimpleNonIndexedTexGenWaterProgram.mFeatures.hasAtmospherics = true; - gObjectSimpleNonIndexedTexGenWaterProgram.mFeatures.hasLighting = true; - gObjectSimpleNonIndexedTexGenWaterProgram.mFeatures.disableTextureIndex = true; - gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.clear(); - gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleTexGenV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleNonIndexedTexGenWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectSimpleNonIndexedTexGenWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectSimpleNonIndexedTexGenWaterProgram.createShader(NULL, NULL); - } +#ifdef LL_WINDOWS + if (success) + { + gTwoTextureCompareProgram.mName = "Two Texture Compare Shader"; + gTwoTextureCompareProgram.mShaderFiles.clear(); + gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareV.glsl", GL_VERTEX_SHADER_ARB)); + gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareF.glsl", GL_FRAGMENT_SHADER_ARB)); + gTwoTextureCompareProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gTwoTextureCompareProgram.createShader(NULL, NULL); + if (success) + { + gTwoTextureCompareProgram.bind(); + gTwoTextureCompareProgram.uniform1i(sTex0, 0); + gTwoTextureCompareProgram.uniform1i(sTex1, 1); + gTwoTextureCompareProgram.uniform1i(sDitherTex, 2); + } + } + + if (success) + { + gOneTextureFilterProgram.mName = "One Texture Filter Shader"; + gOneTextureFilterProgram.mShaderFiles.clear(); + gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterV.glsl", GL_VERTEX_SHADER_ARB)); + gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gOneTextureFilterProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gOneTextureFilterProgram.createShader(NULL, NULL); + if (success) + { + gOneTextureFilterProgram.bind(); + gOneTextureFilterProgram.uniform1i(sTex0, 0); + } + } +#endif + + if (success) + { + gOneTextureNoColorProgram.mName = "One Texture No Color Shader"; + gOneTextureNoColorProgram.mShaderFiles.clear(); + gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorV.glsl", GL_VERTEX_SHADER_ARB)); + gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorF.glsl", GL_FRAGMENT_SHADER_ARB)); + gOneTextureNoColorProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gOneTextureNoColorProgram.createShader(NULL, NULL); + if (success) + { + gOneTextureNoColorProgram.bind(); + gOneTextureNoColorProgram.uniform1i(sTex0, 0); + } + } + + if (success) + { + gSolidColorProgram.mName = "Solid Color Shader"; + gSolidColorProgram.mShaderFiles.clear(); + gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorV.glsl", GL_VERTEX_SHADER_ARB)); + gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSolidColorProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gSolidColorProgram.createShader(NULL, NULL); + if (success) + { + gSolidColorProgram.bind(); + gSolidColorProgram.uniform1i(sTex0, 0); + gSolidColorProgram.unbind(); + } + } + + if (success) + { + gOcclusionProgram.mName = "Occlusion Shader"; + gOcclusionProgram.mShaderFiles.clear(); + gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionV.glsl", GL_VERTEX_SHADER_ARB)); + gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB)); + gOcclusionProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gOcclusionProgram.createShader(NULL, NULL); + } + + if (success) + { + gOcclusionCubeProgram.mName = "Occlusion Cube Shader"; + gOcclusionCubeProgram.mShaderFiles.clear(); + gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionCubeV.glsl", GL_VERTEX_SHADER_ARB)); + gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB)); + gOcclusionCubeProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gOcclusionCubeProgram.createShader(NULL, NULL); + } + + if (success) + { + gDebugProgram.mName = "Debug Shader"; + gDebugProgram.mShaderFiles.clear(); + gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER_ARB)); + gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDebugProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gDebugProgram.createShader(NULL, NULL); + } + + if (success) + { + gClipProgram.mName = "Clip Shader"; + gClipProgram.mShaderFiles.clear(); + gClipProgram.mShaderFiles.push_back(make_pair("interface/clipV.glsl", GL_VERTEX_SHADER_ARB)); + gClipProgram.mShaderFiles.push_back(make_pair("interface/clipF.glsl", GL_FRAGMENT_SHADER_ARB)); + gClipProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gClipProgram.createShader(NULL, NULL); + } + + if (success) + { + gDownsampleDepthProgram.mName = "DownsampleDepth Shader"; + gDownsampleDepthProgram.mShaderFiles.clear(); + gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB)); + gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDownsampleDepthProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gDownsampleDepthProgram.createShader(NULL, NULL); + } + + if (success) + { + gBenchmarkProgram.mName = "Benchmark Shader"; + gBenchmarkProgram.mShaderFiles.clear(); + gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkV.glsl", GL_VERTEX_SHADER_ARB)); + gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkF.glsl", GL_FRAGMENT_SHADER_ARB)); + gBenchmarkProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gBenchmarkProgram.createShader(NULL, NULL); + } + + if (success) + { + gDownsampleDepthRectProgram.mName = "DownsampleDepthRect Shader"; + gDownsampleDepthRectProgram.mShaderFiles.clear(); + gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB)); + gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthRectF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDownsampleDepthRectProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gDownsampleDepthRectProgram.createShader(NULL, NULL); + } + + if (success) + { + gAlphaMaskProgram.mName = "Alpha Mask Shader"; + gAlphaMaskProgram.mShaderFiles.clear(); + gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskV.glsl", GL_VERTEX_SHADER_ARB)); + gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskF.glsl", GL_FRAGMENT_SHADER_ARB)); + gAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gAlphaMaskProgram.createShader(NULL, NULL); + } + + if( !success ) + { + mShaderLevel[SHADER_INTERFACE] = 0; + return FALSE; + } + + return TRUE; +} + +BOOL LLViewerShaderMgr::loadShadersWindLight() +{ + BOOL success = TRUE; + + if (mShaderLevel[SHADER_WINDLIGHT] < 2) + { + gWLSkyProgram.unload(); + gWLCloudProgram.unload(); + gWLSunProgram.unload(); + gWLMoonProgram.unload(); + return TRUE; + } if (success) { - gObjectAlphaMaskNonIndexedProgram.mName = "Non indexed alpha mask Shader"; - gObjectAlphaMaskNonIndexedProgram.mFeatures.calculatesLighting = true; - gObjectAlphaMaskNonIndexedProgram.mFeatures.calculatesAtmospherics = true; - gObjectAlphaMaskNonIndexedProgram.mFeatures.hasGamma = true; - gObjectAlphaMaskNonIndexedProgram.mFeatures.hasAtmospherics = true; - gObjectAlphaMaskNonIndexedProgram.mFeatures.hasLighting = true; - gObjectAlphaMaskNonIndexedProgram.mFeatures.disableTextureIndex = true; - gObjectAlphaMaskNonIndexedProgram.mFeatures.hasAlphaMask = true; - gObjectAlphaMaskNonIndexedProgram.mShaderFiles.clear(); - gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleNonIndexedV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectAlphaMaskNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectAlphaMaskNonIndexedProgram.createShader(NULL, NULL); + gWLSkyProgram.mName = "Windlight Sky Shader"; + //gWLSkyProgram.mFeatures.hasGamma = true; + gWLSkyProgram.mShaderFiles.clear(); + gWLSkyProgram.mFeatures.calculatesAtmospherics = true; + gWLSkyProgram.mFeatures.hasTransport = true; + gWLSkyProgram.mFeatures.hasGamma = true; + gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyV.glsl", GL_VERTEX_SHADER_ARB)); + gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gWLSkyProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT]; + gWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY; + success = gWLSkyProgram.createShader(NULL, NULL); } - + if (success) { - gObjectAlphaMaskNonIndexedWaterProgram.mName = "Non indexed alpha mask Water Shader"; - gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.calculatesLighting = true; - gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasWaterFog = true; - gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasAtmospherics = true; - gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasLighting = true; - gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; - gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasAlphaMask = true; - gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.clear(); - gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleNonIndexedV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectAlphaMaskNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectAlphaMaskNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectAlphaMaskNonIndexedWaterProgram.createShader(NULL, NULL); + gWLCloudProgram.mName = "Windlight Cloud Program"; + gWLCloudProgram.mShaderFiles.clear(); + gWLCloudProgram.mFeatures.calculatesAtmospherics = true; + gWLCloudProgram.mFeatures.hasTransport = true; + gWLCloudProgram.mFeatures.hasGamma = true; + gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsV.glsl", GL_VERTEX_SHADER_ARB)); + gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB)); + gWLCloudProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT]; + gWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY; + success = gWLCloudProgram.createShader(NULL, NULL); } - if (success) - { - gObjectAlphaMaskNoColorProgram.mName = "No color alpha mask Shader"; - gObjectAlphaMaskNoColorProgram.mFeatures.calculatesLighting = true; - gObjectAlphaMaskNoColorProgram.mFeatures.calculatesAtmospherics = true; - gObjectAlphaMaskNoColorProgram.mFeatures.hasGamma = true; - gObjectAlphaMaskNoColorProgram.mFeatures.hasAtmospherics = true; - gObjectAlphaMaskNoColorProgram.mFeatures.hasLighting = true; - gObjectAlphaMaskNoColorProgram.mFeatures.disableTextureIndex = true; - gObjectAlphaMaskNoColorProgram.mFeatures.hasAlphaMask = true; - gObjectAlphaMaskNoColorProgram.mShaderFiles.clear(); - gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectAlphaMaskNoColorProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectAlphaMaskNoColorWaterProgram.mName = "No color alpha mask Water Shader"; - gObjectAlphaMaskNoColorWaterProgram.mFeatures.calculatesLighting = true; - gObjectAlphaMaskNoColorWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectAlphaMaskNoColorWaterProgram.mFeatures.hasWaterFog = true; - gObjectAlphaMaskNoColorWaterProgram.mFeatures.hasAtmospherics = true; - gObjectAlphaMaskNoColorWaterProgram.mFeatures.hasLighting = true; - gObjectAlphaMaskNoColorWaterProgram.mFeatures.disableTextureIndex = true; - gObjectAlphaMaskNoColorWaterProgram.mFeatures.hasAlphaMask = true; - gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.clear(); - gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectAlphaMaskNoColorWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectAlphaMaskNoColorWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectAlphaMaskNoColorWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gTreeProgram.mName = "Tree Shader"; - gTreeProgram.mFeatures.calculatesLighting = true; - gTreeProgram.mFeatures.calculatesAtmospherics = true; - gTreeProgram.mFeatures.hasGamma = true; - gTreeProgram.mFeatures.hasAtmospherics = true; - gTreeProgram.mFeatures.hasLighting = true; - gTreeProgram.mFeatures.disableTextureIndex = true; - gTreeProgram.mFeatures.hasAlphaMask = true; - gTreeProgram.mShaderFiles.clear(); - gTreeProgram.mShaderFiles.push_back(make_pair("objects/treeV.glsl", GL_VERTEX_SHADER_ARB)); - gTreeProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gTreeProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gTreeProgram.createShader(NULL, NULL); - } - - if (success) - { - gTreeWaterProgram.mName = "Tree Water Shader"; - gTreeWaterProgram.mFeatures.calculatesLighting = true; - gTreeWaterProgram.mFeatures.calculatesAtmospherics = true; - gTreeWaterProgram.mFeatures.hasWaterFog = true; - gTreeWaterProgram.mFeatures.hasAtmospherics = true; - gTreeWaterProgram.mFeatures.hasLighting = true; - gTreeWaterProgram.mFeatures.disableTextureIndex = true; - gTreeWaterProgram.mFeatures.hasAlphaMask = true; - gTreeWaterProgram.mShaderFiles.clear(); - gTreeWaterProgram.mShaderFiles.push_back(make_pair("objects/treeV.glsl", GL_VERTEX_SHADER_ARB)); - gTreeWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gTreeWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gTreeWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gTreeWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightNonIndexedProgram.mName = "Non Indexed Fullbright Shader"; - gObjectFullbrightNonIndexedProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightNonIndexedProgram.mFeatures.hasGamma = true; - gObjectFullbrightNonIndexedProgram.mFeatures.hasTransport = true; - gObjectFullbrightNonIndexedProgram.mFeatures.isFullbright = true; - gObjectFullbrightNonIndexedProgram.mFeatures.disableTextureIndex = true; - gObjectFullbrightNonIndexedProgram.mFeatures.hasSrgb = true; - gObjectFullbrightNonIndexedProgram.mShaderFiles.clear(); - gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectFullbrightNonIndexedProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightNonIndexedWaterProgram.mName = "Non Indexed Fullbright Water Shader"; - gObjectFullbrightNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightNonIndexedWaterProgram.mFeatures.isFullbright = true; - gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasWaterFog = true; - gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasTransport = true; - gObjectFullbrightNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; - gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasSrgb = true; - gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.clear(); - gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectFullbrightNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectFullbrightNonIndexedWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectEmissiveNonIndexedProgram.mName = "Non Indexed Emissive Shader"; - gObjectEmissiveNonIndexedProgram.mFeatures.calculatesAtmospherics = true; - gObjectEmissiveNonIndexedProgram.mFeatures.hasGamma = true; - gObjectEmissiveNonIndexedProgram.mFeatures.hasTransport = true; - gObjectEmissiveNonIndexedProgram.mFeatures.isFullbright = true; - gObjectEmissiveNonIndexedProgram.mFeatures.disableTextureIndex = true; - gObjectEmissiveNonIndexedProgram.mFeatures.hasSrgb = true; - gObjectEmissiveNonIndexedProgram.mShaderFiles.clear(); - gObjectEmissiveNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectEmissiveNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectEmissiveNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectEmissiveNonIndexedProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectEmissiveNonIndexedWaterProgram.mName = "Non Indexed Emissive Water Shader"; - gObjectEmissiveNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectEmissiveNonIndexedWaterProgram.mFeatures.isFullbright = true; - gObjectEmissiveNonIndexedWaterProgram.mFeatures.hasWaterFog = true; - gObjectEmissiveNonIndexedWaterProgram.mFeatures.hasTransport = true; - gObjectEmissiveNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; - gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.clear(); - gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectEmissiveNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectEmissiveNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectEmissiveNonIndexedWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightNoColorProgram.mName = "Non Indexed no color Fullbright Shader"; - gObjectFullbrightNoColorProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightNoColorProgram.mFeatures.hasGamma = true; - gObjectFullbrightNoColorProgram.mFeatures.hasTransport = true; - gObjectFullbrightNoColorProgram.mFeatures.isFullbright = true; - gObjectFullbrightNoColorProgram.mFeatures.hasSrgb = true; - gObjectFullbrightNoColorProgram.mFeatures.disableTextureIndex = true; - gObjectFullbrightNoColorProgram.mShaderFiles.clear(); - gObjectFullbrightNoColorProgram.mShaderFiles.push_back(make_pair("objects/fullbrightNoColorV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightNoColorProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightNoColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectFullbrightNoColorProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightNoColorWaterProgram.mName = "Non Indexed no color Fullbright Water Shader"; - gObjectFullbrightNoColorWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightNoColorWaterProgram.mFeatures.isFullbright = true; - gObjectFullbrightNoColorWaterProgram.mFeatures.hasWaterFog = true; - gObjectFullbrightNoColorWaterProgram.mFeatures.hasTransport = true; - gObjectFullbrightNoColorWaterProgram.mFeatures.disableTextureIndex = true; - gObjectFullbrightNoColorWaterProgram.mShaderFiles.clear(); - gObjectFullbrightNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightNoColorV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightNoColorWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectFullbrightNoColorWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectFullbrightNoColorWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectShinyNonIndexedProgram.mName = "Non Indexed Shiny Shader"; - gObjectShinyNonIndexedProgram.mFeatures.calculatesAtmospherics = true; - gObjectShinyNonIndexedProgram.mFeatures.calculatesLighting = true; - gObjectShinyNonIndexedProgram.mFeatures.hasGamma = true; - gObjectShinyNonIndexedProgram.mFeatures.hasAtmospherics = true; - gObjectShinyNonIndexedProgram.mFeatures.isShiny = true; - gObjectShinyNonIndexedProgram.mFeatures.disableTextureIndex = true; - gObjectShinyNonIndexedProgram.mShaderFiles.clear(); - gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectShinyNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectShinyNonIndexedProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectShinyNonIndexedWaterProgram.mName = "Non Indexed Shiny Water Shader"; - gObjectShinyNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectShinyNonIndexedWaterProgram.mFeatures.calculatesLighting = true; - gObjectShinyNonIndexedWaterProgram.mFeatures.isShiny = true; - gObjectShinyNonIndexedWaterProgram.mFeatures.hasWaterFog = true; - gObjectShinyNonIndexedWaterProgram.mFeatures.hasAtmospherics = true; - gObjectShinyNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; - gObjectShinyNonIndexedWaterProgram.mShaderFiles.clear(); - gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectShinyNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectShinyNonIndexedWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightShinyNonIndexedProgram.mName = "Non Indexed Fullbright Shiny Shader"; - gObjectFullbrightShinyNonIndexedProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightShinyNonIndexedProgram.mFeatures.isFullbright = true; - gObjectFullbrightShinyNonIndexedProgram.mFeatures.isShiny = true; - gObjectFullbrightShinyNonIndexedProgram.mFeatures.hasGamma = true; - gObjectFullbrightShinyNonIndexedProgram.mFeatures.hasTransport = true; - gObjectFullbrightShinyNonIndexedProgram.mFeatures.disableTextureIndex = true; - gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.clear(); - gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightShinyNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectFullbrightShinyNonIndexedProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightShinyNonIndexedWaterProgram.mName = "Non Indexed Fullbright Shiny Water Shader"; - gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.isFullbright = true; - gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.isShiny = true; - gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasGamma = true; - gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasTransport = true; - gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasWaterFog = true; - gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; - gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.clear(); - gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightShinyNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectFullbrightShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectFullbrightShinyNonIndexedWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gImpostorProgram.mName = "Impostor Shader"; - gImpostorProgram.mFeatures.disableTextureIndex = true; - gImpostorProgram.mFeatures.hasSrgb = true; - gImpostorProgram.mShaderFiles.clear(); - gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorV.glsl", GL_VERTEX_SHADER_ARB)); - gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorF.glsl", GL_FRAGMENT_SHADER_ARB)); - gImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gImpostorProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectPreviewProgram.mName = "Simple Shader"; - gObjectPreviewProgram.mFeatures.calculatesLighting = false; - gObjectPreviewProgram.mFeatures.calculatesAtmospherics = false; - gObjectPreviewProgram.mFeatures.hasGamma = false; - gObjectPreviewProgram.mFeatures.hasAtmospherics = false; - gObjectPreviewProgram.mFeatures.hasLighting = false; - gObjectPreviewProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectPreviewProgram.mFeatures.disableTextureIndex = true; - gObjectPreviewProgram.mShaderFiles.clear(); - gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectPreviewProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectPreviewProgram.createShader(NULL, NULL); - gObjectPreviewProgram.mFeatures.hasLighting = true; - } - - if (success) - { - gObjectSimpleProgram.mName = "Simple Shader"; - gObjectSimpleProgram.mFeatures.calculatesLighting = true; - gObjectSimpleProgram.mFeatures.calculatesAtmospherics = true; - gObjectSimpleProgram.mFeatures.hasGamma = true; - gObjectSimpleProgram.mFeatures.hasAtmospherics = true; - gObjectSimpleProgram.mFeatures.hasLighting = true; - gObjectSimpleProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectSimpleProgram.mShaderFiles.clear(); - gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectSimpleProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectSimpleImpostorProgram.mName = "Simple Impostor Shader"; - gObjectSimpleImpostorProgram.mFeatures.calculatesLighting = true; - gObjectSimpleImpostorProgram.mFeatures.calculatesAtmospherics = true; - gObjectSimpleImpostorProgram.mFeatures.hasGamma = true; - gObjectSimpleImpostorProgram.mFeatures.hasAtmospherics = true; - gObjectSimpleImpostorProgram.mFeatures.hasLighting = true; - gObjectSimpleImpostorProgram.mFeatures.mIndexedTextureChannels = 0; - // force alpha mask version of lighting so we can weed out - // transparent pixels from impostor temp buffer - // - gObjectSimpleImpostorProgram.mFeatures.hasAlphaMask = true; - gObjectSimpleImpostorProgram.mShaderFiles.clear(); - gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - - success = gObjectSimpleImpostorProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectSimpleWaterProgram.mName = "Simple Water Shader"; - gObjectSimpleWaterProgram.mFeatures.calculatesLighting = true; - gObjectSimpleWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectSimpleWaterProgram.mFeatures.hasWaterFog = true; - gObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true; - gObjectSimpleWaterProgram.mFeatures.hasLighting = true; - gObjectSimpleWaterProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectSimpleWaterProgram.mShaderFiles.clear(); - gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectSimpleWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectBumpProgram.mName = "Bump Shader"; - /*gObjectBumpProgram.mFeatures.calculatesLighting = true; - gObjectBumpProgram.mFeatures.calculatesAtmospherics = true; - gObjectBumpProgram.mFeatures.hasGamma = true; - gObjectBumpProgram.mFeatures.hasAtmospherics = true; - gObjectBumpProgram.mFeatures.hasLighting = true; - gObjectBumpProgram.mFeatures.mIndexedTextureChannels = 0;*/ - gObjectBumpProgram.mFeatures.encodesNormal = true; - gObjectBumpProgram.mShaderFiles.clear(); - gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectBumpProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectBumpProgram.createShader(NULL, NULL); - if (success) - { //lldrawpoolbump assumes "texture0" has channel 0 and "texture1" has channel 1 - gObjectBumpProgram.bind(); - gObjectBumpProgram.uniform1i(sTexture0, 0); - gObjectBumpProgram.uniform1i(sTexture1, 1); - gObjectBumpProgram.unbind(); - } - } - - - if (success) - { - gObjectSimpleAlphaMaskProgram.mName = "Simple Alpha Mask Shader"; - gObjectSimpleAlphaMaskProgram.mFeatures.calculatesLighting = true; - gObjectSimpleAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; - gObjectSimpleAlphaMaskProgram.mFeatures.hasGamma = true; - gObjectSimpleAlphaMaskProgram.mFeatures.hasAtmospherics = true; - gObjectSimpleAlphaMaskProgram.mFeatures.hasLighting = true; - gObjectSimpleAlphaMaskProgram.mFeatures.hasAlphaMask = true; - gObjectSimpleAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectSimpleAlphaMaskProgram.mShaderFiles.clear(); - gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectSimpleAlphaMaskProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectSimpleWaterAlphaMaskProgram.mName = "Simple Water Alpha Mask Shader"; - gObjectSimpleWaterAlphaMaskProgram.mFeatures.calculatesLighting = true; - gObjectSimpleWaterAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; - gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasWaterFog = true; - gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasAtmospherics = true; - gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasLighting = true; - gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasAlphaMask = true; - gObjectSimpleWaterAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.clear(); - gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectSimpleWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectSimpleWaterAlphaMaskProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightProgram.mName = "Fullbright Shader"; - gObjectFullbrightProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightProgram.mFeatures.hasGamma = true; - gObjectFullbrightProgram.mFeatures.hasTransport = true; - gObjectFullbrightProgram.mFeatures.isFullbright = true; - gObjectFullbrightProgram.mFeatures.hasSrgb = true; - gObjectFullbrightProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectFullbrightProgram.mShaderFiles.clear(); - gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectFullbrightProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightWaterProgram.mName = "Fullbright Water Shader"; - gObjectFullbrightWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightWaterProgram.mFeatures.isFullbright = true; - gObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true; - gObjectFullbrightWaterProgram.mFeatures.hasTransport = true; - gObjectFullbrightWaterProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectFullbrightWaterProgram.mShaderFiles.clear(); - gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectFullbrightWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectEmissiveProgram.mName = "Emissive Shader"; - gObjectEmissiveProgram.mFeatures.calculatesAtmospherics = true; - gObjectEmissiveProgram.mFeatures.hasGamma = true; - gObjectEmissiveProgram.mFeatures.hasTransport = true; - gObjectEmissiveProgram.mFeatures.isFullbright = true; - gObjectEmissiveProgram.mFeatures.hasSrgb = true; - gObjectEmissiveProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectEmissiveProgram.mShaderFiles.clear(); - gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectEmissiveProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectEmissiveWaterProgram.mName = "Emissive Water Shader"; - gObjectEmissiveWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectEmissiveWaterProgram.mFeatures.isFullbright = true; - gObjectEmissiveWaterProgram.mFeatures.hasWaterFog = true; - gObjectEmissiveWaterProgram.mFeatures.hasTransport = true; - gObjectEmissiveWaterProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectEmissiveWaterProgram.mShaderFiles.clear(); - gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectEmissiveWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectEmissiveWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightAlphaMaskProgram.mName = "Fullbright Alpha Mask Shader"; - gObjectFullbrightAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightAlphaMaskProgram.mFeatures.hasGamma = true; - gObjectFullbrightAlphaMaskProgram.mFeatures.hasTransport = true; - gObjectFullbrightAlphaMaskProgram.mFeatures.isFullbright = true; - gObjectFullbrightAlphaMaskProgram.mFeatures.hasAlphaMask = true; - gObjectFullbrightAlphaMaskProgram.mFeatures.hasSrgb = true; - gObjectFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectFullbrightAlphaMaskProgram.mShaderFiles.clear(); - gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectFullbrightAlphaMaskProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightWaterAlphaMaskProgram.mName = "Fullbright Water Shader"; - gObjectFullbrightWaterAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightWaterAlphaMaskProgram.mFeatures.isFullbright = true; - gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasWaterFog = true; - gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasTransport = true; - gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasAlphaMask = true; - gObjectFullbrightWaterAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.clear(); - gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectFullbrightWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectFullbrightWaterAlphaMaskProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectShinyProgram.mName = "Shiny Shader"; - gObjectShinyProgram.mFeatures.calculatesAtmospherics = true; - gObjectShinyProgram.mFeatures.calculatesLighting = true; - gObjectShinyProgram.mFeatures.hasGamma = true; - gObjectShinyProgram.mFeatures.hasAtmospherics = true; - gObjectShinyProgram.mFeatures.isShiny = true; - gObjectShinyProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectShinyProgram.mShaderFiles.clear(); - gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectShinyProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectShinyWaterProgram.mName = "Shiny Water Shader"; - gObjectShinyWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectShinyWaterProgram.mFeatures.calculatesLighting = true; - gObjectShinyWaterProgram.mFeatures.isShiny = true; - gObjectShinyWaterProgram.mFeatures.hasWaterFog = true; - gObjectShinyWaterProgram.mFeatures.hasAtmospherics = true; - gObjectShinyWaterProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectShinyWaterProgram.mShaderFiles.clear(); - gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectShinyWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightShinyProgram.mName = "Fullbright Shiny Shader"; - gObjectFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightShinyProgram.mFeatures.isFullbright = true; - gObjectFullbrightShinyProgram.mFeatures.isShiny = true; - gObjectFullbrightShinyProgram.mFeatures.hasGamma = true; - gObjectFullbrightShinyProgram.mFeatures.hasTransport = true; - gObjectFullbrightShinyProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectFullbrightShinyProgram.mShaderFiles.clear(); - gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectFullbrightShinyProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightShinyWaterProgram.mName = "Fullbright Shiny Water Shader"; - gObjectFullbrightShinyWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightShinyWaterProgram.mFeatures.isFullbright = true; - gObjectFullbrightShinyWaterProgram.mFeatures.isShiny = true; - gObjectFullbrightShinyWaterProgram.mFeatures.hasGamma = true; - gObjectFullbrightShinyWaterProgram.mFeatures.hasTransport = true; - gObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true; - gObjectFullbrightShinyWaterProgram.mFeatures.mIndexedTextureChannels = 0; - gObjectFullbrightShinyWaterProgram.mShaderFiles.clear(); - gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectFullbrightShinyWaterProgram.createShader(NULL, NULL); - } - - if (mShaderLevel[SHADER_AVATAR] > 0) - { //load hardware skinned attachment shaders - if (success) - { - gSkinnedObjectSimpleProgram.mName = "Skinned Simple Shader"; - gSkinnedObjectSimpleProgram.mFeatures.calculatesLighting = true; - gSkinnedObjectSimpleProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectSimpleProgram.mFeatures.hasGamma = true; - gSkinnedObjectSimpleProgram.mFeatures.hasAtmospherics = true; - gSkinnedObjectSimpleProgram.mFeatures.hasLighting = true; - gSkinnedObjectSimpleProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectSimpleProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectSimpleProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectSimpleProgram.mShaderFiles.clear(); - gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectSimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectSimpleProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectFullbrightProgram.mName = "Skinned Fullbright Shader"; - gSkinnedObjectFullbrightProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectFullbrightProgram.mFeatures.hasGamma = true; - gSkinnedObjectFullbrightProgram.mFeatures.hasTransport = true; - gSkinnedObjectFullbrightProgram.mFeatures.isFullbright = true; - gSkinnedObjectFullbrightProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectFullbrightProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectFullbrightProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectFullbrightProgram.mFeatures.hasSrgb = true; - gSkinnedObjectFullbrightProgram.mShaderFiles.clear(); - gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectFullbrightProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectEmissiveProgram.mName = "Skinned Emissive Shader"; - gSkinnedObjectEmissiveProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectEmissiveProgram.mFeatures.hasGamma = true; - gSkinnedObjectEmissiveProgram.mFeatures.hasTransport = true; - gSkinnedObjectEmissiveProgram.mFeatures.isFullbright = true; - gSkinnedObjectEmissiveProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectEmissiveProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectEmissiveProgram.mFeatures.hasSrgb = true; - gSkinnedObjectEmissiveProgram.mShaderFiles.clear(); - gSkinnedObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectEmissiveProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectEmissiveWaterProgram.mName = "Skinned Emissive Water Shader"; - gSkinnedObjectEmissiveWaterProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectEmissiveWaterProgram.mFeatures.hasGamma = true; - gSkinnedObjectEmissiveWaterProgram.mFeatures.hasTransport = true; - gSkinnedObjectEmissiveWaterProgram.mFeatures.isFullbright = true; - gSkinnedObjectEmissiveWaterProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectEmissiveWaterProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectEmissiveWaterProgram.mFeatures.hasWaterFog = true; - gSkinnedObjectEmissiveWaterProgram.mShaderFiles.clear(); - gSkinnedObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectEmissiveWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectFullbrightShinyProgram.mName = "Skinned Fullbright Shiny Shader"; - gSkinnedObjectFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectFullbrightShinyProgram.mFeatures.hasGamma = true; - gSkinnedObjectFullbrightShinyProgram.mFeatures.hasTransport = true; - gSkinnedObjectFullbrightShinyProgram.mFeatures.isShiny = true; - gSkinnedObjectFullbrightShinyProgram.mFeatures.isFullbright = true; - gSkinnedObjectFullbrightShinyProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectFullbrightShinyProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectFullbrightShinyProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectFullbrightShinyProgram.mShaderFiles.clear(); - gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectFullbrightShinyProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectShinySimpleProgram.mName = "Skinned Shiny Simple Shader"; - gSkinnedObjectShinySimpleProgram.mFeatures.calculatesLighting = true; - gSkinnedObjectShinySimpleProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectShinySimpleProgram.mFeatures.hasGamma = true; - gSkinnedObjectShinySimpleProgram.mFeatures.hasAtmospherics = true; - gSkinnedObjectShinySimpleProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectShinySimpleProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectShinySimpleProgram.mFeatures.isShiny = true; - gSkinnedObjectShinySimpleProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectShinySimpleProgram.mShaderFiles.clear(); - gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectShinySimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectShinySimpleProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectSimpleWaterProgram.mName = "Skinned Simple Water Shader"; - gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesLighting = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasGamma = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasLighting = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasWaterFog = true; - gSkinnedObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear(); - gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectSimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectSimpleWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectFullbrightWaterProgram.mName = "Skinned Fullbright Water Shader"; - gSkinnedObjectFullbrightWaterProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectFullbrightWaterProgram.mFeatures.hasGamma = true; - gSkinnedObjectFullbrightWaterProgram.mFeatures.hasTransport = true; - gSkinnedObjectFullbrightWaterProgram.mFeatures.isFullbright = true; - gSkinnedObjectFullbrightWaterProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectFullbrightWaterProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true; - gSkinnedObjectFullbrightWaterProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gSkinnedObjectFullbrightWaterProgram.mShaderFiles.clear(); - gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectFullbrightWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectFullbrightShinyWaterProgram.mName = "Skinned Fullbright Shiny Water Shader"; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasGamma = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasTransport = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.isShiny = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.isFullbright = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.clear(); - gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectFullbrightShinyWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectShinySimpleWaterProgram.mName = "Skinned Shiny Simple Water Shader"; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.calculatesLighting = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasGamma = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasAtmospherics = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.isShiny = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasWaterFog = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectShinySimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.clear(); - gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectShinySimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectShinySimpleWaterProgram.createShader(NULL, NULL); - } - } - - if( !success ) - { - mShaderLevel[SHADER_OBJECT] = 0; - return FALSE; - } - - return TRUE; -} - -BOOL LLViewerShaderMgr::loadShadersAvatar() -{ - BOOL success = TRUE; - - if (mShaderLevel[SHADER_AVATAR] == 0) - { - gAvatarProgram.unload(); - gAvatarWaterProgram.unload(); - gAvatarEyeballProgram.unload(); - gAvatarPickProgram.unload(); - return TRUE; - } - - if (success) - { - gAvatarProgram.mName = "Avatar Shader"; - gAvatarProgram.mFeatures.hasSkinning = true; - gAvatarProgram.mFeatures.calculatesAtmospherics = true; - gAvatarProgram.mFeatures.calculatesLighting = true; - gAvatarProgram.mFeatures.hasGamma = true; - gAvatarProgram.mFeatures.hasAtmospherics = true; - gAvatarProgram.mFeatures.hasLighting = true; - gAvatarProgram.mFeatures.hasAlphaMask = true; - gAvatarProgram.mFeatures.disableTextureIndex = true; - gAvatarProgram.mShaderFiles.clear(); - gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB)); - gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarF.glsl", GL_FRAGMENT_SHADER_ARB)); - gAvatarProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR]; - success = gAvatarProgram.createShader(NULL, NULL); - - if (success) - { - gAvatarWaterProgram.mName = "Avatar Water Shader"; - gAvatarWaterProgram.mFeatures.hasSkinning = true; - gAvatarWaterProgram.mFeatures.calculatesAtmospherics = true; - gAvatarWaterProgram.mFeatures.calculatesLighting = true; - gAvatarWaterProgram.mFeatures.hasWaterFog = true; - gAvatarWaterProgram.mFeatures.hasAtmospherics = true; - gAvatarWaterProgram.mFeatures.hasLighting = true; - gAvatarWaterProgram.mFeatures.hasAlphaMask = true; - gAvatarWaterProgram.mFeatures.disableTextureIndex = true; - gAvatarWaterProgram.mShaderFiles.clear(); - gAvatarWaterProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB)); - gAvatarWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - // Note: no cloth under water: - gAvatarWaterProgram.mShaderLevel = llmin(mShaderLevel[SHADER_AVATAR], 1); - gAvatarWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gAvatarWaterProgram.createShader(NULL, NULL); - } - - /// Keep track of avatar levels - if (gAvatarProgram.mShaderLevel != mShaderLevel[SHADER_AVATAR]) - { - mMaxAvatarShaderLevel = mShaderLevel[SHADER_AVATAR] = gAvatarProgram.mShaderLevel; - } - } - - if (success) - { - gAvatarPickProgram.mName = "Avatar Pick Shader"; - gAvatarPickProgram.mFeatures.hasSkinning = true; - gAvatarPickProgram.mFeatures.disableTextureIndex = true; - gAvatarPickProgram.mShaderFiles.clear(); - gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarV.glsl", GL_VERTEX_SHADER_ARB)); - gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarF.glsl", GL_FRAGMENT_SHADER_ARB)); - gAvatarPickProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR]; - success = gAvatarPickProgram.createShader(NULL, NULL); - } - - if (success) - { - gAvatarEyeballProgram.mName = "Avatar Eyeball Program"; - gAvatarEyeballProgram.mFeatures.calculatesLighting = true; - gAvatarEyeballProgram.mFeatures.isSpecular = true; - gAvatarEyeballProgram.mFeatures.calculatesAtmospherics = true; - gAvatarEyeballProgram.mFeatures.hasGamma = true; - gAvatarEyeballProgram.mFeatures.hasAtmospherics = true; - gAvatarEyeballProgram.mFeatures.hasLighting = true; - gAvatarEyeballProgram.mFeatures.hasAlphaMask = true; - gAvatarEyeballProgram.mFeatures.disableTextureIndex = true; - gAvatarEyeballProgram.mShaderFiles.clear(); - gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER_ARB)); - gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballF.glsl", GL_FRAGMENT_SHADER_ARB)); - gAvatarEyeballProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR]; - success = gAvatarEyeballProgram.createShader(NULL, NULL); - } - - if( !success ) - { - mShaderLevel[SHADER_AVATAR] = 0; - mMaxAvatarShaderLevel = 0; - return FALSE; - } - - return TRUE; -} - -BOOL LLViewerShaderMgr::loadShadersInterface() -{ - BOOL success = TRUE; - - if (mShaderLevel[SHADER_INTERFACE] == 0) - { - gHighlightProgram.unload(); - return TRUE; - } - - if (success) - { - gHighlightProgram.mName = "Highlight Shader"; - gHighlightProgram.mShaderFiles.clear(); - gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER_ARB)); - gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gHighlightProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gHighlightProgram.createShader(NULL, NULL); - } - - if (success) - { - gHighlightNormalProgram.mName = "Highlight Normals Shader"; - gHighlightNormalProgram.mShaderFiles.clear(); - gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightNormV.glsl", GL_VERTEX_SHADER_ARB)); - gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gHighlightNormalProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gHighlightNormalProgram.createShader(NULL, NULL); - } - - if (success) - { - gHighlightSpecularProgram.mName = "Highlight Spec Shader"; - gHighlightSpecularProgram.mShaderFiles.clear(); - gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightSpecV.glsl", GL_VERTEX_SHADER_ARB)); - gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gHighlightSpecularProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gHighlightSpecularProgram.createShader(NULL, NULL); - } - - if (success) - { - gUIProgram.mName = "UI Shader"; - gUIProgram.mShaderFiles.clear(); - gUIProgram.mShaderFiles.push_back(make_pair("interface/uiV.glsl", GL_VERTEX_SHADER_ARB)); - gUIProgram.mShaderFiles.push_back(make_pair("interface/uiF.glsl", GL_FRAGMENT_SHADER_ARB)); - gUIProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gUIProgram.createShader(NULL, NULL); - } - - if (success) - { - gPathfindingProgram.mName = "Pathfinding Shader"; - gPathfindingProgram.mShaderFiles.clear(); - gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingV.glsl", GL_VERTEX_SHADER_ARB)); - gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER_ARB)); - gPathfindingProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gPathfindingProgram.createShader(NULL, NULL); - } - - if (success) - { - gPathfindingNoNormalsProgram.mName = "PathfindingNoNormals Shader"; - gPathfindingNoNormalsProgram.mShaderFiles.clear(); - gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingNoNormalV.glsl", GL_VERTEX_SHADER_ARB)); - gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER_ARB)); - gPathfindingNoNormalsProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gPathfindingNoNormalsProgram.createShader(NULL, NULL); - } - - if (success) - { - gCustomAlphaProgram.mName = "Custom Alpha Shader"; - gCustomAlphaProgram.mShaderFiles.clear(); - gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaV.glsl", GL_VERTEX_SHADER_ARB)); - gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaF.glsl", GL_FRAGMENT_SHADER_ARB)); - gCustomAlphaProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gCustomAlphaProgram.createShader(NULL, NULL); - } - - if (success) - { - gSplatTextureRectProgram.mName = "Splat Texture Rect Shader"; - gSplatTextureRectProgram.mShaderFiles.clear(); - gSplatTextureRectProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectV.glsl", GL_VERTEX_SHADER_ARB)); - gSplatTextureRectProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSplatTextureRectProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gSplatTextureRectProgram.createShader(NULL, NULL); - if (success) - { - gSplatTextureRectProgram.bind(); - gSplatTextureRectProgram.uniform1i(sScreenMap, 0); - gSplatTextureRectProgram.unbind(); - } - } - - if (success) - { - gGlowCombineProgram.mName = "Glow Combine Shader"; - gGlowCombineProgram.mShaderFiles.clear(); - gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineV.glsl", GL_VERTEX_SHADER_ARB)); - gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineF.glsl", GL_FRAGMENT_SHADER_ARB)); - gGlowCombineProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gGlowCombineProgram.createShader(NULL, NULL); - if (success) - { - gGlowCombineProgram.bind(); - gGlowCombineProgram.uniform1i(sGlowMap, 0); - gGlowCombineProgram.uniform1i(sScreenMap, 1); - gGlowCombineProgram.unbind(); - } - } - - if (success) - { - gGlowCombineFXAAProgram.mName = "Glow CombineFXAA Shader"; - gGlowCombineFXAAProgram.mShaderFiles.clear(); - gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAV.glsl", GL_VERTEX_SHADER_ARB)); - gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAF.glsl", GL_FRAGMENT_SHADER_ARB)); - gGlowCombineFXAAProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gGlowCombineFXAAProgram.createShader(NULL, NULL); - if (success) - { - gGlowCombineFXAAProgram.bind(); - gGlowCombineFXAAProgram.uniform1i(sGlowMap, 0); - gGlowCombineFXAAProgram.uniform1i(sScreenMap, 1); - gGlowCombineFXAAProgram.unbind(); - } - } - - - if (success) - { - gTwoTextureAddProgram.mName = "Two Texture Add Shader"; - gTwoTextureAddProgram.mShaderFiles.clear(); - gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddV.glsl", GL_VERTEX_SHADER_ARB)); - gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddF.glsl", GL_FRAGMENT_SHADER_ARB)); - gTwoTextureAddProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gTwoTextureAddProgram.createShader(NULL, NULL); - if (success) - { - gTwoTextureAddProgram.bind(); - gTwoTextureAddProgram.uniform1i(sTex0, 0); - gTwoTextureAddProgram.uniform1i(sTex1, 1); - } - } - -#ifdef LL_WINDOWS - if (success) - { - gTwoTextureCompareProgram.mName = "Two Texture Compare Shader"; - gTwoTextureCompareProgram.mShaderFiles.clear(); - gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareV.glsl", GL_VERTEX_SHADER_ARB)); - gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareF.glsl", GL_FRAGMENT_SHADER_ARB)); - gTwoTextureCompareProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gTwoTextureCompareProgram.createShader(NULL, NULL); - if (success) - { - gTwoTextureCompareProgram.bind(); - gTwoTextureCompareProgram.uniform1i(sTex0, 0); - gTwoTextureCompareProgram.uniform1i(sTex1, 1); - gTwoTextureCompareProgram.uniform1i(sDitherTex, 2); - } - } - - if (success) - { - gOneTextureFilterProgram.mName = "One Texture Filter Shader"; - gOneTextureFilterProgram.mShaderFiles.clear(); - gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterV.glsl", GL_VERTEX_SHADER_ARB)); - gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gOneTextureFilterProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gOneTextureFilterProgram.createShader(NULL, NULL); - if (success) - { - gOneTextureFilterProgram.bind(); - gOneTextureFilterProgram.uniform1i(sTex0, 0); - } - } -#endif - - if (success) - { - gOneTextureNoColorProgram.mName = "One Texture No Color Shader"; - gOneTextureNoColorProgram.mShaderFiles.clear(); - gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorV.glsl", GL_VERTEX_SHADER_ARB)); - gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorF.glsl", GL_FRAGMENT_SHADER_ARB)); - gOneTextureNoColorProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gOneTextureNoColorProgram.createShader(NULL, NULL); - if (success) - { - gOneTextureNoColorProgram.bind(); - gOneTextureNoColorProgram.uniform1i(sTex0, 0); - } - } - - if (success) - { - gSolidColorProgram.mName = "Solid Color Shader"; - gSolidColorProgram.mShaderFiles.clear(); - gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorV.glsl", GL_VERTEX_SHADER_ARB)); - gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSolidColorProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gSolidColorProgram.createShader(NULL, NULL); - if (success) - { - gSolidColorProgram.bind(); - gSolidColorProgram.uniform1i(sTex0, 0); - gSolidColorProgram.unbind(); - } - } - - if (success) - { - gOcclusionProgram.mName = "Occlusion Shader"; - gOcclusionProgram.mShaderFiles.clear(); - gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionV.glsl", GL_VERTEX_SHADER_ARB)); - gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB)); - gOcclusionProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gOcclusionProgram.createShader(NULL, NULL); - } - - if (success) - { - gOcclusionCubeProgram.mName = "Occlusion Cube Shader"; - gOcclusionCubeProgram.mShaderFiles.clear(); - gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionCubeV.glsl", GL_VERTEX_SHADER_ARB)); - gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB)); - gOcclusionCubeProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gOcclusionCubeProgram.createShader(NULL, NULL); - } - - if (success) - { - gDebugProgram.mName = "Debug Shader"; - gDebugProgram.mShaderFiles.clear(); - gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER_ARB)); - gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDebugProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gDebugProgram.createShader(NULL, NULL); - } - - if (success) - { - gClipProgram.mName = "Clip Shader"; - gClipProgram.mShaderFiles.clear(); - gClipProgram.mShaderFiles.push_back(make_pair("interface/clipV.glsl", GL_VERTEX_SHADER_ARB)); - gClipProgram.mShaderFiles.push_back(make_pair("interface/clipF.glsl", GL_FRAGMENT_SHADER_ARB)); - gClipProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gClipProgram.createShader(NULL, NULL); - } - - if (success) - { - gDownsampleDepthProgram.mName = "DownsampleDepth Shader"; - gDownsampleDepthProgram.mShaderFiles.clear(); - gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB)); - gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDownsampleDepthProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gDownsampleDepthProgram.createShader(NULL, NULL); - } - - if (success) - { - gBenchmarkProgram.mName = "Benchmark Shader"; - gBenchmarkProgram.mShaderFiles.clear(); - gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkV.glsl", GL_VERTEX_SHADER_ARB)); - gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkF.glsl", GL_FRAGMENT_SHADER_ARB)); - gBenchmarkProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gBenchmarkProgram.createShader(NULL, NULL); - } - - if (success) - { - gDownsampleDepthRectProgram.mName = "DownsampleDepthRect Shader"; - gDownsampleDepthRectProgram.mShaderFiles.clear(); - gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB)); - gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthRectF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDownsampleDepthRectProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gDownsampleDepthRectProgram.createShader(NULL, NULL); - } - - if (success) - { - gAlphaMaskProgram.mName = "Alpha Mask Shader"; - gAlphaMaskProgram.mShaderFiles.clear(); - gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskV.glsl", GL_VERTEX_SHADER_ARB)); - gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskF.glsl", GL_FRAGMENT_SHADER_ARB)); - gAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gAlphaMaskProgram.createShader(NULL, NULL); - } - - if( !success ) - { - mShaderLevel[SHADER_INTERFACE] = 0; - return FALSE; - } - - return TRUE; -} - -BOOL LLViewerShaderMgr::loadShadersWindLight() -{ - BOOL success = TRUE; - - if (mShaderLevel[SHADER_WINDLIGHT] < 2) - { - gWLSkyProgram.unload(); - gWLCloudProgram.unload(); - gWLCloudShadowProgram.unload(); - gWLSunProgram.unload(); - gWLMoonProgram.unload(); - gDownsampleMinMaxDepthRectProgram.unload(); - gInscatterRectProgram.unload(); - return TRUE; - } - - if (success) - { - gWLSkyProgram.mName = "Windlight Sky Shader"; - //gWLSkyProgram.mFeatures.hasGamma = true; - gWLSkyProgram.mShaderFiles.clear(); - gWLSkyProgram.mFeatures.calculatesAtmospherics = true; - gWLSkyProgram.mFeatures.hasTransport = true; - gWLSkyProgram.mFeatures.hasGamma = true; - gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyV.glsl", GL_VERTEX_SHADER_ARB)); - gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gWLSkyProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT]; - gWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY; - success = gWLSkyProgram.createShader(NULL, NULL); - } - - if (success) - { - gWLCloudProgram.mName = "Windlight Cloud Program"; - //gWLCloudProgram.mFeatures.hasGamma = true; - gWLCloudProgram.mShaderFiles.clear(); - gWLCloudProgram.mFeatures.calculatesAtmospherics = true; - gWLCloudProgram.mFeatures.hasTransport = true; - gWLCloudProgram.mFeatures.hasGamma = true; - gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsV.glsl", GL_VERTEX_SHADER_ARB)); - gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB)); - gWLCloudProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT]; - gWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY; - success = gWLCloudProgram.createShader(NULL, NULL); - } - - /* unused outside of ALM at the moment and failing to link on OSX for reasons only Timmy knows. - if (success) - { - gWLCloudShadowProgram.mName = "Windlight Cloud Shadow Program"; - gWLCloudShadowProgram.mShaderFiles.clear(); - gWLCloudShadowProgram.mFeatures.hasGamma = true; - gWLCloudShadowProgram.mFeatures.hasShadows = true; - gWLCloudShadowProgram.mFeatures.isDeferred = true; - gWLCloudShadowProgram.mShaderFiles.push_back(make_pair("windlight/cloudShadowV.glsl", GL_VERTEX_SHADER_ARB)); - gWLCloudShadowProgram.mShaderFiles.push_back(make_pair("windlight/cloudShadowF.glsl", GL_FRAGMENT_SHADER_ARB)); - gWLCloudShadowProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT]; - gWLCloudShadowProgram.mShaderGroup = LLGLSLShader::SG_SKY; - success = gWLCloudShadowProgram.createShader(NULL, NULL); - }*/ - if (success) { gWLSunProgram.mName = "Windlight Sun Program"; @@ -3893,101 +3842,101 @@ BOOL LLViewerShaderMgr::loadShadersWindLight() success = gWLMoonProgram.createShader(NULL, NULL); } - return success; + return success; } BOOL LLViewerShaderMgr::loadTransformShaders() { - BOOL success = TRUE; - - if (mShaderLevel[SHADER_TRANSFORM] < 1) - { - gTransformPositionProgram.unload(); - gTransformTexCoordProgram.unload(); - gTransformNormalProgram.unload(); - gTransformColorProgram.unload(); - gTransformTangentProgram.unload(); - return TRUE; - } - - if (success) - { + BOOL success = TRUE; + + if (mShaderLevel[SHADER_TRANSFORM] < 1) + { + gTransformPositionProgram.unload(); + gTransformTexCoordProgram.unload(); + gTransformNormalProgram.unload(); + gTransformColorProgram.unload(); + gTransformTangentProgram.unload(); + return TRUE; + } + + if (success) + { gTransformPositionProgram.mName = "Position Transform Shader"; - gTransformPositionProgram.mShaderFiles.clear(); - gTransformPositionProgram.mShaderFiles.push_back(make_pair("transform/positionV.glsl", GL_VERTEX_SHADER_ARB)); - gTransformPositionProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM]; - - const char* varyings[] = { - "position_out", - "texture_index_out", - }; - - success = gTransformPositionProgram.createShader(NULL, NULL, 2, varyings); - } - - if (success) - { - gTransformTexCoordProgram.mName = "TexCoord Transform Shader"; - gTransformTexCoordProgram.mShaderFiles.clear(); - gTransformTexCoordProgram.mShaderFiles.push_back(make_pair("transform/texcoordV.glsl", GL_VERTEX_SHADER_ARB)); - gTransformTexCoordProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM]; - - const char* varyings[] = { - "texcoord_out", - }; - - success = gTransformTexCoordProgram.createShader(NULL, NULL, 1, varyings); - } - - if (success) - { - gTransformNormalProgram.mName = "Normal Transform Shader"; - gTransformNormalProgram.mShaderFiles.clear(); - gTransformNormalProgram.mShaderFiles.push_back(make_pair("transform/normalV.glsl", GL_VERTEX_SHADER_ARB)); - gTransformNormalProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM]; - - const char* varyings[] = { - "normal_out", - }; - - success = gTransformNormalProgram.createShader(NULL, NULL, 1, varyings); - } - - if (success) - { - gTransformColorProgram.mName = "Color Transform Shader"; - gTransformColorProgram.mShaderFiles.clear(); - gTransformColorProgram.mShaderFiles.push_back(make_pair("transform/colorV.glsl", GL_VERTEX_SHADER_ARB)); - gTransformColorProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM]; - - const char* varyings[] = { - "color_out", - }; - - success = gTransformColorProgram.createShader(NULL, NULL, 1, varyings); - } - - if (success) - { - gTransformTangentProgram.mName = "Binormal Transform Shader"; - gTransformTangentProgram.mShaderFiles.clear(); - gTransformTangentProgram.mShaderFiles.push_back(make_pair("transform/binormalV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformPositionProgram.mShaderFiles.clear(); + gTransformPositionProgram.mShaderFiles.push_back(make_pair("transform/positionV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformPositionProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM]; + + const char* varyings[] = { + "position_out", + "texture_index_out", + }; + + success = gTransformPositionProgram.createShader(NULL, NULL, 2, varyings); + } + + if (success) + { + gTransformTexCoordProgram.mName = "TexCoord Transform Shader"; + gTransformTexCoordProgram.mShaderFiles.clear(); + gTransformTexCoordProgram.mShaderFiles.push_back(make_pair("transform/texcoordV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformTexCoordProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM]; + + const char* varyings[] = { + "texcoord_out", + }; + + success = gTransformTexCoordProgram.createShader(NULL, NULL, 1, varyings); + } + + if (success) + { + gTransformNormalProgram.mName = "Normal Transform Shader"; + gTransformNormalProgram.mShaderFiles.clear(); + gTransformNormalProgram.mShaderFiles.push_back(make_pair("transform/normalV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformNormalProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM]; + + const char* varyings[] = { + "normal_out", + }; + + success = gTransformNormalProgram.createShader(NULL, NULL, 1, varyings); + } + + if (success) + { + gTransformColorProgram.mName = "Color Transform Shader"; + gTransformColorProgram.mShaderFiles.clear(); + gTransformColorProgram.mShaderFiles.push_back(make_pair("transform/colorV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformColorProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM]; + + const char* varyings[] = { + "color_out", + }; + + success = gTransformColorProgram.createShader(NULL, NULL, 1, varyings); + } + + if (success) + { + gTransformTangentProgram.mName = "Binormal Transform Shader"; + gTransformTangentProgram.mShaderFiles.clear(); + gTransformTangentProgram.mShaderFiles.push_back(make_pair("transform/binormalV.glsl", GL_VERTEX_SHADER_ARB)); gTransformTangentProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM]; - const char* varyings[] = { - "tangent_out", - }; - - success = gTransformTangentProgram.createShader(NULL, NULL, 1, varyings); - } + const char* varyings[] = { + "tangent_out", + }; + + success = gTransformTangentProgram.createShader(NULL, NULL, 1, varyings); + } - - return success; + + return success; } std::string LLViewerShaderMgr::getShaderDirPrefix(void) { - return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/class"); + return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/class"); } void LLViewerShaderMgr::updateShaderUniforms(LLGLSLShader * shader) @@ -3997,11 +3946,11 @@ void LLViewerShaderMgr::updateShaderUniforms(LLGLSLShader * shader) LLViewerShaderMgr::shader_iter LLViewerShaderMgr::beginShaders() const { - return mShaderList.begin(); + return mShaderList.begin(); } LLViewerShaderMgr::shader_iter LLViewerShaderMgr::endShaders() const { - return mShaderList.end(); + return mShaderList.end(); } diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 8e1801612e..66cb80657f 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -166,8 +166,6 @@ extern LLGLSLShader gDebugProgram; extern LLGLSLShader gClipProgram; extern LLGLSLShader gDownsampleDepthProgram; extern LLGLSLShader gDownsampleDepthRectProgram; -extern LLGLSLShader gDownsampleMinMaxDepthRectProgram; -extern LLGLSLShader gInscatterRectProgram; extern LLGLSLShader gBenchmarkProgram; //output tex0[tc0] + tex1[tc1] @@ -262,7 +260,6 @@ extern LLGLSLShader gImpostorProgram; // WindLight shader handles extern LLGLSLShader gWLSkyProgram; extern LLGLSLShader gWLCloudProgram; -extern LLGLSLShader gWLCloudShadowProgram; extern LLGLSLShader gWLSunProgram; extern LLGLSLShader gWLMoonProgram; @@ -320,7 +317,6 @@ extern LLGLSLShader gDeferredAvatarEyesProgram; extern LLGLSLShader gDeferredAvatarAlphaProgram; extern LLGLSLShader gDeferredWLSkyProgram; extern LLGLSLShader gDeferredWLCloudProgram; -extern LLGLSLShader gDeferredWLCloudShadowProgram; extern LLGLSLShader gDeferredWLSunProgram; extern LLGLSLShader gDeferredWLMoonProgram; extern LLGLSLShader gDeferredStarProgram; @@ -329,7 +325,6 @@ extern LLGLSLShader gDeferredSkinnedFullbrightShinyProgram; extern LLGLSLShader gDeferredSkinnedFullbrightProgram; extern LLGLSLShader gNormalMapGenProgram; - // Deferred materials shaders extern LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2]; extern LLGLSLShader gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2]; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 507936190a..1ba7a7b2b9 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1193,12 +1193,12 @@ void LLViewerFetchedTexture::loadFromFastCache() { return; //no need to access the fast cache. } - mInFastCacheList = FALSE; + mInFastCacheList = FALSE; mRawImage = LLAppViewer::getTextureCache()->readFromFastCache(getID(), mRawDiscardLevel); if(mRawImage.notNull()) { - mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; + mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; setTexelsPerImage(); @@ -1213,20 +1213,20 @@ void LLViewerFetchedTexture::loadFromFastCache() else { if (mBoostLevel == LLGLTexture::BOOST_ICON) - { - S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; - S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; - if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) { - // scale oversized icon, no need to give more work to gl - mRawImage->scale(expected_width, expected_height); - } + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; + if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) + { + // scale oversized icon, no need to give more work to gl + mRawImage->scale(expected_width, expected_height); + } } - mRequestedDiscardLevel = mDesiredDiscardLevel + 1; - mIsRawImageValid = TRUE; - addToCreateTexture(); - } + mRequestedDiscardLevel = mDesiredDiscardLevel + 1; + mIsRawImageValid = TRUE; + addToCreateTexture(); + } } } @@ -1989,7 +1989,7 @@ bool LLViewerFetchedTexture::updateFetch() mIsFetched = TRUE; tester->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)); } - mRawDiscardLevel = fetch_discard; + mRawDiscardLevel = fetch_discard; if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) && (current_discard < 0 || mRawDiscardLevel < current_discard)) { diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 11cf303753..3421b99ba4 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4608,7 +4608,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei // PRE SNAPSHOT gDisplaySwapBuffers = FALSE; - + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); setCursor(UI_CURSOR_WAIT); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 9c761cc4a6..671f4d49a7 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -2345,7 +2345,7 @@ bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture) switch(range_it->second.map) { - case LLRender::DIFFUSE_MAP: + case LLRender::DIFFUSE_MAP: { if(LLMaterial::DIFFUSE_ALPHA_MODE_NONE != cur_material->getDiffuseAlphaMode()) { //missing texture + !LLMaterial::DIFFUSE_ALPHA_MODE_NONE => LLMaterial::DIFFUSE_ALPHA_MODE_NONE diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index 08bb2d2b2b..37689e0683 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -99,7 +99,7 @@ LLDrawable * LLVOWLSky::createDrawable(LLPipeline * pipeline) inline F32 LLVOWLSky::calcPhi(U32 i) { - // i should range from [0..SKY_STACKS] so t will range from [0.f .. 1.f] + // i should range from [0..SKY_STACKS] so t will range from [0.f .. 1.f] F32 t = float(i) / float(getNumStacks()); // ^4 the parameter of the tesselation to bias things toward 0 (the dome's apex) diff --git a/indra/newview/llvowlsky.h b/indra/newview/llvowlsky.h index c52acba98b..73ecf1a717 100644 --- a/indra/newview/llvowlsky.h +++ b/indra/newview/llvowlsky.h @@ -81,9 +81,9 @@ private: std::vector< LLPointer > mStripsVerts; LLPointer mStarsVerts; - std::vector mStarVertices; // Star verticies - std::vector mStarColors; // Star colors - std::vector mStarIntensities; // Star intensities + std::vector mStarVertices; // Star verticies + std::vector mStarColors; // Star colors + std::vector mStarIntensities; // Star intensities }; #endif // LL_VOWLSKY_H diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 2760ebd1df..768db047a4 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -268,9 +268,12 @@ bool LLWeb::useExternalBrowser(const std::string &url) boost::match_results matches; return !(boost::regex_search(uri_string, matches, pattern)); } - - boost::regex pattern = boost::regex("^mailto:", boost::regex::perl | boost::regex::icase); - boost::match_results matches; - return boost::regex_search(url, matches, pattern); + else + { + boost::regex pattern = boost::regex("^mailto:", boost::regex::perl | boost::regex::icase); + boost::match_results matches; + return boost::regex_search(url, matches, pattern); + } + return false; #endif } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 6e7e8eef21..08a4812a28 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -43,7 +43,7 @@ #include "llui.h" #include "llglheaders.h" #include "llrender.h" -#include "llwindow.h" // swapBuffers() +#include "llwindow.h" // swapBuffers() // newview includes #include "llagent.h" @@ -217,9 +217,9 @@ extern S32 gBoxFrame; extern BOOL gDisplaySwapBuffers; extern BOOL gDebugGL; -bool gAvatarBacklight = false; +bool gAvatarBacklight = false; -bool gDebugPipeline = false; +bool gDebugPipeline = false; LLPipeline gPipeline; const LLMatrix4* gGLLastMatrix = NULL; @@ -277,26 +277,26 @@ static LLStaticHashedString sKernScale("kern_scale"); //---------------------------------------- std::string gPoolNames[] = { - // Correspond to LLDrawpool enum render type - "NONE", - "POOL_SIMPLE", - "POOL_GROUND", - "POOL_FULLBRIGHT", - "POOL_BUMP", - "POOL_MATERIALS", - "POOL_TERRAIN," - "POOL_SKY", - "POOL_WL_SKY", - "POOL_TREE", - "POOL_ALPHA_MASK", - "POOL_FULLBRIGHT_ALPHA_MASK", - "POOL_GRASS", - "POOL_INVISIBLE", - "POOL_AVATAR", - "POOL_VOIDWATER", - "POOL_WATER", - "POOL_GLOW", - "POOL_ALPHA" + // Correspond to LLDrawpool enum render type + "NONE", + "POOL_SIMPLE", + "POOL_GROUND", + "POOL_FULLBRIGHT", + "POOL_BUMP", + "POOL_MATERIALS", + "POOL_TERRAIN," + "POOL_SKY", + "POOL_WL_SKY", + "POOL_TREE", + "POOL_ALPHA_MASK", + "POOL_FULLBRIGHT_ALPHA_MASK", + "POOL_GRASS", + "POOL_INVISIBLE", + "POOL_AVATAR", + "POOL_VOIDWATER", + "POOL_WATER", + "POOL_GLOW", + "POOL_ALPHA" }; void drawBox(const LLVector4a& c, const LLVector4a& r); @@ -307,48 +307,48 @@ LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage); void display_update_camera(); //---------------------------------------- -S32 LLPipeline::sCompiles = 0; - -bool LLPipeline::sPickAvatar = true; -bool LLPipeline::sDynamicLOD = true; -bool LLPipeline::sShowHUDAttachments = true; -bool LLPipeline::sRenderMOAPBeacons = false; -bool LLPipeline::sRenderPhysicalBeacons = true; -bool LLPipeline::sRenderScriptedBeacons = false; -bool LLPipeline::sRenderScriptedTouchBeacons = true; -bool LLPipeline::sRenderParticleBeacons = false; -bool LLPipeline::sRenderSoundBeacons = false; -bool LLPipeline::sRenderBeacons = false; -bool LLPipeline::sRenderHighlight = true; +S32 LLPipeline::sCompiles = 0; + +bool LLPipeline::sPickAvatar = true; +bool LLPipeline::sDynamicLOD = true; +bool LLPipeline::sShowHUDAttachments = true; +bool LLPipeline::sRenderMOAPBeacons = false; +bool LLPipeline::sRenderPhysicalBeacons = true; +bool LLPipeline::sRenderScriptedBeacons = false; +bool LLPipeline::sRenderScriptedTouchBeacons = true; +bool LLPipeline::sRenderParticleBeacons = false; +bool LLPipeline::sRenderSoundBeacons = false; +bool LLPipeline::sRenderBeacons = false; +bool LLPipeline::sRenderHighlight = true; LLRender::eTexIndex LLPipeline::sRenderHighlightTextureChannel = LLRender::DIFFUSE_MAP; -bool LLPipeline::sForceOldBakedUpload = false; -S32 LLPipeline::sUseOcclusion = 0; -bool LLPipeline::sDelayVBUpdate = true; -bool LLPipeline::sAutoMaskAlphaDeferred = true; -bool LLPipeline::sAutoMaskAlphaNonDeferred = false; -bool LLPipeline::sDisableShaders = false; -bool LLPipeline::sRenderBump = true; -bool LLPipeline::sBakeSunlight = false; -bool LLPipeline::sNoAlpha = false; -bool LLPipeline::sUseTriStrips = true; -bool LLPipeline::sUseFarClip = true; -bool LLPipeline::sShadowRender = false; -bool LLPipeline::sWaterReflections = false; -bool LLPipeline::sRenderGlow = false; -bool LLPipeline::sReflectionRender = false; +bool LLPipeline::sForceOldBakedUpload = false; +S32 LLPipeline::sUseOcclusion = 0; +bool LLPipeline::sDelayVBUpdate = true; +bool LLPipeline::sAutoMaskAlphaDeferred = true; +bool LLPipeline::sAutoMaskAlphaNonDeferred = false; +bool LLPipeline::sDisableShaders = false; +bool LLPipeline::sRenderBump = true; +bool LLPipeline::sBakeSunlight = false; +bool LLPipeline::sNoAlpha = false; +bool LLPipeline::sUseTriStrips = true; +bool LLPipeline::sUseFarClip = true; +bool LLPipeline::sShadowRender = false; +bool LLPipeline::sWaterReflections = false; +bool LLPipeline::sRenderGlow = false; +bool LLPipeline::sReflectionRender = false; bool LLPipeline::sDistortionRender = false; -bool LLPipeline::sImpostorRender = false; -bool LLPipeline::sImpostorRenderAlphaDepthPass = false; -bool LLPipeline::sUnderWaterRender = false; -bool LLPipeline::sTextureBindTest = false; -bool LLPipeline::sRenderFrameTest = false; -bool LLPipeline::sRenderAttachedLights = true; -bool LLPipeline::sRenderAttachedParticles = true; -bool LLPipeline::sRenderDeferred = false; +bool LLPipeline::sImpostorRender = false; +bool LLPipeline::sImpostorRenderAlphaDepthPass = false; +bool LLPipeline::sUnderWaterRender = false; +bool LLPipeline::sTextureBindTest = false; +bool LLPipeline::sRenderFrameTest = false; +bool LLPipeline::sRenderAttachedLights = true; +bool LLPipeline::sRenderAttachedParticles = true; +bool LLPipeline::sRenderDeferred = false; bool LLPipeline::sMemAllocationThrottled = false; -S32 LLPipeline::sVisibleLightCount = 0; -F32 LLPipeline::sMinRenderSize = 0.f; -bool LLPipeline::sRenderingHUDs; +S32 LLPipeline::sVisibleLightCount = 0; +F32 LLPipeline::sMinRenderSize = 0.f; +bool LLPipeline::sRenderingHUDs; F32 LLPipeline::sDistortionWaterClipPlaneMargin = 1.0001f; // EventHost API LLPipeline listener. @@ -361,246 +361,245 @@ void validate_framebuffer_object(); bool addDeferredAttachments(LLRenderTarget& target) { - return target.addColorAttachment(GL_SRGB8_ALPHA8) && //specular - target.addColorAttachment(GL_RGB10_A2); //normal+z + return target.addColorAttachment(GL_SRGB8_ALPHA8) && //specular + target.addColorAttachment(GL_RGB10_A2); //normal+z } LLPipeline::LLPipeline() : - mBackfaceCull(false), - mMatrixOpCount(0), - mTextureMatrixOps(0), - mNumVisibleNodes(0), - mNumVisibleFaces(0), - - mInitialized(false), - mVertexShadersEnabled(false), - mVertexShadersLoaded(0), - mTransformFeedbackPrimitives(0), - mRenderDebugFeatureMask(0), - mRenderDebugMask(0), - mOldRenderDebugMask(0), - mMeshDirtyQueryObject(0), - mGroupQ1Locked(false), - mGroupQ2Locked(false), - mResetVertexBuffers(false), - mLastRebuildPool(NULL), - mAlphaPool(NULL), - mSkyPool(NULL), - mTerrainPool(NULL), - mWaterPool(NULL), - mGroundPool(NULL), - mSimplePool(NULL), - mGrassPool(NULL), - mAlphaMaskPool(NULL), - mFullbrightAlphaMaskPool(NULL), - mFullbrightPool(NULL), - mInvisiblePool(NULL), - mGlowPool(NULL), - mBumpPool(NULL), - mMaterialsPool(NULL), - mWLSkyPool(NULL), - mLightMask(0), - mLightMovingMask(0), - mLightingDetail(0), - mScreenWidth(0), - mScreenHeight(0), - mNeedsShadowTargetClear(true) -{ - mNoiseMap = 0; - mTrueNoiseMap = 0; - mLightFunc = 0; + mBackfaceCull(false), + mMatrixOpCount(0), + mTextureMatrixOps(0), + mNumVisibleNodes(0), + mNumVisibleFaces(0), + + mInitialized(false), + mVertexShadersEnabled(false), + mVertexShadersLoaded(0), + mTransformFeedbackPrimitives(0), + mRenderDebugFeatureMask(0), + mRenderDebugMask(0), + mOldRenderDebugMask(0), + mMeshDirtyQueryObject(0), + mGroupQ1Locked(false), + mGroupQ2Locked(false), + mResetVertexBuffers(false), + mLastRebuildPool(NULL), + mAlphaPool(NULL), + mSkyPool(NULL), + mTerrainPool(NULL), + mWaterPool(NULL), + mGroundPool(NULL), + mSimplePool(NULL), + mGrassPool(NULL), + mAlphaMaskPool(NULL), + mFullbrightAlphaMaskPool(NULL), + mFullbrightPool(NULL), + mInvisiblePool(NULL), + mGlowPool(NULL), + mBumpPool(NULL), + mMaterialsPool(NULL), + mWLSkyPool(NULL), + mLightMask(0), + mLightMovingMask(0), + mLightingDetail(0), + mScreenWidth(0), + mScreenHeight(0) +{ + mNoiseMap = 0; + mTrueNoiseMap = 0; + mLightFunc = 0; } void LLPipeline::connectRefreshCachedSettingsSafe(const std::string name) { - LLPointer cntrl_ptr = gSavedSettings.getControl(name); - if ( cntrl_ptr.isNull() ) - { - LL_WARNS() << "Global setting name not found:" << name << LL_ENDL; - } - else - { - cntrl_ptr->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); - } + LLPointer cntrl_ptr = gSavedSettings.getControl(name); + if ( cntrl_ptr.isNull() ) + { + LL_WARNS() << "Global setting name not found:" << name << LL_ENDL; + } + else + { + cntrl_ptr->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); + } } void LLPipeline::init() { - refreshCachedSettings(); - - gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity"); - gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize"); - sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD"); - sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); - sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips"); - LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO"); - LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO"); - LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw"); - sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); - sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); - - mInitialized = true; - - stop_glerror(); - - //create render pass pools - getPool(LLDrawPool::POOL_ALPHA); - getPool(LLDrawPool::POOL_SIMPLE); - getPool(LLDrawPool::POOL_ALPHA_MASK); - getPool(LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK); - getPool(LLDrawPool::POOL_GRASS); - getPool(LLDrawPool::POOL_FULLBRIGHT); - getPool(LLDrawPool::POOL_INVISIBLE); - getPool(LLDrawPool::POOL_BUMP); - getPool(LLDrawPool::POOL_MATERIALS); - getPool(LLDrawPool::POOL_GLOW); - - resetFrameStats(); - - if (gSavedSettings.getBOOL("DisableAllRenderFeatures")) - { - clearAllRenderDebugFeatures(); - } - else - { - setAllRenderDebugFeatures(); // By default, all debugging features on - } - clearAllRenderDebugDisplays(); // All debug displays off + refreshCachedSettings(); + + gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity"); + gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize"); + sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD"); + sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); + sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips"); + LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO"); + LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO"); + LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw"); + sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); + sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); + + mInitialized = true; + + stop_glerror(); + + //create render pass pools + getPool(LLDrawPool::POOL_ALPHA); + getPool(LLDrawPool::POOL_SIMPLE); + getPool(LLDrawPool::POOL_ALPHA_MASK); + getPool(LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK); + getPool(LLDrawPool::POOL_GRASS); + getPool(LLDrawPool::POOL_FULLBRIGHT); + getPool(LLDrawPool::POOL_INVISIBLE); + getPool(LLDrawPool::POOL_BUMP); + getPool(LLDrawPool::POOL_MATERIALS); + getPool(LLDrawPool::POOL_GLOW); + + resetFrameStats(); + + if (gSavedSettings.getBOOL("DisableAllRenderFeatures")) + { + clearAllRenderDebugFeatures(); + } + else + { + setAllRenderDebugFeatures(); // By default, all debugging features on + } + clearAllRenderDebugDisplays(); // All debug displays off - if (gSavedSettings.getBOOL("DisableAllRenderTypes")) - { - clearAllRenderTypes(); - } - else - { - setAllRenderTypes(); // By default, all rendering types start enabled - // Don't turn on ground when this is set - // Mac Books with intel 950s need this - if(!gSavedSettings.getBOOL("RenderGround")) - { - toggleRenderType(RENDER_TYPE_GROUND); - } - } + if (gSavedSettings.getBOOL("DisableAllRenderTypes")) + { + clearAllRenderTypes(); + } + else + { + setAllRenderTypes(); // By default, all rendering types start enabled + // Don't turn on ground when this is set + // Mac Books with intel 950s need this + if(!gSavedSettings.getBOOL("RenderGround")) + { + toggleRenderType(RENDER_TYPE_GROUND); + } + } - // make sure RenderPerformanceTest persists (hackity hack hack) - // disables non-object rendering (UI, sky, water, etc) - if (gSavedSettings.getBOOL("RenderPerformanceTest")) - { - gSavedSettings.setBOOL("RenderPerformanceTest", FALSE); - gSavedSettings.setBOOL("RenderPerformanceTest", TRUE); - } + // make sure RenderPerformanceTest persists (hackity hack hack) + // disables non-object rendering (UI, sky, water, etc) + if (gSavedSettings.getBOOL("RenderPerformanceTest")) + { + gSavedSettings.setBOOL("RenderPerformanceTest", FALSE); + gSavedSettings.setBOOL("RenderPerformanceTest", TRUE); + } - mOldRenderDebugMask = mRenderDebugMask; + mOldRenderDebugMask = mRenderDebugMask; - mBackfaceCull = true; + mBackfaceCull = true; - stop_glerror(); - - // Enable features - - LLViewerShaderMgr::instance()->setShaders(); + stop_glerror(); + + // Enable features + + LLViewerShaderMgr::instance()->setShaders(); - stop_glerror(); + stop_glerror(); - for (U32 i = 0; i < 2; ++i) - { - mSpotLightFade[i] = 1.f; - } + for (U32 i = 0; i < 2; ++i) + { + mSpotLightFade[i] = 1.f; + } - if (mCubeVB.isNull()) - { - mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); - } + if (mCubeVB.isNull()) + { + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } - mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0); - mDeferredVB->allocateBuffer(8, 0, true); - setLightingDetail(-1); - - // - // Update all settings to trigger a cached settings refresh - // - connectRefreshCachedSettingsSafe("RenderAutoMaskAlphaDeferred"); - connectRefreshCachedSettingsSafe("RenderAutoMaskAlphaNonDeferred"); - connectRefreshCachedSettingsSafe("RenderUseFarClip"); - connectRefreshCachedSettingsSafe("RenderAvatarMaxNonImpostors"); - connectRefreshCachedSettingsSafe("RenderDelayVBUpdate"); - connectRefreshCachedSettingsSafe("UseOcclusion"); - connectRefreshCachedSettingsSafe("VertexShaderEnable"); - connectRefreshCachedSettingsSafe("RenderAvatarVP"); - connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders"); - connectRefreshCachedSettingsSafe("RenderDeferred"); - connectRefreshCachedSettingsSafe("RenderDeferredSunWash"); - connectRefreshCachedSettingsSafe("RenderFSAASamples"); - connectRefreshCachedSettingsSafe("RenderResolutionDivisor"); - connectRefreshCachedSettingsSafe("RenderUIBuffer"); - connectRefreshCachedSettingsSafe("RenderShadowDetail"); - connectRefreshCachedSettingsSafe("RenderDeferredSSAO"); - connectRefreshCachedSettingsSafe("RenderShadowResolutionScale"); - connectRefreshCachedSettingsSafe("RenderLocalLights"); - connectRefreshCachedSettingsSafe("RenderDelayCreation"); - connectRefreshCachedSettingsSafe("RenderAnimateRes"); - connectRefreshCachedSettingsSafe("FreezeTime"); - connectRefreshCachedSettingsSafe("DebugBeaconLineWidth"); - connectRefreshCachedSettingsSafe("RenderHighlightBrightness"); - connectRefreshCachedSettingsSafe("RenderHighlightColor"); - connectRefreshCachedSettingsSafe("RenderHighlightThickness"); - connectRefreshCachedSettingsSafe("RenderSpotLightsInNondeferred"); - connectRefreshCachedSettingsSafe("PreviewAmbientColor"); - connectRefreshCachedSettingsSafe("PreviewDiffuse0"); - connectRefreshCachedSettingsSafe("PreviewSpecular0"); - connectRefreshCachedSettingsSafe("PreviewDiffuse1"); - connectRefreshCachedSettingsSafe("PreviewSpecular1"); - connectRefreshCachedSettingsSafe("PreviewDiffuse2"); - connectRefreshCachedSettingsSafe("PreviewSpecular2"); - connectRefreshCachedSettingsSafe("PreviewDirection0"); - connectRefreshCachedSettingsSafe("PreviewDirection1"); - connectRefreshCachedSettingsSafe("PreviewDirection2"); - connectRefreshCachedSettingsSafe("RenderGlowMinLuminance"); - connectRefreshCachedSettingsSafe("RenderGlowMaxExtractAlpha"); - connectRefreshCachedSettingsSafe("RenderGlowWarmthAmount"); - connectRefreshCachedSettingsSafe("RenderGlowLumWeights"); - connectRefreshCachedSettingsSafe("RenderGlowWarmthWeights"); - connectRefreshCachedSettingsSafe("RenderGlowResolutionPow"); - connectRefreshCachedSettingsSafe("RenderGlowIterations"); - connectRefreshCachedSettingsSafe("RenderGlowWidth"); - connectRefreshCachedSettingsSafe("RenderGlowStrength"); - connectRefreshCachedSettingsSafe("RenderDepthOfField"); - connectRefreshCachedSettingsSafe("RenderDepthOfFieldInEditMode"); - connectRefreshCachedSettingsSafe("CameraFocusTransitionTime"); - connectRefreshCachedSettingsSafe("CameraFNumber"); - connectRefreshCachedSettingsSafe("CameraFocalLength"); - connectRefreshCachedSettingsSafe("CameraFieldOfView"); - connectRefreshCachedSettingsSafe("RenderShadowNoise"); - connectRefreshCachedSettingsSafe("RenderShadowBlurSize"); - connectRefreshCachedSettingsSafe("RenderSSAOScale"); - connectRefreshCachedSettingsSafe("RenderSSAOMaxScale"); - connectRefreshCachedSettingsSafe("RenderSSAOFactor"); - connectRefreshCachedSettingsSafe("RenderSSAOEffect"); - connectRefreshCachedSettingsSafe("RenderShadowOffsetError"); - connectRefreshCachedSettingsSafe("RenderShadowBiasError"); - connectRefreshCachedSettingsSafe("RenderShadowOffset"); - connectRefreshCachedSettingsSafe("RenderShadowBias"); - connectRefreshCachedSettingsSafe("RenderSpotShadowOffset"); - connectRefreshCachedSettingsSafe("RenderSpotShadowBias"); - connectRefreshCachedSettingsSafe("RenderEdgeDepthCutoff"); - connectRefreshCachedSettingsSafe("RenderEdgeNormCutoff"); - connectRefreshCachedSettingsSafe("RenderShadowGaussian"); - connectRefreshCachedSettingsSafe("RenderShadowBlurDistFactor"); - connectRefreshCachedSettingsSafe("RenderDeferredAtmospheric"); - connectRefreshCachedSettingsSafe("RenderReflectionDetail"); - connectRefreshCachedSettingsSafe("RenderHighlightFadeTime"); - connectRefreshCachedSettingsSafe("RenderShadowClipPlanes"); - connectRefreshCachedSettingsSafe("RenderShadowOrthoClipPlanes"); - connectRefreshCachedSettingsSafe("RenderShadowNearDist"); - connectRefreshCachedSettingsSafe("RenderFarClip"); - connectRefreshCachedSettingsSafe("RenderShadowSplitExponent"); - connectRefreshCachedSettingsSafe("RenderShadowErrorCutoff"); - connectRefreshCachedSettingsSafe("RenderShadowFOVCutoff"); - connectRefreshCachedSettingsSafe("CameraOffset"); - connectRefreshCachedSettingsSafe("CameraMaxCoF"); - connectRefreshCachedSettingsSafe("CameraDoFResScale"); - connectRefreshCachedSettingsSafe("RenderAutoHideSurfaceAreaLimit"); - gSavedSettings.getControl("RenderAutoHideSurfaceAreaLimit")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); + mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0); + mDeferredVB->allocateBuffer(8, 0, true); + setLightingDetail(-1); + + // + // Update all settings to trigger a cached settings refresh + // + connectRefreshCachedSettingsSafe("RenderAutoMaskAlphaDeferred"); + connectRefreshCachedSettingsSafe("RenderAutoMaskAlphaNonDeferred"); + connectRefreshCachedSettingsSafe("RenderUseFarClip"); + connectRefreshCachedSettingsSafe("RenderAvatarMaxNonImpostors"); + connectRefreshCachedSettingsSafe("RenderDelayVBUpdate"); + connectRefreshCachedSettingsSafe("UseOcclusion"); + connectRefreshCachedSettingsSafe("VertexShaderEnable"); + connectRefreshCachedSettingsSafe("RenderAvatarVP"); + connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders"); + connectRefreshCachedSettingsSafe("RenderDeferred"); + connectRefreshCachedSettingsSafe("RenderDeferredSunWash"); + connectRefreshCachedSettingsSafe("RenderFSAASamples"); + connectRefreshCachedSettingsSafe("RenderResolutionDivisor"); + connectRefreshCachedSettingsSafe("RenderUIBuffer"); + connectRefreshCachedSettingsSafe("RenderShadowDetail"); + connectRefreshCachedSettingsSafe("RenderDeferredSSAO"); + connectRefreshCachedSettingsSafe("RenderShadowResolutionScale"); + connectRefreshCachedSettingsSafe("RenderLocalLights"); + connectRefreshCachedSettingsSafe("RenderDelayCreation"); + connectRefreshCachedSettingsSafe("RenderAnimateRes"); + connectRefreshCachedSettingsSafe("FreezeTime"); + connectRefreshCachedSettingsSafe("DebugBeaconLineWidth"); + connectRefreshCachedSettingsSafe("RenderHighlightBrightness"); + connectRefreshCachedSettingsSafe("RenderHighlightColor"); + connectRefreshCachedSettingsSafe("RenderHighlightThickness"); + connectRefreshCachedSettingsSafe("RenderSpotLightsInNondeferred"); + connectRefreshCachedSettingsSafe("PreviewAmbientColor"); + connectRefreshCachedSettingsSafe("PreviewDiffuse0"); + connectRefreshCachedSettingsSafe("PreviewSpecular0"); + connectRefreshCachedSettingsSafe("PreviewDiffuse1"); + connectRefreshCachedSettingsSafe("PreviewSpecular1"); + connectRefreshCachedSettingsSafe("PreviewDiffuse2"); + connectRefreshCachedSettingsSafe("PreviewSpecular2"); + connectRefreshCachedSettingsSafe("PreviewDirection0"); + connectRefreshCachedSettingsSafe("PreviewDirection1"); + connectRefreshCachedSettingsSafe("PreviewDirection2"); + connectRefreshCachedSettingsSafe("RenderGlowMinLuminance"); + connectRefreshCachedSettingsSafe("RenderGlowMaxExtractAlpha"); + connectRefreshCachedSettingsSafe("RenderGlowWarmthAmount"); + connectRefreshCachedSettingsSafe("RenderGlowLumWeights"); + connectRefreshCachedSettingsSafe("RenderGlowWarmthWeights"); + connectRefreshCachedSettingsSafe("RenderGlowResolutionPow"); + connectRefreshCachedSettingsSafe("RenderGlowIterations"); + connectRefreshCachedSettingsSafe("RenderGlowWidth"); + connectRefreshCachedSettingsSafe("RenderGlowStrength"); + connectRefreshCachedSettingsSafe("RenderDepthOfField"); + connectRefreshCachedSettingsSafe("RenderDepthOfFieldInEditMode"); + connectRefreshCachedSettingsSafe("CameraFocusTransitionTime"); + connectRefreshCachedSettingsSafe("CameraFNumber"); + connectRefreshCachedSettingsSafe("CameraFocalLength"); + connectRefreshCachedSettingsSafe("CameraFieldOfView"); + connectRefreshCachedSettingsSafe("RenderShadowNoise"); + connectRefreshCachedSettingsSafe("RenderShadowBlurSize"); + connectRefreshCachedSettingsSafe("RenderSSAOScale"); + connectRefreshCachedSettingsSafe("RenderSSAOMaxScale"); + connectRefreshCachedSettingsSafe("RenderSSAOFactor"); + connectRefreshCachedSettingsSafe("RenderSSAOEffect"); + connectRefreshCachedSettingsSafe("RenderShadowOffsetError"); + connectRefreshCachedSettingsSafe("RenderShadowBiasError"); + connectRefreshCachedSettingsSafe("RenderShadowOffset"); + connectRefreshCachedSettingsSafe("RenderShadowBias"); + connectRefreshCachedSettingsSafe("RenderSpotShadowOffset"); + connectRefreshCachedSettingsSafe("RenderSpotShadowBias"); + connectRefreshCachedSettingsSafe("RenderEdgeDepthCutoff"); + connectRefreshCachedSettingsSafe("RenderEdgeNormCutoff"); + connectRefreshCachedSettingsSafe("RenderShadowGaussian"); + connectRefreshCachedSettingsSafe("RenderShadowBlurDistFactor"); + connectRefreshCachedSettingsSafe("RenderDeferredAtmospheric"); + connectRefreshCachedSettingsSafe("RenderReflectionDetail"); + connectRefreshCachedSettingsSafe("RenderHighlightFadeTime"); + connectRefreshCachedSettingsSafe("RenderShadowClipPlanes"); + connectRefreshCachedSettingsSafe("RenderShadowOrthoClipPlanes"); + connectRefreshCachedSettingsSafe("RenderShadowNearDist"); + connectRefreshCachedSettingsSafe("RenderFarClip"); + connectRefreshCachedSettingsSafe("RenderShadowSplitExponent"); + connectRefreshCachedSettingsSafe("RenderShadowErrorCutoff"); + connectRefreshCachedSettingsSafe("RenderShadowFOVCutoff"); + connectRefreshCachedSettingsSafe("CameraOffset"); + connectRefreshCachedSettingsSafe("CameraMaxCoF"); + connectRefreshCachedSettingsSafe("CameraDoFResScale"); + connectRefreshCachedSettingsSafe("RenderAutoHideSurfaceAreaLimit"); + gSavedSettings.getControl("RenderAutoHideSurfaceAreaLimit")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); } LLPipeline::~LLPipeline() @@ -610,104 +609,104 @@ LLPipeline::~LLPipeline() void LLPipeline::cleanup() { - assertInitialized(); + assertInitialized(); - mGroupQ1.clear() ; - mGroupQ2.clear() ; + mGroupQ1.clear() ; + mGroupQ2.clear() ; - for(pool_set_t::iterator iter = mPools.begin(); - iter != mPools.end(); ) - { - pool_set_t::iterator curiter = iter++; - LLDrawPool* poolp = *curiter; - if (poolp->isFacePool()) - { - LLFacePool* face_pool = (LLFacePool*) poolp; - if (face_pool->mReferences.empty()) - { - mPools.erase(curiter); - removeFromQuickLookup( poolp ); - delete poolp; - } - } - else - { - mPools.erase(curiter); - removeFromQuickLookup( poolp ); - delete poolp; - } - } - - if (!mTerrainPools.empty()) - { - LL_WARNS() << "Terrain Pools not cleaned up" << LL_ENDL; - } - if (!mTreePools.empty()) - { - LL_WARNS() << "Tree Pools not cleaned up" << LL_ENDL; - } - - delete mAlphaPool; - mAlphaPool = NULL; - delete mSkyPool; - mSkyPool = NULL; - delete mTerrainPool; - mTerrainPool = NULL; - delete mWaterPool; - mWaterPool = NULL; - delete mGroundPool; - mGroundPool = NULL; - delete mSimplePool; - mSimplePool = NULL; - delete mFullbrightPool; - mFullbrightPool = NULL; - delete mInvisiblePool; - mInvisiblePool = NULL; - delete mGlowPool; - mGlowPool = NULL; - delete mBumpPool; - mBumpPool = NULL; - // don't delete wl sky pool it was handled above in the for loop - //delete mWLSkyPool; - mWLSkyPool = NULL; - - releaseGLBuffers(); - - mFaceSelectImagep = NULL; - - mMovedBridge.clear(); - - mInitialized = false; - - mDeferredVB = NULL; - - mCubeVB = NULL; + for(pool_set_t::iterator iter = mPools.begin(); + iter != mPools.end(); ) + { + pool_set_t::iterator curiter = iter++; + LLDrawPool* poolp = *curiter; + if (poolp->isFacePool()) + { + LLFacePool* face_pool = (LLFacePool*) poolp; + if (face_pool->mReferences.empty()) + { + mPools.erase(curiter); + removeFromQuickLookup( poolp ); + delete poolp; + } + } + else + { + mPools.erase(curiter); + removeFromQuickLookup( poolp ); + delete poolp; + } + } + + if (!mTerrainPools.empty()) + { + LL_WARNS() << "Terrain Pools not cleaned up" << LL_ENDL; + } + if (!mTreePools.empty()) + { + LL_WARNS() << "Tree Pools not cleaned up" << LL_ENDL; + } + + delete mAlphaPool; + mAlphaPool = NULL; + delete mSkyPool; + mSkyPool = NULL; + delete mTerrainPool; + mTerrainPool = NULL; + delete mWaterPool; + mWaterPool = NULL; + delete mGroundPool; + mGroundPool = NULL; + delete mSimplePool; + mSimplePool = NULL; + delete mFullbrightPool; + mFullbrightPool = NULL; + delete mInvisiblePool; + mInvisiblePool = NULL; + delete mGlowPool; + mGlowPool = NULL; + delete mBumpPool; + mBumpPool = NULL; + // don't delete wl sky pool it was handled above in the for loop + //delete mWLSkyPool; + mWLSkyPool = NULL; + + releaseGLBuffers(); + + mFaceSelectImagep = NULL; + + mMovedBridge.clear(); + + mInitialized = false; + + mDeferredVB = NULL; + + mCubeVB = NULL; } //============================================================================ void LLPipeline::destroyGL() { - stop_glerror(); - unloadShaders(); - mHighlightFaces.clear(); - - resetDrawOrders(); + stop_glerror(); + unloadShaders(); + mHighlightFaces.clear(); + + resetDrawOrders(); - resetVertexBuffers(); + resetVertexBuffers(); - releaseGLBuffers(); + releaseGLBuffers(); - if (LLVertexBuffer::sEnableVBOs) - { - LLVertexBuffer::sEnableVBOs = FALSE; - } + if (LLVertexBuffer::sEnableVBOs) + { + LLVertexBuffer::sEnableVBOs = FALSE; + } - if (mMeshDirtyQueryObject) - { - glDeleteQueriesARB(1, &mMeshDirtyQueryObject); - mMeshDirtyQueryObject = 0; - } + if (mMeshDirtyQueryObject) + { + glDeleteQueriesARB(1, &mMeshDirtyQueryObject); + mMeshDirtyQueryObject = 0; + } } static LLTrace::BlockTimerStatHandle FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture"); @@ -715,148 +714,148 @@ static LLTrace::BlockTimerStatHandle FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Te //static void LLPipeline::throttleNewMemoryAllocation(bool disable) { - if(sMemAllocationThrottled != disable) - { - sMemAllocationThrottled = disable ; + if(sMemAllocationThrottled != disable) + { + sMemAllocationThrottled = disable ; - if(sMemAllocationThrottled) - { - //send out notification - LLNotification::Params params("LowMemory"); - LLNotifications::instance().add(params); + if(sMemAllocationThrottled) + { + //send out notification + LLNotification::Params params("LowMemory"); + LLNotifications::instance().add(params); - //release some memory. - } - } + //release some memory. + } + } } void LLPipeline::resizeScreenTexture() { - LL_RECORD_BLOCK_TIME(FTM_RESIZE_SCREEN_TEXTURE); - if (gPipeline.canUseVertexShaders() && assertInitialized()) - { - GLuint resX = gViewerWindow->getWorldViewWidthRaw(); - GLuint resY = gViewerWindow->getWorldViewHeightRaw(); - - if ((resX != mScreen.getWidth()) || (resY != mScreen.getHeight())) - { - releaseScreenBuffers(); - if (!allocateScreenBuffer(resX,resY)) - { + LL_RECORD_BLOCK_TIME(FTM_RESIZE_SCREEN_TEXTURE); + if (gPipeline.canUseVertexShaders() && assertInitialized()) + { + GLuint resX = gViewerWindow->getWorldViewWidthRaw(); + GLuint resY = gViewerWindow->getWorldViewHeightRaw(); + + if ((resX != mScreen.getWidth()) || (resY != mScreen.getHeight())) + { + releaseScreenBuffers(); + if (!allocateScreenBuffer(resX,resY)) + { #if PROBABLE_FALSE_DISABLES_OF_ALM_HERE - //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled - //NOTE: if the session closes successfully after this call, deferred rendering will be - // disabled on future sessions - if (LLPipeline::sRenderDeferred) - { - gSavedSettings.setBOOL("RenderDeferred", FALSE); - LLPipeline::refreshCachedSettings(); - - } + //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled + //NOTE: if the session closes successfully after this call, deferred rendering will be + // disabled on future sessions + if (LLPipeline::sRenderDeferred) + { + gSavedSettings.setBOOL("RenderDeferred", FALSE); + LLPipeline::refreshCachedSettings(); + + } #endif - } - } - } + } + } + } } void LLPipeline::allocatePhysicsBuffer() { - GLuint resX = gViewerWindow->getWorldViewWidthRaw(); - GLuint resY = gViewerWindow->getWorldViewHeightRaw(); + GLuint resX = gViewerWindow->getWorldViewWidthRaw(); + GLuint resY = gViewerWindow->getWorldViewHeightRaw(); - if (mPhysicsDisplay.getWidth() != resX || mPhysicsDisplay.getHeight() != resY) - { - mPhysicsDisplay.allocate(resX, resY, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); - } + if (mPhysicsDisplay.getWidth() != resX || mPhysicsDisplay.getHeight() != resY) + { + mPhysicsDisplay.allocate(resX, resY, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + } } bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) { - refreshCachedSettings(); - - bool save_settings = sRenderDeferred; - if (save_settings) - { - // Set this flag in case we crash while resizing window or allocating space for deferred rendering targets - gSavedSettings.setBOOL("RenderInitError", TRUE); - gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); - } + refreshCachedSettings(); + + bool save_settings = sRenderDeferred; + if (save_settings) + { + // Set this flag in case we crash while resizing window or allocating space for deferred rendering targets + gSavedSettings.setBOOL("RenderInitError", TRUE); + gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); + } - eFBOStatus ret = doAllocateScreenBuffer(resX, resY); + eFBOStatus ret = doAllocateScreenBuffer(resX, resY); - if (save_settings) - { - // don't disable shaders on next session - gSavedSettings.setBOOL("RenderInitError", FALSE); - gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); - } - - if (ret == FBO_FAILURE) - { //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled - //NOTE: if the session closes successfully after this call, deferred rendering will be - // disabled on future sessions - if (LLPipeline::sRenderDeferred) - { - gSavedSettings.setBOOL("RenderDeferred", FALSE); - LLPipeline::refreshCachedSettings(); - } - } + if (save_settings) + { + // don't disable shaders on next session + gSavedSettings.setBOOL("RenderInitError", FALSE); + gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); + } + + if (ret == FBO_FAILURE) + { //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled + //NOTE: if the session closes successfully after this call, deferred rendering will be + // disabled on future sessions + if (LLPipeline::sRenderDeferred) + { + gSavedSettings.setBOOL("RenderDeferred", FALSE); + LLPipeline::refreshCachedSettings(); + } + } - return ret == FBO_SUCCESS_FULLRES; + return ret == FBO_SUCCESS_FULLRES; } LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY) { - // try to allocate screen buffers at requested resolution and samples - // - on failure, shrink number of samples and try again - // - if not multisampled, shrink resolution and try again (favor X resolution over Y) - // Make sure to call "releaseScreenBuffers" after each failure to cleanup the partially loaded state - - U32 samples = RenderFSAASamples; - - eFBOStatus ret = FBO_SUCCESS_FULLRES; - if (!allocateScreenBuffer(resX, resY, samples)) - { - //failed to allocate at requested specification, return false - ret = FBO_FAILURE; - - releaseScreenBuffers(); - //reduce number of samples - while (samples > 0) - { - samples /= 2; - if (allocateScreenBuffer(resX, resY, samples)) - { //success - return FBO_SUCCESS_LOWRES; - } - releaseScreenBuffers(); - } - - samples = 0; - - //reduce resolution - while (resY > 0 && resX > 0) - { - resY /= 2; - if (allocateScreenBuffer(resX, resY, samples)) - { - return FBO_SUCCESS_LOWRES; - } - releaseScreenBuffers(); + // try to allocate screen buffers at requested resolution and samples + // - on failure, shrink number of samples and try again + // - if not multisampled, shrink resolution and try again (favor X resolution over Y) + // Make sure to call "releaseScreenBuffers" after each failure to cleanup the partially loaded state - resX /= 2; - if (allocateScreenBuffer(resX, resY, samples)) - { - return FBO_SUCCESS_LOWRES; - } - releaseScreenBuffers(); - } + U32 samples = RenderFSAASamples; - LL_WARNS() << "Unable to allocate screen buffer at any resolution!" << LL_ENDL; - } + eFBOStatus ret = FBO_SUCCESS_FULLRES; + if (!allocateScreenBuffer(resX, resY, samples)) + { + //failed to allocate at requested specification, return false + ret = FBO_FAILURE; + + releaseScreenBuffers(); + //reduce number of samples + while (samples > 0) + { + samples /= 2; + if (allocateScreenBuffer(resX, resY, samples)) + { //success + return FBO_SUCCESS_LOWRES; + } + releaseScreenBuffers(); + } + + samples = 0; + + //reduce resolution + while (resY > 0 && resX > 0) + { + resY /= 2; + if (allocateScreenBuffer(resX, resY, samples)) + { + return FBO_SUCCESS_LOWRES; + } + releaseScreenBuffers(); + + resX /= 2; + if (allocateScreenBuffer(resX, resY, samples)) + { + return FBO_SUCCESS_LOWRES; + } + releaseScreenBuffers(); + } + + LL_WARNS() << "Unable to allocate screen buffer at any resolution!" << LL_ENDL; + } - return ret; + return ret; } // must be even to avoid a stripe in the horizontal shadow blur @@ -864,70 +863,70 @@ inline U32 BlurHappySize(U32 x, U32 scale) { return (((x*scale)+1)&~1); } bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) { - refreshCachedSettings(); - - // remember these dimensions - mScreenWidth = resX; - mScreenHeight = resY; - - U32 res_mod = RenderResolutionDivisor; - - if (res_mod > 1 && res_mod < resX && res_mod < resY) - { - resX /= res_mod; - resY /= res_mod; - } - - if (RenderUIBuffer) - { - if (!mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) - { - return false; - } - } + refreshCachedSettings(); - if (LLPipeline::sRenderDeferred) - { - S32 shadow_detail = RenderShadowDetail; - bool ssao = RenderDeferredSSAO; - - const U32 occlusion_divisor = 4; + // remember these dimensions + mScreenWidth = resX; + mScreenHeight = resY; + + U32 res_mod = RenderResolutionDivisor; - //allocate deferred rendering color buffers - if (!mDeferredScreen.allocate(resX, resY, GL_SRGB8_ALPHA8, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; - if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; - if (!mOcclusionDepth.allocate(resX/occlusion_divisor, resY/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; - if (!addDeferredAttachments(mDeferredScreen)) return false; + if (res_mod > 1 && res_mod < resX && res_mod < resY) + { + resX /= res_mod; + resY /= res_mod; + } - GLuint screenFormat = GL_RGBA16; - if (gGLManager.mIsATI) - { - screenFormat = GL_RGBA12; - } + if (RenderUIBuffer) + { + if (!mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) + { + return false; + } + } - if (gGLManager.mGLVersion < 4.f && gGLManager.mIsNVIDIA) - { - screenFormat = GL_RGBA16F_ARB; - } - - if (!mScreen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; - if (samples > 0) - { - if (!mFXAABuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; - } - else - { - mFXAABuffer.release(); - } + if (LLPipeline::sRenderDeferred) + { + S32 shadow_detail = RenderShadowDetail; + bool ssao = RenderDeferredSSAO; + + const U32 occlusion_divisor = 3; + + //allocate deferred rendering color buffers + if (!mDeferredScreen.allocate(resX, resY, GL_SRGB8_ALPHA8, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; + if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; + if (!mOcclusionDepth.allocate(resX/occlusion_divisor, resY/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; + if (!addDeferredAttachments(mDeferredScreen)) return false; + + GLuint screenFormat = GL_RGBA16; + if (gGLManager.mIsATI) + { + screenFormat = GL_RGBA12; + } + + if (gGLManager.mGLVersion < 4.f && gGLManager.mIsNVIDIA) + { + screenFormat = GL_RGBA16F_ARB; + } - if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0) - { //only need mDeferredLight for shadows OR ssao OR dof OR fxaa - if (!mDeferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; - } - else - { - mDeferredLight.release(); - } + if (!mScreen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; + if (samples > 0) + { + if (!mFXAABuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; + } + else + { + mFXAABuffer.release(); + } + + if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0) + { //only need mDeferredLight for shadows OR ssao OR dof OR fxaa + if (!mDeferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; + } + else + { + mDeferredLight.release(); + } F32 scale = RenderShadowResolutionScale; U32 sun_shadow_map_width = BlurHappySize(resX, scale); @@ -1031,177 +1030,177 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) //static void LLPipeline::updateRenderBump() { - sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); + sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); } //static void LLPipeline::updateRenderDeferred() { - bool deferred = (bool(RenderDeferred && - LLRenderTarget::sUseFBO && - LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && - LLPipeline::sRenderBump && - VertexShaderEnable && - RenderAvatarVP && - WindLightUseAtmosShaders)) && - !gUseWireframe; - - sRenderDeferred = deferred; - if (deferred) - { //must render glow when rendering deferred since post effect pass is needed to present any lighting at all - sRenderGlow = true; - } + bool deferred = (bool(RenderDeferred && + LLRenderTarget::sUseFBO && + LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && + LLPipeline::sRenderBump && + VertexShaderEnable && + RenderAvatarVP && + WindLightUseAtmosShaders)) && + !gUseWireframe; + + sRenderDeferred = deferred; + if (deferred) + { //must render glow when rendering deferred since post effect pass is needed to present any lighting at all + sRenderGlow = true; + } } //static void LLPipeline::refreshCachedSettings() { - LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred"); - LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred"); - LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip"); - LLVOAvatar::sMaxNonImpostors = gSavedSettings.getU32("RenderAvatarMaxNonImpostors"); - LLVOAvatar::updateImpostorRendering(LLVOAvatar::sMaxNonImpostors); - LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate"); - - LLPipeline::sUseOcclusion = - (!gUseWireframe - && LLGLSLShader::sNoFixedFunction - && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") - && gSavedSettings.getBOOL("UseOcclusion") - && gGLManager.mHasOcclusionQuery) ? 2 : 0; - - VertexShaderEnable = gSavedSettings.getBOOL("VertexShaderEnable"); - RenderAvatarVP = gSavedSettings.getBOOL("RenderAvatarVP"); - WindLightUseAtmosShaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders"); - RenderDeferred = gSavedSettings.getBOOL("RenderDeferred"); - RenderDeferredSunWash = gSavedSettings.getF32("RenderDeferredSunWash"); - RenderFSAASamples = gSavedSettings.getU32("RenderFSAASamples"); - RenderResolutionDivisor = gSavedSettings.getU32("RenderResolutionDivisor"); - RenderUIBuffer = gSavedSettings.getBOOL("RenderUIBuffer"); - RenderShadowDetail = gSavedSettings.getS32("RenderShadowDetail"); - RenderDeferredSSAO = gSavedSettings.getBOOL("RenderDeferredSSAO"); - RenderShadowResolutionScale = gSavedSettings.getF32("RenderShadowResolutionScale"); - RenderLocalLights = gSavedSettings.getBOOL("RenderLocalLights"); - RenderDelayCreation = gSavedSettings.getBOOL("RenderDelayCreation"); - RenderAnimateRes = gSavedSettings.getBOOL("RenderAnimateRes"); - FreezeTime = gSavedSettings.getBOOL("FreezeTime"); - DebugBeaconLineWidth = gSavedSettings.getS32("DebugBeaconLineWidth"); - RenderHighlightBrightness = gSavedSettings.getF32("RenderHighlightBrightness"); - RenderHighlightColor = gSavedSettings.getColor4("RenderHighlightColor"); - RenderHighlightThickness = gSavedSettings.getF32("RenderHighlightThickness"); - RenderSpotLightsInNondeferred = gSavedSettings.getBOOL("RenderSpotLightsInNondeferred"); - PreviewAmbientColor = gSavedSettings.getColor4("PreviewAmbientColor"); - PreviewDiffuse0 = gSavedSettings.getColor4("PreviewDiffuse0"); - PreviewSpecular0 = gSavedSettings.getColor4("PreviewSpecular0"); - PreviewDiffuse1 = gSavedSettings.getColor4("PreviewDiffuse1"); - PreviewSpecular1 = gSavedSettings.getColor4("PreviewSpecular1"); - PreviewDiffuse2 = gSavedSettings.getColor4("PreviewDiffuse2"); - PreviewSpecular2 = gSavedSettings.getColor4("PreviewSpecular2"); - PreviewDirection0 = gSavedSettings.getVector3("PreviewDirection0"); - PreviewDirection1 = gSavedSettings.getVector3("PreviewDirection1"); - PreviewDirection2 = gSavedSettings.getVector3("PreviewDirection2"); - RenderGlowMinLuminance = gSavedSettings.getF32("RenderGlowMinLuminance"); - RenderGlowMaxExtractAlpha = gSavedSettings.getF32("RenderGlowMaxExtractAlpha"); - RenderGlowWarmthAmount = gSavedSettings.getF32("RenderGlowWarmthAmount"); - RenderGlowLumWeights = gSavedSettings.getVector3("RenderGlowLumWeights"); - RenderGlowWarmthWeights = gSavedSettings.getVector3("RenderGlowWarmthWeights"); - RenderGlowResolutionPow = gSavedSettings.getS32("RenderGlowResolutionPow"); - RenderGlowIterations = gSavedSettings.getS32("RenderGlowIterations"); - RenderGlowWidth = gSavedSettings.getF32("RenderGlowWidth"); - RenderGlowStrength = gSavedSettings.getF32("RenderGlowStrength"); - RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField"); - RenderDepthOfFieldInEditMode = gSavedSettings.getBOOL("RenderDepthOfFieldInEditMode"); - CameraFocusTransitionTime = gSavedSettings.getF32("CameraFocusTransitionTime"); - CameraFNumber = gSavedSettings.getF32("CameraFNumber"); - CameraFocalLength = gSavedSettings.getF32("CameraFocalLength"); - CameraFieldOfView = gSavedSettings.getF32("CameraFieldOfView"); - RenderShadowNoise = gSavedSettings.getF32("RenderShadowNoise"); - RenderShadowBlurSize = gSavedSettings.getF32("RenderShadowBlurSize"); - RenderSSAOScale = gSavedSettings.getF32("RenderSSAOScale"); - RenderSSAOMaxScale = gSavedSettings.getU32("RenderSSAOMaxScale"); - RenderSSAOFactor = gSavedSettings.getF32("RenderSSAOFactor"); - RenderSSAOEffect = gSavedSettings.getVector3("RenderSSAOEffect"); - RenderShadowOffsetError = gSavedSettings.getF32("RenderShadowOffsetError"); - RenderShadowBiasError = gSavedSettings.getF32("RenderShadowBiasError"); - RenderShadowOffset = gSavedSettings.getF32("RenderShadowOffset"); - RenderShadowBias = gSavedSettings.getF32("RenderShadowBias"); - RenderSpotShadowOffset = gSavedSettings.getF32("RenderSpotShadowOffset"); - RenderSpotShadowBias = gSavedSettings.getF32("RenderSpotShadowBias"); - RenderEdgeDepthCutoff = gSavedSettings.getF32("RenderEdgeDepthCutoff"); - RenderEdgeNormCutoff = gSavedSettings.getF32("RenderEdgeNormCutoff"); - RenderShadowGaussian = gSavedSettings.getVector3("RenderShadowGaussian"); - RenderShadowBlurDistFactor = gSavedSettings.getF32("RenderShadowBlurDistFactor"); - RenderDeferredAtmospheric = gSavedSettings.getBOOL("RenderDeferredAtmospheric"); - RenderReflectionDetail = gSavedSettings.getS32("RenderReflectionDetail"); - RenderHighlightFadeTime = gSavedSettings.getF32("RenderHighlightFadeTime"); - RenderShadowClipPlanes = gSavedSettings.getVector3("RenderShadowClipPlanes"); - RenderShadowOrthoClipPlanes = gSavedSettings.getVector3("RenderShadowOrthoClipPlanes"); - RenderShadowNearDist = gSavedSettings.getVector3("RenderShadowNearDist"); - RenderFarClip = gSavedSettings.getF32("RenderFarClip"); - RenderShadowSplitExponent = gSavedSettings.getVector3("RenderShadowSplitExponent"); - RenderShadowErrorCutoff = gSavedSettings.getF32("RenderShadowErrorCutoff"); - RenderShadowFOVCutoff = gSavedSettings.getF32("RenderShadowFOVCutoff"); - CameraOffset = gSavedSettings.getBOOL("CameraOffset"); - CameraMaxCoF = gSavedSettings.getF32("CameraMaxCoF"); - CameraDoFResScale = gSavedSettings.getF32("CameraDoFResScale"); - RenderAutoHideSurfaceAreaLimit = gSavedSettings.getF32("RenderAutoHideSurfaceAreaLimit"); - - updateRenderDeferred(); + LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred"); + LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred"); + LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip"); + LLVOAvatar::sMaxNonImpostors = gSavedSettings.getU32("RenderAvatarMaxNonImpostors"); + LLVOAvatar::updateImpostorRendering(LLVOAvatar::sMaxNonImpostors); + LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate"); + + LLPipeline::sUseOcclusion = + (!gUseWireframe + && LLGLSLShader::sNoFixedFunction + && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") + && gSavedSettings.getBOOL("UseOcclusion") + && gGLManager.mHasOcclusionQuery) ? 2 : 0; + + VertexShaderEnable = gSavedSettings.getBOOL("VertexShaderEnable"); + RenderAvatarVP = gSavedSettings.getBOOL("RenderAvatarVP"); + WindLightUseAtmosShaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders"); + RenderDeferred = gSavedSettings.getBOOL("RenderDeferred"); + RenderDeferredSunWash = gSavedSettings.getF32("RenderDeferredSunWash"); + RenderFSAASamples = gSavedSettings.getU32("RenderFSAASamples"); + RenderResolutionDivisor = gSavedSettings.getU32("RenderResolutionDivisor"); + RenderUIBuffer = gSavedSettings.getBOOL("RenderUIBuffer"); + RenderShadowDetail = gSavedSettings.getS32("RenderShadowDetail"); + RenderDeferredSSAO = gSavedSettings.getBOOL("RenderDeferredSSAO"); + RenderShadowResolutionScale = gSavedSettings.getF32("RenderShadowResolutionScale"); + RenderLocalLights = gSavedSettings.getBOOL("RenderLocalLights"); + RenderDelayCreation = gSavedSettings.getBOOL("RenderDelayCreation"); + RenderAnimateRes = gSavedSettings.getBOOL("RenderAnimateRes"); + FreezeTime = gSavedSettings.getBOOL("FreezeTime"); + DebugBeaconLineWidth = gSavedSettings.getS32("DebugBeaconLineWidth"); + RenderHighlightBrightness = gSavedSettings.getF32("RenderHighlightBrightness"); + RenderHighlightColor = gSavedSettings.getColor4("RenderHighlightColor"); + RenderHighlightThickness = gSavedSettings.getF32("RenderHighlightThickness"); + RenderSpotLightsInNondeferred = gSavedSettings.getBOOL("RenderSpotLightsInNondeferred"); + PreviewAmbientColor = gSavedSettings.getColor4("PreviewAmbientColor"); + PreviewDiffuse0 = gSavedSettings.getColor4("PreviewDiffuse0"); + PreviewSpecular0 = gSavedSettings.getColor4("PreviewSpecular0"); + PreviewDiffuse1 = gSavedSettings.getColor4("PreviewDiffuse1"); + PreviewSpecular1 = gSavedSettings.getColor4("PreviewSpecular1"); + PreviewDiffuse2 = gSavedSettings.getColor4("PreviewDiffuse2"); + PreviewSpecular2 = gSavedSettings.getColor4("PreviewSpecular2"); + PreviewDirection0 = gSavedSettings.getVector3("PreviewDirection0"); + PreviewDirection1 = gSavedSettings.getVector3("PreviewDirection1"); + PreviewDirection2 = gSavedSettings.getVector3("PreviewDirection2"); + RenderGlowMinLuminance = gSavedSettings.getF32("RenderGlowMinLuminance"); + RenderGlowMaxExtractAlpha = gSavedSettings.getF32("RenderGlowMaxExtractAlpha"); + RenderGlowWarmthAmount = gSavedSettings.getF32("RenderGlowWarmthAmount"); + RenderGlowLumWeights = gSavedSettings.getVector3("RenderGlowLumWeights"); + RenderGlowWarmthWeights = gSavedSettings.getVector3("RenderGlowWarmthWeights"); + RenderGlowResolutionPow = gSavedSettings.getS32("RenderGlowResolutionPow"); + RenderGlowIterations = gSavedSettings.getS32("RenderGlowIterations"); + RenderGlowWidth = gSavedSettings.getF32("RenderGlowWidth"); + RenderGlowStrength = gSavedSettings.getF32("RenderGlowStrength"); + RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField"); + RenderDepthOfFieldInEditMode = gSavedSettings.getBOOL("RenderDepthOfFieldInEditMode"); + CameraFocusTransitionTime = gSavedSettings.getF32("CameraFocusTransitionTime"); + CameraFNumber = gSavedSettings.getF32("CameraFNumber"); + CameraFocalLength = gSavedSettings.getF32("CameraFocalLength"); + CameraFieldOfView = gSavedSettings.getF32("CameraFieldOfView"); + RenderShadowNoise = gSavedSettings.getF32("RenderShadowNoise"); + RenderShadowBlurSize = gSavedSettings.getF32("RenderShadowBlurSize"); + RenderSSAOScale = gSavedSettings.getF32("RenderSSAOScale"); + RenderSSAOMaxScale = gSavedSettings.getU32("RenderSSAOMaxScale"); + RenderSSAOFactor = gSavedSettings.getF32("RenderSSAOFactor"); + RenderSSAOEffect = gSavedSettings.getVector3("RenderSSAOEffect"); + RenderShadowOffsetError = gSavedSettings.getF32("RenderShadowOffsetError"); + RenderShadowBiasError = gSavedSettings.getF32("RenderShadowBiasError"); + RenderShadowOffset = gSavedSettings.getF32("RenderShadowOffset"); + RenderShadowBias = gSavedSettings.getF32("RenderShadowBias"); + RenderSpotShadowOffset = gSavedSettings.getF32("RenderSpotShadowOffset"); + RenderSpotShadowBias = gSavedSettings.getF32("RenderSpotShadowBias"); + RenderEdgeDepthCutoff = gSavedSettings.getF32("RenderEdgeDepthCutoff"); + RenderEdgeNormCutoff = gSavedSettings.getF32("RenderEdgeNormCutoff"); + RenderShadowGaussian = gSavedSettings.getVector3("RenderShadowGaussian"); + RenderShadowBlurDistFactor = gSavedSettings.getF32("RenderShadowBlurDistFactor"); + RenderDeferredAtmospheric = gSavedSettings.getBOOL("RenderDeferredAtmospheric"); + RenderReflectionDetail = gSavedSettings.getS32("RenderReflectionDetail"); + RenderHighlightFadeTime = gSavedSettings.getF32("RenderHighlightFadeTime"); + RenderShadowClipPlanes = gSavedSettings.getVector3("RenderShadowClipPlanes"); + RenderShadowOrthoClipPlanes = gSavedSettings.getVector3("RenderShadowOrthoClipPlanes"); + RenderShadowNearDist = gSavedSettings.getVector3("RenderShadowNearDist"); + RenderFarClip = gSavedSettings.getF32("RenderFarClip"); + RenderShadowSplitExponent = gSavedSettings.getVector3("RenderShadowSplitExponent"); + RenderShadowErrorCutoff = gSavedSettings.getF32("RenderShadowErrorCutoff"); + RenderShadowFOVCutoff = gSavedSettings.getF32("RenderShadowFOVCutoff"); + CameraOffset = gSavedSettings.getBOOL("CameraOffset"); + CameraMaxCoF = gSavedSettings.getF32("CameraMaxCoF"); + CameraDoFResScale = gSavedSettings.getF32("CameraDoFResScale"); + RenderAutoHideSurfaceAreaLimit = gSavedSettings.getF32("RenderAutoHideSurfaceAreaLimit"); + + updateRenderDeferred(); } void LLPipeline::releaseGLBuffers() { - assertInitialized(); - - if (mNoiseMap) - { - LLImageGL::deleteTextures(1, &mNoiseMap); - mNoiseMap = 0; - } + assertInitialized(); + + if (mNoiseMap) + { + LLImageGL::deleteTextures(1, &mNoiseMap); + mNoiseMap = 0; + } - if (mTrueNoiseMap) - { - LLImageGL::deleteTextures(1, &mTrueNoiseMap); - mTrueNoiseMap = 0; - } + if (mTrueNoiseMap) + { + LLImageGL::deleteTextures(1, &mTrueNoiseMap); + mTrueNoiseMap = 0; + } - releaseLUTBuffers(); + releaseLUTBuffers(); - mWaterRef.release(); - mWaterDis.release(); - mHighlight.release(); - - for (U32 i = 0; i < 3; i++) - { - mGlow[i].release(); - } + mWaterRef.release(); + mWaterDis.release(); + mHighlight.release(); + + for (U32 i = 0; i < 3; i++) + { + mGlow[i].release(); + } - releaseScreenBuffers(); + releaseScreenBuffers(); - gBumpImageList.destroyGL(); - LLVOAvatar::resetImpostors(); + gBumpImageList.destroyGL(); + LLVOAvatar::resetImpostors(); } void LLPipeline::releaseLUTBuffers() { - if (mLightFunc) - { - LLImageGL::deleteTextures(1, &mLightFunc); - mLightFunc = 0; - } + if (mLightFunc) + { + LLImageGL::deleteTextures(1, &mLightFunc); + mLightFunc = 0; + } } void LLPipeline::releaseScreenBuffers() { - mUIScreen.release(); - mScreen.release(); - mFXAABuffer.release(); - mPhysicsDisplay.release(); - mDeferredScreen.release(); - mDeferredDepth.release(); - mDeferredLight.release(); - mOcclusionDepth.release(); - releaseShadowTargets(); + mUIScreen.release(); + mScreen.release(); + mFXAABuffer.release(); + mPhysicsDisplay.release(); + mDeferredScreen.release(); + mDeferredDepth.release(); + mDeferredLight.release(); + mOcclusionDepth.release(); + releaseShadowTargets(); } @@ -1221,11 +1220,10 @@ void LLPipeline::releaseShadowTargets() void LLPipeline::createGLBuffers() { - stop_glerror(); - assertInitialized(); - - updateRenderDeferred(); + stop_glerror(); + assertInitialized(); + updateRenderDeferred(); if (LLPipeline::sWaterReflections) { //water reflection texture U32 res = (U32) llmax(gSavedSettings.getS32("RenderWaterRefResolution"), 512); @@ -1235,488 +1233,488 @@ void LLPipeline::createGLBuffers() mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,LLTexUnit::TT_TEXTURE, true); } - mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE); - - stop_glerror(); - - GLuint resX = gViewerWindow->getWorldViewWidthRaw(); - GLuint resY = gViewerWindow->getWorldViewHeightRaw(); - - if (LLPipeline::sRenderGlow) - { //screen space glow buffers - const U32 glow_res = llmax(1, - llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow"))); - - for (U32 i = 0; i < 3; i++) - { - mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE); - } - - allocateScreenBuffer(resX,resY); - mScreenWidth = 0; - mScreenHeight = 0; - } - - if (sRenderDeferred) - { - if (!mNoiseMap) - { - const U32 noiseRes = 128; - LLVector3 noise[noiseRes*noiseRes]; - - F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f; - for (U32 i = 0; i < noiseRes*noiseRes; ++i) - { - noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f); - noise[i].normVec(); - noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f; - } + mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE); - LLImageGL::generateTextures(1, &mNoiseMap); - - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } + stop_glerror(); - if (!mTrueNoiseMap) - { - const U32 noiseRes = 128; - F32 noise[noiseRes*noiseRes*3]; - for (U32 i = 0; i < noiseRes*noiseRes*3; i++) - { - noise[i] = ll_frand()*2.0-1.0; - } + GLuint resX = gViewerWindow->getWorldViewWidthRaw(); + GLuint resY = gViewerWindow->getWorldViewHeightRaw(); + + if (LLPipeline::sRenderGlow) + { //screen space glow buffers + const U32 glow_res = llmax(1, + llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow"))); - LLImageGL::generateTextures(1, &mTrueNoiseMap); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } + for (U32 i = 0; i < 3; i++) + { + mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE); + } - createLUTBuffers(); - } + allocateScreenBuffer(resX,resY); + mScreenWidth = 0; + mScreenHeight = 0; + } + + if (sRenderDeferred) + { + if (!mNoiseMap) + { + const U32 noiseRes = 128; + LLVector3 noise[noiseRes*noiseRes]; + + F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f; + for (U32 i = 0; i < noiseRes*noiseRes; ++i) + { + noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f); + noise[i].normVec(); + noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f; + } + + LLImageGL::generateTextures(1, &mNoiseMap); + + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + if (!mTrueNoiseMap) + { + const U32 noiseRes = 128; + F32 noise[noiseRes*noiseRes*3]; + for (U32 i = 0; i < noiseRes*noiseRes*3; i++) + { + noise[i] = ll_frand()*2.0-1.0; + } + + LLImageGL::generateTextures(1, &mTrueNoiseMap); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + createLUTBuffers(); + } - gBumpImageList.restoreGL(); + gBumpImageList.restoreGL(); } F32 lerpf(F32 a, F32 b, F32 w) { - return a + w * (b - a); + return a + w * (b - a); } void LLPipeline::createLUTBuffers() { - if (sRenderDeferred) - { - if (!mLightFunc) - { - U32 lightResX = gSavedSettings.getU32("RenderSpecularResX"); - U32 lightResY = gSavedSettings.getU32("RenderSpecularResY"); - F32* ls = new F32[lightResX*lightResY]; - F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); + if (sRenderDeferred) + { + if (!mLightFunc) + { + U32 lightResX = gSavedSettings.getU32("RenderSpecularResX"); + U32 lightResY = gSavedSettings.getU32("RenderSpecularResY"); + F32* ls = new F32[lightResX*lightResY]; + F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); // Calculate the (normalized) blinn-phong specular lookup texture. (with a few tweaks) - for (U32 y = 0; y < lightResY; ++y) - { - for (U32 x = 0; x < lightResX; ++x) - { - ls[y*lightResX+x] = 0; - F32 sa = (F32) x/(lightResX-1); - F32 spec = (F32) y/(lightResY-1); - F32 n = spec * spec * specExp; - - // Nothing special here. Just your typical blinn-phong term. - spec = powf(sa, n); - - // Apply our normalization function. - // Note: This is the full equation that applies the full normalization curve, not an approximation. - // This is fine, given we only need to create our LUT once per buffer initialization. - spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n))); - - // Since we use R16F, we no longer have a dynamic range issue we need to work around here. - // Though some older drivers may not like this, newer drivers shouldn't have this problem. - ls[y*lightResX+x] = spec; - } - } - - U32 pix_format = GL_R16F; + for (U32 y = 0; y < lightResY; ++y) + { + for (U32 x = 0; x < lightResX; ++x) + { + ls[y*lightResX+x] = 0; + F32 sa = (F32) x/(lightResX-1); + F32 spec = (F32) y/(lightResY-1); + F32 n = spec * spec * specExp; + + // Nothing special here. Just your typical blinn-phong term. + spec = powf(sa, n); + + // Apply our normalization function. + // Note: This is the full equation that applies the full normalization curve, not an approximation. + // This is fine, given we only need to create our LUT once per buffer initialization. + spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n))); + + // Since we use R16F, we no longer have a dynamic range issue we need to work around here. + // Though some older drivers may not like this, newer drivers shouldn't have this problem. + ls[y*lightResX+x] = spec; + } + } + + U32 pix_format = GL_R16F; #if LL_DARWIN - // Need to work around limited precision with 10.6.8 and older drivers - // - pix_format = GL_R32F; + // Need to work around limited precision with 10.6.8 and older drivers + // + pix_format = GL_R32F; #endif - LLImageGL::generateTextures(1, &mLightFunc); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, pix_format, lightResX, lightResY, GL_RED, GL_FLOAT, ls, false); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - delete [] ls; - } - } + LLImageGL::generateTextures(1, &mLightFunc); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, pix_format, lightResX, lightResY, GL_RED, GL_FLOAT, ls, false); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + delete [] ls; + } + } } void LLPipeline::restoreGL() { - assertInitialized(); + assertInitialized(); - if (mVertexShadersEnabled) - { - LLViewerShaderMgr::instance()->setShaders(); - } + if (mVertexShadersEnabled) + { + LLViewerShaderMgr::instance()->setShaders(); + } - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) - { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) - { - part->restoreGL(); - } - } - } + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + part->restoreGL(); + } + } + } } bool LLPipeline::canUseVertexShaders() { - static const std::string vertex_shader_enable_feature_string = "VertexShaderEnable"; + static const std::string vertex_shader_enable_feature_string = "VertexShaderEnable"; - if (sDisableShaders || - !gGLManager.mHasVertexShader || - !gGLManager.mHasFragmentShader || - !LLFeatureManager::getInstance()->isFeatureAvailable(vertex_shader_enable_feature_string) || - (assertInitialized() && mVertexShadersLoaded != 1) ) - { - return false; - } - else - { - return true; - } + if (sDisableShaders || + !gGLManager.mHasVertexShader || + !gGLManager.mHasFragmentShader || + !LLFeatureManager::getInstance()->isFeatureAvailable(vertex_shader_enable_feature_string) || + (assertInitialized() && mVertexShadersLoaded != 1) ) + { + return false; + } + else + { + return true; + } } bool LLPipeline::canUseWindLightShaders() const { - bool usingWindlight = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1; - bool haveShaders = ((gWLSkyProgram.mProgramObject != 0) || (gDeferredWLSkyProgram.mProgramObject != 0)); - return (!LLPipeline::sDisableShaders && haveShaders && usingWindlight); + return (!LLPipeline::sDisableShaders && + gWLSkyProgram.mProgramObject != 0 && + LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1); } bool LLPipeline::canUseWindLightShadersOnObjects() const { - return (canUseWindLightShaders() - && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0); + return (canUseWindLightShaders() + && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0); } bool LLPipeline::canUseAntiAliasing() const { - return true; + return true; } void LLPipeline::unloadShaders() { - LLViewerShaderMgr::instance()->unloadShaders(); + LLViewerShaderMgr::instance()->unloadShaders(); - mVertexShadersLoaded = 0; + mVertexShadersLoaded = 0; } void LLPipeline::assertInitializedDoError() { - LL_ERRS() << "LLPipeline used when uninitialized." << LL_ENDL; + LL_ERRS() << "LLPipeline used when uninitialized." << LL_ENDL; } //============================================================================ void LLPipeline::enableShadows(const bool enable_shadows) { - //should probably do something here to wrangle shadows.... + //should probably do something here to wrangle shadows.... } S32 LLPipeline::getMaxLightingDetail() const { - /*if (mShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS) - { - return 3; - } - else*/ - { - return 1; - } + /*if (mShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS) + { + return 3; + } + else*/ + { + return 1; + } } S32 LLPipeline::setLightingDetail(S32 level) { - refreshCachedSettings(); + refreshCachedSettings(); - if (level < 0) - { - if (RenderLocalLights) - { - level = 1; - } - else - { - level = 0; - } - } - level = llclamp(level, 0, getMaxLightingDetail()); - mLightingDetail = level; - - return mLightingDetail; + if (level < 0) + { + if (RenderLocalLights) + { + level = 1; + } + else + { + level = 0; + } + } + level = llclamp(level, 0, getMaxLightingDetail()); + mLightingDetail = level; + + return mLightingDetail; } class LLOctreeDirtyTexture : public OctreeTraveler { public: - const std::set& mTextures; - - LLOctreeDirtyTexture(const std::set& textures) : mTextures(textures) { } - - virtual void visit(const OctreeNode* node) - { - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + const std::set& mTextures; - if (!group->hasState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty()) - { - for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) - { - for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) - { - LLDrawInfo* params = *j; - LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params->mTexture); - if (tex && mTextures.find(tex) != mTextures.end()) - { - group->setState(LLSpatialGroup::GEOM_DIRTY); - } - } - } - } + LLOctreeDirtyTexture(const std::set& textures) : mTextures(textures) { } - for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i) - { - LLSpatialBridge* bridge = *i; - traverse(bridge->mOctree); - } - } + virtual void visit(const OctreeNode* node) + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + if (!group->hasState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty()) + { + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) + { + for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) + { + LLDrawInfo* params = *j; + LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params->mTexture); + if (tex && mTextures.find(tex) != mTextures.end()) + { + group->setState(LLSpatialGroup::GEOM_DIRTY); + } + } + } + } + + for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i) + { + LLSpatialBridge* bridge = *i; + traverse(bridge->mOctree); + } + } }; // Called when a texture changes # of channels (causes faces to move to alpha pool) void LLPipeline::dirtyPoolObjectTextures(const std::set& textures) { - assertInitialized(); + assertInitialized(); - // *TODO: This is inefficient and causes frame spikes; need a better way to do this - // Most of the time is spent in dirty.traverse. + // *TODO: This is inefficient and causes frame spikes; need a better way to do this + // Most of the time is spent in dirty.traverse. - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - if (poolp->isFacePool()) - { - ((LLFacePool*) poolp)->dirtyTextures(textures); - } - } - - LLOctreeDirtyTexture dirty(textures); - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) - { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) - { - dirty.traverse(part->mOctree); - } - } - } + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + { + LLDrawPool *poolp = *iter; + if (poolp->isFacePool()) + { + ((LLFacePool*) poolp)->dirtyTextures(textures); + } + } + + LLOctreeDirtyTexture dirty(textures); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + dirty.traverse(part->mOctree); + } + } + } } LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0) { - assertInitialized(); + assertInitialized(); - LLDrawPool *poolp = NULL; - switch( type ) - { - case LLDrawPool::POOL_SIMPLE: - poolp = mSimplePool; - break; - - case LLDrawPool::POOL_GRASS: - poolp = mGrassPool; - break; - - case LLDrawPool::POOL_ALPHA_MASK: - poolp = mAlphaMaskPool; - break; - - case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: - poolp = mFullbrightAlphaMaskPool; - break; - - case LLDrawPool::POOL_FULLBRIGHT: - poolp = mFullbrightPool; - break; - - case LLDrawPool::POOL_INVISIBLE: - poolp = mInvisiblePool; - break; - - case LLDrawPool::POOL_GLOW: - poolp = mGlowPool; - break; - - case LLDrawPool::POOL_TREE: - poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 ); - break; - - case LLDrawPool::POOL_TERRAIN: - poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 ); - break; - - case LLDrawPool::POOL_BUMP: - poolp = mBumpPool; - break; - case LLDrawPool::POOL_MATERIALS: - poolp = mMaterialsPool; - break; - case LLDrawPool::POOL_ALPHA: - poolp = mAlphaPool; - break; - - case LLDrawPool::POOL_AVATAR: - break; // Do nothing - - case LLDrawPool::POOL_SKY: - poolp = mSkyPool; - break; - - case LLDrawPool::POOL_WATER: - poolp = mWaterPool; - break; - - case LLDrawPool::POOL_GROUND: - poolp = mGroundPool; - break; - - case LLDrawPool::POOL_WL_SKY: - poolp = mWLSkyPool; - break; - - default: - llassert(0); - LL_ERRS() << "Invalid Pool Type in LLPipeline::findPool() type=" << type << LL_ENDL; - break; - } + LLDrawPool *poolp = NULL; + switch( type ) + { + case LLDrawPool::POOL_SIMPLE: + poolp = mSimplePool; + break; + + case LLDrawPool::POOL_GRASS: + poolp = mGrassPool; + break; + + case LLDrawPool::POOL_ALPHA_MASK: + poolp = mAlphaMaskPool; + break; + + case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: + poolp = mFullbrightAlphaMaskPool; + break; + + case LLDrawPool::POOL_FULLBRIGHT: + poolp = mFullbrightPool; + break; + + case LLDrawPool::POOL_INVISIBLE: + poolp = mInvisiblePool; + break; + + case LLDrawPool::POOL_GLOW: + poolp = mGlowPool; + break; + + case LLDrawPool::POOL_TREE: + poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 ); + break; + + case LLDrawPool::POOL_TERRAIN: + poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 ); + break; + + case LLDrawPool::POOL_BUMP: + poolp = mBumpPool; + break; + case LLDrawPool::POOL_MATERIALS: + poolp = mMaterialsPool; + break; + case LLDrawPool::POOL_ALPHA: + poolp = mAlphaPool; + break; + + case LLDrawPool::POOL_AVATAR: + break; // Do nothing + + case LLDrawPool::POOL_SKY: + poolp = mSkyPool; + break; + + case LLDrawPool::POOL_WATER: + poolp = mWaterPool; + break; + + case LLDrawPool::POOL_GROUND: + poolp = mGroundPool; + break; + + case LLDrawPool::POOL_WL_SKY: + poolp = mWLSkyPool; + break; + + default: + llassert(0); + LL_ERRS() << "Invalid Pool Type in LLPipeline::findPool() type=" << type << LL_ENDL; + break; + } - return poolp; + return poolp; } -LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerTexture *tex0) +LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerTexture *tex0) { - LLDrawPool *poolp = findPool(type, tex0); - if (poolp) - { - return poolp; - } + LLDrawPool *poolp = findPool(type, tex0); + if (poolp) + { + return poolp; + } - LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0); - addPool( new_poolp ); + LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0); + addPool( new_poolp ); - return new_poolp; + return new_poolp; } // static LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerTexture* imagep) { - U32 type = getPoolTypeFromTE(te, imagep); - return gPipeline.getPool(type, imagep); + U32 type = getPoolTypeFromTE(te, imagep); + return gPipeline.getPool(type, imagep); } //static U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* imagep) { - if (!te || !imagep) - { - return 0; - } - - LLMaterial* mat = te->getMaterialParams().get(); + if (!te || !imagep) + { + return 0; + } + + LLMaterial* mat = te->getMaterialParams().get(); - bool color_alpha = te->getColor().mV[3] < 0.999f; - bool alpha = color_alpha; - if (imagep) - { - alpha = alpha || (imagep->getComponents() == 4 && imagep->getType() != LLViewerTexture::MEDIA_TEXTURE) || (imagep->getComponents() == 2); - } + bool color_alpha = te->getColor().mV[3] < 0.999f; + bool alpha = color_alpha; + if (imagep) + { + alpha = alpha || (imagep->getComponents() == 4 && imagep->getType() != LLViewerTexture::MEDIA_TEXTURE) || (imagep->getComponents() == 2); + } - if (alpha && mat) - { - switch (mat->getDiffuseAlphaMode()) - { - case 1: - alpha = true; // Material's alpha mode is set to blend. Toss it into the alpha draw pool. - break; - case 0: //alpha mode set to none, never go to alpha pool - case 3: //alpha mode set to emissive, never go to alpha pool - alpha = color_alpha; - break; - default: //alpha mode set to "mask", go to alpha pool if fullbright - alpha = color_alpha; // Material's alpha mode is set to none, mask, or emissive. Toss it into the opaque material draw pool. - break; - } - } - - if (alpha) - { - return LLDrawPool::POOL_ALPHA; - } - else if ((te->getBumpmap() || te->getShiny()) && (!mat || mat->getNormalID().isNull())) - { - return LLDrawPool::POOL_BUMP; - } - else if (mat && !alpha) - { - return LLDrawPool::POOL_MATERIALS; - } - else - { - return LLDrawPool::POOL_SIMPLE; - } + if (alpha && mat) + { + switch (mat->getDiffuseAlphaMode()) + { + case 1: + alpha = true; // Material's alpha mode is set to blend. Toss it into the alpha draw pool. + break; + case 0: //alpha mode set to none, never go to alpha pool + case 3: //alpha mode set to emissive, never go to alpha pool + alpha = color_alpha; + break; + default: //alpha mode set to "mask", go to alpha pool if fullbright + alpha = color_alpha; // Material's alpha mode is set to none, mask, or emissive. Toss it into the opaque material draw pool. + break; + } + } + + if (alpha) + { + return LLDrawPool::POOL_ALPHA; + } + else if ((te->getBumpmap() || te->getShiny()) && (!mat || mat->getNormalID().isNull())) + { + return LLDrawPool::POOL_BUMP; + } + else if (mat && !alpha) + { + return LLDrawPool::POOL_MATERIALS; + } + else + { + return LLDrawPool::POOL_SIMPLE; + } } void LLPipeline::addPool(LLDrawPool *new_poolp) { - assertInitialized(); - mPools.insert(new_poolp); - addToQuickLookup( new_poolp ); + assertInitialized(); + mPools.insert(new_poolp); + addToQuickLookup( new_poolp ); } void LLPipeline::allocDrawable(LLViewerObject *vobj) { - LLDrawable *drawable = new LLDrawable(vobj); - vobj->mDrawable = drawable; - - //encompass completely sheared objects by taking - //the most extreme point possible (<1,1,0.5>) - drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).length()); - if (vobj->isOrphaned()) - { - drawable->setState(LLDrawable::FORCE_INVISIBLE); - } - drawable->updateXform(TRUE); + LLDrawable *drawable = new LLDrawable(vobj); + vobj->mDrawable = drawable; + + //encompass completely sheared objects by taking + //the most extreme point possible (<1,1,0.5>) + drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).length()); + if (vobj->isOrphaned()) + { + drawable->setState(LLDrawable::FORCE_INVISIBLE); + } + drawable->updateXform(TRUE); } @@ -1728,74 +1726,74 @@ static LLTrace::BlockTimerStatHandle FTM_REMOVE_FROM_HIGHLIGHT_SET("Highlight Se void LLPipeline::unlinkDrawable(LLDrawable *drawable) { - LL_RECORD_BLOCK_TIME(FTM_UNLINK); + LL_RECORD_BLOCK_TIME(FTM_UNLINK); - assertInitialized(); + assertInitialized(); - LLPointer drawablep = drawable; // make sure this doesn't get deleted before we are done - - // Based on flags, remove the drawable from the queues that it's on. - if (drawablep->isState(LLDrawable::ON_MOVE_LIST)) - { - LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_MOVE_LIST); - LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep); - if (iter != mMovedList.end()) - { - mMovedList.erase(iter); - } - } + LLPointer drawablep = drawable; // make sure this doesn't get deleted before we are done + + // Based on flags, remove the drawable from the queues that it's on. + if (drawablep->isState(LLDrawable::ON_MOVE_LIST)) + { + LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_MOVE_LIST); + LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep); + if (iter != mMovedList.end()) + { + mMovedList.erase(iter); + } + } - if (drawablep->getSpatialGroup()) - { - LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_SPATIAL_PARTITION); - if (!drawablep->getSpatialGroup()->getSpatialPartition()->remove(drawablep, drawablep->getSpatialGroup())) - { + if (drawablep->getSpatialGroup()) + { + LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_SPATIAL_PARTITION); + if (!drawablep->getSpatialGroup()->getSpatialPartition()->remove(drawablep, drawablep->getSpatialGroup())) + { #ifdef LL_RELEASE_FOR_DOWNLOAD - LL_WARNS() << "Couldn't remove object from spatial group!" << LL_ENDL; + LL_WARNS() << "Couldn't remove object from spatial group!" << LL_ENDL; #else - LL_ERRS() << "Couldn't remove object from spatial group!" << LL_ENDL; + LL_ERRS() << "Couldn't remove object from spatial group!" << LL_ENDL; #endif - } - } - - { - LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_LIGHT_SET); - mLights.erase(drawablep); - - for (light_set_t::iterator iter = mNearbyLights.begin(); - iter != mNearbyLights.end(); iter++) - { - if (iter->drawable == drawablep) - { - mNearbyLights.erase(iter); - break; - } - } - } - - { - LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_HIGHLIGHT_SET); - HighlightItem item(drawablep); - mHighlightSet.erase(item); + } + } - if (mHighlightObject == drawablep) - { - mHighlightObject = NULL; - } - } + { + LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_LIGHT_SET); + mLights.erase(drawablep); + + for (light_set_t::iterator iter = mNearbyLights.begin(); + iter != mNearbyLights.end(); iter++) + { + if (iter->drawable == drawablep) + { + mNearbyLights.erase(iter); + break; + } + } + } - for (U32 i = 0; i < 2; ++i) - { - if (mShadowSpotLight[i] == drawablep) - { - mShadowSpotLight[i] = NULL; - } + { + LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_HIGHLIGHT_SET); + HighlightItem item(drawablep); + mHighlightSet.erase(item); + + if (mHighlightObject == drawablep) + { + mHighlightObject = NULL; + } + } - if (mTargetShadowSpotLight[i] == drawablep) - { - mTargetShadowSpotLight[i] = NULL; - } - } + for (U32 i = 0; i < 2; ++i) + { + if (mShadowSpotLight[i] == drawablep) + { + mShadowSpotLight[i] = NULL; + } + + if (mTargetShadowSpotLight[i] == drawablep) + { + mTargetShadowSpotLight[i] = NULL; + } + } } @@ -1803,201 +1801,201 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) //static void LLPipeline::removeMutedAVsLights(LLVOAvatar* muted_avatar) { - LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_LIGHT_SET); - for (light_set_t::iterator iter = gPipeline.mNearbyLights.begin(); - iter != gPipeline.mNearbyLights.end(); iter++) - { - if (iter->drawable->getVObj()->isAttachment() && iter->drawable->getVObj()->getAvatar() == muted_avatar) - { - gPipeline.mLights.erase(iter->drawable); - gPipeline.mNearbyLights.erase(iter); - } - } + LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_LIGHT_SET); + for (light_set_t::iterator iter = gPipeline.mNearbyLights.begin(); + iter != gPipeline.mNearbyLights.end(); iter++) + { + if (iter->drawable->getVObj()->isAttachment() && iter->drawable->getVObj()->getAvatar() == muted_avatar) + { + gPipeline.mLights.erase(iter->drawable); + gPipeline.mNearbyLights.erase(iter); + } + } } U32 LLPipeline::addObject(LLViewerObject *vobj) { - if (RenderDelayCreation) - { - mCreateQ.push_back(vobj); - } - else - { - createObject(vobj); - } + if (RenderDelayCreation) + { + mCreateQ.push_back(vobj); + } + else + { + createObject(vobj); + } - return 1; + return 1; } void LLPipeline::createObjects(F32 max_dtime) { - LL_RECORD_BLOCK_TIME(FTM_PIPELINE_CREATE); + LL_RECORD_BLOCK_TIME(FTM_PIPELINE_CREATE); - LLTimer update_timer; + LLTimer update_timer; - while (!mCreateQ.empty() && update_timer.getElapsedTimeF32() < max_dtime) - { - LLViewerObject* vobj = mCreateQ.front(); - if (!vobj->isDead()) - { - createObject(vobj); - } - mCreateQ.pop_front(); - } - - //for (LLViewerObject::vobj_list_t::iterator iter = mCreateQ.begin(); iter != mCreateQ.end(); ++iter) - //{ - // createObject(*iter); - //} + while (!mCreateQ.empty() && update_timer.getElapsedTimeF32() < max_dtime) + { + LLViewerObject* vobj = mCreateQ.front(); + if (!vobj->isDead()) + { + createObject(vobj); + } + mCreateQ.pop_front(); + } + + //for (LLViewerObject::vobj_list_t::iterator iter = mCreateQ.begin(); iter != mCreateQ.end(); ++iter) + //{ + // createObject(*iter); + //} - //mCreateQ.clear(); + //mCreateQ.clear(); } void LLPipeline::createObject(LLViewerObject* vobj) { - LLDrawable* drawablep = vobj->mDrawable; + LLDrawable* drawablep = vobj->mDrawable; - if (!drawablep) - { - drawablep = vobj->createDrawable(this); - } - else - { - LL_ERRS() << "Redundant drawable creation!" << LL_ENDL; - } - - llassert(drawablep); + if (!drawablep) + { + drawablep = vobj->createDrawable(this); + } + else + { + LL_ERRS() << "Redundant drawable creation!" << LL_ENDL; + } + + llassert(drawablep); - if (vobj->getParent()) - { - vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1 - } - else - { - vobj->setDrawableParent(NULL); // LLPipeline::addObject 2 - } + if (vobj->getParent()) + { + vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1 + } + else + { + vobj->setDrawableParent(NULL); // LLPipeline::addObject 2 + } - markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE); + markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE); - if (drawablep->getVOVolume() && RenderAnimateRes) - { - // fun animated res - drawablep->updateXform(TRUE); - drawablep->clearState(LLDrawable::MOVE_UNDAMPED); - drawablep->setScale(LLVector3(0,0,0)); - drawablep->makeActive(); - } + if (drawablep->getVOVolume() && RenderAnimateRes) + { + // fun animated res + drawablep->updateXform(TRUE); + drawablep->clearState(LLDrawable::MOVE_UNDAMPED); + drawablep->setScale(LLVector3(0,0,0)); + drawablep->makeActive(); + } } void LLPipeline::resetFrameStats() { - assertInitialized(); + assertInitialized(); - sCompiles = 0; - mNumVisibleFaces = 0; + sCompiles = 0; + mNumVisibleFaces = 0; - if (mOldRenderDebugMask != mRenderDebugMask) - { - gObjectList.clearDebugText(); - mOldRenderDebugMask = mRenderDebugMask; - } + if (mOldRenderDebugMask != mRenderDebugMask) + { + gObjectList.clearDebugText(); + mOldRenderDebugMask = mRenderDebugMask; + } } //external functions for asynchronous updating void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep) { - if (FreezeTime) - { - return; - } - if (!drawablep) - { - LL_ERRS() << "updateMove called with NULL drawablep" << LL_ENDL; - return; - } - if (drawablep->isState(LLDrawable::EARLY_MOVE)) - { - return; - } + if (FreezeTime) + { + return; + } + if (!drawablep) + { + LL_ERRS() << "updateMove called with NULL drawablep" << LL_ENDL; + return; + } + if (drawablep->isState(LLDrawable::EARLY_MOVE)) + { + return; + } - assertInitialized(); + assertInitialized(); - // update drawable now - drawablep->clearState(LLDrawable::MOVE_UNDAMPED); // force to DAMPED - drawablep->updateMove(); // returns done - drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame - // Put on move list so that EARLY_MOVE gets cleared - if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) - { - mMovedList.push_back(drawablep); - drawablep->setState(LLDrawable::ON_MOVE_LIST); - } + // update drawable now + drawablep->clearState(LLDrawable::MOVE_UNDAMPED); // force to DAMPED + drawablep->updateMove(); // returns done + drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame + // Put on move list so that EARLY_MOVE gets cleared + if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) + { + mMovedList.push_back(drawablep); + drawablep->setState(LLDrawable::ON_MOVE_LIST); + } } void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep) { - if (FreezeTime) - { - return; - } - if (!drawablep) - { - LL_ERRS() << "updateMove called with NULL drawablep" << LL_ENDL; - return; - } - if (drawablep->isState(LLDrawable::EARLY_MOVE)) - { - return; - } + if (FreezeTime) + { + return; + } + if (!drawablep) + { + LL_ERRS() << "updateMove called with NULL drawablep" << LL_ENDL; + return; + } + if (drawablep->isState(LLDrawable::EARLY_MOVE)) + { + return; + } - assertInitialized(); + assertInitialized(); - // update drawable now - drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED - drawablep->updateMove(); - drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame - // Put on move list so that EARLY_MOVE gets cleared - if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) - { - mMovedList.push_back(drawablep); - drawablep->setState(LLDrawable::ON_MOVE_LIST); - } + // update drawable now + drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED + drawablep->updateMove(); + drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame + // Put on move list so that EARLY_MOVE gets cleared + if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) + { + mMovedList.push_back(drawablep); + drawablep->setState(LLDrawable::ON_MOVE_LIST); + } } void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list) { - for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin(); - iter != moved_list.end(); ) - { - LLDrawable::drawable_vector_t::iterator curiter = iter++; - LLDrawable *drawablep = *curiter; - bool done = true; - if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE))) - { - done = drawablep->updateMove(); - } - drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED); - if (done) - { - if (drawablep->isRoot()) - { - drawablep->makeStatic(); - } - drawablep->clearState(LLDrawable::ON_MOVE_LIST); - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { //will likely not receive any future world matrix updates - // -- this keeps attachments from getting stuck in space and falling off your avatar - drawablep->clearState(LLDrawable::ANIMATED_CHILD); - markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, TRUE); - if (drawablep->getVObj()) - { - drawablep->getVObj()->dirtySpatialGroup(TRUE); - } - } - iter = moved_list.erase(curiter); - } - } + for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin(); + iter != moved_list.end(); ) + { + LLDrawable::drawable_vector_t::iterator curiter = iter++; + LLDrawable *drawablep = *curiter; + bool done = true; + if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE))) + { + done = drawablep->updateMove(); + } + drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED); + if (done) + { + if (drawablep->isRoot()) + { + drawablep->makeStatic(); + } + drawablep->clearState(LLDrawable::ON_MOVE_LIST); + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { //will likely not receive any future world matrix updates + // -- this keeps attachments from getting stuck in space and falling off your avatar + drawablep->clearState(LLDrawable::ANIMATED_CHILD); + markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, TRUE); + if (drawablep->getVObj()) + { + drawablep->getVObj()->dirtySpatialGroup(TRUE); + } + } + iter = moved_list.erase(curiter); + } + } } static LLTrace::BlockTimerStatHandle FTM_OCTREE_BALANCE("Balance Octree"); @@ -2007,60 +2005,60 @@ static LLTrace::BlockTimerStatHandle FTM_MOVED_LIST("Moved List"); void LLPipeline::updateMove() { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_MOVE); - - if (FreezeTime) - { - return; - } + LL_RECORD_BLOCK_TIME(FTM_UPDATE_MOVE); - assertInitialized(); + if (FreezeTime) + { + return; + } - { - LL_RECORD_BLOCK_TIME(FTM_RETEXTURE); + assertInitialized(); - for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin(); - iter != mRetexturedList.end(); ++iter) - { - LLDrawable* drawablep = *iter; - if (drawablep && !drawablep->isDead()) - { - drawablep->updateTexture(); - } - } - mRetexturedList.clear(); - } - - { - LL_RECORD_BLOCK_TIME(FTM_MOVED_LIST); - updateMovedList(mMovedList); - } - - //balance octrees - { - LL_RECORD_BLOCK_TIME(FTM_OCTREE_BALANCE); + { + LL_RECORD_BLOCK_TIME(FTM_RETEXTURE); + + for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin(); + iter != mRetexturedList.end(); ++iter) + { + LLDrawable* drawablep = *iter; + if (drawablep && !drawablep->isDead()) + { + drawablep->updateTexture(); + } + } + mRetexturedList.clear(); + } - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) - { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) - { - part->mOctree->balance(); - } - } + { + LL_RECORD_BLOCK_TIME(FTM_MOVED_LIST); + updateMovedList(mMovedList); + } - //balance the VO Cache tree - LLVOCachePartition* vo_part = region->getVOCachePartition(); - if(vo_part) - { - vo_part->mOctree->balance(); - } - } - } + //balance octrees + { + LL_RECORD_BLOCK_TIME(FTM_OCTREE_BALANCE); + + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + part->mOctree->balance(); + } + } + + //balance the VO Cache tree + LLVOCachePartition* vo_part = region->getVOCachePartition(); + if(vo_part) + { + vo_part->mOctree->balance(); + } + } + } } ///////////////////////////////////////////////////////////////////////////// @@ -2070,349 +2068,349 @@ void LLPipeline::updateMove() //static F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera) { - LLVector3 lookAt = center - camera.getOrigin(); - F32 dist = lookAt.length(); + LLVector3 lookAt = center - camera.getOrigin(); + F32 dist = lookAt.length(); - //ramp down distance for nearby objects - //shrink dist by dist/16. - if (dist < 16.f) - { - dist /= 16.f; - dist *= dist; - dist *= 16.f; - } + //ramp down distance for nearby objects + //shrink dist by dist/16. + if (dist < 16.f) + { + dist /= 16.f; + dist *= dist; + dist *= 16.f; + } - //get area of circle around node - F32 app_angle = atanf(size.length()/dist); - F32 radius = app_angle*LLDrawable::sCurPixelAngle; - return radius*radius * F_PI; + //get area of circle around node + F32 app_angle = atanf(size.length()/dist); + F32 radius = app_angle*LLDrawable::sCurPixelAngle; + return radius*radius * F_PI; } //static F32 LLPipeline::calcPixelArea(const LLVector4a& center, const LLVector4a& size, LLCamera &camera) { - LLVector4a origin; - origin.load3(camera.getOrigin().mV); + LLVector4a origin; + origin.load3(camera.getOrigin().mV); - LLVector4a lookAt; - lookAt.setSub(center, origin); - F32 dist = lookAt.getLength3().getF32(); + LLVector4a lookAt; + lookAt.setSub(center, origin); + F32 dist = lookAt.getLength3().getF32(); - //ramp down distance for nearby objects - //shrink dist by dist/16. - if (dist < 16.f) - { - dist /= 16.f; - dist *= dist; - dist *= 16.f; - } + //ramp down distance for nearby objects + //shrink dist by dist/16. + if (dist < 16.f) + { + dist /= 16.f; + dist *= dist; + dist *= 16.f; + } - //get area of circle around node - F32 app_angle = atanf(size.getLength3().getF32()/dist); - F32 radius = app_angle*LLDrawable::sCurPixelAngle; - return radius*radius * F_PI; + //get area of circle around node + F32 app_angle = atanf(size.getLength3().getF32()/dist); + F32 radius = app_angle*LLDrawable::sCurPixelAngle; + return radius*radius * F_PI; } void LLPipeline::grabReferences(LLCullResult& result) { - sCull = &result; + sCull = &result; } void LLPipeline::clearReferences() { - sCull = NULL; - mGroupSaveQ1.clear(); + sCull = NULL; + mGroupSaveQ1.clear(); } void check_references(LLSpatialGroup* group, LLDrawable* drawable) { - for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) - { - if (drawable == (LLDrawable*)(*i)->getDrawable()) - { - LL_ERRS() << "LLDrawable deleted while actively reference by LLPipeline." << LL_ENDL; - } - } + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { + if (drawable == (LLDrawable*)(*i)->getDrawable()) + { + LL_ERRS() << "LLDrawable deleted while actively reference by LLPipeline." << LL_ENDL; + } + } } void check_references(LLDrawable* drawable, LLFace* face) { - for (S32 i = 0; i < drawable->getNumFaces(); ++i) - { - if (drawable->getFace(i) == face) - { - LL_ERRS() << "LLFace deleted while actively referenced by LLPipeline." << LL_ENDL; - } - } + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + if (drawable->getFace(i) == face) + { + LL_ERRS() << "LLFace deleted while actively referenced by LLPipeline." << LL_ENDL; + } + } } void check_references(LLSpatialGroup* group, LLFace* face) { - for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(drawable) - { - check_references(drawable, face); - } + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(drawable) + { + check_references(drawable, face); + } } } void LLPipeline::checkReferences(LLFace* face) { -#if CHECK_PIPELINE_REFERENCES - if (sCull) - { - for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, face); - } - - for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, face); - } - - for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, face); - } - - for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) - { - LLDrawable* drawable = *iter; - check_references(drawable, face); - } - } +#if 0 + if (sCull) + { + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, face); + } + + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, face); + } + + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, face); + } + + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) + { + LLDrawable* drawable = *iter; + check_references(drawable, face); + } + } #endif } void LLPipeline::checkReferences(LLDrawable* drawable) { -#if CHECK_PIPELINE_REFERENCES - if (sCull) - { - for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, drawable); - } - - for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, drawable); - } - - for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, drawable); - } - - for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) - { - if (drawable == *iter) - { - LL_ERRS() << "LLDrawable deleted while actively referenced by LLPipeline." << LL_ENDL; - } - } - } +#if 0 + if (sCull) + { + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, drawable); + } + + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, drawable); + } + + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, drawable); + } + + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) + { + if (drawable == *iter) + { + LL_ERRS() << "LLDrawable deleted while actively referenced by LLPipeline." << LL_ENDL; + } + } + } #endif } void check_references(LLSpatialGroup* group, LLDrawInfo* draw_info) { - for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) - { - LLSpatialGroup::drawmap_elem_t& draw_vec = i->second; - for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) - { - LLDrawInfo* params = *j; - if (params == draw_info) - { - LL_ERRS() << "LLDrawInfo deleted while actively referenced by LLPipeline." << LL_ENDL; - } - } - } + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) + { + LLSpatialGroup::drawmap_elem_t& draw_vec = i->second; + for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) + { + LLDrawInfo* params = *j; + if (params == draw_info) + { + LL_ERRS() << "LLDrawInfo deleted while actively referenced by LLPipeline." << LL_ENDL; + } + } + } } void LLPipeline::checkReferences(LLDrawInfo* draw_info) { -#if CHECK_PIPELINE_REFERENCES - if (sCull) - { - for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, draw_info); - } - - for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, draw_info); - } - - for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, draw_info); - } - } +#if 0 + if (sCull) + { + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, draw_info); + } + + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, draw_info); + } + + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, draw_info); + } + } #endif } void LLPipeline::checkReferences(LLSpatialGroup* group) { #if CHECK_PIPELINE_REFERENCES - if (sCull) - { - for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) - { - if (group == *iter) - { - LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; - } - } - - for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) - { - if (group == *iter) - { - LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; - } - } - - for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) - { - if (group == *iter) - { - LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; - } - } - } + if (sCull) + { + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + if (group == *iter) + { + LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; + } + } + + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + if (group == *iter) + { + LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; + } + } + + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + if (group == *iter) + { + LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; + } + } + } #endif } bool LLPipeline::visibleObjectsInFrustum(LLCamera& camera) { - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) - { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) - { - if (hasRenderType(part->mDrawableType)) - { - if (part->visibleObjectsInFrustum(camera)) - { - return true; - } - } - } - } - } + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + if (hasRenderType(part->mDrawableType)) + { + if (part->visibleObjectsInFrustum(camera)) + { + return true; + } + } + } + } + } - return false; + return false; } bool LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& max) { - const F32 X = 65536.f; + const F32 X = 65536.f; - min = LLVector3(X,X,X); - max = LLVector3(-X,-X,-X); + min = LLVector3(X,X,X); + max = LLVector3(-X,-X,-X); - LLViewerCamera::eCameraID saved_camera_id = LLViewerCamera::sCurCameraID; - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; + LLViewerCamera::eCameraID saved_camera_id = LLViewerCamera::sCurCameraID; + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; - bool res = true; - - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; + bool res = true; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) - { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) - { - if (hasRenderType(part->mDrawableType)) - { - if (!part->getVisibleExtents(camera, min, max)) - { - res = false; - } - } - } - } - } + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + if (hasRenderType(part->mDrawableType)) + { + if (!part->getVisibleExtents(camera, min, max)) + { + res = false; + } + } + } + } + } - LLViewerCamera::sCurCameraID = saved_camera_id; + LLViewerCamera::sCurCameraID = saved_camera_id; - return res; + return res; } static LLTrace::BlockTimerStatHandle FTM_CULL("Object Culling"); void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip, LLPlane* planep) { - static LLCachedControl use_occlusion(gSavedSettings,"UseOcclusion"); - static bool can_use_occlusion = LLGLSLShader::sNoFixedFunction - && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") - && gGLManager.mHasOcclusionQuery; + static LLCachedControl use_occlusion(gSavedSettings,"UseOcclusion"); + static bool can_use_occlusion = LLGLSLShader::sNoFixedFunction + && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") + && gGLManager.mHasOcclusionQuery; - LL_RECORD_BLOCK_TIME(FTM_CULL); + LL_RECORD_BLOCK_TIME(FTM_CULL); - grabReferences(result); + grabReferences(result); - sCull->clear(); + sCull->clear(); - bool to_texture = LLPipeline::sUseOcclusion > 1 && - !hasRenderType(LLPipeline::RENDER_TYPE_HUD) && - LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && - gPipeline.canUseVertexShaders() && - sRenderGlow; + bool to_texture = LLPipeline::sUseOcclusion > 1 && + !hasRenderType(LLPipeline::RENDER_TYPE_HUD) && + LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && + gPipeline.canUseVertexShaders() && + sRenderGlow; - if (to_texture) - { - if (LLPipeline::sRenderDeferred && can_use_occlusion) - { - mOcclusionDepth.bindTarget(); - } - else - { - mScreen.bindTarget(); - } - } + if (to_texture) + { + if (LLPipeline::sRenderDeferred && can_use_occlusion) + { + mOcclusionDepth.bindTarget(); + } + else + { + mScreen.bindTarget(); + } + } - if (sUseOcclusion > 1) - { - gGL.setColorMask(false, false); - } + if (sUseOcclusion > 1) + { + gGL.setColorMask(false, false); + } - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadMatrix(gGLLastProjection); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLLastModelView); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadMatrix(gGLLastProjection); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLLastModelView); - LLGLDisable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLDisable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLGLDepthTest depth(GL_TRUE, GL_FALSE); @@ -2467,32 +2465,33 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl LLPipeline::sUseFarClip = use_far_clip; - if (bound_shader) - { - gOcclusionCubeProgram.unbind(); - } + if (bound_shader) + { + gOcclusionCubeProgram.unbind(); + } - camera.disableUserClipPlane(); + camera.disableUserClipPlane(); - if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) && - gSky.mVOSkyp.notNull() && - gSky.mVOSkyp->mDrawable.notNull()) - { - gSky.mVOSkyp->mDrawable->setVisible(camera); - sCull->pushDrawable(gSky.mVOSkyp->mDrawable); - gSky.updateCull(); - stop_glerror(); - } + if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) && + gSky.mVOSkyp.notNull() && + gSky.mVOSkyp->mDrawable.notNull()) + { + gSky.mVOSkyp->mDrawable->setVisible(camera); + sCull->pushDrawable(gSky.mVOSkyp->mDrawable); + gSky.updateCull(); + stop_glerror(); + } + + if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) && + !gPipeline.canUseWindLightShaders() && + gSky.mVOGroundp.notNull() && + gSky.mVOGroundp->mDrawable.notNull() && + !LLPipeline::sWaterReflections) + { + gSky.mVOGroundp->mDrawable->setVisible(camera); + sCull->pushDrawable(gSky.mVOGroundp->mDrawable); + } - if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) && - !gPipeline.canUseWindLightShaders() && - gSky.mVOGroundp.notNull() && - gSky.mVOGroundp->mDrawable.notNull() && - !LLPipeline::sWaterReflections) - { - gSky.mVOGroundp->mDrawable->setVisible(camera); - sCull->pushDrawable(gSky.mVOGroundp->mDrawable); - } if (hasRenderType(LLPipeline::RENDER_TYPE_WL_SKY) && gPipeline.canUseWindLightShaders() && @@ -2514,304 +2513,247 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl } #endif - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); + + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); if (sUseOcclusion > 1) - { - gGL.setColorMask(true, false); - } + { + gGL.setColorMask(true, false); + } - if (to_texture) - { - if (LLPipeline::sRenderDeferred && can_use_occlusion) - { - mOcclusionDepth.flush(); - } - else - { - mScreen.flush(); - } - } + if (to_texture) + { + if (LLPipeline::sRenderDeferred && can_use_occlusion) + { + mOcclusionDepth.flush(); + } + else + { + mScreen.flush(); + } + } } void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) { - if (group->isEmpty()) - { - return; - } - - group->setVisible(); + if (group->isEmpty()) + { + return; + } + + group->setVisible(); - if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) - { - group->updateDistance(camera); - } - - const F32 MINIMUM_PIXEL_AREA = 16.f; + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) + { + group->updateDistance(camera); + } + + const F32 MINIMUM_PIXEL_AREA = 16.f; - if (group->mPixelArea < MINIMUM_PIXEL_AREA) - { - return; - } + if (group->mPixelArea < MINIMUM_PIXEL_AREA) + { + return; + } - const LLVector4a* bounds = group->getBounds(); - if (sMinRenderSize > 0.f && - llmax(llmax(bounds[1][0], bounds[1][1]), bounds[1][2]) < sMinRenderSize) - { - return; - } + const LLVector4a* bounds = group->getBounds(); + if (sMinRenderSize > 0.f && + llmax(llmax(bounds[1][0], bounds[1][1]), bounds[1][2]) < sMinRenderSize) + { + return; + } - assertInitialized(); - - if (!group->getSpatialPartition()->mRenderByGroup) - { //render by drawable - sCull->pushDrawableGroup(group); - } - else - { //render by group - sCull->pushVisibleGroup(group); - } + assertInitialized(); + + if (!group->getSpatialPartition()->mRenderByGroup) + { //render by drawable + sCull->pushDrawableGroup(group); + } + else + { //render by group + sCull->pushVisibleGroup(group); + } - mNumVisibleNodes++; + mNumVisibleNodes++; } void LLPipeline::markOccluder(LLSpatialGroup* group) { - if (sUseOcclusion > 1 && group && !group->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION)) - { - LLSpatialGroup* parent = group->getParent(); - - if (!parent || !parent->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { //only mark top most occluders as active occlusion - sCull->pushOcclusionGroup(group); - group->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); - - if (parent && - !parent->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION) && - parent->getElementCount() == 0 && - parent->needsUpdate()) - { - sCull->pushOcclusionGroup(group); - parent->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); - } - } - } + if (sUseOcclusion > 1 && group && !group->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION)) + { + LLSpatialGroup* parent = group->getParent(); + + if (!parent || !parent->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { //only mark top most occluders as active occlusion + sCull->pushOcclusionGroup(group); + group->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); + + if (parent && + !parent->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION) && + parent->getElementCount() == 0 && + parent->needsUpdate()) + { + sCull->pushOcclusionGroup(group); + parent->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); + } + } + } } -void LLPipeline::downsampleMinMaxDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space) +void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space) { - LLGLSLShader* last_shader = LLGLSLShader::sCurBoundShaderPtr; - - LLGLSLShader* shader = NULL; - - if (scratch_space) - { - scratch_space->copyContents(source, - 0, 0, source.getWidth(), source.getHeight(), - 0, 0, scratch_space->getWidth(), scratch_space->getHeight(), source.hasStencil() ? GL_DEPTH_BUFFER_BIT : GL_COLOR_BUFFER_BIT, GL_NEAREST); - } - - dest.bindTarget(); - dest.clear(GL_COLOR_BUFFER_BIT); // dest should be an RG16F target + LLGLSLShader* last_shader = LLGLSLShader::sCurBoundShaderPtr; - LLStrider vert; - mDeferredVB->getVertexStrider(vert); - LLStrider tc0; + LLGLSLShader* shader = NULL; - vert[0].set(-1, 1, 0); - vert[1].set(-1, -3, 0); - vert[2].set(3, 1, 0); + if (scratch_space) + { + scratch_space->copyContents(source, + 0, 0, source.getWidth(), source.getHeight(), + 0, 0, scratch_space->getWidth(), scratch_space->getHeight(), source.hasStencil() ? (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) : GL_COLOR_BUFFER_BIT, GL_NEAREST); + } - if (source.getUsage() == LLTexUnit::TT_RECT_TEXTURE) - { - shader = &gDownsampleMinMaxDepthRectProgram; - shader->bind(); - shader->uniform2f(sDelta, 1.f, 1.f); - shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, source.getWidth(), source.getHeight()); - } - else - { - shader = &gDownsampleMinMaxDepthRectProgram; - shader->bind(); - shader->uniform2f(sDelta, 1.f / source.getWidth(), 1.f / source.getHeight()); - shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, 1.f, 1.f); - } - - gGL.getTexUnit(0)->bind(scratch_space ? scratch_space : &source, TRUE); - - { - LLGLDepthTest depth(GL_FALSE, GL_FALSE, GL_ALWAYS); - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); - mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); - } - - dest.flush(); - - if (last_shader) - { - last_shader->bind(); - } - else - { - shader->unbind(); - } -} - -void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space) -{ - LLGLSLShader* last_shader = LLGLSLShader::sCurBoundShaderPtr; - - LLGLSLShader* shader = NULL; - - if (scratch_space) - { - scratch_space->copyContents(source, - 0, 0, source.getWidth(), source.getHeight(), - 0, 0, scratch_space->getWidth(), scratch_space->getHeight(), source.hasStencil() ? (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) : GL_COLOR_BUFFER_BIT, GL_NEAREST); - } - - dest.bindTarget(); - dest.clear(GL_DEPTH_BUFFER_BIT); - - LLStrider vert; - mDeferredVB->getVertexStrider(vert); - LLStrider tc0; - - vert[0].set(-1,1,0); - vert[1].set(-1,-3,0); - vert[2].set(3,1,0); - - if (source.getUsage() == LLTexUnit::TT_RECT_TEXTURE) - { - shader = &gDownsampleDepthRectProgram; - shader->bind(); - shader->uniform2f(sDelta, 1.f, 1.f); - shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, source.getWidth(), source.getHeight()); - } - else - { - shader = &gDownsampleDepthProgram; - shader->bind(); - shader->uniform2f(sDelta, 1.f/source.getWidth(), 1.f/source.getHeight()); - shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, 1.f, 1.f); - } + dest.bindTarget(); + dest.clear(GL_DEPTH_BUFFER_BIT); + + LLStrider vert; + mDeferredVB->getVertexStrider(vert); + LLStrider tc0; + + vert[0].set(-1,1,0); + vert[1].set(-1,-3,0); + vert[2].set(3,1,0); + + if (source.getUsage() == LLTexUnit::TT_RECT_TEXTURE) + { + shader = &gDownsampleDepthRectProgram; + shader->bind(); + shader->uniform2f(sDelta, 1.f, 1.f); + shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, source.getWidth(), source.getHeight()); + } + else + { + shader = &gDownsampleDepthProgram; + shader->bind(); + shader->uniform2f(sDelta, 1.f/source.getWidth(), 1.f/source.getHeight()); + shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, 1.f, 1.f); + } - gGL.getTexUnit(0)->bind(scratch_space ? scratch_space : &source, TRUE); + gGL.getTexUnit(0)->bind(scratch_space ? scratch_space : &source, TRUE); - { - LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); - mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); - } - - dest.flush(); - - if (last_shader) - { - last_shader->bind(); - } - else - { - shader->unbind(); - } + { + LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); + mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } + + dest.flush(); + + if (last_shader) + { + last_shader->bind(); + } + else + { + shader->unbind(); + } } void LLPipeline::doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space) { - downsampleDepthBuffer(source, dest, scratch_space); - dest.bindTarget(); - doOcclusion(camera); - dest.flush(); + downsampleDepthBuffer(source, dest, scratch_space); + dest.bindTarget(); + doOcclusion(camera); + dest.flush(); } void LLPipeline::doOcclusion(LLCamera& camera) { - if (LLPipeline::sUseOcclusion > 1 && !LLSpatialPartition::sTeleportRequested && - (sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck)) - { - LLVertexBuffer::unbind(); - - if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) - { - gGL.setColorMask(true, false, false, false); - } - else - { - gGL.setColorMask(false, false); - } - LLGLDisable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - - LLGLDisable cull(GL_CULL_FACE); - - - bool bind_shader = LLGLSLShader::sNoFixedFunction && LLGLSLShader::sCurBoundShader == 0; - if (bind_shader) - { - if (LLPipeline::sShadowRender) - { - gDeferredShadowCubeProgram.bind(); - } - else - { - gOcclusionCubeProgram.bind(); - } - } - - if (mCubeVB.isNull()) - { //cube VB will be used for issuing occlusion queries - mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); - } - mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); - - for (LLCullResult::sg_iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - group->doOcclusion(&camera); - group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); - } - - //apply occlusion culling to object cache tree - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLVOCachePartition* vo_part = (*iter)->getVOCachePartition(); - if(vo_part) - { - vo_part->processOccluders(&camera); - } - } - - if (bind_shader) - { - if (LLPipeline::sShadowRender) - { - gDeferredShadowCubeProgram.unbind(); - } - else - { - gOcclusionCubeProgram.unbind(); - } - } - - gGL.setColorMask(true, false); - } + if (LLPipeline::sUseOcclusion > 1 && !LLSpatialPartition::sTeleportRequested && + (sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck)) + { + LLVertexBuffer::unbind(); + + if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) + { + gGL.setColorMask(true, false, false, false); + } + else + { + gGL.setColorMask(false, false); + } + LLGLDisable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + + LLGLDisable cull(GL_CULL_FACE); + + + bool bind_shader = LLGLSLShader::sNoFixedFunction && LLGLSLShader::sCurBoundShader == 0; + if (bind_shader) + { + if (LLPipeline::sShadowRender) + { + gDeferredShadowCubeProgram.bind(); + } + else + { + gOcclusionCubeProgram.bind(); + } + } + + if (mCubeVB.isNull()) + { //cube VB will be used for issuing occlusion queries + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + + for (LLCullResult::sg_iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + group->doOcclusion(&camera); + group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); + } + + //apply occlusion culling to object cache tree + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLVOCachePartition* vo_part = (*iter)->getVOCachePartition(); + if(vo_part) + { + vo_part->processOccluders(&camera); + } + } + + if (bind_shader) + { + if (LLPipeline::sShadowRender) + { + gDeferredShadowCubeProgram.unbind(); + } + else + { + gOcclusionCubeProgram.unbind(); + } + } + + gGL.setColorMask(true, false); + } } - + bool LLPipeline::updateDrawableGeom(LLDrawable* drawablep, bool priority) { - bool update_complete = drawablep->updateGeometry(priority); - if (update_complete && assertInitialized()) - { - drawablep->setState(LLDrawable::BUILT); - } - return update_complete; + bool update_complete = drawablep->updateGeometry(priority); + if (update_complete && assertInitialized()) + { + drawablep->setState(LLDrawable::BUILT); + } + return update_complete; } static LLTrace::BlockTimerStatHandle FTM_SEED_VBO_POOLS("Seed VBO Pool"); @@ -2820,150 +2762,150 @@ static LLTrace::BlockTimerStatHandle FTM_UPDATE_GL("Update GL"); void LLPipeline::updateGL() { - { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_GL); - while (!LLGLUpdate::sGLQ.empty()) - { - LLGLUpdate* glu = LLGLUpdate::sGLQ.front(); - glu->updateGL(); - glu->mInQ = FALSE; - LLGLUpdate::sGLQ.pop_front(); - } - } + { + LL_RECORD_BLOCK_TIME(FTM_UPDATE_GL); + while (!LLGLUpdate::sGLQ.empty()) + { + LLGLUpdate* glu = LLGLUpdate::sGLQ.front(); + glu->updateGL(); + glu->mInQ = FALSE; + LLGLUpdate::sGLQ.pop_front(); + } + } - { //seed VBO Pools - LL_RECORD_BLOCK_TIME(FTM_SEED_VBO_POOLS); - LLVertexBuffer::seedPools(); - } + { //seed VBO Pools + LL_RECORD_BLOCK_TIME(FTM_SEED_VBO_POOLS); + LLVertexBuffer::seedPools(); + } } static LLTrace::BlockTimerStatHandle FTM_REBUILD_PRIORITY_GROUPS("Rebuild Priority Groups"); void LLPipeline::clearRebuildGroups() { - LLSpatialGroup::sg_vector_t hudGroups; - - mGroupQ1Locked = true; - // Iterate through all drawables on the priority build queue, - for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin(); - iter != mGroupQ1.end(); ++iter) - { - LLSpatialGroup* group = *iter; - - // If the group contains HUD objects, save the group - if (group->isHUDGroup()) - { - hudGroups.push_back(group); - } - // Else, no HUD objects so clear the build state - else - { - group->clearState(LLSpatialGroup::IN_BUILD_Q1); - } - } + LLSpatialGroup::sg_vector_t hudGroups; - // Clear the group - mGroupQ1.clear(); - - // Copy the saved HUD groups back in - mGroupQ1.assign(hudGroups.begin(), hudGroups.end()); - mGroupQ1Locked = false; + mGroupQ1Locked = true; + // Iterate through all drawables on the priority build queue, + for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin(); + iter != mGroupQ1.end(); ++iter) + { + LLSpatialGroup* group = *iter; + + // If the group contains HUD objects, save the group + if (group->isHUDGroup()) + { + hudGroups.push_back(group); + } + // Else, no HUD objects so clear the build state + else + { + group->clearState(LLSpatialGroup::IN_BUILD_Q1); + } + } - // Clear the HUD groups - hudGroups.clear(); + // Clear the group + mGroupQ1.clear(); - mGroupQ2Locked = true; - for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin(); - iter != mGroupQ2.end(); ++iter) - { - LLSpatialGroup* group = *iter; + // Copy the saved HUD groups back in + mGroupQ1.assign(hudGroups.begin(), hudGroups.end()); + mGroupQ1Locked = false; - // If the group contains HUD objects, save the group - if (group->isHUDGroup()) - { - hudGroups.push_back(group); - } - // Else, no HUD objects so clear the build state - else - { - group->clearState(LLSpatialGroup::IN_BUILD_Q2); - } - } - // Clear the group - mGroupQ2.clear(); + // Clear the HUD groups + hudGroups.clear(); - // Copy the saved HUD groups back in - mGroupQ2.assign(hudGroups.begin(), hudGroups.end()); - mGroupQ2Locked = false; + mGroupQ2Locked = true; + for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin(); + iter != mGroupQ2.end(); ++iter) + { + LLSpatialGroup* group = *iter; + + // If the group contains HUD objects, save the group + if (group->isHUDGroup()) + { + hudGroups.push_back(group); + } + // Else, no HUD objects so clear the build state + else + { + group->clearState(LLSpatialGroup::IN_BUILD_Q2); + } + } + // Clear the group + mGroupQ2.clear(); + + // Copy the saved HUD groups back in + mGroupQ2.assign(hudGroups.begin(), hudGroups.end()); + mGroupQ2Locked = false; } void LLPipeline::clearRebuildDrawables() { - // Clear all drawables on the priority build queue, - for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); - iter != mBuildQ1.end(); ++iter) - { - LLDrawable* drawablep = *iter; - if (drawablep && !drawablep->isDead()) - { - drawablep->clearState(LLDrawable::IN_REBUILD_Q2); - drawablep->clearState(LLDrawable::IN_REBUILD_Q1); - } - } - mBuildQ1.clear(); + // Clear all drawables on the priority build queue, + for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); + iter != mBuildQ1.end(); ++iter) + { + LLDrawable* drawablep = *iter; + if (drawablep && !drawablep->isDead()) + { + drawablep->clearState(LLDrawable::IN_REBUILD_Q2); + drawablep->clearState(LLDrawable::IN_REBUILD_Q1); + } + } + mBuildQ1.clear(); - // clear drawables on the non-priority build queue - for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin(); - iter != mBuildQ2.end(); ++iter) - { - LLDrawable* drawablep = *iter; - if (!drawablep->isDead()) - { - drawablep->clearState(LLDrawable::IN_REBUILD_Q2); - } - } - mBuildQ2.clear(); - - //clear all moving bridges - for (LLDrawable::drawable_vector_t::iterator iter = mMovedBridge.begin(); - iter != mMovedBridge.end(); ++iter) - { - LLDrawable *drawablep = *iter; - drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD); - } - mMovedBridge.clear(); + // clear drawables on the non-priority build queue + for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin(); + iter != mBuildQ2.end(); ++iter) + { + LLDrawable* drawablep = *iter; + if (!drawablep->isDead()) + { + drawablep->clearState(LLDrawable::IN_REBUILD_Q2); + } + } + mBuildQ2.clear(); + + //clear all moving bridges + for (LLDrawable::drawable_vector_t::iterator iter = mMovedBridge.begin(); + iter != mMovedBridge.end(); ++iter) + { + LLDrawable *drawablep = *iter; + drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD); + } + mMovedBridge.clear(); - //clear all moving drawables - for (LLDrawable::drawable_vector_t::iterator iter = mMovedList.begin(); - iter != mMovedList.end(); ++iter) - { - LLDrawable *drawablep = *iter; - drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD); - } - mMovedList.clear(); + //clear all moving drawables + for (LLDrawable::drawable_vector_t::iterator iter = mMovedList.begin(); + iter != mMovedList.end(); ++iter) + { + LLDrawable *drawablep = *iter; + drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD); + } + mMovedList.clear(); } void LLPipeline::rebuildPriorityGroups() { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_PRIORITY_GROUPS); - LLTimer update_timer; - assertInitialized(); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_PRIORITY_GROUPS); + LLTimer update_timer; + assertInitialized(); - gMeshRepo.notifyLoadedMeshes(); + gMeshRepo.notifyLoadedMeshes(); - mGroupQ1Locked = true; - // Iterate through all drawables on the priority build queue, - for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin(); - iter != mGroupQ1.end(); ++iter) - { - LLSpatialGroup* group = *iter; - group->rebuildGeom(); - group->clearState(LLSpatialGroup::IN_BUILD_Q1); - } + mGroupQ1Locked = true; + // Iterate through all drawables on the priority build queue, + for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin(); + iter != mGroupQ1.end(); ++iter) + { + LLSpatialGroup* group = *iter; + group->rebuildGeom(); + group->clearState(LLSpatialGroup::IN_BUILD_Q1); + } - mGroupSaveQ1 = mGroupQ1; - mGroupQ1.clear(); - mGroupQ1Locked = false; + mGroupSaveQ1 = mGroupQ1; + mGroupQ1.clear(); + mGroupQ1Locked = false; } @@ -2971,406 +2913,406 @@ static LLTrace::BlockTimerStatHandle FTM_REBUILD_GROUPS("Rebuild Groups"); void LLPipeline::rebuildGroups() { - if (mGroupQ2.empty()) - { - return; - } + if (mGroupQ2.empty()) + { + return; + } - LL_RECORD_BLOCK_TIME(FTM_REBUILD_GROUPS); - mGroupQ2Locked = true; - // Iterate through some drawables on the non-priority build queue - S32 size = (S32) mGroupQ2.size(); - S32 min_count = llclamp((S32) ((F32) (size * size)/4096*0.25f), 1, size); - - S32 count = 0; - - std::sort(mGroupQ2.begin(), mGroupQ2.end(), LLSpatialGroup::CompareUpdateUrgency()); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_GROUPS); + mGroupQ2Locked = true; + // Iterate through some drawables on the non-priority build queue + S32 size = (S32) mGroupQ2.size(); + S32 min_count = llclamp((S32) ((F32) (size * size)/4096*0.25f), 1, size); + + S32 count = 0; + + std::sort(mGroupQ2.begin(), mGroupQ2.end(), LLSpatialGroup::CompareUpdateUrgency()); + + LLSpatialGroup::sg_vector_t::iterator iter; + LLSpatialGroup::sg_vector_t::iterator last_iter = mGroupQ2.begin(); + + for (iter = mGroupQ2.begin(); + iter != mGroupQ2.end() && count <= min_count; ++iter) + { + LLSpatialGroup* group = *iter; + last_iter = iter; - LLSpatialGroup::sg_vector_t::iterator iter; - LLSpatialGroup::sg_vector_t::iterator last_iter = mGroupQ2.begin(); + if (!group->isDead()) + { + group->rebuildGeom(); + + if (group->getSpatialPartition()->mRenderByGroup) + { + count++; + } + } - for (iter = mGroupQ2.begin(); - iter != mGroupQ2.end() && count <= min_count; ++iter) - { - LLSpatialGroup* group = *iter; - last_iter = iter; + group->clearState(LLSpatialGroup::IN_BUILD_Q2); + } - if (!group->isDead()) - { - group->rebuildGeom(); - - if (group->getSpatialPartition()->mRenderByGroup) - { - count++; - } - } + mGroupQ2.erase(mGroupQ2.begin(), ++last_iter); + + mGroupQ2Locked = false; + + updateMovedList(mMovedBridge); +} + +void LLPipeline::updateGeom(F32 max_dtime) +{ + LLTimer update_timer; + LLPointer drawablep; - group->clearState(LLSpatialGroup::IN_BUILD_Q2); - } + LL_RECORD_BLOCK_TIME(FTM_GEO_UPDATE); - mGroupQ2.erase(mGroupQ2.begin(), ++last_iter); + assertInitialized(); - mGroupQ2Locked = false; + // notify various object types to reset internal cost metrics, etc. + // for now, only LLVOVolume does this to throttle LOD changes + LLVOVolume::preUpdateGeom(); - updateMovedList(mMovedBridge); + // Iterate through all drawables on the priority build queue, + for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); + iter != mBuildQ1.end();) + { + LLDrawable::drawable_list_t::iterator curiter = iter++; + LLDrawable* drawablep = *curiter; + if (drawablep && !drawablep->isDead()) + { + if (drawablep->isState(LLDrawable::IN_REBUILD_Q2)) + { + drawablep->clearState(LLDrawable::IN_REBUILD_Q2); + LLDrawable::drawable_list_t::iterator find = std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep); + if (find != mBuildQ2.end()) + { + mBuildQ2.erase(find); + } + } + + if (drawablep->isUnload()) + { + drawablep->unload(); + drawablep->clearState(LLDrawable::FOR_UNLOAD); + } + + if (updateDrawableGeom(drawablep, TRUE)) + { + drawablep->clearState(LLDrawable::IN_REBUILD_Q1); + mBuildQ1.erase(curiter); + } + } + else + { + mBuildQ1.erase(curiter); + } + } + + // Iterate through some drawables on the non-priority build queue + S32 min_count = 16; + S32 size = (S32) mBuildQ2.size(); + if (size > 1024) + { + min_count = llclamp((S32) (size * (F32) size/4096), 16, size); + } + + S32 count = 0; + + max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, F32SecondsImplicit(max_dtime)); + LLSpatialGroup* last_group = NULL; + LLSpatialBridge* last_bridge = NULL; + + for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin(); + iter != mBuildQ2.end(); ) + { + LLDrawable::drawable_list_t::iterator curiter = iter++; + LLDrawable* drawablep = *curiter; + + LLSpatialBridge* bridge = drawablep->isRoot() ? drawablep->getSpatialBridge() : + drawablep->getParent()->getSpatialBridge(); + + if (drawablep->getSpatialGroup() != last_group && + (!last_bridge || bridge != last_bridge) && + (update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count) + { + break; + } + + //make sure updates don't stop in the middle of a spatial group + //to avoid thrashing (objects are enqueued by group) + last_group = drawablep->getSpatialGroup(); + last_bridge = bridge; + + bool update_complete = true; + if (!drawablep->isDead()) + { + update_complete = updateDrawableGeom(drawablep, FALSE); + count++; + } + if (update_complete) + { + drawablep->clearState(LLDrawable::IN_REBUILD_Q2); + mBuildQ2.erase(curiter); + } + } + + updateMovedList(mMovedBridge); } -void LLPipeline::updateGeom(F32 max_dtime) +void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera) { - LLTimer update_timer; - LLPointer drawablep; + if(drawablep && !drawablep->isDead()) + { + if (drawablep->isSpatialBridge()) + { + const LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable; + llassert(root); // trying to catch a bad assumption + + if (root && // // this test may not be needed, see above + root->getVObj()->isAttachment()) + { + LLDrawable* rootparent = root->getParent(); + if (rootparent) // this IS sometimes NULL + { + LLViewerObject *vobj = rootparent->getVObj(); + llassert(vobj); // trying to catch a bad assumption + if (vobj) // this test may not be needed, see above + { + LLVOAvatar* av = vobj->asAvatar(); + if (av && (av->isImpostor() + || av->isInMuteList() + || (LLVOAvatar::AV_DO_NOT_RENDER == av->getVisualMuteSettings() && !av->needsImpostorUpdate()) )) + { + return; + } + } + } + } + sCull->pushBridge((LLSpatialBridge*) drawablep); + } + else + { + + sCull->pushDrawable(drawablep); + } + + drawablep->setVisible(camera); + } +} - LL_RECORD_BLOCK_TIME(FTM_GEO_UPDATE); +void LLPipeline::markMoved(LLDrawable *drawablep, bool damped_motion) +{ + if (!drawablep) + { + //LL_ERRS() << "Sending null drawable to moved list!" << LL_ENDL; + return; + } + + if (drawablep->isDead()) + { + LL_WARNS() << "Marking NULL or dead drawable moved!" << LL_ENDL; + return; + } + + if (drawablep->getParent()) + { + //ensure that parent drawables are moved first + markMoved(drawablep->getParent(), damped_motion); + } - assertInitialized(); + assertInitialized(); - // notify various object types to reset internal cost metrics, etc. - // for now, only LLVOVolume does this to throttle LOD changes - LLVOVolume::preUpdateGeom(); + if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) + { + if (drawablep->isSpatialBridge()) + { + mMovedBridge.push_back(drawablep); + } + else + { + mMovedList.push_back(drawablep); + } + drawablep->setState(LLDrawable::ON_MOVE_LIST); + } + if (! damped_motion) + { + drawablep->setState(LLDrawable::MOVE_UNDAMPED); // UNDAMPED trumps DAMPED + } + else if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) + { + drawablep->clearState(LLDrawable::MOVE_UNDAMPED); + } +} - // Iterate through all drawables on the priority build queue, - for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); - iter != mBuildQ1.end();) - { - LLDrawable::drawable_list_t::iterator curiter = iter++; - LLDrawable* drawablep = *curiter; - if (drawablep && !drawablep->isDead()) - { - if (drawablep->isState(LLDrawable::IN_REBUILD_Q2)) - { - drawablep->clearState(LLDrawable::IN_REBUILD_Q2); - LLDrawable::drawable_list_t::iterator find = std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep); - if (find != mBuildQ2.end()) - { - mBuildQ2.erase(find); - } - } +void LLPipeline::markShift(LLDrawable *drawablep) +{ + if (!drawablep || drawablep->isDead()) + { + return; + } - if (drawablep->isUnload()) - { - drawablep->unload(); - drawablep->clearState(LLDrawable::FOR_UNLOAD); - } + assertInitialized(); - if (updateDrawableGeom(drawablep, TRUE)) - { - drawablep->clearState(LLDrawable::IN_REBUILD_Q1); - mBuildQ1.erase(curiter); - } - } - else - { - mBuildQ1.erase(curiter); - } - } - - // Iterate through some drawables on the non-priority build queue - S32 min_count = 16; - S32 size = (S32) mBuildQ2.size(); - if (size > 1024) - { - min_count = llclamp((S32) (size * (F32) size/4096), 16, size); - } - - S32 count = 0; - - max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, F32SecondsImplicit(max_dtime)); - LLSpatialGroup* last_group = NULL; - LLSpatialBridge* last_bridge = NULL; + if (!drawablep->isState(LLDrawable::ON_SHIFT_LIST)) + { + drawablep->getVObj()->setChanged(LLXform::SHIFTED | LLXform::SILHOUETTE); + if (drawablep->getParent()) + { + markShift(drawablep->getParent()); + } + mShiftList.push_back(drawablep); + drawablep->setState(LLDrawable::ON_SHIFT_LIST); + } +} - for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin(); - iter != mBuildQ2.end(); ) - { - LLDrawable::drawable_list_t::iterator curiter = iter++; - LLDrawable* drawablep = *curiter; +static LLTrace::BlockTimerStatHandle FTM_SHIFT_DRAWABLE("Shift Drawable"); +static LLTrace::BlockTimerStatHandle FTM_SHIFT_OCTREE("Shift Octree"); +static LLTrace::BlockTimerStatHandle FTM_SHIFT_HUD("Shift HUD"); - LLSpatialBridge* bridge = drawablep->isRoot() ? drawablep->getSpatialBridge() : - drawablep->getParent()->getSpatialBridge(); +void LLPipeline::shiftObjects(const LLVector3 &offset) +{ + assertInitialized(); - if (drawablep->getSpatialGroup() != last_group && - (!last_bridge || bridge != last_bridge) && - (update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count) - { - break; - } + glClear(GL_DEPTH_BUFFER_BIT); + gDepthDirty = true; + + LLVector4a offseta; + offseta.load3(offset.mV); - //make sure updates don't stop in the middle of a spatial group - //to avoid thrashing (objects are enqueued by group) - last_group = drawablep->getSpatialGroup(); - last_bridge = bridge; + { + LL_RECORD_BLOCK_TIME(FTM_SHIFT_DRAWABLE); + + for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); + iter != mShiftList.end(); iter++) + { + LLDrawable *drawablep = *iter; + if (drawablep->isDead()) + { + continue; + } + drawablep->shiftPos(offseta); + drawablep->clearState(LLDrawable::ON_SHIFT_LIST); + } + mShiftList.resize(0); + } - bool update_complete = true; - if (!drawablep->isDead()) - { - update_complete = updateDrawableGeom(drawablep, FALSE); - count++; - } - if (update_complete) - { - drawablep->clearState(LLDrawable::IN_REBUILD_Q2); - mBuildQ2.erase(curiter); - } - } + + { + LL_RECORD_BLOCK_TIME(FTM_SHIFT_OCTREE); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + part->shift(offseta); + } + } + } + } - updateMovedList(mMovedBridge); + { + LL_RECORD_BLOCK_TIME(FTM_SHIFT_HUD); + LLHUDText::shiftAll(offset); + LLHUDNameTag::shiftAll(offset); + } + display_update_camera(); } -void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera) +void LLPipeline::markTextured(LLDrawable *drawablep) { - if(drawablep && !drawablep->isDead()) - { - if (drawablep->isSpatialBridge()) - { - const LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable; - llassert(root); // trying to catch a bad assumption - - if (root && // // this test may not be needed, see above - root->getVObj()->isAttachment()) - { - LLDrawable* rootparent = root->getParent(); - if (rootparent) // this IS sometimes NULL - { - LLViewerObject *vobj = rootparent->getVObj(); - llassert(vobj); // trying to catch a bad assumption - if (vobj) // this test may not be needed, see above - { - LLVOAvatar* av = vobj->asAvatar(); - if (av && (av->isImpostor() - || av->isInMuteList() - || (LLVOAvatar::AV_DO_NOT_RENDER == av->getVisualMuteSettings() && !av->needsImpostorUpdate()) )) - { - return; - } - } - } - } - sCull->pushBridge((LLSpatialBridge*) drawablep); - } - else - { - - sCull->pushDrawable(drawablep); - } - - drawablep->setVisible(camera); - } -} - -void LLPipeline::markMoved(LLDrawable *drawablep, bool damped_motion) -{ - if (!drawablep) - { - //LL_ERRS() << "Sending null drawable to moved list!" << LL_ENDL; - return; - } - - if (drawablep->isDead()) - { - LL_WARNS() << "Marking NULL or dead drawable moved!" << LL_ENDL; - return; - } - - if (drawablep->getParent()) - { - //ensure that parent drawables are moved first - markMoved(drawablep->getParent(), damped_motion); - } - - assertInitialized(); - - if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) - { - if (drawablep->isSpatialBridge()) - { - mMovedBridge.push_back(drawablep); - } - else - { - mMovedList.push_back(drawablep); - } - drawablep->setState(LLDrawable::ON_MOVE_LIST); - } - if (! damped_motion) - { - drawablep->setState(LLDrawable::MOVE_UNDAMPED); // UNDAMPED trumps DAMPED - } - else if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) - { - drawablep->clearState(LLDrawable::MOVE_UNDAMPED); - } -} - -void LLPipeline::markShift(LLDrawable *drawablep) -{ - if (!drawablep || drawablep->isDead()) - { - return; - } - - assertInitialized(); - - if (!drawablep->isState(LLDrawable::ON_SHIFT_LIST)) - { - drawablep->getVObj()->setChanged(LLXform::SHIFTED | LLXform::SILHOUETTE); - if (drawablep->getParent()) - { - markShift(drawablep->getParent()); - } - mShiftList.push_back(drawablep); - drawablep->setState(LLDrawable::ON_SHIFT_LIST); - } -} - -static LLTrace::BlockTimerStatHandle FTM_SHIFT_DRAWABLE("Shift Drawable"); -static LLTrace::BlockTimerStatHandle FTM_SHIFT_OCTREE("Shift Octree"); -static LLTrace::BlockTimerStatHandle FTM_SHIFT_HUD("Shift HUD"); - -void LLPipeline::shiftObjects(const LLVector3 &offset) -{ - assertInitialized(); - - glClear(GL_DEPTH_BUFFER_BIT); - gDepthDirty = true; - - LLVector4a offseta; - offseta.load3(offset.mV); - - { - LL_RECORD_BLOCK_TIME(FTM_SHIFT_DRAWABLE); - - for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); - iter != mShiftList.end(); iter++) - { - LLDrawable *drawablep = *iter; - if (drawablep->isDead()) - { - continue; - } - drawablep->shiftPos(offseta); - drawablep->clearState(LLDrawable::ON_SHIFT_LIST); - } - mShiftList.resize(0); - } - - - { - LL_RECORD_BLOCK_TIME(FTM_SHIFT_OCTREE); - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) - { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) - { - part->shift(offseta); - } - } - } - } - - { - LL_RECORD_BLOCK_TIME(FTM_SHIFT_HUD); - LLHUDText::shiftAll(offset); - LLHUDNameTag::shiftAll(offset); - } - display_update_camera(); -} - -void LLPipeline::markTextured(LLDrawable *drawablep) -{ - if (drawablep && !drawablep->isDead() && assertInitialized()) - { - mRetexturedList.insert(drawablep); - } + if (drawablep && !drawablep->isDead() && assertInitialized()) + { + mRetexturedList.insert(drawablep); + } } void LLPipeline::markGLRebuild(LLGLUpdate* glu) { - if (glu && !glu->mInQ) - { - LLGLUpdate::sGLQ.push_back(glu); - glu->mInQ = TRUE; - } + if (glu && !glu->mInQ) + { + LLGLUpdate::sGLQ.push_back(glu); + glu->mInQ = TRUE; + } } void LLPipeline::markPartitionMove(LLDrawable* drawable) { - if (!drawable->isState(LLDrawable::PARTITION_MOVE) && - !drawable->getPositionGroup().equals3(LLVector4a::getZero())) - { - drawable->setState(LLDrawable::PARTITION_MOVE); - mPartitionQ.push_back(drawable); - } + if (!drawable->isState(LLDrawable::PARTITION_MOVE) && + !drawable->getPositionGroup().equals3(LLVector4a::getZero())) + { + drawable->setState(LLDrawable::PARTITION_MOVE); + mPartitionQ.push_back(drawable); + } } static LLTrace::BlockTimerStatHandle FTM_PROCESS_PARTITIONQ("PartitionQ"); void LLPipeline::processPartitionQ() { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_PARTITIONQ); - for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter) - { - LLDrawable* drawable = *iter; - if (!drawable->isDead()) - { - drawable->updateBinRadius(); - drawable->movePartition(); - } - drawable->clearState(LLDrawable::PARTITION_MOVE); - } + LL_RECORD_BLOCK_TIME(FTM_PROCESS_PARTITIONQ); + for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter) + { + LLDrawable* drawable = *iter; + if (!drawable->isDead()) + { + drawable->updateBinRadius(); + drawable->movePartition(); + } + drawable->clearState(LLDrawable::PARTITION_MOVE); + } - mPartitionQ.clear(); + mPartitionQ.clear(); } void LLPipeline::markMeshDirty(LLSpatialGroup* group) { - mMeshDirtyGroup.push_back(group); + mMeshDirtyGroup.push_back(group); } void LLPipeline::markRebuild(LLSpatialGroup* group, bool priority) { - if (group && !group->isDead() && group->getSpatialPartition()) - { - if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD) - { - priority = true; - } - - if (priority) - { - if (!group->hasState(LLSpatialGroup::IN_BUILD_Q1)) - { - llassert_always(!mGroupQ1Locked); - - mGroupQ1.push_back(group); - group->setState(LLSpatialGroup::IN_BUILD_Q1); - - if (group->hasState(LLSpatialGroup::IN_BUILD_Q2)) - { - LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group); - if (iter != mGroupQ2.end()) - { - mGroupQ2.erase(iter); - } - group->clearState(LLSpatialGroup::IN_BUILD_Q2); - } - } - } - else if (!group->hasState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1)) - { - llassert_always(!mGroupQ2Locked); - mGroupQ2.push_back(group); - group->setState(LLSpatialGroup::IN_BUILD_Q2); - - } - } + if (group && !group->isDead() && group->getSpatialPartition()) + { + if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD) + { + priority = true; + } + + if (priority) + { + if (!group->hasState(LLSpatialGroup::IN_BUILD_Q1)) + { + llassert_always(!mGroupQ1Locked); + + mGroupQ1.push_back(group); + group->setState(LLSpatialGroup::IN_BUILD_Q1); + + if (group->hasState(LLSpatialGroup::IN_BUILD_Q2)) + { + LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group); + if (iter != mGroupQ2.end()) + { + mGroupQ2.erase(iter); + } + group->clearState(LLSpatialGroup::IN_BUILD_Q2); + } + } + } + else if (!group->hasState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1)) + { + llassert_always(!mGroupQ2Locked); + mGroupQ2.push_back(group); + group->setState(LLSpatialGroup::IN_BUILD_Q2); + + } + } } void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, bool priority) { - if (drawablep && !drawablep->isDead() && assertInitialized()) - { + if (drawablep && !drawablep->isDead() && assertInitialized()) + { if (debugLoggingEnabled("AnimatedObjectsLinkset")) { LLVOVolume *vol_obj = drawablep->getVOVolume(); @@ -3383,4801 +3325,4831 @@ void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags f } } - if (!drawablep->isState(LLDrawable::BUILT)) - { - priority = true; - } - if (priority) - { - if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1)) - { - mBuildQ1.push_back(drawablep); - drawablep->setState(LLDrawable::IN_REBUILD_Q1); // mark drawable as being in priority queue - } - } - else if (!drawablep->isState(LLDrawable::IN_REBUILD_Q2)) - { - mBuildQ2.push_back(drawablep); - drawablep->setState(LLDrawable::IN_REBUILD_Q2); // need flag here because it is just a list - } - if (flag & (LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION)) - { - drawablep->getVObj()->setChanged(LLXform::SILHOUETTE); - } - drawablep->setState(flag); - } + if (!drawablep->isState(LLDrawable::BUILT)) + { + priority = true; + } + if (priority) + { + if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1)) + { + mBuildQ1.push_back(drawablep); + drawablep->setState(LLDrawable::IN_REBUILD_Q1); // mark drawable as being in priority queue + } + } + else if (!drawablep->isState(LLDrawable::IN_REBUILD_Q2)) + { + mBuildQ2.push_back(drawablep); + drawablep->setState(LLDrawable::IN_REBUILD_Q2); // need flag here because it is just a list + } + if (flag & (LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION)) + { + drawablep->getVObj()->setChanged(LLXform::SILHOUETTE); + } + drawablep->setState(flag); + } } static LLTrace::BlockTimerStatHandle FTM_RESET_DRAWORDER("Reset Draw Order"); void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) { - if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR, - LLPipeline::RENDER_TYPE_GROUND, - LLPipeline::RENDER_TYPE_TERRAIN, - LLPipeline::RENDER_TYPE_TREE, - LLPipeline::RENDER_TYPE_SKY, - LLPipeline::RENDER_TYPE_VOIDWATER, - LLPipeline::RENDER_TYPE_WATER, - LLPipeline::END_RENDER_TYPES)) - { - //clear faces from face pools - LL_RECORD_BLOCK_TIME(FTM_RESET_DRAWORDER); - gPipeline.resetDrawOrders(); - } - - LL_RECORD_BLOCK_TIME(FTM_STATESORT); - - //LLVertexBuffer::unbind(); - - grabReferences(result); - for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - group->checkOcclusion(); - if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { - markOccluder(group); - } - else - { - group->setVisible(); - for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) - { - markVisible((LLDrawable*)(*i)->getDrawable(), camera); - } - - if (!sDelayVBUpdate) - { //rebuild mesh as soon as we know it's visible - group->rebuildMesh(); - } - } - } - - if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) - { - LLSpatialGroup* last_group = NULL; - BOOL fov_changed = LLViewerCamera::getInstance()->isDefaultFOVChanged(); - for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) - { - LLCullResult::bridge_iterator cur_iter = i; - LLSpatialBridge* bridge = *cur_iter; - LLSpatialGroup* group = bridge->getSpatialGroup(); - - if (last_group == NULL) - { - last_group = group; - } - - if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { - stateSort(bridge, camera, fov_changed); - } + if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_GROUND, + LLPipeline::RENDER_TYPE_TERRAIN, + LLPipeline::RENDER_TYPE_TREE, + LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_VOIDWATER, + LLPipeline::RENDER_TYPE_WATER, + LLPipeline::END_RENDER_TYPES)) + { + //clear faces from face pools + LL_RECORD_BLOCK_TIME(FTM_RESET_DRAWORDER); + gPipeline.resetDrawOrders(); + } - if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && - last_group != group && last_group->changeLOD()) - { - last_group->mLastUpdateDistance = last_group->mDistance; - } + LL_RECORD_BLOCK_TIME(FTM_STATESORT); - last_group = group; - } + //LLVertexBuffer::unbind(); - if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && - last_group && last_group->changeLOD()) - { - last_group->mLastUpdateDistance = last_group->mDistance; - } - } + grabReferences(result); + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + group->checkOcclusion(); + if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { + markOccluder(group); + } + else + { + group->setVisible(); + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { + markVisible((LLDrawable*)(*i)->getDrawable(), camera); + } + + if (!sDelayVBUpdate) + { //rebuild mesh as soon as we know it's visible + group->rebuildMesh(); + } + } + } - for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - group->checkOcclusion(); - if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { - markOccluder(group); - } - else - { - group->setVisible(); - stateSort(group, camera); + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) + { + LLSpatialGroup* last_group = NULL; + BOOL fov_changed = LLViewerCamera::getInstance()->isDefaultFOVChanged(); + for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + { + LLCullResult::bridge_iterator cur_iter = i; + LLSpatialBridge* bridge = *cur_iter; + LLSpatialGroup* group = bridge->getSpatialGroup(); + + if (last_group == NULL) + { + last_group = group; + } + + if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { + stateSort(bridge, camera, fov_changed); + } + + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && + last_group != group && last_group->changeLOD()) + { + last_group->mLastUpdateDistance = last_group->mDistance; + } + + last_group = group; + } + + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && + last_group && last_group->changeLOD()) + { + last_group->mLastUpdateDistance = last_group->mDistance; + } + } - if (!sDelayVBUpdate) - { //rebuild mesh as soon as we know it's visible - group->rebuildMesh(); - } - } - } - - { - LL_RECORD_BLOCK_TIME(FTM_STATESORT_DRAWABLE); - for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); - iter != sCull->endVisibleList(); ++iter) - { - LLDrawable *drawablep = *iter; - if (!drawablep->isDead()) - { - stateSort(drawablep, camera); - } - } - } - - postSort(camera); + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + group->checkOcclusion(); + if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { + markOccluder(group); + } + else + { + group->setVisible(); + stateSort(group, camera); + + if (!sDelayVBUpdate) + { //rebuild mesh as soon as we know it's visible + group->rebuildMesh(); + } + } + } + + { + LL_RECORD_BLOCK_TIME(FTM_STATESORT_DRAWABLE); + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); + iter != sCull->endVisibleList(); ++iter) + { + LLDrawable *drawablep = *iter; + if (!drawablep->isDead()) + { + stateSort(drawablep, camera); + } + } + } + + postSort(camera); } void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) { - if (group->changeLOD()) - { - for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) - { - stateSort((LLDrawable*)(*i)->getDrawable(), camera); - } - - if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) - { //avoid redundant stateSort calls - group->mLastUpdateDistance = group->mDistance; - } - } + if (group->changeLOD()) + { + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { + stateSort((LLDrawable*)(*i)->getDrawable(), camera); + } + + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) + { //avoid redundant stateSort calls + group->mLastUpdateDistance = group->mDistance; + } + } } void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed) { - if (bridge->getSpatialGroup()->changeLOD() || fov_changed) - { - bool force_update = false; - bridge->updateDistance(camera, force_update); - } + if (bridge->getSpatialGroup()->changeLOD() || fov_changed) + { + bool force_update = false; + bridge->updateDistance(camera, force_update); + } } void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) { - if (!drawablep - || drawablep->isDead() - || !hasRenderType(drawablep->getRenderType())) - { - return; - } - - if (LLSelectMgr::getInstance()->mHideSelectedObjects) - { - if (drawablep->getVObj().notNull() && - drawablep->getVObj()->isSelected()) - { - return; - } - } + if (!drawablep + || drawablep->isDead() + || !hasRenderType(drawablep->getRenderType())) + { + return; + } + + if (LLSelectMgr::getInstance()->mHideSelectedObjects) + { + if (drawablep->getVObj().notNull() && + drawablep->getVObj()->isSelected()) + { + return; + } + } - if (drawablep->isAvatar()) - { //don't draw avatars beyond render distance or if we don't have a spatial group. - if ((drawablep->getSpatialGroup() == NULL) || - (drawablep->getSpatialGroup()->mDistance > LLVOAvatar::sRenderDistance)) - { - return; - } + if (drawablep->isAvatar()) + { //don't draw avatars beyond render distance or if we don't have a spatial group. + if ((drawablep->getSpatialGroup() == NULL) || + (drawablep->getSpatialGroup()->mDistance > LLVOAvatar::sRenderDistance)) + { + return; + } + + LLVOAvatar* avatarp = (LLVOAvatar*) drawablep->getVObj().get(); + if (!avatarp->isVisible()) + { + return; + } + } - LLVOAvatar* avatarp = (LLVOAvatar*) drawablep->getVObj().get(); - if (!avatarp->isVisible()) - { - return; - } - } + assertInitialized(); - assertInitialized(); + if (hasRenderType(drawablep->mRenderType)) + { + if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE)) + { + drawablep->setVisible(camera, NULL, FALSE); + } + } - if (hasRenderType(drawablep->mRenderType)) - { - if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE)) - { - drawablep->setVisible(camera, NULL, FALSE); - } - } + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) + { + //if (drawablep->isVisible()) isVisible() check here is redundant, if it wasn't visible, it wouldn't be here + { + if (!drawablep->isActive()) + { + bool force_update = false; + drawablep->updateDistance(camera, force_update); + } + else if (drawablep->isAvatar()) + { + bool force_update = false; + drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility() + } + } + } - if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) - { - //if (drawablep->isVisible()) isVisible() check here is redundant, if it wasn't visible, it wouldn't be here - { - if (!drawablep->isActive()) - { - bool force_update = false; - drawablep->updateDistance(camera, force_update); - } - else if (drawablep->isAvatar()) - { - bool force_update = false; - drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility() - } - } - } - - if (!drawablep->getVOVolume()) - { - for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin(); - iter != drawablep->mFaces.end(); iter++) - { - LLFace* facep = *iter; - - if (facep->hasGeometry()) - { - if (facep->getPool()) - { - facep->getPool()->enqueue(facep); - } - else - { - break; - } - } - } - } - - mNumVisibleFaces += drawablep->getNumFaces(); -} + if (!drawablep->getVOVolume()) + { + for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin(); + iter != drawablep->mFaces.end(); iter++) + { + LLFace* facep = *iter; + + if (facep->hasGeometry()) + { + if (facep->getPool()) + { + facep->getPool()->enqueue(facep); + } + else + { + break; + } + } + } + } + + mNumVisibleFaces += drawablep->getNumFaces(); +} void forAllDrawables(LLCullResult::sg_iterator begin, - LLCullResult::sg_iterator end, - void (*func)(LLDrawable*)) + LLCullResult::sg_iterator end, + void (*func)(LLDrawable*)) { - for (LLCullResult::sg_iterator i = begin; i != end; ++i) - { - for (LLSpatialGroup::element_iter j = (*i)->getDataBegin(); j != (*i)->getDataEnd(); ++j) - { - if((*j)->hasDrawable()) - { - func((LLDrawable*)(*j)->getDrawable()); - } - } - } + for (LLCullResult::sg_iterator i = begin; i != end; ++i) + { + for (LLSpatialGroup::element_iter j = (*i)->getDataBegin(); j != (*i)->getDataEnd(); ++j) + { + if((*j)->hasDrawable()) + { + func((LLDrawable*)(*j)->getDrawable()); + } + } + } } void LLPipeline::forAllVisibleDrawables(void (*func)(LLDrawable*)) { - forAllDrawables(sCull->beginDrawableGroups(), sCull->endDrawableGroups(), func); - forAllDrawables(sCull->beginVisibleGroups(), sCull->endVisibleGroups(), func); + forAllDrawables(sCull->beginDrawableGroups(), sCull->endDrawableGroups(), func); + forAllDrawables(sCull->beginVisibleGroups(), sCull->endVisibleGroups(), func); } //function for creating scripted beacons void renderScriptedBeacons(LLDrawable* drawablep) { - LLViewerObject *vobj = drawablep->getVObj(); - if (vobj - && !vobj->isAvatar() - && !vobj->getParent() - && vobj->flagScripted()) - { - if (gPipeline.sRenderBeacons) - { - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth); - } - - if (gPipeline.sRenderHighlight) - { - S32 face_id; - S32 count = drawablep->getNumFaces(); - for (face_id = 0; face_id < count; face_id++) - { - LLFace * facep = drawablep->getFace(face_id); - if (facep) - { - gPipeline.mHighlightFaces.push_back(facep); - } - } - } - } + LLViewerObject *vobj = drawablep->getVObj(); + if (vobj + && !vobj->isAvatar() + && !vobj->getParent() + && vobj->flagScripted()) + { + if (gPipeline.sRenderBeacons) + { + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth); + } + + if (gPipeline.sRenderHighlight) + { + S32 face_id; + S32 count = drawablep->getNumFaces(); + for (face_id = 0; face_id < count; face_id++) + { + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } + } + } + } } void renderScriptedTouchBeacons(LLDrawable* drawablep) { - LLViewerObject *vobj = drawablep->getVObj(); - if (vobj - && !vobj->isAvatar() - && !vobj->getParent() - && vobj->flagScripted() - && vobj->flagHandleTouch()) - { - if (gPipeline.sRenderBeacons) - { - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth); - } - - if (gPipeline.sRenderHighlight) - { - S32 face_id; - S32 count = drawablep->getNumFaces(); - for (face_id = 0; face_id < count; face_id++) - { - LLFace * facep = drawablep->getFace(face_id); - if (facep) - { - gPipeline.mHighlightFaces.push_back(facep); - } - } - } + LLViewerObject *vobj = drawablep->getVObj(); + if (vobj + && !vobj->isAvatar() + && !vobj->getParent() + && vobj->flagScripted() + && vobj->flagHandleTouch()) + { + if (gPipeline.sRenderBeacons) + { + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth); + } + + if (gPipeline.sRenderHighlight) + { + S32 face_id; + S32 count = drawablep->getNumFaces(); + for (face_id = 0; face_id < count; face_id++) + { + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } + } + } } } void renderPhysicalBeacons(LLDrawable* drawablep) { - LLViewerObject *vobj = drawablep->getVObj(); - if (vobj - && !vobj->isAvatar() - //&& !vobj->getParent() - && vobj->flagUsePhysics()) - { - if (gPipeline.sRenderBeacons) - { - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth); - } - - if (gPipeline.sRenderHighlight) - { - S32 face_id; - S32 count = drawablep->getNumFaces(); - for (face_id = 0; face_id < count; face_id++) - { - LLFace * facep = drawablep->getFace(face_id); - if (facep) - { - gPipeline.mHighlightFaces.push_back(facep); - } - } - } + LLViewerObject *vobj = drawablep->getVObj(); + if (vobj + && !vobj->isAvatar() + //&& !vobj->getParent() + && vobj->flagUsePhysics()) + { + if (gPipeline.sRenderBeacons) + { + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth); + } + + if (gPipeline.sRenderHighlight) + { + S32 face_id; + S32 count = drawablep->getNumFaces(); + for (face_id = 0; face_id < count; face_id++) + { + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } + } + } } } void renderMOAPBeacons(LLDrawable* drawablep) { - LLViewerObject *vobj = drawablep->getVObj(); + LLViewerObject *vobj = drawablep->getVObj(); - if(!vobj || vobj->isAvatar()) - return; - - bool beacon=false; - U8 tecount=vobj->getNumTEs(); - for(int x=0;xgetTE(x)->hasMedia()) - { - beacon=true; - break; - } - } - if(beacon) - { - if (gPipeline.sRenderBeacons) - { - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 1.f, 1.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth); - } + if(!vobj || vobj->isAvatar()) + return; - if (gPipeline.sRenderHighlight) - { - S32 face_id; - S32 count = drawablep->getNumFaces(); - for (face_id = 0; face_id < count; face_id++) - { - LLFace * facep = drawablep->getFace(face_id); - if (facep) - { - gPipeline.mHighlightFaces.push_back(facep); - } - } - } + bool beacon=false; + U8 tecount=vobj->getNumTEs(); + for(int x=0;xgetTE(x)->hasMedia()) + { + beacon=true; + break; + } + } + if(beacon) + { + if (gPipeline.sRenderBeacons) + { + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 1.f, 1.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth); + } + + if (gPipeline.sRenderHighlight) + { + S32 face_id; + S32 count = drawablep->getNumFaces(); + for (face_id = 0; face_id < count; face_id++) + { + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } + } + } } } void renderParticleBeacons(LLDrawable* drawablep) { - // Look for attachments, objects, etc. - LLViewerObject *vobj = drawablep->getVObj(); - if (vobj - && vobj->isParticleSource()) - { - if (gPipeline.sRenderBeacons) - { - LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f); - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth); - } - - if (gPipeline.sRenderHighlight) - { - S32 face_id; - S32 count = drawablep->getNumFaces(); - for (face_id = 0; face_id < count; face_id++) - { - LLFace * facep = drawablep->getFace(face_id); - if (facep) - { - gPipeline.mHighlightFaces.push_back(facep); - } - } - } + // Look for attachments, objects, etc. + LLViewerObject *vobj = drawablep->getVObj(); + if (vobj + && vobj->isParticleSource()) + { + if (gPipeline.sRenderBeacons) + { + LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f); + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth); + } + + if (gPipeline.sRenderHighlight) + { + S32 face_id; + S32 count = drawablep->getNumFaces(); + for (face_id = 0; face_id < count; face_id++) + { + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } + } + } } } void renderSoundHighlights(LLDrawable* drawablep) { - // Look for attachments, objects, etc. - LLViewerObject *vobj = drawablep->getVObj(); - if (vobj && vobj->isAudioSource()) - { - if (gPipeline.sRenderHighlight) - { - S32 face_id; - S32 count = drawablep->getNumFaces(); - for (face_id = 0; face_id < count; face_id++) - { - LLFace * facep = drawablep->getFace(face_id); - if (facep) - { - gPipeline.mHighlightFaces.push_back(facep); - } - } - } + // Look for attachments, objects, etc. + LLViewerObject *vobj = drawablep->getVObj(); + if (vobj && vobj->isAudioSource()) + { + if (gPipeline.sRenderHighlight) + { + S32 face_id; + S32 count = drawablep->getNumFaces(); + for (face_id = 0; face_id < count; face_id++) + { + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } + } + } } } void LLPipeline::postSort(LLCamera& camera) { - LL_RECORD_BLOCK_TIME(FTM_STATESORT_POSTSORT); + LL_RECORD_BLOCK_TIME(FTM_STATESORT_POSTSORT); - assertInitialized(); + assertInitialized(); - LL_PUSH_CALLSTACKS(); - //rebuild drawable geometry - for (LLCullResult::sg_iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i) - { - LLSpatialGroup* group = *i; - if (!sUseOcclusion || - !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { - group->rebuildGeom(); - } - } - LL_PUSH_CALLSTACKS(); - //rebuild groups - sCull->assertDrawMapsEmpty(); + LL_PUSH_CALLSTACKS(); + //rebuild drawable geometry + for (LLCullResult::sg_iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i) + { + LLSpatialGroup* group = *i; + if (!sUseOcclusion || + !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { + group->rebuildGeom(); + } + } + LL_PUSH_CALLSTACKS(); + //rebuild groups + sCull->assertDrawMapsEmpty(); - rebuildPriorityGroups(); - LL_PUSH_CALLSTACKS(); + rebuildPriorityGroups(); + LL_PUSH_CALLSTACKS(); - - //build render map - for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) - { - LLSpatialGroup* group = *i; - if ((sUseOcclusion && - group->isOcclusionState(LLSpatialGroup::OCCLUDED)) || - (RenderAutoHideSurfaceAreaLimit > 0.f && - group->mSurfaceArea > RenderAutoHideSurfaceAreaLimit*llmax(group->mObjectBoxSize, 10.f))) - { - continue; - } + + //build render map + for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) + { + LLSpatialGroup* group = *i; + if ((sUseOcclusion && + group->isOcclusionState(LLSpatialGroup::OCCLUDED)) || + (RenderAutoHideSurfaceAreaLimit > 0.f && + group->mSurfaceArea > RenderAutoHideSurfaceAreaLimit*llmax(group->mObjectBoxSize, 10.f))) + { + continue; + } + + if (group->hasState(LLSpatialGroup::NEW_DRAWINFO) && group->hasState(LLSpatialGroup::GEOM_DIRTY)) + { //no way this group is going to be drawable without a rebuild + group->rebuildGeom(); + } + + for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j) + { + LLSpatialGroup::drawmap_elem_t& src_vec = j->second; + if (!hasRenderType(j->first)) + { + continue; + } + + for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k) + { + if (sMinRenderSize > 0.f) + { + LLVector4a bounds; + bounds.setSub((*k)->mExtents[1],(*k)->mExtents[0]); + + if (llmax(llmax(bounds[0], bounds[1]), bounds[2]) > sMinRenderSize) + { + sCull->pushDrawInfo(j->first, *k); + } + } + else + { + sCull->pushDrawInfo(j->first, *k); + } + } + } + + if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA)) + { + LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA); + + if (alpha != group->mDrawMap.end()) + { //store alpha groups for sorting + LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) + { + if (bridge) + { + LLCamera trans_camera = bridge->transformCamera(camera); + group->updateDistance(trans_camera); + } + else + { + group->updateDistance(camera); + } + } + + if (hasRenderType(LLDrawPool::POOL_ALPHA)) + { + sCull->pushAlphaGroup(group); + } + } + } + } + + //flush particle VB + if (LLVOPartGroup::sVB) + { + LLVOPartGroup::sVB->flush(); + } + else + { + LL_WARNS_ONCE() << "Missing particle buffer" << LL_ENDL; + } - if (group->hasState(LLSpatialGroup::NEW_DRAWINFO) && group->hasState(LLSpatialGroup::GEOM_DIRTY)) - { //no way this group is going to be drawable without a rebuild - group->rebuildGeom(); - } + /*bool use_transform_feedback = gTransformPositionProgram.mProgramObject && !mMeshDirtyGroup.empty(); - for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j) - { - LLSpatialGroup::drawmap_elem_t& src_vec = j->second; - if (!hasRenderType(j->first)) - { - continue; - } - - for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k) - { - if (sMinRenderSize > 0.f) - { - LLVector4a bounds; - bounds.setSub((*k)->mExtents[1],(*k)->mExtents[0]); + if (use_transform_feedback) + { //place a query around potential transform feedback code for synchronization + mTransformFeedbackPrimitives = 0; - if (llmax(llmax(bounds[0], bounds[1]), bounds[2]) > sMinRenderSize) - { - sCull->pushDrawInfo(j->first, *k); - } - } - else - { - sCull->pushDrawInfo(j->first, *k); - } - } - } + if (!mMeshDirtyQueryObject) + { + glGenQueriesARB(1, &mMeshDirtyQueryObject); + } - if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA)) - { - LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA); - - if (alpha != group->mDrawMap.end()) - { //store alpha groups for sorting - LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); - if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) - { - if (bridge) - { - LLCamera trans_camera = bridge->transformCamera(camera); - group->updateDistance(trans_camera); - } - else - { - group->updateDistance(camera); - } - } - - if (hasRenderType(LLDrawPool::POOL_ALPHA)) - { - sCull->pushAlphaGroup(group); - } - } - } - } - - //flush particle VB - if (LLVOPartGroup::sVB) - { - LLVOPartGroup::sVB->flush(); - } - else - { - LL_WARNS_ONCE() << "Missing particle buffer" << LL_ENDL; - } + + glBeginQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, mMeshDirtyQueryObject); + }*/ - /*bool use_transform_feedback = gTransformPositionProgram.mProgramObject && !mMeshDirtyGroup.empty(); + //pack vertex buffers for groups that chose to delay their updates + for (LLSpatialGroup::sg_vector_t::iterator iter = mMeshDirtyGroup.begin(); iter != mMeshDirtyGroup.end(); ++iter) + { + (*iter)->rebuildMesh(); + } - if (use_transform_feedback) - { //place a query around potential transform feedback code for synchronization - mTransformFeedbackPrimitives = 0; + /*if (use_transform_feedback) + { + glEndQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); + }*/ + + mMeshDirtyGroup.clear(); - if (!mMeshDirtyQueryObject) - { - glGenQueriesARB(1, &mMeshDirtyQueryObject); - } + if (!sShadowRender) + { + std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater()); + } - - glBeginQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, mMeshDirtyQueryObject); - }*/ + LL_PUSH_CALLSTACKS(); + // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus + if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender) + { + if (sRenderScriptedTouchBeacons) + { + // Only show the beacon on the root object. + forAllVisibleDrawables(renderScriptedTouchBeacons); + } + else + if (sRenderScriptedBeacons) + { + // Only show the beacon on the root object. + forAllVisibleDrawables(renderScriptedBeacons); + } + + if (sRenderPhysicalBeacons) + { + // Only show the beacon on the root object. + forAllVisibleDrawables(renderPhysicalBeacons); + } + + if(sRenderMOAPBeacons) + { + forAllVisibleDrawables(renderMOAPBeacons); + } + + if (sRenderParticleBeacons) + { + forAllVisibleDrawables(renderParticleBeacons); + } + + // If god mode, also show audio cues + if (sRenderSoundBeacons && gAudiop) + { + // Walk all sound sources and render out beacons for them. Note, this isn't done in the ForAllVisibleDrawables function, because some are not visible. + LLAudioEngine::source_map::iterator iter; + for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter) + { + LLAudioSource *sourcep = iter->second; + + LLVector3d pos_global = sourcep->getPositionGlobal(); + LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global); + if (gPipeline.sRenderBeacons) + { + //pos += LLVector3(0.f, 0.f, 0.2f); + gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), DebugBeaconLineWidth); + } + } + // now deal with highlights for all those seeable sound sources + forAllVisibleDrawables(renderSoundHighlights); + } + } + LL_PUSH_CALLSTACKS(); + // If managing your telehub, draw beacons at telehub and currently selected spawnpoint. + if (LLFloaterTelehub::renderBeacons()) + { + LLFloaterTelehub::addBeacons(); + } - //pack vertex buffers for groups that chose to delay their updates - for (LLSpatialGroup::sg_vector_t::iterator iter = mMeshDirtyGroup.begin(); iter != mMeshDirtyGroup.end(); ++iter) - { - (*iter)->rebuildMesh(); - } + if (!sShadowRender) + { + mSelectedFaces.clear(); + + LLPipeline::setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit()); + + // Draw face highlights for selected faces. + if (LLSelectMgr::getInstance()->getTEMode()) + { + struct f : public LLSelectedTEFunctor + { + virtual bool apply(LLViewerObject* object, S32 te) + { + if (object->mDrawable) + { + LLFace * facep = object->mDrawable->getFace(te); + if (facep) + { + gPipeline.mSelectedFaces.push_back(facep); + } + } + return true; + } + } func; + LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func); + } + } - /*if (use_transform_feedback) - { - glEndQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); - }*/ - - mMeshDirtyGroup.clear(); + //LLSpatialGroup::sNoDelete = FALSE; + LL_PUSH_CALLSTACKS(); +} - if (!sShadowRender) - { - std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater()); - } - LL_PUSH_CALLSTACKS(); - // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus - if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender) - { - if (sRenderScriptedTouchBeacons) - { - // Only show the beacon on the root object. - forAllVisibleDrawables(renderScriptedTouchBeacons); - } - else - if (sRenderScriptedBeacons) - { - // Only show the beacon on the root object. - forAllVisibleDrawables(renderScriptedBeacons); - } +void render_hud_elements() +{ + LL_RECORD_BLOCK_TIME(FTM_RENDER_UI); + gPipeline.disableLights(); + + LLGLDisable fog(GL_FOG); + LLGLSUIDefault gls_ui; + + LLGLEnable stencil(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF); + glStencilMask(0xFFFFFFFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + gGL.color4f(1,1,1,1); + + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + } + LLGLDepthTest depth(GL_TRUE, GL_FALSE); - if (sRenderPhysicalBeacons) - { - // Only show the beacon on the root object. - forAllVisibleDrawables(renderPhysicalBeacons); - } + if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + LLGLEnable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d() + + // Draw the tracking overlays + LLTracker::render3D(); + + // Show the property lines + LLWorld::getInstance()->renderPropertyLines(); + LLViewerParcelMgr::getInstance()->render(); + LLViewerParcelMgr::getInstance()->renderParcelCollision(); + + // Render name tags. + LLHUDObject::renderAll(); + } + else if (gForceRenderLandFence) + { + // This is only set when not rendering the UI, for parcel snapshots + LLViewerParcelMgr::getInstance()->render(); + } + else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { + LLHUDText::renderAllHUD(); + } - if(sRenderMOAPBeacons) - { - forAllVisibleDrawables(renderMOAPBeacons); - } + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.unbind(); + } + gGL.flush(); +} - if (sRenderParticleBeacons) - { - forAllVisibleDrawables(renderParticleBeacons); - } +void LLPipeline::renderHighlights() +{ + assertInitialized(); - // If god mode, also show audio cues - if (sRenderSoundBeacons && gAudiop) - { - // Walk all sound sources and render out beacons for them. Note, this isn't done in the ForAllVisibleDrawables function, because some are not visible. - LLAudioEngine::source_map::iterator iter; - for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter) - { - LLAudioSource *sourcep = iter->second; + // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD) + // Render highlighted faces. + LLGLSPipelineAlpha gls_pipeline_alpha; + LLColor4 color(1.f, 1.f, 1.f, 0.5f); + LLGLEnable color_mat(GL_COLOR_MATERIAL); + disableLights(); - LLVector3d pos_global = sourcep->getPositionGlobal(); - LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global); - if (gPipeline.sRenderBeacons) - { - //pos += LLVector3(0.f, 0.f, 0.2f); - gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), DebugBeaconLineWidth); - } - } - // now deal with highlights for all those seeable sound sources - forAllVisibleDrawables(renderSoundHighlights); - } - } - LL_PUSH_CALLSTACKS(); - // If managing your telehub, draw beacons at telehub and currently selected spawnpoint. - if (LLFloaterTelehub::renderBeacons()) - { - LLFloaterTelehub::addBeacons(); - } + if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && !mHighlightSet.empty()) + { //draw blurry highlight image over screen + LLGLEnable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); + LLGLDisable test(GL_ALPHA_TEST); - if (!sShadowRender) - { - mSelectedFaces.clear(); + LLGLEnable stencil(GL_STENCIL_TEST); + gGL.flush(); + glStencilMask(0xFFFFFFFF); + glClearStencil(1); + glClear(GL_STENCIL_BUFFER_BIT); - LLPipeline::setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit()); + glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + + gGL.setColorMask(false, false); - // Draw face highlights for selected faces. - if (LLSelectMgr::getInstance()->getTEMode()) + if (LLGLSLShader::sNoFixedFunction) { - struct f : public LLSelectedTEFunctor - { - virtual bool apply(LLViewerObject* object, S32 te) - { - if (object->mDrawable) - { - LLFace * facep = object->mDrawable->getFace(te); - if (facep) - { - gPipeline.mSelectedFaces.push_back(facep); - } - } - return true; - } - } func; - LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func); - } - } + gHighlightProgram.bind(); + } + + for (std::set::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ++iter) + { + renderHighlight(iter->mItem->getVObj(), 1.f); + } + gGL.setColorMask(true, false); + + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF); + + //gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); + + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + + gGL.getTexUnit(0)->bind(&mHighlight); + + LLVector2 tc1; + LLVector2 tc2; + + tc1.setVec(0,0); + tc2.setVec(2,2); + + gGL.begin(LLRender::TRIANGLES); + + F32 scale = RenderHighlightBrightness; + LLColor4 color = RenderHighlightColor; + F32 thickness = RenderHighlightThickness; + + for (S32 pass = 0; pass < 2; ++pass) + { + if (pass == 0) + { + gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); + } + else + { + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } + + for (S32 i = 0; i < 8; ++i) + { + for (S32 j = 0; j < 8; ++j) + { + LLVector2 tc(i-4+0.5f, j-4+0.5f); + + F32 dist = 1.f-(tc.length()/sqrtf(32.f)); + dist *= scale/64.f; + + tc *= thickness; + tc.mV[0] = (tc.mV[0])/mHighlight.getWidth(); + tc.mV[1] = (tc.mV[1])/mHighlight.getHeight(); + + gGL.color4f(color.mV[0], + color.mV[1], + color.mV[2], + color.mV[3]*dist); + + gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc2.mV[1]); + gGL.vertex2f(-1,3); + + gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc1.mV[1]); + gGL.vertex2f(-1,-1); + + gGL.texCoord2f(tc.mV[0]+tc2.mV[0], tc.mV[1]+tc1.mV[1]); + gGL.vertex2f(3,-1); + } + } + } + + gGL.end(); + + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + + //gGL.setSceneBlendType(LLRender::BT_ALPHA); + } - //LLSpatialGroup::sNoDelete = FALSE; - LL_PUSH_CALLSTACKS(); -} + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightProgram.bind(); + gGL.diffuseColor4f(1,1,1,0.5f); + } + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && !mFaceSelectImagep) + { + mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT); + } + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::DIFFUSE_MAP)) + { + // Make sure the selection image gets downloaded and decoded + mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + + U32 count = mSelectedFaces.size(); + for (U32 i = 0; i < count; i++) + { + LLFace *facep = mSelectedFaces[i]; + if (!facep || facep->getDrawable()->isDead()) + { + LL_ERRS() << "Bad face on selection" << LL_ENDL; + return; + } + + facep->renderSelected(mFaceSelectImagep, color); + } + } -void render_hud_elements() -{ - gPipeline.disableLights(); - - LLGLDisable fog(GL_FOG); - LLGLSUIDefault gls_ui; + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) + { + // Paint 'em red! + color.setVec(1.f, 0.f, 0.f, 0.5f); + + int count = mHighlightFaces.size(); + for (S32 i = 0; i < count; i++) + { + LLFace* facep = mHighlightFaces[i]; + facep->renderSelected(LLViewerTexture::sNullImagep, color); + } + } - LLGLEnable stencil(GL_STENCIL_TEST); - glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF); - glStencilMask(0xFFFFFFFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - - gGL.color4f(1,1,1,1); - - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } - LLGLDepthTest depth(GL_TRUE, GL_FALSE); + // Contains a list of the faces of objects that are physical or + // have touch-handlers. + mHighlightFaces.clear(); - if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - LLGLEnable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); - gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d() - - // Draw the tracking overlays - LLTracker::render3D(); - - // Show the property lines - LLWorld::getInstance()->renderPropertyLines(); - LLViewerParcelMgr::getInstance()->render(); - LLViewerParcelMgr::getInstance()->renderParcelCollision(); - - // Render name tags. - LLHUDObject::renderAll(); - } - else if (gForceRenderLandFence) - { - // This is only set when not rendering the UI, for parcel snapshots - LLViewerParcelMgr::getInstance()->render(); - } - else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) - { - LLHUDText::renderAllHUD(); - } + if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0) + { + gHighlightProgram.unbind(); + } - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.unbind(); - } - gGL.flush(); + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::NORMAL_MAP)) + { + color.setVec(1.0f, 0.5f, 0.5f, 0.5f); + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightNormalProgram.bind(); + gGL.diffuseColor4f(1,1,1,0.5f); + } + + mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + + U32 count = mSelectedFaces.size(); + for (U32 i = 0; i < count; i++) + { + LLFace *facep = mSelectedFaces[i]; + if (!facep || facep->getDrawable()->isDead()) + { + LL_ERRS() << "Bad face on selection" << LL_ENDL; + return; + } + + facep->renderSelected(mFaceSelectImagep, color); + } + + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightNormalProgram.unbind(); + } + } + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::SPECULAR_MAP)) + { + color.setVec(0.0f, 0.3f, 1.0f, 0.8f); + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightSpecularProgram.bind(); + gGL.diffuseColor4f(1,1,1,0.5f); + } + + mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + + U32 count = mSelectedFaces.size(); + for (U32 i = 0; i < count; i++) + { + LLFace *facep = mSelectedFaces[i]; + if (!facep || facep->getDrawable()->isDead()) + { + LL_ERRS() << "Bad face on selection" << LL_ENDL; + return; + } + + facep->renderSelected(mFaceSelectImagep, color); + } + + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightSpecularProgram.unbind(); + } + } } -void LLPipeline::renderHighlights() +//debug use +U32 LLPipeline::sCurRenderPoolType = 0 ; + +void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate) { - assertInitialized(); + LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY); - // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD) - // Render highlighted faces. - LLGLSPipelineAlpha gls_pipeline_alpha; - LLColor4 color(1.f, 1.f, 1.f, 0.5f); - LLGLEnable color_mat(GL_COLOR_MATERIAL); - disableLights(); + assertInitialized(); - if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && !mHighlightSet.empty()) - { //draw blurry highlight image over screen - LLGLEnable blend(GL_BLEND); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - LLGLDisable test(GL_ALPHA_TEST); + F32 saved_modelview[16]; + F32 saved_projection[16]; - LLGLEnable stencil(GL_STENCIL_TEST); - gGL.flush(); - glStencilMask(0xFFFFFFFF); - glClearStencil(1); - glClear(GL_STENCIL_BUFFER_BIT); + //HACK: preserve/restore matrices around HUD render + if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { + for (U32 i = 0; i < 16; i++) + { + saved_modelview[i] = gGLModelView[i]; + saved_projection[i] = gGLProjection[i]; + } + } - glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF); - glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); - - gGL.setColorMask(false, false); - for (std::set::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ++iter) - { - renderHighlight(iter->mItem->getVObj(), 1.f); - } - gGL.setColorMask(true, false); + /////////////////////////////////////////// + // + // Sync and verify GL state + // + // - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF); - - //gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); + stop_glerror(); - gGL.pushMatrix(); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadIdentity(); + LLVertexBuffer::unbind(); - gGL.getTexUnit(0)->bind(&mHighlight); + // Do verification of GL state + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + if (mRenderDebugMask & RENDER_DEBUG_VERIFY) + { + if (!verify()) + { + LL_ERRS() << "Pipeline verification failed!" << LL_ENDL; + } + } - LLVector2 tc1; - LLVector2 tc2; + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO"); + + // Initialize lots of GL state to "safe" values + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + + LLGLSPipeline gls_pipeline; + LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + + LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2); + + // Toggle backface culling for debugging + LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0); + // Set fog + bool use_fog = hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG); + LLGLEnable fog_enable(use_fog && + !gPipeline.canUseWindLightShadersOnObjects() ? GL_FOG : 0); + gSky.updateFog(camera.getFar()); + if (!use_fog) + { + sUnderWaterRender = false; + } - tc1.setVec(0,0); - tc2.setVec(2,2); + gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sDefaultImagep); + LLViewerFetchedTexture::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP); + - gGL.begin(LLRender::TRIANGLES); - - F32 scale = RenderHighlightBrightness; - LLColor4 color = RenderHighlightColor; - F32 thickness = RenderHighlightThickness; + ////////////////////////////////////////////// + // + // Actually render all of the geometry + // + // + stop_glerror(); + + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools"); - for (S32 pass = 0; pass < 2; ++pass) - { - if (pass == 0) - { - gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); - } - else - { - gGL.setSceneBlendType(LLRender::BT_ALPHA); - } + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + { + LLDrawPool *poolp = *iter; + if (hasRenderType(poolp->getType())) + { + poolp->prerender(); + } + } - for (S32 i = 0; i < 8; ++i) - { - for (S32 j = 0; j < 8; ++j) - { - LLVector2 tc(i-4+0.5f, j-4+0.5f); + { + LL_RECORD_BLOCK_TIME(FTM_POOLS); + + // HACK: don't calculate local lights if we're rendering the HUD! + // Removing this check will cause bad flickering when there are + // HUD elements being rendered AND the user is in flycam mode -nyx + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { + calcNearbyLights(camera); + setupHWLights(NULL); + } + + bool occlude = sUseOcclusion > 1; + U32 cur_type = 0; + + pool_set_t::iterator iter1 = mPools.begin(); + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; + + cur_type = poolp->getType(); + + //debug use + sCurRenderPoolType = cur_type ; + + if (occlude && cur_type >= LLDrawPool::POOL_GRASS) + { + occlude = false; + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + LLGLSLShader::bindNoShader(); + doOcclusion(camera); + } + + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0) + { + LL_RECORD_BLOCK_TIME(FTM_POOLRENDER); + + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + + for( S32 i = 0; i < poolp->getNumPasses(); i++ ) + { + LLVertexBuffer::unbind(); + poolp->beginRenderPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + if ( !p->getSkipRenderFlag() ) { p->render(i); } + } + poolp->endRenderPass(i); + LLVertexBuffer::unbind(); + if (gDebugGL) + { + std::string msg = llformat("pass %d", i); + LLGLState::checkStates(msg); + //LLGLState::checkTextureChannels(msg); + //LLGLState::checkClientArrays(msg); + } + } + } + else + { + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + } + } + iter1 = iter2; + stop_glerror(); + } + + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPoolsEnd"); + + LLVertexBuffer::unbind(); + + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + + if (occlude) + { + occlude = false; + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + LLGLSLShader::bindNoShader(); + doOcclusion(camera); + } + } - F32 dist = 1.f-(tc.length()/sqrtf(32.f)); - dist *= scale/64.f; + LLVertexBuffer::unbind(); + LLGLState::checkStates(); - tc *= thickness; - tc.mV[0] = (tc.mV[0])/mHighlight.getWidth(); - tc.mV[1] = (tc.mV[1])/mHighlight.getHeight(); + if (!LLPipeline::sImpostorRender) + { + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights"); + + if (!sReflectionRender) + { + renderHighlights(); + } + + // Contains a list of the faces of objects that are physical or + // have touch-handlers. + mHighlightFaces.clear(); + + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDebug"); + + renderDebug(); + + LLVertexBuffer::unbind(); + + if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred) + { + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + // Render debugging beacons. + gObjectList.renderObjectBeacons(); + gObjectList.resetObjectBeacons(); + } + else + { + // Make sure particle effects disappear + LLHUDObject::renderAllForTimer(); + } + } + else + { + // Make sure particle effects disappear + LLHUDObject::renderAllForTimer(); + } + + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd"); + + //HACK: preserve/restore matrices around HUD render + if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { + for (U32 i = 0; i < 16; i++) + { + gGLModelView[i] = saved_modelview[i]; + gGLProjection[i] = saved_projection[i]; + } + } + } - gGL.color4f(color.mV[0], - color.mV[1], - color.mV[2], - color.mV[3]*dist); - - gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc2.mV[1]); - gGL.vertex2f(-1,3); - - gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc1.mV[1]); - gGL.vertex2f(-1,-1); - - gGL.texCoord2f(tc.mV[0]+tc2.mV[0], tc.mV[1]+tc1.mV[1]); - gGL.vertex2f(3,-1); - } - } - } + LLVertexBuffer::unbind(); - gGL.end(); + LLGLState::checkStates(); +// LLGLState::checkTextureChannels(); +// LLGLState::checkClientArrays(); +} - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); - - //gGL.setSceneBlendType(LLRender::BT_ALPHA); - } +void LLPipeline::renderGeomDeferred(LLCamera& camera) +{ + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred"); - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) - { - gHighlightProgram.bind(); - gGL.diffuseColor4f(1,1,1,0.5f); - } - - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && !mFaceSelectImagep) - { - mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT); - } + LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY); - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::DIFFUSE_MAP)) - { - // Make sure the selection image gets downloaded and decoded - mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLS); - U32 count = mSelectedFaces.size(); - for (U32 i = 0; i < count; i++) - { - LLFace *facep = mSelectedFaces[i]; - if (!facep || facep->getDrawable()->isDead()) - { - LL_ERRS() << "Bad face on selection" << LL_ENDL; - return; - } - - facep->renderSelected(mFaceSelectImagep, color); - } - } + LLGLEnable cull(GL_CULL_FACE); - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) - { - // Paint 'em red! - color.setVec(1.f, 0.f, 0.f, 0.5f); - - int count = mHighlightFaces.size(); - for (S32 i = 0; i < count; i++) - { - LLFace* facep = mHighlightFaces[i]; - facep->renderSelected(LLViewerTexture::sNullImagep, color); - } - } + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + { + LLDrawPool *poolp = *iter; + if (hasRenderType(poolp->getType())) + { + poolp->prerender(); + } + } - // Contains a list of the faces of objects that are physical or - // have touch-handlers. - mHighlightFaces.clear(); + LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); - if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0) - { - gHighlightProgram.unbind(); - } + LLVertexBuffer::unbind(); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::NORMAL_MAP)) - { - color.setVec(1.0f, 0.5f, 0.5f, 0.5f); - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) - { - gHighlightNormalProgram.bind(); - gGL.diffuseColor4f(1,1,1,0.5f); - } + U32 cur_type = 0; - mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + gGL.setColorMask(true, true); + + pool_set_t::iterator iter1 = mPools.begin(); - U32 count = mSelectedFaces.size(); - for (U32 i = 0; i < count; i++) - { - LLFace *facep = mSelectedFaces[i]; - if (!facep || facep->getDrawable()->isDead()) - { - LL_ERRS() << "Bad face on selection" << LL_ENDL; - return; - } + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; + + cur_type = poolp->getType(); + + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0) + { + LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLRENDER); + + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + + for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ ) + { + LLVertexBuffer::unbind(); + poolp->beginDeferredPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + if ( !p->getSkipRenderFlag() ) { p->renderDeferred(i); } + } + poolp->endDeferredPass(i); + LLVertexBuffer::unbind(); + + if (gDebugGL || gDebugPipeline) + { + LLGLState::checkStates(); + } + } + } + else + { + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + } + } + iter1 = iter2; + stop_glerror(); + } - facep->renderSelected(mFaceSelectImagep, color); - } + gGLLastMatrix = NULL; + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.loadMatrix(gGLModelView); - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) - { - gHighlightNormalProgram.unbind(); - } - } + gGL.setColorMask(true, false); +} - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::SPECULAR_MAP)) - { - color.setVec(0.0f, 0.3f, 1.0f, 0.8f); - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) - { - gHighlightSpecularProgram.bind(); - gGL.diffuseColor4f(1,1,1,0.5f); - } +void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion) +{ + LL_RECORD_BLOCK_TIME(FTM_POST_DEFERRED_POOLS); + U32 cur_type = 0; - mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + LLGLEnable cull(GL_CULL_FACE); - U32 count = mSelectedFaces.size(); - for (U32 i = 0; i < count; i++) - { - LLFace *facep = mSelectedFaces[i]; - if (!facep || facep->getDrawable()->isDead()) - { - LL_ERRS() << "Bad face on selection" << LL_ENDL; - return; - } + LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); - facep->renderSelected(mFaceSelectImagep, color); - } + calcNearbyLights(camera); + setupHWLights(NULL); - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) - { - gHighlightSpecularProgram.unbind(); - } - } -} + gGL.setColorMask(true, false); -//debug use -U32 LLPipeline::sCurRenderPoolType = 0 ; + pool_set_t::iterator iter1 = mPools.begin(); + bool occlude = LLPipeline::sUseOcclusion > 1 && do_occlusion; -void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY); + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; + + cur_type = poolp->getType(); + + if (occlude && cur_type >= LLDrawPool::POOL_GRASS) + { + occlude = false; + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + LLGLSLShader::bindNoShader(); + doOcclusion(camera, mScreen, mOcclusionDepth, &mDeferredDepth); + gGL.setColorMask(true, false); + } + + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0) + { + LL_RECORD_BLOCK_TIME(FTM_POST_DEFERRED_POOLRENDER); + + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + + for( S32 i = 0; i < poolp->getNumPostDeferredPasses(); i++ ) + { + LLVertexBuffer::unbind(); + poolp->beginPostDeferredPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + p->renderPostDeferred(i); + } + poolp->endPostDeferredPass(i); + LLVertexBuffer::unbind(); + + if (gDebugGL || gDebugPipeline) + { + LLGLState::checkStates(); + } + } + } + else + { + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + } + } + iter1 = iter2; + stop_glerror(); + } - assertInitialized(); + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); - F32 saved_modelview[16]; - F32 saved_projection[16]; + if (occlude) + { + occlude = false; + LLGLSLShader::bindNoShader(); + doOcclusion(camera); + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + } +} - //HACK: preserve/restore matrices around HUD render - if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) - { - for (U32 i = 0; i < 16; i++) - { - saved_modelview[i] = gGLModelView[i]; - saved_projection[i] = gGLProjection[i]; - } - } +void LLPipeline::renderGeomShadow(LLCamera& camera) +{ + U32 cur_type = 0; + + LLGLEnable cull(GL_CULL_FACE); - /////////////////////////////////////////// - // - // Sync and verify GL state - // - // + LLVertexBuffer::unbind(); - stop_glerror(); + pool_set_t::iterator iter1 = mPools.begin(); + + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; + + cur_type = poolp->getType(); + + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumShadowPasses() > 0) + { + poolp->prerender() ; + + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + + for( S32 i = 0; i < poolp->getNumShadowPasses(); i++ ) + { + LLVertexBuffer::unbind(); + poolp->beginShadowPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + p->renderShadow(i); + } + poolp->endShadowPass(i); + LLVertexBuffer::unbind(); + + LLGLState::checkStates(); + } + } + else + { + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + } + } + iter1 = iter2; + stop_glerror(); + } - LLVertexBuffer::unbind(); + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); +} - // Do verification of GL state - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - if (mRenderDebugMask & RENDER_DEBUG_VERIFY) - { - if (!verify()) - { - LL_ERRS() << "Pipeline verification failed!" << LL_ENDL; - } - } - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO"); - - // Initialize lots of GL state to "safe" values - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); +void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type) +{ + assertInitialized(); + S32 count = 0; + if (render_type == LLRender::TRIANGLE_STRIP) + { + count = index_count-2; + } + else + { + count = index_count/3; + } - LLGLSPipeline gls_pipeline; - LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + record(sStatBatchSize, count); + add(LLStatViewer::TRIANGLES_DRAWN, LLUnits::Triangles::fromValue(count)); - LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2); - - // Toggle backface culling for debugging - LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0); - // Set fog - bool use_fog = hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG); - LLGLEnable fog_enable(use_fog && - !gPipeline.canUseWindLightShadersOnObjects() ? GL_FOG : 0); - gSky.updateFog(camera.getFar()); - if (!use_fog) - { - sUnderWaterRender = false; - } + if (LLPipeline::sRenderFrameTest) + { + gViewerWindow->getWindow()->swapBuffers(); + ms_sleep(16); + } +} - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sDefaultImagep); - LLViewerFetchedTexture::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP); - +void LLPipeline::renderPhysicsDisplay() +{ + if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) + { + return; + } - ////////////////////////////////////////////// - // - // Actually render all of the geometry - // - // - stop_glerror(); - - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools"); + allocatePhysicsBuffer(); - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - if (hasRenderType(poolp->getType())) - { - poolp->prerender(); - } - } + gGL.flush(); + mPhysicsDisplay.bindTarget(); + glClearColor(0,0,0,1); + gGL.setColorMask(true, true); + mPhysicsDisplay.clear(); + glClearColor(0,0,0,0); - { - LL_RECORD_BLOCK_TIME(FTM_POOLS); - - // HACK: don't calculate local lights if we're rendering the HUD! - // Removing this check will cause bad flickering when there are - // HUD elements being rendered AND the user is in flycam mode -nyx - if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) - { - calcNearbyLights(camera); - setupHWLights(NULL); - } + gGL.setColorMask(true, false); - bool occlude = sUseOcclusion > 1; - U32 cur_type = 0; + if (LLGLSLShader::sNoFixedFunction) + { + gDebugProgram.bind(); + } - pool_set_t::iterator iter1 = mPools.begin(); - while ( iter1 != mPools.end() ) - { - LLDrawPool *poolp = *iter1; - - cur_type = poolp->getType(); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + if (hasRenderType(part->mDrawableType)) + { + part->renderPhysicsShapes(); + } + } + } + } - //debug use - sCurRenderPoolType = cur_type ; + gGL.flush(); - if (occlude && cur_type >= LLDrawPool::POOL_GRASS) - { - occlude = false; - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - LLGLSLShader::bindNoShader(); - doOcclusion(camera); - } + if (LLGLSLShader::sNoFixedFunction) + { + gDebugProgram.unbind(); + } - pool_set_t::iterator iter2 = iter1; - if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0) - { - LL_RECORD_BLOCK_TIME(FTM_POOLRENDER); + mPhysicsDisplay.flush(); +} - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - - for( S32 i = 0; i < poolp->getNumPasses(); i++ ) - { - LLVertexBuffer::unbind(); - poolp->beginRenderPass(i); - for (iter2 = iter1; iter2 != mPools.end(); iter2++) - { - LLDrawPool *p = *iter2; - if (p->getType() != cur_type) - { - break; - } - - if ( !p->getSkipRenderFlag() ) { p->render(i); } - } - poolp->endRenderPass(i); - LLVertexBuffer::unbind(); - if (gDebugGL) - { - std::string msg = llformat("pass %d", i); - LLGLState::checkStates(msg); - //LLGLState::checkTextureChannels(msg); - //LLGLState::checkClientArrays(msg); - } - } - } - else - { - // Skip all pools of this type - for (iter2 = iter1; iter2 != mPools.end(); iter2++) - { - LLDrawPool *p = *iter2; - if (p->getType() != cur_type) - { - break; - } - } - } - iter1 = iter2; - stop_glerror(); - } - - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPoolsEnd"); +extern std::set visible_selected_groups; - LLVertexBuffer::unbind(); - - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); +void LLPipeline::renderDebug() +{ + assertInitialized(); - if (occlude) - { - occlude = false; - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - LLGLSLShader::bindNoShader(); - doOcclusion(camera); - } - } + bool hud_only = hasRenderType(LLPipeline::RENDER_TYPE_HUD); - LLVertexBuffer::unbind(); - LLGLState::checkStates(); + if (!hud_only ) + { + //Render any navmesh geometry + LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance(); + if ( llPathingLibInstance != NULL ) + { + //character floater renderables + + LLHandle pathfindingCharacterHandle = LLFloaterPathfindingCharacters::getInstanceHandle(); + if ( !pathfindingCharacterHandle.isDead() ) + { + LLFloaterPathfindingCharacters *pathfindingCharacter = pathfindingCharacterHandle.get(); + + if ( pathfindingCharacter->getVisible() || gAgentCamera.cameraMouselook() ) + { + if (LLGLSLShader::sNoFixedFunction) + { + gPathfindingProgram.bind(); + gPathfindingProgram.uniform1f(sTint, 1.f); + gPathfindingProgram.uniform1f(sAmbiance, 1.f); + gPathfindingProgram.uniform1f(sAlphaScale, 1.f); + } + + //Requried character physics capsule render parameters + LLUUID id; + LLVector3 pos; + LLQuaternion rot; + + if ( pathfindingCharacter->isPhysicsCapsuleEnabled( id, pos, rot ) ) + { + if (LLGLSLShader::sNoFixedFunction) + { + //remove blending artifacts + gGL.setColorMask(false, false); + llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); + gGL.setColorMask(true, false); + LLGLEnable blend(GL_BLEND); + gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); + llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); + gPathfindingProgram.bind(); + } + else + { + llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); + } + } + } + } + + + //pathing console renderables + LLHandle pathfindingConsoleHandle = LLFloaterPathfindingConsole::getInstanceHandle(); + if (!pathfindingConsoleHandle.isDead()) + { + LLFloaterPathfindingConsole *pathfindingConsole = pathfindingConsoleHandle.get(); + + if ( pathfindingConsole->getVisible() || gAgentCamera.cameraMouselook() ) + { + F32 ambiance = gSavedSettings.getF32("PathfindingAmbiance"); + + if (LLGLSLShader::sNoFixedFunction) + { + gPathfindingProgram.bind(); + + gPathfindingProgram.uniform1f(sTint, 1.f); + gPathfindingProgram.uniform1f(sAmbiance, ambiance); + gPathfindingProgram.uniform1f(sAlphaScale, 1.f); + } + + if ( !pathfindingConsole->isRenderWorld() ) + { + const LLColor4 clearColor = gSavedSettings.getColor4("PathfindingNavMeshClear"); + gGL.setColorMask(true, true); + glClearColor(clearColor.mV[0],clearColor.mV[1],clearColor.mV[2],0); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + gGL.setColorMask(true, false); + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + } + + //NavMesh + if ( pathfindingConsole->isRenderNavMesh() ) + { + gGL.flush(); + glLineWidth(2.0f); + LLGLEnable cull(GL_CULL_FACE); + LLGLDisable blend(GL_BLEND); + + if ( pathfindingConsole->isRenderWorld() ) + { + LLGLEnable blend(GL_BLEND); + gPathfindingProgram.uniform1f(sAlphaScale, 0.66f); + llPathingLibInstance->renderNavMesh(); + } + else + { + llPathingLibInstance->renderNavMesh(); + } + + //render edges + if (LLGLSLShader::sNoFixedFunction) + { + gPathfindingNoNormalsProgram.bind(); + gPathfindingNoNormalsProgram.uniform1f(sTint, 1.f); + gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, 1.f); + llPathingLibInstance->renderNavMeshEdges(); + gPathfindingProgram.bind(); + } + else + { + llPathingLibInstance->renderNavMeshEdges(); + } + + gGL.flush(); + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + glLineWidth(1.0f); + gGL.flush(); + } + //User designated path + if ( LLPathfindingPathTool::getInstance()->isRenderPath() ) + { + //The path + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); + llPathingLibInstance->renderPath(); + gPathfindingProgram.bind(); + } + else + { + llPathingLibInstance->renderPath(); + } + //The bookends + if (LLGLSLShader::sNoFixedFunction) + { + //remove blending artifacts + gGL.setColorMask(false, false); + llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); + llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); + + gGL.setColorMask(true, false); + //render the bookends + LLGLEnable blend(GL_BLEND); + gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); + llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); + llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); + gPathfindingProgram.bind(); + } + else + { + llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); + llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); + } + + } + + if ( pathfindingConsole->isRenderWaterPlane() ) + { + if (LLGLSLShader::sNoFixedFunction) + { + LLGLEnable blend(GL_BLEND); + gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); + llPathingLibInstance->renderSimpleShapes( gGL, gAgent.getRegion()->getWaterHeight() ); + } + else + { + llPathingLibInstance->renderSimpleShapes( gGL, gAgent.getRegion()->getWaterHeight() ); + } + } + //physics/exclusion shapes + if ( pathfindingConsole->isRenderAnyShapes() ) + { + U32 render_order[] = { + 1 << LLPathingLib::LLST_ObstacleObjects, + 1 << LLPathingLib::LLST_WalkableObjects, + 1 << LLPathingLib::LLST_ExclusionPhantoms, + 1 << LLPathingLib::LLST_MaterialPhantoms, + }; + + U32 flags = pathfindingConsole->getRenderShapeFlags(); + + for (U32 i = 0; i < 4; i++) + { + if (!(flags & render_order[i])) + { + continue; + } + + //turn off backface culling for volumes so they are visible when camera is inside volume + LLGLDisable cull(i >= 2 ? GL_CULL_FACE : 0); + + gGL.flush(); + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + + //get rid of some z-fighting + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0f, 1.0f); + + //render to depth first to avoid blending artifacts + gGL.setColorMask(false, false); + llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); + gGL.setColorMask(true, false); + + //get rid of some z-fighting + glPolygonOffset(0.f, 0.f); + + LLGLEnable blend(GL_BLEND); + + { + gPathfindingProgram.uniform1f(sAmbiance, ambiance); + + { //draw solid overlay + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_LEQUAL); + llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); + gGL.flush(); + } + + LLGLEnable lineOffset(GL_POLYGON_OFFSET_LINE); + glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); + + F32 offset = gSavedSettings.getF32("PathfindingLineOffset"); + + if (pathfindingConsole->isRenderXRay()) + { + gPathfindingProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); + gPathfindingProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); + LLGLEnable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); + + glPolygonOffset(offset, -offset); + + if (gSavedSettings.getBOOL("PathfindingXRayWireframe")) + { //draw hidden wireframe as darker and less opaque + gPathfindingProgram.uniform1f(sAmbiance, 1.f); + llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); + } + else + { + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + gPathfindingProgram.uniform1f(sAmbiance, ambiance); + llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } + } + + { //draw visible wireframe as brighter, thicker and more opaque + glPolygonOffset(offset, offset); + gPathfindingProgram.uniform1f(sAmbiance, 1.f); + gPathfindingProgram.uniform1f(sTint, 1.f); + gPathfindingProgram.uniform1f(sAlphaScale, 1.f); + + glLineWidth(gSavedSettings.getF32("PathfindingLineWidth")); + LLGLDisable blendOut(GL_BLEND); + llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); + gGL.flush(); + glLineWidth(1.f); + } + + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + } + } + } + + glPolygonOffset(0.f, 0.f); + + if ( pathfindingConsole->isRenderNavMesh() && pathfindingConsole->isRenderXRay() ) + { //render navmesh xray + F32 ambiance = gSavedSettings.getF32("PathfindingAmbiance"); + + LLGLEnable lineOffset(GL_POLYGON_OFFSET_LINE); + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + + F32 offset = gSavedSettings.getF32("PathfindingLineOffset"); + glPolygonOffset(offset, -offset); + + LLGLEnable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); + gGL.flush(); + glLineWidth(2.0f); + LLGLEnable cull(GL_CULL_FACE); + + gPathfindingProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); + gPathfindingProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); + + if (gSavedSettings.getBOOL("PathfindingXRayWireframe")) + { //draw hidden wireframe as darker and less opaque + glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); + gPathfindingProgram.uniform1f(sAmbiance, 1.f); + llPathingLibInstance->renderNavMesh(); + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + } + else + { + gPathfindingProgram.uniform1f(sAmbiance, ambiance); + llPathingLibInstance->renderNavMesh(); + } + + //render edges + if (LLGLSLShader::sNoFixedFunction) + { + gPathfindingNoNormalsProgram.bind(); + gPathfindingNoNormalsProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); + gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); + llPathingLibInstance->renderNavMeshEdges(); + gPathfindingProgram.bind(); + } + else + { + llPathingLibInstance->renderNavMeshEdges(); + } + + gGL.flush(); + glLineWidth(1.0f); + } + + glPolygonOffset(0.f, 0.f); + + gGL.flush(); + if (LLGLSLShader::sNoFixedFunction) + { + gPathfindingProgram.unbind(); + } + } + } + } + } - if (!LLPipeline::sImpostorRender) - { - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights"); + gGL.color4f(1,1,1,1); + + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + gGL.setColorMask(true, false); + + + if (!hud_only && !mDebugBlips.empty()) + { //render debug blips + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + } + + gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep, true); + + glPointSize(8.f); + LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); + + gGL.begin(LLRender::POINTS); + for (std::list::iterator iter = mDebugBlips.begin(); iter != mDebugBlips.end(); ) + { + DebugBlip& blip = *iter; + + blip.mAge += gFrameIntervalSeconds.value(); + if (blip.mAge > 2.f) + { + mDebugBlips.erase(iter++); + } + else + { + iter++; + } + + blip.mPosition.mV[2] += gFrameIntervalSeconds.value()*2.f; + + gGL.color4fv(blip.mColor.mV); + gGL.vertex3fv(blip.mPosition.mV); + } + gGL.end(); + gGL.flush(); + glPointSize(1.f); + } - if (!sReflectionRender) - { - renderHighlights(); - } - // Contains a list of the faces of objects that are physical or - // have touch-handlers. - mHighlightFaces.clear(); + // Debug stuff. + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + if ( (hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES)) || + (!hud_only && hasRenderType(part->mDrawableType)) ) + { + part->renderDebug(); + } + } + } + } - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDebug"); - - renderDebug(); + for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + { + LLSpatialBridge* bridge = *i; + if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) + { + gGL.pushMatrix(); + gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); + bridge->renderDebug(); + gGL.popMatrix(); + } + } - LLVertexBuffer::unbind(); - - if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred) - { - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - // Render debugging beacons. - gObjectList.renderObjectBeacons(); - gObjectList.resetObjectBeacons(); - gSky.addSunMoonBeacons(); - } - else - { - // Make sure particle effects disappear - LLHUDObject::renderAllForTimer(); - } - } - else - { - // Make sure particle effects disappear - LLHUDObject::renderAllForTimer(); - } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION) && LLGLSLShader::sNoFixedFunction) + { //render visible selected group occlusion geometry + gDebugProgram.bind(); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + gGL.diffuseColor3f(1,0,1); + for (std::set::iterator iter = visible_selected_groups.begin(); iter != visible_selected_groups.end(); ++iter) + { + LLSpatialGroup* group = *iter; + + LLVector4a fudge; + fudge.splat(0.25f); //SG_OCCLUSION_FUDGE + + LLVector4a size; + const LLVector4a* bounds = group->getBounds(); + size.setAdd(fudge, bounds[1]); + + drawBox(bounds[0], size); + } + } - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd"); + visible_selected_groups.clear(); - //HACK: preserve/restore matrices around HUD render - if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) - { - for (U32 i = 0; i < 16; i++) - { - gGLModelView[i] = saved_modelview[i]; - gGLProjection[i] = saved_projection[i]; - } - } - } + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + } - LLVertexBuffer::unbind(); + if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST) && !hud_only) + { //draw crosshairs on particle intersection + if (gDebugRaycastParticle) + { + if (LLGLSLShader::sNoFixedFunction) + { //this debug display requires shaders + gDebugProgram.bind(); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + LLVector3 center(gDebugRaycastParticleIntersection.getF32ptr()); + LLVector3 size(0.1f, 0.1f, 0.1f); + + LLVector3 p[6]; + + p[0] = center + size.scaledVec(LLVector3(1,0,0)); + p[1] = center + size.scaledVec(LLVector3(-1,0,0)); + p[2] = center + size.scaledVec(LLVector3(0,1,0)); + p[3] = center + size.scaledVec(LLVector3(0,-1,0)); + p[4] = center + size.scaledVec(LLVector3(0,0,1)); + p[5] = center + size.scaledVec(LLVector3(0,0,-1)); + + gGL.begin(LLRender::LINES); + gGL.diffuseColor3f(1.f, 1.f, 0.f); + for (U32 i = 0; i < 6; i++) + { + gGL.vertex3fv(p[i].mV); + } + gGL.end(); + gGL.flush(); + + gDebugProgram.unbind(); + } + } + } - LLGLState::checkStates(); -// LLGLState::checkTextureChannels(); -// LLGLState::checkClientArrays(); -} + if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + LLVertexBuffer::unbind(); + + LLGLEnable blend(GL_BLEND); + LLGLDepthTest depth(TRUE, FALSE); + LLGLDisable cull(GL_CULL_FACE); + + gGL.color4f(1,1,1,1); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + F32 a = 0.1f; + + F32 col[] = + { + 1,0,0,a, + 0,1,0,a, + 0,0,1,a, + 1,0,1,a, + + 1,1,0,a, + 0,1,1,a, + 1,1,1,a, + 1,0,1,a, + }; + + for (U32 i = 0; i < 8; i++) + { + LLVector3* frust = mShadowCamera[i].mAgentFrustum; + + if (i > 3) + { //render shadow frusta as volumes + if (mShadowFrustPoints[i-4].empty()) + { + continue; + } + + gGL.color4fv(col+(i-4)*4); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV); + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); + gGL.end(); + + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex3fv(frust[0].mV); + gGL.vertex3fv(frust[1].mV); + gGL.vertex3fv(frust[3].mV); + gGL.vertex3fv(frust[2].mV); + gGL.end(); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[7].mV); + gGL.vertex3fv(frust[6].mV); + gGL.end(); + } + + + if (i < 4) + { + + //if (i == 0 || !mShadowFrustPoints[i].empty()) + { + //render visible point cloud + gGL.flush(); + glPointSize(8.f); + gGL.begin(LLRender::POINTS); + + F32* c = col+i*4; + gGL.color3fv(c); + + for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j) + { + gGL.vertex3fv(mShadowFrustPoints[i][j].mV); + + } + gGL.end(); + + gGL.flush(); + glPointSize(1.f); + + LLVector3* ext = mShadowExtents[i]; + LLVector3 pos = (ext[0]+ext[1])*0.5f; + LLVector3 size = (ext[1]-ext[0])*0.5f; + drawBoxOutline(pos, size); + + //render camera frustum splits as outlines + gGL.begin(LLRender::LINES); + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV); + gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV); + gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV); + gGL.end(); + } + } + + /*gGL.flush(); + glLineWidth(16-i*2); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++) + { + LLSpatialPartition* part = region->getSpatialPartition(j); + if (part) + { + if (hasRenderType(part->mDrawableType)) + { + part->renderIntersectingBBoxes(&mShadowCamera[i]); + } + } + } + } + gGL.flush(); + glLineWidth(1.f);*/ + } + } -void LLPipeline::renderGeomDeferred(LLCamera& camera) -{ - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred"); + if (mRenderDebugMask & RENDER_DEBUG_WIND_VECTORS) + { + gAgent.getRegion()->mWind.renderVectors(); + } + + if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION) + { + // Debug composition layers + F32 x, y; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + if (gAgent.getRegion()) + { + gGL.begin(LLRender::POINTS); + // Draw the composition layer for the region that I'm in. + for (x = 0; x <= 260; x++) + { + for (y = 0; y <= 260; y++) + { + if ((x > 255) || (y > 255)) + { + gGL.color4f(1.f, 0.f, 0.f, 1.f); + } + else + { + gGL.color4f(0.f, 0.f, 1.f, 1.f); + } + F32 z = gAgent.getRegion()->getCompositionXY((S32)x, (S32)y); + z *= 5.f; + z += 50.f; + gGL.vertex3f(x, y, z); + } + } + gGL.end(); + } + } - LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY); + if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_BUILD_QUEUE) + { + U32 count = 0; + U32 size = mGroupQ2.size(); + LLColor4 col; + + LLVertexBuffer::unbind(); + LLGLEnable blend(GL_BLEND); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); + + gGL.pushMatrix(); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; + + for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin(); iter != mGroupQ2.end(); ++iter) + { + LLSpatialGroup* group = *iter; + if (group->isDead()) + { + continue; + } + + LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); + + if (bridge && (!bridge->mDrawable || bridge->mDrawable->isDead())) + { + continue; + } + + if (bridge) + { + gGL.pushMatrix(); + gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); + } + + F32 alpha = llclamp((F32) (size-count)/size, 0.f, 1.f); + + + LLVector2 c(1.f-alpha, alpha); + c.normVec(); + + + ++count; + col.set(c.mV[0], c.mV[1], 0, alpha*0.5f+0.5f); + group->drawObjectBox(col); + + if (bridge) + { + gGL.popMatrix(); + } + } + + gGL.popMatrix(); + } - LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLS); + gGL.flush(); + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.unbind(); + } +} - LLGLEnable cull(GL_CULL_FACE); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_POOLS("Rebuild Pools"); - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - if (hasRenderType(poolp->getType())) - { - poolp->prerender(); - } - } +void LLPipeline::rebuildPools() +{ + LL_RECORD_BLOCK_TIME(FTM_REBUILD_POOLS); - LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + assertInitialized(); - LLVertexBuffer::unbind(); + S32 max_count = mPools.size(); + pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool); + while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS) + { + if (iter1 == mPools.end()) + { + iter1 = mPools.begin(); + } + LLDrawPool* poolp = *iter1; + + if (poolp->isDead()) + { + mPools.erase(iter1++); + removeFromQuickLookup( poolp ); + if (poolp == mLastRebuildPool) + { + mLastRebuildPool = NULL; + } + delete poolp; + } + else + { + mLastRebuildPool = poolp; + iter1++; + } + max_count--; + } +} - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); +void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) +{ + assertInitialized(); - gGL.setColorMask(true, true); - - pool_set_t::iterator iter = mPools.begin(); - while ( iter != mPools.end() ) - { - LLDrawPool* poolp = *iter; - llassert(poolp != nullptr); - if (poolp) - { - U32 pool_type = poolp->getType(); - S32 deferred_passes = poolp->getNumDeferredPasses(); - if (hasRenderType(pool_type) && (deferred_passes > 0)) - { - LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLRENDER); - - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - - for( S32 i = 0; i < deferred_passes; i++ ) - { - LLVertexBuffer::unbind(); - stop_glerror(); - - poolp->beginDeferredPass(i); - poolp->renderDeferred(i); - poolp->endDeferredPass(i); - - // per-pass validation that our conception of current GL state is correct - if (gDebugGL || gDebugPipeline) - { - LLGLState::checkStates(); - } - } - - LLVertexBuffer::unbind(); - stop_glerror(); - } - } - - iter++; - } - - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - - gGL.setColorMask(true, false); + switch( new_poolp->getType() ) + { + case LLDrawPool::POOL_SIMPLE: + if (mSimplePool) + { + llassert(0); + LL_WARNS() << "Ignoring duplicate simple pool." << LL_ENDL; + } + else + { + mSimplePool = (LLRenderPass*) new_poolp; + } + break; + + case LLDrawPool::POOL_ALPHA_MASK: + if (mAlphaMaskPool) + { + llassert(0); + LL_WARNS() << "Ignoring duplicate alpha mask pool." << LL_ENDL; + break; + } + else + { + mAlphaMaskPool = (LLRenderPass*) new_poolp; + } + break; + + case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: + if (mFullbrightAlphaMaskPool) + { + llassert(0); + LL_WARNS() << "Ignoring duplicate alpha mask pool." << LL_ENDL; + break; + } + else + { + mFullbrightAlphaMaskPool = (LLRenderPass*) new_poolp; + } + break; + + case LLDrawPool::POOL_GRASS: + if (mGrassPool) + { + llassert(0); + LL_WARNS() << "Ignoring duplicate grass pool." << LL_ENDL; + } + else + { + mGrassPool = (LLRenderPass*) new_poolp; + } + break; + + case LLDrawPool::POOL_FULLBRIGHT: + if (mFullbrightPool) + { + llassert(0); + LL_WARNS() << "Ignoring duplicate simple pool." << LL_ENDL; + } + else + { + mFullbrightPool = (LLRenderPass*) new_poolp; + } + break; + + case LLDrawPool::POOL_INVISIBLE: + if (mInvisiblePool) + { + llassert(0); + LL_WARNS() << "Ignoring duplicate simple pool." << LL_ENDL; + } + else + { + mInvisiblePool = (LLRenderPass*) new_poolp; + } + break; + + case LLDrawPool::POOL_GLOW: + if (mGlowPool) + { + llassert(0); + LL_WARNS() << "Ignoring duplicate glow pool." << LL_ENDL; + } + else + { + mGlowPool = (LLRenderPass*) new_poolp; + } + break; + + case LLDrawPool::POOL_TREE: + mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; + break; + + case LLDrawPool::POOL_TERRAIN: + mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; + break; + + case LLDrawPool::POOL_BUMP: + if (mBumpPool) + { + llassert(0); + LL_WARNS() << "Ignoring duplicate bump pool." << LL_ENDL; + } + else + { + mBumpPool = new_poolp; + } + break; + case LLDrawPool::POOL_MATERIALS: + if (mMaterialsPool) + { + llassert(0); + LL_WARNS() << "Ignorning duplicate materials pool." << LL_ENDL; + } + else + { + mMaterialsPool = new_poolp; + } + break; + case LLDrawPool::POOL_ALPHA: + if( mAlphaPool ) + { + llassert(0); + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << LL_ENDL; + } + else + { + mAlphaPool = (LLDrawPoolAlpha*) new_poolp; + } + break; + + case LLDrawPool::POOL_AVATAR: + break; // Do nothing + + case LLDrawPool::POOL_SKY: + if( mSkyPool ) + { + llassert(0); + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << LL_ENDL; + } + else + { + mSkyPool = new_poolp; + } + break; + + case LLDrawPool::POOL_WATER: + if( mWaterPool ) + { + llassert(0); + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Water pool" << LL_ENDL; + } + else + { + mWaterPool = new_poolp; + } + break; + + case LLDrawPool::POOL_GROUND: + if( mGroundPool ) + { + llassert(0); + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << LL_ENDL; + } + else + { + mGroundPool = new_poolp; + } + break; + + case LLDrawPool::POOL_WL_SKY: + if( mWLSkyPool ) + { + llassert(0); + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate WLSky Pool" << LL_ENDL; + } + else + { + mWLSkyPool = new_poolp; + } + break; + + default: + llassert(0); + LL_WARNS() << "Invalid Pool Type in LLPipeline::addPool()" << LL_ENDL; + break; + } } -void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion) +void LLPipeline::removePool( LLDrawPool* poolp ) { - LL_RECORD_BLOCK_TIME(FTM_POST_DEFERRED_POOLS); - U32 cur_type = 0; + assertInitialized(); + removeFromQuickLookup(poolp); + mPools.erase(poolp); + delete poolp; +} - LLGLEnable cull(GL_CULL_FACE); +void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) +{ + assertInitialized(); + switch( poolp->getType() ) + { + case LLDrawPool::POOL_SIMPLE: + llassert(mSimplePool == poolp); + mSimplePool = NULL; + break; + + case LLDrawPool::POOL_ALPHA_MASK: + llassert(mAlphaMaskPool == poolp); + mAlphaMaskPool = NULL; + break; + + case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: + llassert(mFullbrightAlphaMaskPool == poolp); + mFullbrightAlphaMaskPool = NULL; + break; + + case LLDrawPool::POOL_GRASS: + llassert(mGrassPool == poolp); + mGrassPool = NULL; + break; + + case LLDrawPool::POOL_FULLBRIGHT: + llassert(mFullbrightPool == poolp); + mFullbrightPool = NULL; + break; + + case LLDrawPool::POOL_INVISIBLE: + llassert(mInvisiblePool == poolp); + mInvisiblePool = NULL; + break; + + case LLDrawPool::POOL_WL_SKY: + llassert(mWLSkyPool == poolp); + mWLSkyPool = NULL; + break; + + case LLDrawPool::POOL_GLOW: + llassert(mGlowPool == poolp); + mGlowPool = NULL; + break; + + case LLDrawPool::POOL_TREE: + #ifdef _DEBUG + { + bool found = mTreePools.erase( (uintptr_t)poolp->getTexture() ); + llassert( found ); + } + #else + mTreePools.erase( (uintptr_t)poolp->getTexture() ); + #endif + break; + + case LLDrawPool::POOL_TERRAIN: + #ifdef _DEBUG + { + bool found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() ); + llassert( found ); + } + #else + mTerrainPools.erase( (uintptr_t)poolp->getTexture() ); + #endif + break; + + case LLDrawPool::POOL_BUMP: + llassert( poolp == mBumpPool ); + mBumpPool = NULL; + break; + + case LLDrawPool::POOL_MATERIALS: + llassert(poolp == mMaterialsPool); + mMaterialsPool = NULL; + break; + + case LLDrawPool::POOL_ALPHA: + llassert( poolp == mAlphaPool ); + mAlphaPool = NULL; + break; + + case LLDrawPool::POOL_AVATAR: + break; // Do nothing + + case LLDrawPool::POOL_SKY: + llassert( poolp == mSkyPool ); + mSkyPool = NULL; + break; + + case LLDrawPool::POOL_WATER: + llassert( poolp == mWaterPool ); + mWaterPool = NULL; + break; + + case LLDrawPool::POOL_GROUND: + llassert( poolp == mGroundPool ); + mGroundPool = NULL; + break; + + default: + llassert(0); + LL_WARNS() << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << LL_ENDL; + break; + } +} - LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); +void LLPipeline::resetDrawOrders() +{ + assertInitialized(); + // Iterate through all of the draw pools and rebuild them. + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + { + LLDrawPool *poolp = *iter; + poolp->resetDrawOrders(); + } +} - calcNearbyLights(camera); - setupHWLights(NULL); +//============================================================================ +// Once-per-frame setup of hardware lights, +// including sun/moon, avatar backlight, and up to 6 local lights - gGL.setColorMask(true, false); +void LLPipeline::setupAvatarLights(bool for_edit) +{ + assertInitialized(); - pool_set_t::iterator iter1 = mPools.begin(); - bool occlude = LLPipeline::sUseOcclusion > 1 && do_occlusion; + LLEnvironment& environment = LLEnvironment::instance(); + LLSettingsSky::ptr_t psky = environment.getCurrentSky(); - while ( iter1 != mPools.end() ) - { - LLDrawPool *poolp = *iter1; - - cur_type = poolp->getType(); + bool sun_up = environment.getIsSunUp(); - if (occlude && cur_type >= LLDrawPool::POOL_GRASS) - { - occlude = false; - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - LLGLSLShader::bindNoShader(); - doOcclusion(camera, mScreen, mOcclusionDepth, &mDeferredDepth); - gGL.setColorMask(true, false); - } + if (for_edit) + { + LLColor4 diffuse(1.f, 1.f, 1.f, 0.f); + LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f); // w==0 => directional light + LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview(); + LLMatrix4 camera_rot(camera_mat.getMat3()); + camera_rot.invert(); + LLVector4 light_pos = light_pos_cam * camera_rot; + + light_pos.normalize(); - pool_set_t::iterator iter2 = iter1; - if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0) - { - LL_RECORD_BLOCK_TIME(FTM_POST_DEFERRED_POOLRENDER); + LLLightState* light = gGL.getLight(1); - gGLLastMatrix = NULL; - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.loadMatrix(gGLModelView); - - for( S32 i = 0; i < poolp->getNumPostDeferredPasses(); i++ ) - { - LLVertexBuffer::unbind(); - poolp->beginPostDeferredPass(i); - for (iter2 = iter1; iter2 != mPools.end(); iter2++) - { - LLDrawPool *p = *iter2; - if (p->getType() != cur_type) - { - break; - } - - p->renderPostDeferred(i); - } - poolp->endPostDeferredPass(i); - LLVertexBuffer::unbind(); + mHWLightColors[1] = diffuse; - if (gDebugGL || gDebugPipeline) - { - LLGLState::checkStates(); - } - } - } - else + if (LLPipeline::sRenderDeferred) { - // Skip all pools of this type - for (iter2 = iter1; iter2 != mPools.end(); iter2++) - { - LLDrawPool *p = *iter2; - if (p->getType() != cur_type) - { - break; - } - } + /*diffuse.mV[0] = powf(diffuse.mV[0], 2.2f); + diffuse.mV[1] = powf(diffuse.mV[1], 2.2f); + diffuse.mV[2] = powf(diffuse.mV[2], 2.2f);*/ } - iter1 = iter2; - stop_glerror(); - } - - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - - if (occlude) - { - occlude = false; - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - LLGLSLShader::bindNoShader(); - doOcclusion(camera); - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - } -} -void LLPipeline::renderGeomShadow(LLCamera& camera) -{ - U32 cur_type = 0; - - LLGLEnable cull(GL_CULL_FACE); + mHWLightColors[1] = diffuse; - LLVertexBuffer::unbind(); + light->setDiffuse(diffuse); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); + light->setPosition(light_pos); + light->setConstantAttenuation(1.f); + light->setLinearAttenuation(0.f); + light->setQuadraticAttenuation(0.f); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); + } + else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini) + { + LLVector3 light_dir = sun_up ? LLVector3(mSunDir) : LLVector3(mMoonDir); + LLVector3 opposite_pos = -light_dir; + LLVector3 orthog_light_pos = light_dir % LLVector3::z_axis; + LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f); + backlight_pos.normalize(); - pool_set_t::iterator iter1 = mPools.begin(); - - while ( iter1 != mPools.end() ) - { - LLDrawPool *poolp = *iter1; - - cur_type = poolp->getType(); + LLColor4 light_diffuse = sun_up ? mSunDiffuse : mMoonDiffuse; - pool_set_t::iterator iter2 = iter1; - if (hasRenderType(poolp->getType()) && poolp->getNumShadowPasses() > 0) + LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f); + F32 max_component = 0.001f; + for (S32 i = 0; i < 3; i++) { - poolp->prerender() ; - - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - - for( S32 i = 0; i < poolp->getNumShadowPasses(); i++ ) + if (backlight_diffuse.mV[i] > max_component) { - LLVertexBuffer::unbind(); - poolp->beginShadowPass(i); - for (iter2 = iter1; iter2 != mPools.end(); iter2++) - { - LLDrawPool *p = *iter2; - if (p->getType() != cur_type) - { - break; - } - - p->renderShadow(i); - } - poolp->endShadowPass(i); - LLVertexBuffer::unbind(); - - LLGLState::checkStates(); + max_component = backlight_diffuse.mV[i]; } } + F32 backlight_mag; + if (LLEnvironment::instance().getIsSunUp()) + { + backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT; + } else { - // Skip all pools of this type - for (iter2 = iter1; iter2 != mPools.end(); iter2++) - { - LLDrawPool *p = *iter2; - if (p->getType() != cur_type) - { - break; - } - } + backlight_mag = BACKLIGHT_NIGHT_MAGNITUDE_OBJECT; } - iter1 = iter2; - stop_glerror(); - } + backlight_diffuse *= backlight_mag / max_component; - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); -} + if (LLPipeline::sRenderDeferred) + { + /*backlight_diffuse.mV[0] = powf(backlight_diffuse.mV[0], 2.2f); + backlight_diffuse.mV[1] = powf(backlight_diffuse.mV[1], 2.2f); + backlight_diffuse.mV[2] = powf(backlight_diffuse.mV[2], 2.2f);*/ + } + mHWLightColors[1] = backlight_diffuse; -void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type) -{ - assertInitialized(); - S32 count = 0; - if (render_type == LLRender::TRIANGLE_STRIP) - { - count = index_count-2; + LLLightState* light = gGL.getLight(1); + + light->setPosition(backlight_pos); + light->setDiffuse(backlight_diffuse); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); + light->setConstantAttenuation(1.f); + light->setLinearAttenuation(0.f); + light->setQuadraticAttenuation(0.f); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); } else { - count = index_count/3; - } + LLLightState* light = gGL.getLight(1); - record(sStatBatchSize, count); - add(LLStatViewer::TRIANGLES_DRAWN, LLUnits::Triangles::fromValue(count)); + mHWLightColors[1] = LLColor4::black; - if (LLPipeline::sRenderFrameTest) - { - gViewerWindow->getWindow()->swapBuffers(); - ms_sleep(16); + light->setDiffuse(LLColor4::black); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); } } -void LLPipeline::renderPhysicsDisplay() +static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist) { - if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) - { - return; - } - - allocatePhysicsBuffer(); - - gGL.flush(); - mPhysicsDisplay.bindTarget(); - glClearColor(0,0,0,1); - gGL.setColorMask(true, true); - mPhysicsDisplay.clear(); - glClearColor(0,0,0,0); + F32 inten = light->getLightIntensity(); + if (inten < .001f) + { + return max_dist; + } + F32 radius = light->getLightRadius(); + bool selected = light->isSelected(); + LLVector3 dpos = light->getRenderPosition() - cam_pos; + F32 dist2 = dpos.lengthSquared(); + if (!selected && dist2 > (max_dist + radius)*(max_dist + radius)) + { + return max_dist; + } + F32 dist = (F32) sqrt(dist2); + dist *= 1.f / inten; + dist -= radius; + if (selected) + { + dist -= 10000.f; // selected lights get highest priority + } + if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE)) + { + // moving lights get a little higher priority (too much causes artifacts) + dist -= light->getLightRadius()*0.25f; + } + return dist; +} - gGL.setColorMask(true, false); +void LLPipeline::calcNearbyLights(LLCamera& camera) +{ + assertInitialized(); - if (LLGLSLShader::sNoFixedFunction) - { - gDebugProgram.bind(); - } + if (LLPipeline::sReflectionRender) + { + return; + } - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) - { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) + if (mLightingDetail >= 1) + { + // mNearbyLight (and all light_set_t's) are sorted such that + // begin() == the closest light and rbegin() == the farthest light + const S32 MAX_LOCAL_LIGHTS = 6; +// LLVector3 cam_pos = gAgent.getCameraPositionAgent(); + LLVector3 cam_pos = LLViewerJoystick::getInstance()->getOverrideCamera() ? + camera.getOrigin() : + gAgent.getPositionAgent(); + + F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad + + // UPDATE THE EXISTING NEARBY LIGHTS + light_set_t cur_nearby_lights; + for (light_set_t::iterator iter = mNearbyLights.begin(); + iter != mNearbyLights.end(); iter++) + { + const Light* light = &(*iter); + LLDrawable* drawable = light->drawable; + const LLViewerObject *vobj = light->drawable->getVObj(); + if(vobj && vobj->getAvatar() + && (vobj->getAvatar()->isTooComplex() || vobj->getAvatar()->isInMuteList()) + ) { - if (hasRenderType(part->mDrawableType)) - { - part->renderPhysicsShapes(); - } + drawable->clearState(LLDrawable::NEARBY_LIGHT); + continue; } - } - } - - gGL.flush(); - - if (LLGLSLShader::sNoFixedFunction) - { - gDebugProgram.unbind(); - } - mPhysicsDisplay.flush(); + LLVOVolume* volight = drawable->getVOVolume(); + if (!volight || !drawable->isState(LLDrawable::LIGHT)) + { + drawable->clearState(LLDrawable::NEARBY_LIGHT); + continue; + } + if (light->fade <= -LIGHT_FADE_TIME) + { + drawable->clearState(LLDrawable::NEARBY_LIGHT); + continue; + } + if (!sRenderAttachedLights && volight && volight->isAttachment()) + { + drawable->clearState(LLDrawable::NEARBY_LIGHT); + continue; + } + + F32 dist = calc_light_dist(volight, cam_pos, max_dist); + cur_nearby_lights.insert(Light(drawable, dist, light->fade)); + } + mNearbyLights = cur_nearby_lights; + + // FIND NEW LIGHTS THAT ARE IN RANGE + light_set_t new_nearby_lights; + for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); + iter != mLights.end(); ++iter) + { + LLDrawable* drawable = *iter; + LLVOVolume* light = drawable->getVOVolume(); + if (!light || drawable->isState(LLDrawable::NEARBY_LIGHT)) + { + continue; + } + if (light->isHUDAttachment()) + { + continue; // no lighting from HUD objects + } + F32 dist = calc_light_dist(light, cam_pos, max_dist); + if (dist >= max_dist) + { + continue; + } + if (!sRenderAttachedLights && light && light->isAttachment()) + { + continue; + } + new_nearby_lights.insert(Light(drawable, dist, 0.f)); + if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS) + { + new_nearby_lights.erase(--new_nearby_lights.end()); + const Light& last = *new_nearby_lights.rbegin(); + max_dist = last.dist; + } + } + + // INSERT ANY NEW LIGHTS + for (light_set_t::iterator iter = new_nearby_lights.begin(); + iter != new_nearby_lights.end(); iter++) + { + const Light* light = &(*iter); + if (mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS) + { + mNearbyLights.insert(*light); + ((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT); + } + else + { + // crazy cast so that we can overwrite the fade value + // even though gcc enforces sets as const + // (fade value doesn't affect sort so this is safe) + Light* farthest_light = (const_cast(&(*(mNearbyLights.rbegin())))); + if (light->dist < farthest_light->dist) + { + if (farthest_light->fade >= 0.f) + { + farthest_light->fade = -(gFrameIntervalSeconds.value()); + } + } + else + { + break; // none of the other lights are closer + } + } + } + + //mark nearby lights not-removable. + for (light_set_t::iterator iter = mNearbyLights.begin(); + iter != mNearbyLights.end(); iter++) + { + const Light* light = &(*iter); + ((LLViewerOctreeEntryData*) light->drawable)->setVisible(); + } + } } -extern std::set visible_selected_groups; - -void LLPipeline::renderDebug() +void LLPipeline::setupHWLights(LLDrawPool* pool) { - assertInitialized(); - - bool hud_only = hasRenderType(LLPipeline::RENDER_TYPE_HUD); + assertInitialized(); + + LLEnvironment& environment = LLEnvironment::instance(); + LLSettingsSky::ptr_t psky = environment.getCurrentSky(); + + // Ambient + if (!LLGLSLShader::sNoFixedFunction) + { + gGL.syncMatrices(); + LLColor4 ambient = psky->getTotalAmbient(); + gGL.setAmbientLightColor(ambient); + } - if (!hud_only ) + // Ambient + if (!LLGLSLShader::sNoFixedFunction) { - //Render any navmesh geometry - LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance(); - if ( llPathingLibInstance != NULL ) - { - //character floater renderables - - LLHandle pathfindingCharacterHandle = LLFloaterPathfindingCharacters::getInstanceHandle(); - if ( !pathfindingCharacterHandle.isDead() ) - { - LLFloaterPathfindingCharacters *pathfindingCharacter = pathfindingCharacterHandle.get(); - - if ( pathfindingCharacter->getVisible() || gAgentCamera.cameraMouselook() ) - { - if (LLGLSLShader::sNoFixedFunction) - { - gPathfindingProgram.bind(); - gPathfindingProgram.uniform1f(sTint, 1.f); - gPathfindingProgram.uniform1f(sAmbiance, 1.f); - gPathfindingProgram.uniform1f(sAlphaScale, 1.f); - } + gGL.syncMatrices(); + LLColor4 ambient = psky->getTotalAmbient(); + gGL.setAmbientLightColor(ambient); + } - //Requried character physics capsule render parameters - LLUUID id; - LLVector3 pos; - LLQuaternion rot; - - if ( pathfindingCharacter->isPhysicsCapsuleEnabled( id, pos, rot ) ) - { - if (LLGLSLShader::sNoFixedFunction) - { - //remove blending artifacts - gGL.setColorMask(false, false); - llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); - gGL.setColorMask(true, false); - LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); - llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); - gPathfindingProgram.bind(); - } - else - { - llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); - } - } - } - } - + bool sun_up = environment.getIsSunUp(); - //pathing console renderables - LLHandle pathfindingConsoleHandle = LLFloaterPathfindingConsole::getInstanceHandle(); - if (!pathfindingConsoleHandle.isDead()) - { - LLFloaterPathfindingConsole *pathfindingConsole = pathfindingConsoleHandle.get(); + // Light 0 = Sun or Moon (All objects) + { + LLVector4 sun_dir(environment.getSunDirection(), 0.0f); + LLVector4 moon_dir(environment.getMoonDirection(), 0.0f); - if ( pathfindingConsole->getVisible() || gAgentCamera.cameraMouselook() ) - { - F32 ambiance = gSavedSettings.getF32("PathfindingAmbiance"); + mSunDir.setVec(sun_dir); + mMoonDir.setVec(moon_dir); + mSunDiffuse.setVec(psky->getSunDiffuse()); + mMoonDiffuse.setVec(psky->getMoonDiffuse()); - if (LLGLSLShader::sNoFixedFunction) - { - gPathfindingProgram.bind(); - - gPathfindingProgram.uniform1f(sTint, 1.f); - gPathfindingProgram.uniform1f(sAmbiance, ambiance); - gPathfindingProgram.uniform1f(sAlphaScale, 1.f); - } + F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]); + if (max_color > 1.f) + { + mSunDiffuse *= 1.f/max_color; + } + mSunDiffuse.clamp(); - if ( !pathfindingConsole->isRenderWorld() ) - { - const LLColor4 clearColor = gSavedSettings.getColor4("PathfindingNavMeshClear"); - gGL.setColorMask(true, true); - glClearColor(clearColor.mV[0],clearColor.mV[1],clearColor.mV[2],0); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - gGL.setColorMask(true, false); - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - } - - //NavMesh - if ( pathfindingConsole->isRenderNavMesh() ) - { - gGL.flush(); - glLineWidth(2.0f); - LLGLEnable cull(GL_CULL_FACE); - LLGLDisable blend(GL_BLEND); - - if ( pathfindingConsole->isRenderWorld() ) - { - LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f(sAlphaScale, 0.66f); - llPathingLibInstance->renderNavMesh(); - } - else - { - llPathingLibInstance->renderNavMesh(); - } - - //render edges - if (LLGLSLShader::sNoFixedFunction) - { - gPathfindingNoNormalsProgram.bind(); - gPathfindingNoNormalsProgram.uniform1f(sTint, 1.f); - gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, 1.f); - llPathingLibInstance->renderNavMeshEdges(); - gPathfindingProgram.bind(); - } - else - { - llPathingLibInstance->renderNavMeshEdges(); - } - - gGL.flush(); - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - glLineWidth(1.0f); - gGL.flush(); - } - //User designated path - if ( LLPathfindingPathTool::getInstance()->isRenderPath() ) - { - //The path - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); - llPathingLibInstance->renderPath(); - gPathfindingProgram.bind(); - } - else - { - llPathingLibInstance->renderPath(); - } - //The bookends - if (LLGLSLShader::sNoFixedFunction) - { - //remove blending artifacts - gGL.setColorMask(false, false); - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); - - gGL.setColorMask(true, false); - //render the bookends - LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); - gPathfindingProgram.bind(); - } - else - { - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); - } - - } - - if ( pathfindingConsole->isRenderWaterPlane() ) - { - if (LLGLSLShader::sNoFixedFunction) - { - LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); - llPathingLibInstance->renderSimpleShapes( gGL, gAgent.getRegion()->getWaterHeight() ); - } - else - { - llPathingLibInstance->renderSimpleShapes( gGL, gAgent.getRegion()->getWaterHeight() ); - } - } - //physics/exclusion shapes - if ( pathfindingConsole->isRenderAnyShapes() ) - { - U32 render_order[] = { - 1 << LLPathingLib::LLST_ObstacleObjects, - 1 << LLPathingLib::LLST_WalkableObjects, - 1 << LLPathingLib::LLST_ExclusionPhantoms, - 1 << LLPathingLib::LLST_MaterialPhantoms, - }; - - U32 flags = pathfindingConsole->getRenderShapeFlags(); - - for (U32 i = 0; i < 4; i++) - { - if (!(flags & render_order[i])) - { - continue; - } - - //turn off backface culling for volumes so they are visible when camera is inside volume - LLGLDisable cull(i >= 2 ? GL_CULL_FACE : 0); - - gGL.flush(); - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - - //get rid of some z-fighting - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.0f, 1.0f); - - //render to depth first to avoid blending artifacts - gGL.setColorMask(false, false); - llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); - gGL.setColorMask(true, false); - - //get rid of some z-fighting - glPolygonOffset(0.f, 0.f); - - LLGLEnable blend(GL_BLEND); - - { - gPathfindingProgram.uniform1f(sAmbiance, ambiance); - - { //draw solid overlay - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_LEQUAL); - llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); - gGL.flush(); - } - - LLGLEnable lineOffset(GL_POLYGON_OFFSET_LINE); - glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - - F32 offset = gSavedSettings.getF32("PathfindingLineOffset"); - - if (pathfindingConsole->isRenderXRay()) - { - gPathfindingProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); - gPathfindingProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); - LLGLEnable blend(GL_BLEND); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); - - glPolygonOffset(offset, -offset); - - if (gSavedSettings.getBOOL("PathfindingXRayWireframe")) - { //draw hidden wireframe as darker and less opaque - gPathfindingProgram.uniform1f(sAmbiance, 1.f); - llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); - } - else - { - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - gPathfindingProgram.uniform1f(sAmbiance, ambiance); - llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - } - } - - { //draw visible wireframe as brighter, thicker and more opaque - glPolygonOffset(offset, offset); - gPathfindingProgram.uniform1f(sAmbiance, 1.f); - gPathfindingProgram.uniform1f(sTint, 1.f); - gPathfindingProgram.uniform1f(sAlphaScale, 1.f); - - glLineWidth(gSavedSettings.getF32("PathfindingLineWidth")); - LLGLDisable blendOut(GL_BLEND); - llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); - gGL.flush(); - glLineWidth(1.f); - } - - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - } - } - } - - glPolygonOffset(0.f, 0.f); - - if ( pathfindingConsole->isRenderNavMesh() && pathfindingConsole->isRenderXRay() ) - { //render navmesh xray - F32 ambiance = gSavedSettings.getF32("PathfindingAmbiance"); - - LLGLEnable lineOffset(GL_POLYGON_OFFSET_LINE); - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - - F32 offset = gSavedSettings.getF32("PathfindingLineOffset"); - glPolygonOffset(offset, -offset); - - LLGLEnable blend(GL_BLEND); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); - gGL.flush(); - glLineWidth(2.0f); - LLGLEnable cull(GL_CULL_FACE); - - gPathfindingProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); - gPathfindingProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); - - if (gSavedSettings.getBOOL("PathfindingXRayWireframe")) - { //draw hidden wireframe as darker and less opaque - glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - gPathfindingProgram.uniform1f(sAmbiance, 1.f); - llPathingLibInstance->renderNavMesh(); - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - } - else - { - gPathfindingProgram.uniform1f(sAmbiance, ambiance); - llPathingLibInstance->renderNavMesh(); - } - - //render edges - if (LLGLSLShader::sNoFixedFunction) - { - gPathfindingNoNormalsProgram.bind(); - gPathfindingNoNormalsProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); - gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); - llPathingLibInstance->renderNavMeshEdges(); - gPathfindingProgram.bind(); - } - else - { - llPathingLibInstance->renderNavMeshEdges(); - } - - gGL.flush(); - glLineWidth(1.0f); - } - - glPolygonOffset(0.f, 0.f); - - gGL.flush(); - if (LLGLSLShader::sNoFixedFunction) - { - gPathfindingProgram.unbind(); - } - } - } - } - } - - gGL.color4f(1,1,1,1); - - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - gGL.setColorMask(true, false); - - - if (!hud_only && !mDebugBlips.empty()) - { //render debug blips - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } - - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep, true); - - glPointSize(8.f); - LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); - - gGL.begin(LLRender::POINTS); - for (std::list::iterator iter = mDebugBlips.begin(); iter != mDebugBlips.end(); ) - { - DebugBlip& blip = *iter; - - blip.mAge += gFrameIntervalSeconds.value(); - if (blip.mAge > 2.f) - { - mDebugBlips.erase(iter++); - } - else - { - iter++; - } - - blip.mPosition.mV[2] += gFrameIntervalSeconds.value()*2.f; - - gGL.color4fv(blip.mColor.mV); - gGL.vertex3fv(blip.mPosition.mV); - } - gGL.end(); - gGL.flush(); - glPointSize(1.f); - } - - - // Debug stuff. - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) - { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) - { - if ( (hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES)) || - (!hud_only && hasRenderType(part->mDrawableType)) ) - { - part->renderDebug(); - } - } - } - } - - for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) - { - LLSpatialBridge* bridge = *i; - if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) - { - gGL.pushMatrix(); - gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); - bridge->renderDebug(); - gGL.popMatrix(); - } - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION) && LLGLSLShader::sNoFixedFunction) - { //render visible selected group occlusion geometry - gDebugProgram.bind(); - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - gGL.diffuseColor3f(1,0,1); - for (std::set::iterator iter = visible_selected_groups.begin(); iter != visible_selected_groups.end(); ++iter) - { - LLSpatialGroup* group = *iter; - - LLVector4a fudge; - fudge.splat(0.25f); //SG_OCCLUSION_FUDGE - - LLVector4a size; - const LLVector4a* bounds = group->getBounds(); - size.setAdd(fudge, bounds[1]); - - drawBox(bounds[0], size); - } - } - - visible_selected_groups.clear(); - - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } - - if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST) && !hud_only) - { //draw crosshairs on particle intersection - if (gDebugRaycastParticle) - { - if (LLGLSLShader::sNoFixedFunction) - { //this debug display requires shaders - gDebugProgram.bind(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - LLVector3 center(gDebugRaycastParticleIntersection.getF32ptr()); - LLVector3 size(0.1f, 0.1f, 0.1f); - - LLVector3 p[6]; - - p[0] = center + size.scaledVec(LLVector3(1,0,0)); - p[1] = center + size.scaledVec(LLVector3(-1,0,0)); - p[2] = center + size.scaledVec(LLVector3(0,1,0)); - p[3] = center + size.scaledVec(LLVector3(0,-1,0)); - p[4] = center + size.scaledVec(LLVector3(0,0,1)); - p[5] = center + size.scaledVec(LLVector3(0,0,-1)); - - gGL.begin(LLRender::LINES); - gGL.diffuseColor3f(1.f, 1.f, 0.f); - for (U32 i = 0; i < 6; i++) - { - gGL.vertex3fv(p[i].mV); - } - gGL.end(); - gGL.flush(); - - gDebugProgram.unbind(); - } - } - } - - if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) - { - LLVertexBuffer::unbind(); - - LLGLEnable blend(GL_BLEND); - LLGLDepthTest depth(TRUE, FALSE); - LLGLDisable cull(GL_CULL_FACE); - - gGL.color4f(1,1,1,1); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - F32 a = 0.1f; - - F32 col[] = - { - 1,0,0,a, - 0,1,0,a, - 0,0,1,a, - 1,0,1,a, - - 1,1,0,a, - 0,1,1,a, - 1,1,1,a, - 1,0,1,a, - }; - - for (U32 i = 0; i < 8; i++) - { - LLVector3* frust = mShadowCamera[i].mAgentFrustum; - - if (i > 3) - { //render shadow frusta as volumes - if (mShadowFrustPoints[i-4].empty()) - { - continue; - } - - gGL.color4fv(col+(i-4)*4); - - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); - gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); - gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV); - gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV); - gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); - gGL.end(); - - - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.vertex3fv(frust[0].mV); - gGL.vertex3fv(frust[1].mV); - gGL.vertex3fv(frust[3].mV); - gGL.vertex3fv(frust[2].mV); - gGL.end(); - - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.vertex3fv(frust[4].mV); - gGL.vertex3fv(frust[5].mV); - gGL.vertex3fv(frust[7].mV); - gGL.vertex3fv(frust[6].mV); - gGL.end(); - } - - - if (i < 4) - { - - //if (i == 0 || !mShadowFrustPoints[i].empty()) - { - //render visible point cloud - gGL.flush(); - glPointSize(8.f); - gGL.begin(LLRender::POINTS); - - F32* c = col+i*4; - gGL.color3fv(c); - - for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j) - { - gGL.vertex3fv(mShadowFrustPoints[i][j].mV); - - } - gGL.end(); - - gGL.flush(); - glPointSize(1.f); - - LLVector3* ext = mShadowExtents[i]; - LLVector3 pos = (ext[0]+ext[1])*0.5f; - LLVector3 size = (ext[1]-ext[0])*0.5f; - drawBoxOutline(pos, size); - - //render camera frustum splits as outlines - gGL.begin(LLRender::LINES); - gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV); - gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV); - gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV); - gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV); - gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV); - gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV); - gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV); - gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV); - gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); - gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); - gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV); - gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV); - gGL.end(); - } - } - - /*gGL.flush(); - glLineWidth(16-i*2); - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++) - { - LLSpatialPartition* part = region->getSpatialPartition(j); - if (part) - { - if (hasRenderType(part->mDrawableType)) - { - part->renderIntersectingBBoxes(&mShadowCamera[i]); - } - } - } - } - gGL.flush(); - glLineWidth(1.f);*/ - } - } - - if (mRenderDebugMask & RENDER_DEBUG_WIND_VECTORS) - { - gAgent.getRegion()->mWind.renderVectors(); - } - - if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION) - { - // Debug composition layers - F32 x, y; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - if (gAgent.getRegion()) - { - gGL.begin(LLRender::POINTS); - // Draw the composition layer for the region that I'm in. - for (x = 0; x <= 260; x++) - { - for (y = 0; y <= 260; y++) - { - if ((x > 255) || (y > 255)) - { - gGL.color4f(1.f, 0.f, 0.f, 1.f); - } - else - { - gGL.color4f(0.f, 0.f, 1.f, 1.f); - } - F32 z = gAgent.getRegion()->getCompositionXY((S32)x, (S32)y); - z *= 5.f; - z += 50.f; - gGL.vertex3f(x, y, z); - } - } - gGL.end(); - } - } - - if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_BUILD_QUEUE) - { - U32 count = 0; - U32 size = mGroupQ2.size(); - LLColor4 col; - - LLVertexBuffer::unbind(); - LLGLEnable blend(GL_BLEND); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); - - gGL.pushMatrix(); - gGL.loadMatrix(gGLModelView); - gGLLastMatrix = NULL; - - for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin(); iter != mGroupQ2.end(); ++iter) - { - LLSpatialGroup* group = *iter; - if (group->isDead()) - { - continue; - } - - LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); - - if (bridge && (!bridge->mDrawable || bridge->mDrawable->isDead())) - { - continue; - } - - if (bridge) - { - gGL.pushMatrix(); - gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); - } - - F32 alpha = llclamp((F32) (size-count)/size, 0.f, 1.f); - - - LLVector2 c(1.f-alpha, alpha); - c.normVec(); - - - ++count; - col.set(c.mV[0], c.mV[1], 0, alpha*0.5f+0.5f); - group->drawObjectBox(col); - - if (bridge) - { - gGL.popMatrix(); - } - } - - gGL.popMatrix(); - } - - gGL.flush(); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.unbind(); - } -} - -static LLTrace::BlockTimerStatHandle FTM_REBUILD_POOLS("Rebuild Pools"); - -void LLPipeline::rebuildPools() -{ - LL_RECORD_BLOCK_TIME(FTM_REBUILD_POOLS); - - assertInitialized(); - - S32 max_count = mPools.size(); - pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool); - while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS) - { - if (iter1 == mPools.end()) - { - iter1 = mPools.begin(); - } - LLDrawPool* poolp = *iter1; - - if (poolp->isDead()) - { - mPools.erase(iter1++); - removeFromQuickLookup( poolp ); - if (poolp == mLastRebuildPool) - { - mLastRebuildPool = NULL; - } - delete poolp; - } - else - { - mLastRebuildPool = poolp; - iter1++; - } - max_count--; - } -} - -void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) -{ - assertInitialized(); - - switch( new_poolp->getType() ) - { - case LLDrawPool::POOL_SIMPLE: - if (mSimplePool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate simple pool." << LL_ENDL; - } - else - { - mSimplePool = (LLRenderPass*) new_poolp; - } - break; - - case LLDrawPool::POOL_ALPHA_MASK: - if (mAlphaMaskPool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate alpha mask pool." << LL_ENDL; - break; - } - else - { - mAlphaMaskPool = (LLRenderPass*) new_poolp; - } - break; - - case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: - if (mFullbrightAlphaMaskPool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate alpha mask pool." << LL_ENDL; - break; - } - else - { - mFullbrightAlphaMaskPool = (LLRenderPass*) new_poolp; - } - break; - - case LLDrawPool::POOL_GRASS: - if (mGrassPool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate grass pool." << LL_ENDL; - } - else - { - mGrassPool = (LLRenderPass*) new_poolp; - } - break; - - case LLDrawPool::POOL_FULLBRIGHT: - if (mFullbrightPool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate simple pool." << LL_ENDL; - } - else - { - mFullbrightPool = (LLRenderPass*) new_poolp; - } - break; - - case LLDrawPool::POOL_INVISIBLE: - if (mInvisiblePool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate simple pool." << LL_ENDL; - } - else - { - mInvisiblePool = (LLRenderPass*) new_poolp; - } - break; - - case LLDrawPool::POOL_GLOW: - if (mGlowPool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate glow pool." << LL_ENDL; - } - else - { - mGlowPool = (LLRenderPass*) new_poolp; - } - break; - - case LLDrawPool::POOL_TREE: - mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; - break; - - case LLDrawPool::POOL_TERRAIN: - mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; - break; - - case LLDrawPool::POOL_BUMP: - if (mBumpPool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate bump pool." << LL_ENDL; - } - else - { - mBumpPool = new_poolp; - } - break; - case LLDrawPool::POOL_MATERIALS: - if (mMaterialsPool) - { - llassert(0); - LL_WARNS() << "Ignorning duplicate materials pool." << LL_ENDL; - } - else - { - mMaterialsPool = new_poolp; - } - break; - case LLDrawPool::POOL_ALPHA: - if( mAlphaPool ) - { - llassert(0); - LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << LL_ENDL; - } - else - { - mAlphaPool = (LLDrawPoolAlpha*) new_poolp; - } - break; - - case LLDrawPool::POOL_AVATAR: - break; // Do nothing - - case LLDrawPool::POOL_SKY: - if( mSkyPool ) - { - llassert(0); - LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << LL_ENDL; - } - else - { - mSkyPool = new_poolp; - } - break; - - case LLDrawPool::POOL_WATER: - if( mWaterPool ) - { - llassert(0); - LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Water pool" << LL_ENDL; - } - else - { - mWaterPool = new_poolp; - } - break; - - case LLDrawPool::POOL_GROUND: - if( mGroundPool ) - { - llassert(0); - LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << LL_ENDL; - } - else - { - mGroundPool = new_poolp; - } - break; - - case LLDrawPool::POOL_WL_SKY: - if( mWLSkyPool ) - { - llassert(0); - LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate WLSky Pool" << LL_ENDL; - } - else - { - mWLSkyPool = new_poolp; - } - break; - - default: - llassert(0); - LL_WARNS() << "Invalid Pool Type in LLPipeline::addPool()" << LL_ENDL; - break; - } -} - -void LLPipeline::removePool( LLDrawPool* poolp ) -{ - assertInitialized(); - removeFromQuickLookup(poolp); - mPools.erase(poolp); - delete poolp; -} - -void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) -{ - assertInitialized(); - switch( poolp->getType() ) - { - case LLDrawPool::POOL_SIMPLE: - llassert(mSimplePool == poolp); - mSimplePool = NULL; - break; - - case LLDrawPool::POOL_ALPHA_MASK: - llassert(mAlphaMaskPool == poolp); - mAlphaMaskPool = NULL; - break; - - case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: - llassert(mFullbrightAlphaMaskPool == poolp); - mFullbrightAlphaMaskPool = NULL; - break; - - case LLDrawPool::POOL_GRASS: - llassert(mGrassPool == poolp); - mGrassPool = NULL; - break; - - case LLDrawPool::POOL_FULLBRIGHT: - llassert(mFullbrightPool == poolp); - mFullbrightPool = NULL; - break; - - case LLDrawPool::POOL_INVISIBLE: - llassert(mInvisiblePool == poolp); - mInvisiblePool = NULL; - break; - - case LLDrawPool::POOL_WL_SKY: - llassert(mWLSkyPool == poolp); - mWLSkyPool = NULL; - break; - - case LLDrawPool::POOL_GLOW: - llassert(mGlowPool == poolp); - mGlowPool = NULL; - break; - - case LLDrawPool::POOL_TREE: - #ifdef _DEBUG - { - bool found = mTreePools.erase( (uintptr_t)poolp->getTexture() ); - llassert( found ); - } - #else - mTreePools.erase( (uintptr_t)poolp->getTexture() ); - #endif - break; - - case LLDrawPool::POOL_TERRAIN: - #ifdef _DEBUG - { - bool found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() ); - llassert( found ); - } - #else - mTerrainPools.erase( (uintptr_t)poolp->getTexture() ); - #endif - break; - - case LLDrawPool::POOL_BUMP: - llassert( poolp == mBumpPool ); - mBumpPool = NULL; - break; - - case LLDrawPool::POOL_MATERIALS: - llassert(poolp == mMaterialsPool); - mMaterialsPool = NULL; - break; - - case LLDrawPool::POOL_ALPHA: - llassert( poolp == mAlphaPool ); - mAlphaPool = NULL; - break; - - case LLDrawPool::POOL_AVATAR: - break; // Do nothing - - case LLDrawPool::POOL_SKY: - llassert( poolp == mSkyPool ); - mSkyPool = NULL; - break; - - case LLDrawPool::POOL_WATER: - llassert( poolp == mWaterPool ); - mWaterPool = NULL; - break; - - case LLDrawPool::POOL_GROUND: - llassert( poolp == mGroundPool ); - mGroundPool = NULL; - break; - - default: - llassert(0); - LL_WARNS() << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << LL_ENDL; - break; - } -} - -void LLPipeline::resetDrawOrders() -{ - assertInitialized(); - // Iterate through all of the draw pools and rebuild them. - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - poolp->resetDrawOrders(); - } -} - -//============================================================================ -// Once-per-frame setup of hardware lights, -// including sun/moon, avatar backlight, and up to 6 local lights - -void LLPipeline::setupAvatarLights(bool for_edit) -{ - assertInitialized(); - - LLEnvironment& environment = LLEnvironment::instance(); - LLSettingsSky::ptr_t psky = environment.getCurrentSky(); - - bool sun_up = environment.getIsSunUp(); - - if (for_edit) - { - LLColor4 diffuse(1.f, 1.f, 1.f, 0.f); - LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f); // w==0 => directional light - LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview(); - LLMatrix4 camera_rot(camera_mat.getMat3()); - camera_rot.invert(); - LLVector4 light_pos = light_pos_cam * camera_rot; - - light_pos.normalize(); - - LLLightState* light = gGL.getLight(1); - - if (LLPipeline::sRenderDeferred) - { - /*diffuse.mV[0] = powf(diffuse.mV[0], 2.2f); - diffuse.mV[1] = powf(diffuse.mV[1], 2.2f); - diffuse.mV[2] = powf(diffuse.mV[2], 2.2f);*/ - } - - mHWLightColors[1] = diffuse; - - light->setDiffuse(diffuse); - light->setAmbient(LLColor4::black); - light->setSpecular(LLColor4::black); - light->setPosition(light_pos); - light->setConstantAttenuation(1.f); - light->setLinearAttenuation(0.f); - light->setQuadraticAttenuation(0.f); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); - } - else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini) - { - LLVector3 light_dir = sun_up ? LLVector3(mSunDir) : LLVector3(mMoonDir); - LLVector3 opposite_pos = -light_dir; - LLVector3 orthog_light_pos = light_dir % LLVector3::z_axis; - LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f); - backlight_pos.normalize(); - - LLColor4 light_diffuse = sun_up ? mSunDiffuse : mMoonDiffuse; - - LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f); - F32 max_component = 0.001f; - for (S32 i = 0; i < 3; i++) - { - if (backlight_diffuse.mV[i] > max_component) - { - max_component = backlight_diffuse.mV[i]; - } - } - F32 backlight_mag; - if (LLEnvironment::instance().getIsSunUp()) - { - backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT; - } - else - { - backlight_mag = BACKLIGHT_NIGHT_MAGNITUDE_OBJECT; - } - backlight_diffuse *= backlight_mag / max_component; - - if (LLPipeline::sRenderDeferred) - { - /*backlight_diffuse.mV[0] = powf(backlight_diffuse.mV[0], 2.2f); - backlight_diffuse.mV[1] = powf(backlight_diffuse.mV[1], 2.2f); - backlight_diffuse.mV[2] = powf(backlight_diffuse.mV[2], 2.2f);*/ - } - - mHWLightColors[1] = backlight_diffuse; - - LLLightState* light = gGL.getLight(1); - - light->setPosition(backlight_pos); - light->setDiffuse(backlight_diffuse); - light->setAmbient(LLColor4::black); - light->setSpecular(LLColor4::black); - light->setConstantAttenuation(1.f); - light->setLinearAttenuation(0.f); - light->setQuadraticAttenuation(0.f); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); - } - else - { - LLLightState* light = gGL.getLight(1); - - mHWLightColors[1] = LLColor4::black; - - light->setDiffuse(LLColor4::black); - light->setAmbient(LLColor4::black); - light->setSpecular(LLColor4::black); - } -} - -static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist) -{ - F32 inten = light->getLightIntensity(); - if (inten < .001f) - { - return max_dist; - } - F32 radius = light->getLightRadius(); - bool selected = light->isSelected(); - LLVector3 dpos = light->getRenderPosition() - cam_pos; - F32 dist2 = dpos.lengthSquared(); - if (!selected && dist2 > (max_dist + radius)*(max_dist + radius)) - { - return max_dist; - } - F32 dist = (F32) sqrt(dist2); - dist *= 1.f / inten; - dist -= radius; - if (selected) - { - dist -= 10000.f; // selected lights get highest priority - } - if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE)) - { - // moving lights get a little higher priority (too much causes artifacts) - dist -= light->getLightRadius()*0.25f; - } - return dist; -} - -void LLPipeline::calcNearbyLights(LLCamera& camera) -{ - assertInitialized(); - - if (LLPipeline::sReflectionRender) - { - return; - } - - if (mLightingDetail >= 1) - { - // mNearbyLight (and all light_set_t's) are sorted such that - // begin() == the closest light and rbegin() == the farthest light - const S32 MAX_LOCAL_LIGHTS = 6; -// LLVector3 cam_pos = gAgent.getCameraPositionAgent(); - LLVector3 cam_pos = LLViewerJoystick::getInstance()->getOverrideCamera() ? - camera.getOrigin() : - gAgent.getPositionAgent(); - - F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad - - // UPDATE THE EXISTING NEARBY LIGHTS - light_set_t cur_nearby_lights; - for (light_set_t::iterator iter = mNearbyLights.begin(); - iter != mNearbyLights.end(); iter++) - { - const Light* light = &(*iter); - LLDrawable* drawable = light->drawable; - const LLViewerObject *vobj = light->drawable->getVObj(); - if(vobj && vobj->getAvatar() - && (vobj->getAvatar()->isTooComplex() || vobj->getAvatar()->isInMuteList()) - ) - { - drawable->clearState(LLDrawable::NEARBY_LIGHT); - continue; - } - - LLVOVolume* volight = drawable->getVOVolume(); - if (!volight || !drawable->isState(LLDrawable::LIGHT)) - { - drawable->clearState(LLDrawable::NEARBY_LIGHT); - continue; - } - if (light->fade <= -LIGHT_FADE_TIME) - { - drawable->clearState(LLDrawable::NEARBY_LIGHT); - continue; - } - if (!sRenderAttachedLights && volight && volight->isAttachment()) - { - drawable->clearState(LLDrawable::NEARBY_LIGHT); - continue; - } - - F32 dist = calc_light_dist(volight, cam_pos, max_dist); - cur_nearby_lights.insert(Light(drawable, dist, light->fade)); - } - mNearbyLights = cur_nearby_lights; - - // FIND NEW LIGHTS THAT ARE IN RANGE - light_set_t new_nearby_lights; - for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); - iter != mLights.end(); ++iter) - { - LLDrawable* drawable = *iter; - LLVOVolume* light = drawable->getVOVolume(); - if (!light || drawable->isState(LLDrawable::NEARBY_LIGHT)) - { - continue; - } - if (light->isHUDAttachment()) - { - continue; // no lighting from HUD objects - } - F32 dist = calc_light_dist(light, cam_pos, max_dist); - if (dist >= max_dist) - { - continue; - } - if (!sRenderAttachedLights && light && light->isAttachment()) - { - continue; - } - new_nearby_lights.insert(Light(drawable, dist, 0.f)); - if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS) - { - new_nearby_lights.erase(--new_nearby_lights.end()); - const Light& last = *new_nearby_lights.rbegin(); - max_dist = last.dist; - } - } - - // INSERT ANY NEW LIGHTS - for (light_set_t::iterator iter = new_nearby_lights.begin(); - iter != new_nearby_lights.end(); iter++) - { - const Light* light = &(*iter); - if (mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS) - { - mNearbyLights.insert(*light); - ((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT); - } - else - { - // crazy cast so that we can overwrite the fade value - // even though gcc enforces sets as const - // (fade value doesn't affect sort so this is safe) - Light* farthest_light = (const_cast(&(*(mNearbyLights.rbegin())))); - if (light->dist < farthest_light->dist) - { - if (farthest_light->fade >= 0.f) - { - farthest_light->fade = -(gFrameIntervalSeconds.value()); - } - } - else - { - break; // none of the other lights are closer - } - } - } - - //mark nearby lights not-removable. - for (light_set_t::iterator iter = mNearbyLights.begin(); - iter != mNearbyLights.end(); iter++) - { - const Light* light = &(*iter); - ((LLViewerOctreeEntryData*) light->drawable)->setVisible(); - } - } -} - -void LLPipeline::setupHWLights(LLDrawPool* pool) -{ - assertInitialized(); - - LLEnvironment& environment = LLEnvironment::instance(); - LLSettingsSky::ptr_t psky = environment.getCurrentSky(); - - // Ambient - if (!LLGLSLShader::sNoFixedFunction) - { - gGL.syncMatrices(); - LLColor4 ambient = psky->getTotalAmbient(); - gGL.setAmbientLightColor(ambient); - } - - bool sun_up = environment.getIsSunUp(); - - // Light 0 = Sun or Moon (All objects) - { - LLVector4 sun_dir(environment.getSunDirection(), 0.0f); - LLVector4 moon_dir(environment.getMoonDirection(), 0.0f); - - mSunDir.setVec(sun_dir); - mMoonDir.setVec(moon_dir); - mSunDiffuse.setVec(psky->getSunDiffuse()); - mMoonDiffuse.setVec(psky->getMoonDiffuse()); - - F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]); - if (max_color > 1.f) - { - mSunDiffuse *= 1.f/max_color; - } - mSunDiffuse.clamp(); - - max_color = llmax(mMoonDiffuse.mV[0], mMoonDiffuse.mV[1], mMoonDiffuse.mV[2]); - if (max_color > 1.f) - { - mMoonDiffuse *= 1.f/max_color; - } - mMoonDiffuse.clamp(); - - LLVector4 light_dir = sun_up ? mSunDir : mMoonDir; - - mHWLightColors[0] = mSunDiffuse; - - LLLightState* light = gGL.getLight(0); - light->setPosition(light_dir); - - light->setDiffuse(mSunDiffuse); - light->setDiffuseB(mMoonDiffuse); - light->setAmbient(LLColor4::black); - light->setSpecular(LLColor4::black); - light->setConstantAttenuation(1.f); - light->setLinearAttenuation(0.f); - light->setQuadraticAttenuation(0.f); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); - } - - // Light 1 = Backlight (for avatars) - // (set by enableLightsAvatar) - - S32 cur_light = 2; - - // Nearby lights = LIGHT 2-7 - - mLightMovingMask = 0; - - if (mLightingDetail >= 1) - { - for (light_set_t::iterator iter = mNearbyLights.begin(); - iter != mNearbyLights.end(); ++iter) - { - LLDrawable* drawable = iter->drawable; - LLVOVolume* light = drawable->getVOVolume(); - if (!light) - { - continue; - } - if (drawable->isState(LLDrawable::ACTIVE)) - { - mLightMovingMask |= (1<getLightColor(); - light_color.mV[3] = 0.0f; - - F32 fade = iter->fade; - if (fade < LIGHT_FADE_TIME) - { - // fade in/out light - if (fade >= 0.f) - { - fade = fade / LIGHT_FADE_TIME; - ((Light*) (&(*iter)))->fade += gFrameIntervalSeconds.value(); - } - else - { - fade = 1.f + fade / LIGHT_FADE_TIME; - ((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds.value(); - } - fade = llclamp(fade,0.f,1.f); - light_color *= fade; - } - - LLVector3 light_pos(light->getRenderPosition()); - LLVector4 light_pos_gl(light_pos, 1.0f); - - F32 light_radius = llmax(light->getLightRadius(), 0.001f); - - F32 x = (3.f * (1.f + light->getLightFalloff())); // why this magic? probably trying to match a historic behavior. - float linatten = x / (light_radius); // % of brightness at radius - - mHWLightColors[cur_light] = light_color; - LLLightState* light_state = gGL.getLight(cur_light); - - light_state->setPosition(light_pos_gl); - light_state->setDiffuse(light_color); - light_state->setAmbient(LLColor4::black); - light_state->setConstantAttenuation(0.f); - if (sRenderDeferred) - { - F32 size = light_radius*1.5f; - light_state->setLinearAttenuation(size); - light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f); - } - else - { - light_state->setLinearAttenuation(linatten); - light_state->setQuadraticAttenuation(0.f); - } - - - if (light->isLightSpotlight() // directional (spot-)light - && (LLPipeline::sRenderDeferred || RenderSpotLightsInNondeferred)) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on - { - LLQuaternion quat = light->getRenderRotation(); - LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction - at_axis *= quat; - - light_state->setSpotDirection(at_axis); - light_state->setSpotCutoff(90.f); - light_state->setSpotExponent(2.f); - - LLVector3 spotParams = light->getSpotLightParams(); - - const LLColor4 specular(0.f, 0.f, 0.f, spotParams[2]); - light_state->setSpecular(specular); - } - else // omnidirectional (point) light - { - light_state->setSpotExponent(0.f); - light_state->setSpotCutoff(180.f); - - // we use specular.w = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight - const LLColor4 specular(0.f, 0.f, 1.f, 0.f); - light_state->setSpecular(specular); - } - cur_light++; - if (cur_light >= 8) - { - break; // safety - } - } - } - for ( ; cur_light < 8 ; cur_light++) - { - mHWLightColors[cur_light] = LLColor4::black; - LLLightState* light = gGL.getLight(cur_light); - - light->setDiffuse(LLColor4::black); - light->setAmbient(LLColor4::black); - light->setSpecular(LLColor4::black); - } - if (gAgentAvatarp && - gAgentAvatarp->mSpecialRenderMode == 3) - { - LLColor4 light_color = LLColor4::white; - light_color.mV[3] = 0.0f; - - LLVector3 light_pos(LLViewerCamera::getInstance()->getOrigin()); - LLVector4 light_pos_gl(light_pos, 1.0f); - - F32 light_radius = 16.f; - - F32 x = 3.f; - float linatten = x / (light_radius); // % of brightness at radius - - if (LLPipeline::sRenderDeferred) - { - /*light_color.mV[0] = powf(light_color.mV[0], 2.2f); - light_color.mV[1] = powf(light_color.mV[1], 2.2f); - light_color.mV[2] = powf(light_color.mV[2], 2.2f);*/ - } - - mHWLightColors[2] = light_color; - LLLightState* light = gGL.getLight(2); - - light->setPosition(light_pos_gl); - light->setDiffuse(light_color); - light->setAmbient(LLColor4::black); - light->setSpecular(LLColor4::black); - light->setQuadraticAttenuation(0.f); - light->setConstantAttenuation(0.f); - light->setLinearAttenuation(linatten); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); - } - - // Init GL state - if (!LLGLSLShader::sNoFixedFunction) - { - glDisable(GL_LIGHTING); - } - - for (S32 i = 0; i < 8; ++i) - { - gGL.getLight(i)->disable(); - } - mLightMask = 0; -} - -void LLPipeline::enableLights(U32 mask) -{ - assertInitialized(); - - if (mLightingDetail == 0) - { - mask &= 0xf003; // sun and backlight only (and fullbright bit) - } - if (mLightMask != mask) - { - stop_glerror(); - if (!mLightMask) - { - if (!LLGLSLShader::sNoFixedFunction) - { - glEnable(GL_LIGHTING); - } - } - if (mask) - { - stop_glerror(); - for (S32 i=0; i<8; i++) - { - LLLightState* light = gGL.getLight(i); - if (mask & (1<enable(); - light->setDiffuse(mHWLightColors[i]); - } - else - { - light->disable(); - light->setDiffuse(LLColor4::black); - } - } - stop_glerror(); - } - else - { - if (!LLGLSLShader::sNoFixedFunction) - { - glDisable(GL_LIGHTING); - } - } - mLightMask = mask; - stop_glerror(); - - LLColor4 ambient = LLEnvironment::instance().getCurrentSky()->getTotalAmbient(); - gGL.setAmbientLightColor(ambient); - } -} - -void LLPipeline::enableLightsStatic() -{ - assertInitialized(); - U32 mask = 0x01; // Sun - if (mLightingDetail >= 2) - { - mask |= mLightMovingMask; // Hardware moving lights - } - else - { - mask |= 0xff & (~2); // Hardware local lights - } - enableLights(mask); -} - -void LLPipeline::enableLightsDynamic() -{ - assertInitialized(); - U32 mask = 0xff & (~2); // Local lights - enableLights(mask); - - if (isAgentAvatarValid() && getLightingDetail() <= 0) - { - if (gAgentAvatarp->mSpecialRenderMode == 0) // normal - { - gPipeline.enableLightsAvatar(); - } - else if (gAgentAvatarp->mSpecialRenderMode >= 1) // anim preview - { - gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f)); - } - } -} - -void LLPipeline::enableLightsAvatar() -{ - U32 mask = 0xff; // All lights - setupAvatarLights(FALSE); - enableLights(mask); -} - -void LLPipeline::enableLightsPreview() -{ - disableLights(); - - if (!LLGLSLShader::sNoFixedFunction) - { - glEnable(GL_LIGHTING); - } - - LLColor4 ambient = PreviewAmbientColor; - gGL.setAmbientLightColor(ambient); - - LLColor4 diffuse0 = PreviewDiffuse0; - LLColor4 specular0 = PreviewSpecular0; - LLColor4 diffuse1 = PreviewDiffuse1; - LLColor4 specular1 = PreviewSpecular1; - LLColor4 diffuse2 = PreviewDiffuse2; - LLColor4 specular2 = PreviewSpecular2; - - LLVector3 dir0 = PreviewDirection0; - LLVector3 dir1 = PreviewDirection1; - LLVector3 dir2 = PreviewDirection2; - - dir0.normVec(); - dir1.normVec(); - dir2.normVec(); - - LLVector4 light_pos(dir0, 0.0f); - - LLLightState* light = gGL.getLight(1); - - light->enable(); - light->setPosition(light_pos); - light->setDiffuse(diffuse0); - light->setAmbient(LLColor4::black); - light->setSpecular(specular0); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); - - light_pos = LLVector4(dir1, 0.f); - - light = gGL.getLight(2); - light->enable(); - light->setPosition(light_pos); - light->setDiffuse(diffuse1); - light->setAmbient(LLColor4::black); - light->setSpecular(specular1); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); - - light_pos = LLVector4(dir2, 0.f); - light = gGL.getLight(3); - light->enable(); - light->setPosition(light_pos); - light->setDiffuse(diffuse2); - light->setAmbient(LLColor4::black); - light->setSpecular(specular2); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); -} - - -void LLPipeline::enableLightsAvatarEdit(const LLColor4& color) -{ - U32 mask = 0x2002; // Avatar backlight only, set ambient - setupAvatarLights(TRUE); - enableLights(mask); - - gGL.setAmbientLightColor(color); -} - -void LLPipeline::enableLightsFullbright(const LLColor4& color) -{ - assertInitialized(); - U32 mask = 0x1000; // Non-0 mask, set ambient - enableLights(mask); - - gGL.setAmbientLightColor(color); -} - -void LLPipeline::disableLights() -{ - enableLights(0); // no lighting (full bright) -} - -//============================================================================ - -class LLMenuItemGL; -class LLInvFVBridge; -struct cat_folder_pair; -class LLVOBranch; -class LLVOLeaf; - -void LLPipeline::findReferences(LLDrawable *drawablep) -{ - assertInitialized(); - if (mLights.find(drawablep) != mLights.end()) - { - LL_INFOS() << "In mLights" << LL_ENDL; - } - if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end()) - { - LL_INFOS() << "In mMovedList" << LL_ENDL; - } - if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end()) - { - LL_INFOS() << "In mShiftList" << LL_ENDL; - } - if (mRetexturedList.find(drawablep) != mRetexturedList.end()) - { - LL_INFOS() << "In mRetexturedList" << LL_ENDL; - } - - if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end()) - { - LL_INFOS() << "In mBuildQ1" << LL_ENDL; - } - if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end()) - { - LL_INFOS() << "In mBuildQ2" << LL_ENDL; - } - - S32 count; - - count = gObjectList.findReferences(drawablep); - if (count) - { - LL_INFOS() << "In other drawables: " << count << " references" << LL_ENDL; - } -} - -bool LLPipeline::verify() -{ - bool ok = assertInitialized(); - if (ok) - { - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - if (!poolp->verify()) - { - ok = false; - } - } - } - - if (!ok) - { - LL_WARNS() << "Pipeline verify failed!" << LL_ENDL; - } - return ok; -} - -////////////////////////////// -// -// Collision detection -// -// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * A method to compute a ray-AABB intersection. - * Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990 - * Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500) - * Epsilon value added by Klaus Hartmann. (discarding it saves a few cycles only) - * - * Hence this version is faster as well as more robust than the original one. - * - * Should work provided: - * 1) the integer representation of 0.0f is 0x00000000 - * 2) the sign bit of the float is the most significant one - * - * Report bugs: p.terdiman@codercorner.com - * - * \param aabb [in] the axis-aligned bounding box - * \param origin [in] ray origin - * \param dir [in] ray direction - * \param coord [out] impact coordinates - * \return true if ray intersects AABB - */ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//#define RAYAABB_EPSILON 0.00001f -#define IR(x) ((U32&)x) - -bool LLRayAABB(const LLVector3 ¢er, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon) -{ - bool Inside = true; - LLVector3 MinB = center - size; - LLVector3 MaxB = center + size; - LLVector3 MaxT; - MaxT.mV[VX]=MaxT.mV[VY]=MaxT.mV[VZ]=-1.0f; - - // Find candidate planes. - for(U32 i=0;i<3;i++) - { - if(origin.mV[i] < MinB.mV[i]) - { - coord.mV[i] = MinB.mV[i]; - Inside = false; - - // Calculate T distances to candidate planes - if(IR(dir.mV[i])) MaxT.mV[i] = (MinB.mV[i] - origin.mV[i]) / dir.mV[i]; - } - else if(origin.mV[i] > MaxB.mV[i]) - { - coord.mV[i] = MaxB.mV[i]; - Inside = false; - - // Calculate T distances to candidate planes - if(IR(dir.mV[i])) MaxT.mV[i] = (MaxB.mV[i] - origin.mV[i]) / dir.mV[i]; - } - } - - // Ray origin inside bounding box - if(Inside) - { - coord = origin; - return true; - } - - // Get largest of the maxT's for final choice of intersection - U32 WhichPlane = 0; - if(MaxT.mV[1] > MaxT.mV[WhichPlane]) WhichPlane = 1; - if(MaxT.mV[2] > MaxT.mV[WhichPlane]) WhichPlane = 2; - - // Check final candidate actually inside box - if(IR(MaxT.mV[WhichPlane])&0x80000000) return false; - - for(U32 i=0;i<3;i++) - { - if(i!=WhichPlane) - { - coord.mV[i] = origin.mV[i] + MaxT.mV[WhichPlane] * dir.mV[i]; - if (epsilon > 0) - { - if(coord.mV[i] < MinB.mV[i] - epsilon || coord.mV[i] > MaxB.mV[i] + epsilon) return false; - } - else - { - if(coord.mV[i] < MinB.mV[i] || coord.mV[i] > MaxB.mV[i]) return false; - } - } - } - return true; // ray hits box -} - -////////////////////////////// -// -// Macros, functions, and inline methods from other classes -// -// - -void LLPipeline::setLight(LLDrawable *drawablep, bool is_light) -{ - if (drawablep && assertInitialized()) - { - if (is_light) - { - mLights.insert(drawablep); - drawablep->setState(LLDrawable::LIGHT); - } - else - { - drawablep->clearState(LLDrawable::LIGHT); - mLights.erase(drawablep); - } - } -} - -//static -void LLPipeline::toggleRenderType(U32 type) -{ - gPipeline.mRenderTypeEnabled[type] = !gPipeline.mRenderTypeEnabled[type]; - if (type == LLPipeline::RENDER_TYPE_WATER) - { - gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER] = !gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER]; - } -} - -//static -void LLPipeline::toggleRenderTypeControl(U32 type) -{ - U32 bit = (1< 1.f) + { + mMoonDiffuse *= 1.f/max_color; + } + mMoonDiffuse.clamp(); -// static -void LLPipeline::setRenderMOAPBeacons(bool val) -{ - sRenderMOAPBeacons = val; -} + LLVector4 light_dir = sun_up ? mSunDir : mMoonDir; -// static -void LLPipeline::toggleRenderMOAPBeacons() -{ - sRenderMOAPBeacons = !sRenderMOAPBeacons; -} + mHWLightColors[0] = mSunDiffuse; -// static -bool LLPipeline::getRenderMOAPBeacons() -{ - return sRenderMOAPBeacons; -} + LLLightState* light = gGL.getLight(0); + light->setPosition(light_dir); -// static -void LLPipeline::setRenderPhysicalBeacons(bool val) -{ - sRenderPhysicalBeacons = val; -} + light->setDiffuse(mSunDiffuse); + light->setDiffuseB(mMoonDiffuse); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); + light->setConstantAttenuation(1.f); + light->setLinearAttenuation(0.f); + light->setQuadraticAttenuation(0.f); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); + } + + // Light 1 = Backlight (for avatars) + // (set by enableLightsAvatar) + + S32 cur_light = 2; + + // Nearby lights = LIGHT 2-7 + + mLightMovingMask = 0; + + if (mLightingDetail >= 1) + { + for (light_set_t::iterator iter = mNearbyLights.begin(); + iter != mNearbyLights.end(); ++iter) + { + LLDrawable* drawable = iter->drawable; + LLVOVolume* light = drawable->getVOVolume(); + if (!light) + { + continue; + } + if (drawable->isState(LLDrawable::ACTIVE)) + { + mLightMovingMask |= (1<getLightColor(); + light_color.mV[3] = 0.0f; + + F32 fade = iter->fade; + if (fade < LIGHT_FADE_TIME) + { + // fade in/out light + if (fade >= 0.f) + { + fade = fade / LIGHT_FADE_TIME; + ((Light*) (&(*iter)))->fade += gFrameIntervalSeconds.value(); + } + else + { + fade = 1.f + fade / LIGHT_FADE_TIME; + ((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds.value(); + } + fade = llclamp(fade,0.f,1.f); + light_color *= fade; + } + + LLVector3 light_pos(light->getRenderPosition()); + LLVector4 light_pos_gl(light_pos, 1.0f); + + F32 light_radius = llmax(light->getLightRadius(), 0.001f); + + F32 x = (3.f * (1.f + light->getLightFalloff())); // why this magic? probably trying to match a historic behavior. + float linatten = x / (light_radius); // % of brightness at radius + + mHWLightColors[cur_light] = light_color; + LLLightState* light_state = gGL.getLight(cur_light); + + light_state->setPosition(light_pos_gl); + light_state->setDiffuse(light_color); + light_state->setAmbient(LLColor4::black); + light_state->setConstantAttenuation(0.f); + if (sRenderDeferred) + { + F32 size = light_radius*1.5f; + light_state->setLinearAttenuation(size); + light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f); + } + else + { + light_state->setLinearAttenuation(linatten); + light_state->setQuadraticAttenuation(0.f); + } + + + if (light->isLightSpotlight() // directional (spot-)light + && (LLPipeline::sRenderDeferred || RenderSpotLightsInNondeferred)) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on + { + LLQuaternion quat = light->getRenderRotation(); + LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction + at_axis *= quat; + + light_state->setSpotDirection(at_axis); + light_state->setSpotCutoff(90.f); + light_state->setSpotExponent(2.f); + + LLVector3 spotParams = light->getSpotLightParams(); -// static -void LLPipeline::toggleRenderPhysicalBeacons() -{ - sRenderPhysicalBeacons = !sRenderPhysicalBeacons; -} + const LLColor4 specular(0.f, 0.f, 0.f, spotParams[2]); + light_state->setSpecular(specular); + } + else // omnidirectional (point) light + { + light_state->setSpotExponent(0.f); + light_state->setSpotCutoff(180.f); + + // we use specular.w = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight + const LLColor4 specular(0.f, 0.f, 1.f, 0.f); + light_state->setSpecular(specular); + } + cur_light++; + if (cur_light >= 8) + { + break; // safety + } + } + } + for ( ; cur_light < 8 ; cur_light++) + { + mHWLightColors[cur_light] = LLColor4::black; + LLLightState* light = gGL.getLight(cur_light); -// static -bool LLPipeline::getRenderPhysicalBeacons() -{ - return sRenderPhysicalBeacons; -} + light->setDiffuse(LLColor4::black); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); + } + if (gAgentAvatarp && + gAgentAvatarp->mSpecialRenderMode == 3) + { + LLColor4 light_color = LLColor4::white; + light_color.mV[3] = 0.0f; + + LLVector3 light_pos(LLViewerCamera::getInstance()->getOrigin()); + LLVector4 light_pos_gl(light_pos, 1.0f); + + F32 light_radius = 16.f; + + F32 x = 3.f; + float linatten = x / (light_radius); // % of brightness at radius + + if (LLPipeline::sRenderDeferred) + { + /*light_color.mV[0] = powf(light_color.mV[0], 2.2f); + light_color.mV[1] = powf(light_color.mV[1], 2.2f); + light_color.mV[2] = powf(light_color.mV[2], 2.2f);*/ + } + + mHWLightColors[2] = light_color; + LLLightState* light = gGL.getLight(2); + + light->setPosition(light_pos_gl); + light->setDiffuse(light_color); + light->setDiffuseB(light_color * 0.25f); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); + light->setQuadraticAttenuation(0.f); + light->setConstantAttenuation(0.f); + light->setLinearAttenuation(linatten); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); + } -// static -void LLPipeline::setRenderParticleBeacons(bool val) -{ - sRenderParticleBeacons = val; -} + // Init GL state + if (!LLGLSLShader::sNoFixedFunction) + { + glDisable(GL_LIGHTING); + } -// static -void LLPipeline::toggleRenderParticleBeacons() -{ - sRenderParticleBeacons = !sRenderParticleBeacons; + for (S32 i = 0; i < 8; ++i) + { + gGL.getLight(i)->disable(); + } + mLightMask = 0; } -// static -bool LLPipeline::getRenderParticleBeacons() +void LLPipeline::enableLights(U32 mask) { - return sRenderParticleBeacons; -} + assertInitialized(); -// static -void LLPipeline::setRenderSoundBeacons(bool val) -{ - sRenderSoundBeacons = val; + if (mLightingDetail == 0) + { + mask &= 0xf003; // sun and backlight only (and fullbright bit) + } + if (mLightMask != mask) + { + stop_glerror(); + if (!mLightMask) + { + if (!LLGLSLShader::sNoFixedFunction) + { + glEnable(GL_LIGHTING); + } + } + if (mask) + { + stop_glerror(); + for (S32 i=0; i<8; i++) + { + LLLightState* light = gGL.getLight(i); + if (mask & (1<enable(); + light->setDiffuse(mHWLightColors[i]); + } + else + { + light->disable(); + light->setDiffuse(LLColor4::black); + } + } + stop_glerror(); + } + else + { + if (!LLGLSLShader::sNoFixedFunction) + { + glDisable(GL_LIGHTING); + } + } + mLightMask = mask; + stop_glerror(); + + LLColor4 ambient = LLEnvironment::instance().getCurrentSky()->getTotalAmbient(); + gGL.setAmbientLightColor(ambient); + } } -// static -void LLPipeline::toggleRenderSoundBeacons() +void LLPipeline::enableLightsStatic() { - sRenderSoundBeacons = !sRenderSoundBeacons; + assertInitialized(); + U32 mask = 0x01; // Sun + if (mLightingDetail >= 2) + { + mask |= mLightMovingMask; // Hardware moving lights + } + else + { + mask |= 0xff & (~2); // Hardware local lights + } + enableLights(mask); } -// static -bool LLPipeline::getRenderSoundBeacons() +void LLPipeline::enableLightsDynamic() { - return sRenderSoundBeacons; + assertInitialized(); + U32 mask = 0xff & (~2); // Local lights + enableLights(mask); + + if (isAgentAvatarValid() && getLightingDetail() <= 0) + { + if (gAgentAvatarp->mSpecialRenderMode == 0) // normal + { + gPipeline.enableLightsAvatar(); + } + else if (gAgentAvatarp->mSpecialRenderMode >= 1) // anim preview + { + gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f)); + } + } } -// static -void LLPipeline::setRenderBeacons(bool val) +void LLPipeline::enableLightsAvatar() { - sRenderBeacons = val; + U32 mask = 0xff; // All lights + setupAvatarLights(FALSE); + enableLights(mask); } -// static -void LLPipeline::toggleRenderBeacons() +void LLPipeline::enableLightsPreview() { - sRenderBeacons = !sRenderBeacons; -} + disableLights(); -// static -bool LLPipeline::getRenderBeacons() -{ - return sRenderBeacons; -} + if (!LLGLSLShader::sNoFixedFunction) + { + glEnable(GL_LIGHTING); + } -// static -void LLPipeline::setRenderHighlights(bool val) -{ - sRenderHighlight = val; + LLColor4 ambient = PreviewAmbientColor; + gGL.setAmbientLightColor(ambient); + + LLColor4 diffuse0 = PreviewDiffuse0; + LLColor4 specular0 = PreviewSpecular0; + LLColor4 diffuse1 = PreviewDiffuse1; + LLColor4 specular1 = PreviewSpecular1; + LLColor4 diffuse2 = PreviewDiffuse2; + LLColor4 specular2 = PreviewSpecular2; + + LLVector3 dir0 = PreviewDirection0; + LLVector3 dir1 = PreviewDirection1; + LLVector3 dir2 = PreviewDirection2; + + dir0.normVec(); + dir1.normVec(); + dir2.normVec(); + + LLVector4 light_pos(dir0, 0.0f); + + LLLightState* light = gGL.getLight(1); + + light->enable(); + light->setPosition(light_pos); + light->setDiffuse(diffuse0); + light->setAmbient(LLColor4::black); + light->setSpecular(specular0); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); + + light_pos = LLVector4(dir1, 0.f); + + light = gGL.getLight(2); + light->enable(); + light->setPosition(light_pos); + light->setDiffuse(diffuse1); + light->setAmbient(LLColor4::black); + light->setSpecular(specular1); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); + + light_pos = LLVector4(dir2, 0.f); + light = gGL.getLight(3); + light->enable(); + light->setPosition(light_pos); + light->setDiffuse(diffuse2); + light->setAmbient(LLColor4::black); + light->setSpecular(specular2); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); } -// static -void LLPipeline::toggleRenderHighlights() -{ - sRenderHighlight = !sRenderHighlight; -} -// static -bool LLPipeline::getRenderHighlights() +void LLPipeline::enableLightsAvatarEdit(const LLColor4& color) { - return sRenderHighlight; -} + U32 mask = 0x2002; // Avatar backlight only, set ambient + setupAvatarLights(TRUE); + enableLights(mask); -// static -void LLPipeline::setRenderHighlightTextureChannel(LLRender::eTexIndex channel) -{ - sRenderHighlightTextureChannel = channel; + gGL.setAmbientLightColor(color); } -LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection, - S32* face_hit) +void LLPipeline::enableLightsFullbright(const LLColor4& color) { - LLVector4a local_end = end; - - LLVector4a position; - - LLDrawable* drawable = NULL; - - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - - LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_PARTICLE); - if (part && hasRenderType(part->mDrawableType)) - { - LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, FALSE, face_hit, &position, NULL, NULL, NULL); - if (hit) - { - drawable = hit; - local_end = position; - } - } - } - - LLVOPartGroup* ret = NULL; - if (drawable) - { - //make sure we're returning an LLVOPartGroup - llassert(drawable->getVObj()->getPCode() == LLViewerObject::LL_VO_PART_GROUP); - ret = (LLVOPartGroup*) drawable->getVObj().get(); - } - - if (intersection) - { - *intersection = position; - } + assertInitialized(); + U32 mask = 0x1000; // Non-0 mask, set ambient + enableLights(mask); - return ret; + gGL.setAmbientLightColor(color); } -LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end, - bool pick_transparent, - bool pick_rigged, - S32* face_hit, - LLVector4a* intersection, // return the intersection point - LLVector2* tex_coord, // return the texture coordinates of the intersection point - LLVector4a* normal, // return the surface normal at the intersection point - LLVector4a* tangent // return the surface tangent at the intersection point - ) +void LLPipeline::disableLights() { - LLDrawable* drawable = NULL; - - LLVector4a local_end = end; - - LLVector4a position; - - sPickAvatar = false; //! LLToolMgr::getInstance()->inBuildMode(); - - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - - for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++) - { - if ((j == LLViewerRegion::PARTITION_VOLUME) || - (j == LLViewerRegion::PARTITION_BRIDGE) || - (j == LLViewerRegion::PARTITION_TERRAIN) || - (j == LLViewerRegion::PARTITION_TREE) || - (j == LLViewerRegion::PARTITION_GRASS)) // only check these partitions for now - { - LLSpatialPartition* part = region->getSpatialPartition(j); - if (part && hasRenderType(part->mDrawableType)) - { - LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent); - if (hit) - { - drawable = hit; - local_end = position; - } - } - } - } - } - - if (!sPickAvatar) - { - //save hit info in case we need to restore - //due to attachment override - LLVector4a local_normal; - LLVector4a local_tangent; - LLVector2 local_texcoord; - S32 local_face_hit = -1; - - if (face_hit) - { - local_face_hit = *face_hit; - } - if (tex_coord) - { - local_texcoord = *tex_coord; - } - if (tangent) - { - local_tangent = *tangent; - } - else - { - local_tangent.clear(); - } - if (normal) - { - local_normal = *normal; - } - else - { - local_normal.clear(); - } - - const F32 ATTACHMENT_OVERRIDE_DIST = 0.1f; - - //check against avatars - sPickAvatar = true; - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - - LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE); - if (part && hasRenderType(part->mDrawableType)) - { - LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent); - if (hit) - { - LLVector4a delta; - delta.setSub(position, local_end); - - if (!drawable || - !drawable->getVObj()->isAttachment() || - delta.getLength3().getF32() > ATTACHMENT_OVERRIDE_DIST) - { //avatar overrides if previously hit drawable is not an attachment or - //attachment is far enough away from detected intersection - drawable = hit; - local_end = position; - } - else - { //prioritize attachments over avatars - position = local_end; - - if (face_hit) - { - *face_hit = local_face_hit; - } - if (tex_coord) - { - *tex_coord = local_texcoord; - } - if (tangent) - { - *tangent = local_tangent; - } - if (normal) - { - *normal = local_normal; - } - } - } - } - } - } - - //check all avatar nametags (silly, isn't it?) - for (std::vector< LLCharacter* >::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); - ++iter) - { - LLVOAvatar* av = (LLVOAvatar*) *iter; - if (av->mNameText.notNull() - && av->mNameText->lineSegmentIntersect(start, local_end, position)) - { - drawable = av->mDrawable; - local_end = position; - } - } - - if (intersection) - { - *intersection = position; - } - - return drawable ? drawable->getVObj().get() : NULL; + enableLights(0); // no lighting (full bright) } -LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector4a& start, const LLVector4a& end, - bool pick_transparent, - S32* face_hit, - LLVector4a* intersection, // return the intersection point - LLVector2* tex_coord, // return the texture coordinates of the intersection point - LLVector4a* normal, // return the surface normal at the intersection point - LLVector4a* tangent // return the surface tangent at the intersection point - ) -{ - LLDrawable* drawable = NULL; - - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - - bool toggle = false; - if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD)) - { - toggleRenderType(LLPipeline::RENDER_TYPE_HUD); - toggle = true; - } - - LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD); - if (part) - { - LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, FALSE, face_hit, intersection, tex_coord, normal, tangent); - if (hit) - { - drawable = hit; - } - } +//============================================================================ - if (toggle) - { - toggleRenderType(LLPipeline::RENDER_TYPE_HUD); - } - } - return drawable ? drawable->getVObj().get() : NULL; -} +class LLMenuItemGL; +class LLInvFVBridge; +struct cat_folder_pair; +class LLVOBranch; +class LLVOLeaf; -LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj) +void LLPipeline::findReferences(LLDrawable *drawablep) { - if (vobj) - { - LLViewerRegion* region = vobj->getRegion(); - if (region) - { - return region->getSpatialPartition(vobj->getPartitionType()); - } - } - return NULL; + assertInitialized(); + if (mLights.find(drawablep) != mLights.end()) + { + LL_INFOS() << "In mLights" << LL_ENDL; + } + if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end()) + { + LL_INFOS() << "In mMovedList" << LL_ENDL; + } + if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end()) + { + LL_INFOS() << "In mShiftList" << LL_ENDL; + } + if (mRetexturedList.find(drawablep) != mRetexturedList.end()) + { + LL_INFOS() << "In mRetexturedList" << LL_ENDL; + } + + if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end()) + { + LL_INFOS() << "In mBuildQ1" << LL_ENDL; + } + if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end()) + { + LL_INFOS() << "In mBuildQ2" << LL_ENDL; + } + + S32 count; + + count = gObjectList.findReferences(drawablep); + if (count) + { + LL_INFOS() << "In other drawables: " << count << " references" << LL_ENDL; + } } -void LLPipeline::resetVertexBuffers(LLDrawable* drawable) +bool LLPipeline::verify() { - if (!drawable) - { - return; - } + bool ok = assertInitialized(); + if (ok) + { + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + { + LLDrawPool *poolp = *iter; + if (!poolp->verify()) + { + ok = false; + } + } + } - for (S32 i = 0; i < drawable->getNumFaces(); i++) - { - LLFace* facep = drawable->getFace(i); - if (facep) - { - facep->clearVertexBuffer(); - } - } + if (!ok) + { + LL_WARNS() << "Pipeline verify failed!" << LL_ENDL; + } + return ok; } -void LLPipeline::resetVertexBuffers() -{ - mResetVertexBuffers = true; -} +////////////////////////////// +// +// Collision detection +// +// -static LLTrace::BlockTimerStatHandle FTM_RESET_VB("Reset VB"); +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A method to compute a ray-AABB intersection. + * Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990 + * Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500) + * Epsilon value added by Klaus Hartmann. (discarding it saves a few cycles only) + * + * Hence this version is faster as well as more robust than the original one. + * + * Should work provided: + * 1) the integer representation of 0.0f is 0x00000000 + * 2) the sign bit of the float is the most significant one + * + * Report bugs: p.terdiman@codercorner.com + * + * \param aabb [in] the axis-aligned bounding box + * \param origin [in] ray origin + * \param dir [in] ray direction + * \param coord [out] impact coordinates + * \return true if ray intersects AABB + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//#define RAYAABB_EPSILON 0.00001f +#define IR(x) ((U32&)x) -void LLPipeline::doResetVertexBuffers(bool forced) +bool LLRayAABB(const LLVector3 ¢er, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon) { - if (!mResetVertexBuffers) - { - return; - } - if(!forced && LLSpatialPartition::sTeleportRequested) - { - if(gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) - { - return; //wait for teleporting to finish - } - else - { - //teleporting aborted - LLSpatialPartition::sTeleportRequested = FALSE; - mResetVertexBuffers = false; - return; - } - } + bool Inside = true; + LLVector3 MinB = center - size; + LLVector3 MaxB = center + size; + LLVector3 MaxT; + MaxT.mV[VX]=MaxT.mV[VY]=MaxT.mV[VZ]=-1.0f; - LL_RECORD_BLOCK_TIME(FTM_RESET_VB); - mResetVertexBuffers = false; - - mCubeVB = NULL; + // Find candidate planes. + for(U32 i=0;i<3;i++) + { + if(origin.mV[i] < MinB.mV[i]) + { + coord.mV[i] = MinB.mV[i]; + Inside = false; + + // Calculate T distances to candidate planes + if(IR(dir.mV[i])) MaxT.mV[i] = (MinB.mV[i] - origin.mV[i]) / dir.mV[i]; + } + else if(origin.mV[i] > MaxB.mV[i]) + { + coord.mV[i] = MaxB.mV[i]; + Inside = false; + + // Calculate T distances to candidate planes + if(IR(dir.mV[i])) MaxT.mV[i] = (MaxB.mV[i] - origin.mV[i]) / dir.mV[i]; + } + } - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) - { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) - { - part->resetVertexBuffers(); - } - } - } - if(LLSpatialPartition::sTeleportRequested) - { - LLSpatialPartition::sTeleportRequested = FALSE; + // Ray origin inside bounding box + if(Inside) + { + coord = origin; + return true; + } - LLWorld::getInstance()->clearAllVisibleObjects(); - clearRebuildDrawables(); - } + // Get largest of the maxT's for final choice of intersection + U32 WhichPlane = 0; + if(MaxT.mV[1] > MaxT.mV[WhichPlane]) WhichPlane = 1; + if(MaxT.mV[2] > MaxT.mV[WhichPlane]) WhichPlane = 2; - resetDrawOrders(); + // Check final candidate actually inside box + if(IR(MaxT.mV[WhichPlane])&0x80000000) return false; - gSky.resetVertexBuffers(); + for(U32 i=0;i<3;i++) + { + if(i!=WhichPlane) + { + coord.mV[i] = origin.mV[i] + MaxT.mV[WhichPlane] * dir.mV[i]; + if (epsilon > 0) + { + if(coord.mV[i] < MinB.mV[i] - epsilon || coord.mV[i] > MaxB.mV[i] + epsilon) return false; + } + else + { + if(coord.mV[i] < MinB.mV[i] || coord.mV[i] > MaxB.mV[i]) return false; + } + } + } + return true; // ray hits box +} - LLVOPartGroup::destroyGL(); +////////////////////////////// +// +// Macros, functions, and inline methods from other classes +// +// - if ( LLPathingLib::getInstance() ) - { - LLPathingLib::getInstance()->cleanupVBOManager(); - } - LLVOPartGroup::destroyGL(); +void LLPipeline::setLight(LLDrawable *drawablep, bool is_light) +{ + if (drawablep && assertInitialized()) + { + if (is_light) + { + mLights.insert(drawablep); + drawablep->setState(LLDrawable::LIGHT); + } + else + { + drawablep->clearState(LLDrawable::LIGHT); + mLights.erase(drawablep); + } + } +} - SUBSYSTEM_CLEANUP(LLVertexBuffer); - - //delete all name pool caches - LLGLNamePool::cleanupPools(); +//static +void LLPipeline::toggleRenderType(U32 type) +{ + gPipeline.mRenderTypeEnabled[type] = !gPipeline.mRenderTypeEnabled[type]; + if (type == LLPipeline::RENDER_TYPE_WATER) + { + gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER] = !gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER]; + } +} - +//static +void LLPipeline::toggleRenderTypeControl(U32 type) +{ + U32 bit = (1< 0) - { - LL_WARNS() << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << LL_ENDL; - } +//static +bool LLPipeline::hasRenderTypeControl(U32 type) +{ + return gPipeline.hasRenderType(type); +} - LLVertexBuffer::unbind(); - - updateRenderBump(); - updateRenderDeferred(); +// Allows UI items labeled "Hide foo" instead of "Show foo" +//static +bool LLPipeline::toggleRenderTypeControlNegated(S32 type) +{ + return !gPipeline.hasRenderType(type); +} - sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips"); - LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO"); - LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO"); - LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw"); - LLVertexBuffer::sEnableVBOs = gSavedSettings.getBOOL("RenderVBOEnable"); - LLVertexBuffer::sDisableVBOMapping = LLVertexBuffer::sEnableVBOs && gSavedSettings.getBOOL("RenderVBOMappingDisable") ; - sBakeSunlight = gSavedSettings.getBOOL("RenderBakeSunlight"); - sNoAlpha = gSavedSettings.getBOOL("RenderNoAlpha"); - LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind"); +//static +void LLPipeline::toggleRenderDebug(U64 bit) +{ + if (gPipeline.hasRenderDebugMask(bit)) + { + LL_INFOS() << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << LL_ENDL; + } + else + { + LL_INFOS() << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << LL_ENDL; + } + gPipeline.mRenderDebugMask ^= bit; +} - LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping); - LLVOPartGroup::restoreGL(); +//static +bool LLPipeline::toggleRenderDebugControl(U64 bit) +{ + return gPipeline.hasRenderDebugMask(bit); } -void LLPipeline::renderObjects(U32 type, U32 mask, bool texture, bool batch_texture) +//static +void LLPipeline::toggleRenderDebugFeature(U32 bit) { - assertInitialized(); - gGL.loadMatrix(gGLModelView); - gGLLastMatrix = NULL; - mSimplePool->pushBatches(type, mask, texture, batch_texture); - gGL.loadMatrix(gGLModelView); - gGLLastMatrix = NULL; + gPipeline.mRenderDebugFeatureMask ^= bit; } -void LLPipeline::renderMaskedObjects(U32 type, U32 mask, bool texture, bool batch_texture) + +//static +bool LLPipeline::toggleRenderDebugFeatureControl(U32 bit) { - assertInitialized(); - gGL.loadMatrix(gGLModelView); - gGLLastMatrix = NULL; - mAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture); - gGL.loadMatrix(gGLModelView); - gGLLastMatrix = NULL; + return gPipeline.hasRenderDebugFeatureMask(bit); } +void LLPipeline::setRenderDebugFeatureControl(U32 bit, bool value) +{ + if (value) + { + gPipeline.mRenderDebugFeatureMask |= bit; + } + else + { + gPipeline.mRenderDebugFeatureMask &= !bit; + } +} -void apply_cube_face_rotation(U32 face) +void LLPipeline::pushRenderDebugFeatureMask() { - switch (face) - { - case 0: - gGL.rotatef(90.f, 0, 1, 0); - gGL.rotatef(180.f, 1, 0, 0); - break; - case 2: - gGL.rotatef(-90.f, 1, 0, 0); - break; - case 4: - gGL.rotatef(180.f, 0, 1, 0); - gGL.rotatef(180.f, 0, 0, 1); - break; - case 1: - gGL.rotatef(-90.f, 0, 1, 0); - gGL.rotatef(180.f, 1, 0, 0); - break; - case 3: - gGL.rotatef(90, 1, 0, 0); - break; - case 5: - gGL.rotatef(180, 0, 0, 1); - break; - } + mRenderDebugFeatureStack.push(mRenderDebugFeatureMask); } -void validate_framebuffer_object() -{ - GLenum status; - status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); - switch(status) - { - case GL_FRAMEBUFFER_COMPLETE: - //framebuffer OK, no error. - break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - // frame buffer not OK: probably means unsupported depth buffer format - LL_ERRS() << "Framebuffer Incomplete Missing Attachment." << LL_ENDL; - break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - // frame buffer not OK: probably means unsupported depth buffer format - LL_ERRS() << "Framebuffer Incomplete Attachment." << LL_ENDL; - break; - case GL_FRAMEBUFFER_UNSUPPORTED: - /* choose different formats */ - LL_ERRS() << "Framebuffer unsupported." << LL_ENDL; - break; - default: - LL_ERRS() << "Unknown framebuffer status." << LL_ENDL; - break; - } +void LLPipeline::popRenderDebugFeatureMask() +{ + if (mRenderDebugFeatureStack.empty()) + { + LL_ERRS() << "Depleted render feature stack." << LL_ENDL; + } + + mRenderDebugFeatureMask = mRenderDebugFeatureStack.top(); + mRenderDebugFeatureStack.pop(); } -void LLPipeline::bindScreenToTexture() +// static +void LLPipeline::setRenderScriptedBeacons(bool val) { - + sRenderScriptedBeacons = val; } -static LLTrace::BlockTimerStatHandle FTM_RENDER_BLOOM("Bloom"); +// static +void LLPipeline::toggleRenderScriptedBeacons() +{ + sRenderScriptedBeacons = !sRenderScriptedBeacons; +} -void LLPipeline::renderBloom(bool for_snapshot, F32 zoom_factor, int subfield) +// static +bool LLPipeline::getRenderScriptedBeacons() { - LLRenderTarget* deferred_light_target = &mDeferredLight; + return sRenderScriptedBeacons; +} - if (!(gPipeline.canUseVertexShaders() && - sRenderGlow)) - { - return; - } +// static +void LLPipeline::setRenderScriptedTouchBeacons(bool val) +{ + sRenderScriptedTouchBeacons = val; +} - LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); +// static +void LLPipeline::toggleRenderScriptedTouchBeacons() +{ + sRenderScriptedTouchBeacons = !sRenderScriptedTouchBeacons; +} - assertInitialized(); +// static +bool LLPipeline::getRenderScriptedTouchBeacons() +{ + return sRenderScriptedTouchBeacons; +} - if (gUseWireframe) - { - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } +// static +void LLPipeline::setRenderMOAPBeacons(bool val) +{ + sRenderMOAPBeacons = val; +} - LLVector2 tc1(0,0); - LLVector2 tc2((F32) mScreen.getWidth()*2, - (F32) mScreen.getHeight()*2); +// static +void LLPipeline::toggleRenderMOAPBeacons() +{ + sRenderMOAPBeacons = !sRenderMOAPBeacons; +} - LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM); - gGL.color4f(1,1,1,1); - LLGLDepthTest depth(GL_FALSE); - LLGLDisable blend(GL_BLEND); - LLGLDisable cull(GL_CULL_FACE); - - enableLightsFullbright(LLColor4(1,1,1,1)); +// static +bool LLPipeline::getRenderMOAPBeacons() +{ + return sRenderMOAPBeacons; +} - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.loadIdentity(); +// static +void LLPipeline::setRenderPhysicalBeacons(bool val) +{ + sRenderPhysicalBeacons = val; +} - LLGLDisable test(GL_ALPHA_TEST); +// static +void LLPipeline::toggleRenderPhysicalBeacons() +{ + sRenderPhysicalBeacons = !sRenderPhysicalBeacons; +} - gGL.setColorMask(true, true); - glClearColor(0,0,0,0); - - { - { - LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO); - mGlow[2].bindTarget(); - mGlow[2].clear(); - } - - gGlowExtractProgram.bind(); - F32 minLum = llmax((F32) RenderGlowMinLuminance, 0.0f); - F32 maxAlpha = RenderGlowMaxExtractAlpha; - F32 warmthAmount = RenderGlowWarmthAmount; - LLVector3 lumWeights = RenderGlowLumWeights; - LLVector3 warmthWeights = RenderGlowWarmthWeights; - - - gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, minLum); - gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha); - gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1], lumWeights.mV[2]); - gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1], warmthWeights.mV[2]); - gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount); - LLGLEnable blend_on(GL_BLEND); - LLGLEnable test(GL_ALPHA_TEST); - - gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); - - mScreen.bindTexture(0, 0); - - gGL.color4f(1,1,1,1); - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1,-1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,3); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3,-1); - - gGL.end(); - - gGL.getTexUnit(0)->unbind(mScreen.getUsage()); +// static +bool LLPipeline::getRenderPhysicalBeacons() +{ + return sRenderPhysicalBeacons; +} - mGlow[2].flush(); - } +// static +void LLPipeline::setRenderParticleBeacons(bool val) +{ + sRenderParticleBeacons = val; +} - tc1.setVec(0,0); - tc2.setVec(2,2); +// static +void LLPipeline::toggleRenderParticleBeacons() +{ + sRenderParticleBeacons = !sRenderParticleBeacons; +} - // power of two between 1 and 1024 - U32 glowResPow = RenderGlowResolutionPow; - const U32 glow_res = llmax(1, - llmin(1024, 1 << glowResPow)); +// static +bool LLPipeline::getRenderParticleBeacons() +{ + return sRenderParticleBeacons; +} - S32 kernel = RenderGlowIterations*2; - F32 delta = RenderGlowWidth / glow_res; - // Use half the glow width if we have the res set to less than 9 so that it looks - // almost the same in either case. - if (glowResPow < 9) - { - delta *= 0.5f; - } - F32 strength = RenderGlowStrength; +// static +void LLPipeline::setRenderSoundBeacons(bool val) +{ + sRenderSoundBeacons = val; +} - gGlowProgram.bind(); - gGlowProgram.uniform1f(LLShaderMgr::GLOW_STRENGTH, strength); +// static +void LLPipeline::toggleRenderSoundBeacons() +{ + sRenderSoundBeacons = !sRenderSoundBeacons; +} - for (S32 i = 0; i < kernel; i++) - { - { - LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO); - mGlow[i%2].bindTarget(); - mGlow[i%2].clear(); - } - - if (i == 0) - { - gGL.getTexUnit(0)->bind(&mGlow[2]); - } - else - { - gGL.getTexUnit(0)->bind(&mGlow[(i-1)%2]); - } +// static +bool LLPipeline::getRenderSoundBeacons() +{ + return sRenderSoundBeacons; +} - if (i%2 == 0) - { - gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, delta, 0); - } - else - { - gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta); - } +// static +void LLPipeline::setRenderBeacons(bool val) +{ + sRenderBeacons = val; +} - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1,-1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,3); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3,-1); - - gGL.end(); - - mGlow[i%2].flush(); - } +// static +void LLPipeline::toggleRenderBeacons() +{ + sRenderBeacons = !sRenderBeacons; +} - gGlowProgram.unbind(); +// static +bool LLPipeline::getRenderBeacons() +{ + return sRenderBeacons; +} - /*if (LLRenderTarget::sUseFBO) - { - LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - }*/ +// static +void LLPipeline::setRenderHighlights(bool val) +{ + sRenderHighlight = val; +} - gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; - gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; - gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); - gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); +// static +void LLPipeline::toggleRenderHighlights() +{ + sRenderHighlight = !sRenderHighlight; +} - tc2.setVec((F32) mScreen.getWidth(), - (F32) mScreen.getHeight()); +// static +bool LLPipeline::getRenderHighlights() +{ + return sRenderHighlight; +} - gGL.flush(); - - LLVertexBuffer::unbind(); +// static +void LLPipeline::setRenderHighlightTextureChannel(LLRender::eTexIndex channel) +{ + sRenderHighlightTextureChannel = channel; +} - if (LLPipeline::sRenderDeferred) - { +LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection, + S32* face_hit) +{ + LLVector4a local_end = end; - bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() && - (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) && - RenderDepthOfField; + LLVector4a position; + LLDrawable* drawable = NULL; - bool multisample = RenderFSAASamples > 1 && mFXAABuffer.isComplete(); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_PARTICLE); + if (part && hasRenderType(part->mDrawableType)) + { + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, FALSE, face_hit, &position, NULL, NULL, NULL); + if (hit) + { + drawable = hit; + local_end = position; + } + } + } - gViewerWindow->setup3DViewport(); - - if (dof_enabled) - { - LLGLSLShader* shader = &gDeferredPostProgram; - LLGLDisable blend(GL_BLEND); + LLVOPartGroup* ret = NULL; + if (drawable) + { + //make sure we're returning an LLVOPartGroup + llassert(drawable->getVObj()->getPCode() == LLViewerObject::LL_VO_PART_GROUP); + ret = (LLVOPartGroup*) drawable->getVObj().get(); + } + + if (intersection) + { + *intersection = position; + } - //depth of field focal plane calculations - static F32 current_distance = 16.f; - static F32 start_distance = 16.f; - static F32 transition_time = 1.f; + return ret; +} - LLVector3 focus_point; +LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end, + bool pick_transparent, + bool pick_rigged, + S32* face_hit, + LLVector4a* intersection, // return the intersection point + LLVector2* tex_coord, // return the texture coordinates of the intersection point + LLVector4a* normal, // return the surface normal at the intersection point + LLVector4a* tangent // return the surface tangent at the intersection point + ) +{ + LLDrawable* drawable = NULL; - LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); - if (obj && obj->mDrawable && obj->isSelected()) - { //focus on selected media object - S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); - if (obj && obj->mDrawable) - { - LLFace* face = obj->mDrawable->getFace(face_idx); - if (face) - { - focus_point = face->getPositionAgent(); - } - } - } - - if (focus_point.isExactlyZero()) - { - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { //focus on point under cursor - focus_point.set(gDebugRaycastIntersection.getF32ptr()); - } - else if (gAgentCamera.cameraMouselook()) - { //focus on point under mouselook crosshairs - LLVector4a result; - result.clear(); + LLVector4a local_end = end; - gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, - NULL, - &result); + LLVector4a position; - focus_point.set(result.getF32ptr()); - } - else - { - //focus on alt-zoom target - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - focus_point = LLVector3(gAgentCamera.getFocusGlobal()-region->getOriginGlobal()); - } - } - } + sPickAvatar = false; //! LLToolMgr::getInstance()->inBuildMode(); + + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++) + { + if ((j == LLViewerRegion::PARTITION_VOLUME) || + (j == LLViewerRegion::PARTITION_BRIDGE) || + (j == LLViewerRegion::PARTITION_TERRAIN) || + (j == LLViewerRegion::PARTITION_TREE) || + (j == LLViewerRegion::PARTITION_GRASS)) // only check these partitions for now + { + LLSpatialPartition* part = region->getSpatialPartition(j); + if (part && hasRenderType(part->mDrawableType)) + { + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent); + if (hit) + { + drawable = hit; + local_end = position; + } + } + } + } + } + + if (!sPickAvatar) + { + //save hit info in case we need to restore + //due to attachment override + LLVector4a local_normal; + LLVector4a local_tangent; + LLVector2 local_texcoord; + S32 local_face_hit = -1; + + if (face_hit) + { + local_face_hit = *face_hit; + } + if (tex_coord) + { + local_texcoord = *tex_coord; + } + if (tangent) + { + local_tangent = *tangent; + } + else + { + local_tangent.clear(); + } + if (normal) + { + local_normal = *normal; + } + else + { + local_normal.clear(); + } + + const F32 ATTACHMENT_OVERRIDE_DIST = 0.1f; + + //check against avatars + sPickAvatar = true; + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE); + if (part && hasRenderType(part->mDrawableType)) + { + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent); + if (hit) + { + LLVector4a delta; + delta.setSub(position, local_end); + + if (!drawable || + !drawable->getVObj()->isAttachment() || + delta.getLength3().getF32() > ATTACHMENT_OVERRIDE_DIST) + { //avatar overrides if previously hit drawable is not an attachment or + //attachment is far enough away from detected intersection + drawable = hit; + local_end = position; + } + else + { //prioritize attachments over avatars + position = local_end; + + if (face_hit) + { + *face_hit = local_face_hit; + } + if (tex_coord) + { + *tex_coord = local_texcoord; + } + if (tangent) + { + *tangent = local_tangent; + } + if (normal) + { + *normal = local_normal; + } + } + } + } + } + } - LLVector3 eye = LLViewerCamera::getInstance()->getOrigin(); - F32 target_distance = 16.f; - if (!focus_point.isExactlyZero()) - { - target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point-eye); - } + //check all avatar nametags (silly, isn't it?) + for (std::vector< LLCharacter* >::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); + ++iter) + { + LLVOAvatar* av = (LLVOAvatar*) *iter; + if (av->mNameText.notNull() + && av->mNameText->lineSegmentIntersect(start, local_end, position)) + { + drawable = av->mDrawable; + local_end = position; + } + } - if (transition_time >= 1.f && - fabsf(current_distance-target_distance)/current_distance > 0.01f) - { //large shift happened, interpolate smoothly to new target distance - transition_time = 0.f; - start_distance = current_distance; - } - else if (transition_time < 1.f) - { //currently in a transition, continue interpolating - transition_time += 1.f/CameraFocusTransitionTime*gFrameIntervalSeconds.value(); - transition_time = llmin(transition_time, 1.f); + if (intersection) + { + *intersection = position; + } - F32 t = cosf(transition_time*F_PI+F_PI)*0.5f+0.5f; - current_distance = start_distance + (target_distance-start_distance)*t; - } - else - { //small or no change, just snap to target distance - current_distance = target_distance; - } + return drawable ? drawable->getVObj().get() : NULL; +} - //convert to mm - F32 subject_distance = current_distance*1000.f; - F32 fnumber = CameraFNumber; - F32 default_focal_length = CameraFocalLength; +LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector4a& start, const LLVector4a& end, + bool pick_transparent, + S32* face_hit, + LLVector4a* intersection, // return the intersection point + LLVector2* tex_coord, // return the texture coordinates of the intersection point + LLVector4a* normal, // return the surface normal at the intersection point + LLVector4a* tangent // return the surface tangent at the intersection point + ) +{ + LLDrawable* drawable = NULL; + + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + bool toggle = false; + if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { + toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + toggle = true; + } + + LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD); + if (part) + { + LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, FALSE, face_hit, intersection, tex_coord, normal, tangent); + if (hit) + { + drawable = hit; + } + } + + if (toggle) + { + toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + } + } + return drawable ? drawable->getVObj().get() : NULL; +} - F32 fov = LLViewerCamera::getInstance()->getView(); - - const F32 default_fov = CameraFieldOfView * F_PI/180.f; - - //F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight(); - - F32 dv = 2.f*default_focal_length * tanf(default_fov/2.f); +LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj) +{ + if (vobj) + { + LLViewerRegion* region = vobj->getRegion(); + if (region) + { + return region->getSpatialPartition(vobj->getPartitionType()); + } + } + return NULL; +} - F32 focal_length = dv/(2*tanf(fov/2.f)); - - //F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle); - - // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f)) - // where N = fnumber - // s2 = dot distance - // s1 = subject distance - // f = focal length - // +void LLPipeline::resetVertexBuffers(LLDrawable* drawable) +{ + if (!drawable) + { + return; + } - F32 blur_constant = focal_length*focal_length/(fnumber*(subject_distance-focal_length)); - blur_constant /= 1000.f; //convert to meters for shader - F32 magnification = focal_length/(subject_distance-focal_length); + for (S32 i = 0; i < drawable->getNumFaces(); i++) + { + LLFace* facep = drawable->getFace(i); + if (facep) + { + facep->clearVertexBuffer(); + } + } +} - { //build diffuse+bloom+CoF - deferred_light_target->bindTarget(); - shader = &gDeferredCoFProgram; +void LLPipeline::resetVertexBuffers() +{ + mResetVertexBuffers = true; +} - bindDeferredShader(*shader); +static LLTrace::BlockTimerStatHandle FTM_RESET_VB("Reset VB"); - S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); - if (channel > -1) - { - mScreen.bindTexture(0, channel); - } +void LLPipeline::doResetVertexBuffers(bool forced) +{ + if (!mResetVertexBuffers) + { + return; + } + if(!forced && LLSpatialPartition::sTeleportRequested) + { + if(gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) + { + return; //wait for teleporting to finish + } + else + { + //teleporting aborted + LLSpatialPartition::sTeleportRequested = FALSE; + mResetVertexBuffers = false; + return; + } + } - shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance/1000.f); - shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant); - shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f/LLDrawable::sCurPixelAngle)); - shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification); - shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); - shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + LL_RECORD_BLOCK_TIME(FTM_RESET_VB); + mResetVertexBuffers = false; - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1,-1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,3); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3,-1); - - gGL.end(); + mCubeVB = NULL; - unbindDeferredShader(*shader); - deferred_light_target->flush(); - } + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + part->resetVertexBuffers(); + } + } + } + if(LLSpatialPartition::sTeleportRequested) + { + LLSpatialPartition::sTeleportRequested = FALSE; - U32 dof_width = (U32) (mScreen.getWidth()*CameraDoFResScale); - U32 dof_height = (U32) (mScreen.getHeight()*CameraDoFResScale); - - { //perform DoF sampling at half-res (preserve alpha channel) - mScreen.bindTarget(); - glViewport(0,0, dof_width, dof_height); - gGL.setColorMask(true, false); + LLWorld::getInstance()->clearAllVisibleObjects(); + clearRebuildDrawables(); + } - shader = &gDeferredPostProgram; - bindDeferredShader(*shader); - S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, deferred_light_target->getUsage()); - if (channel > -1) - { - deferred_light_target->bindTexture(0, channel); - } + resetDrawOrders(); - shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); - shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); - - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1,-1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,3); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3,-1); - - gGL.end(); + gSky.resetVertexBuffers(); - unbindDeferredShader(*shader); - mScreen.flush(); - gGL.setColorMask(true, true); - } - - { //combine result based on alpha - if (multisample) - { - deferred_light_target->bindTarget(); - glViewport(0, 0, deferred_light_target->getWidth(), deferred_light_target->getHeight()); - } - else - { - gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; - gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; - gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); - gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - } + LLVOPartGroup::destroyGL(); - shader = &gDeferredDoFCombineProgram; - bindDeferredShader(*shader); - - S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); - if (channel > -1) - { - mScreen.bindTexture(0, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - } + if ( LLPathingLib::getInstance() ) + { + LLPathingLib::getInstance()->cleanupVBOManager(); + } + LLVOPartGroup::destroyGL(); - if (!LLViewerCamera::getInstance()->cameraUnderWater()) - { - shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 2.2); - } else { - shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 1.0); - } + SUBSYSTEM_CLEANUP(LLVertexBuffer); + + //delete all name pool caches + LLGLNamePool::cleanupPools(); - shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); - shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); - shader->uniform1f(LLShaderMgr::DOF_WIDTH, dof_width-1); - shader->uniform1f(LLShaderMgr::DOF_HEIGHT, dof_height-1); + - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1,-1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,3); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3,-1); - - gGL.end(); + if (LLVertexBuffer::sGLCount > 0) + { + LL_WARNS() << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << LL_ENDL; + } - unbindDeferredShader(*shader); + LLVertexBuffer::unbind(); + + updateRenderBump(); + updateRenderDeferred(); - if (multisample) - { - deferred_light_target->flush(); - } - } - } - else - { - if (multisample) - { - deferred_light_target->bindTarget(); - } - LLGLSLShader* shader = &gDeferredPostNoDoFProgram; - - bindDeferredShader(*shader); - - S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); - if (channel > -1) - { - mScreen.bindTexture(0, channel); - } + sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips"); + LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO"); + LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO"); + LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw"); + LLVertexBuffer::sEnableVBOs = gSavedSettings.getBOOL("RenderVBOEnable"); + LLVertexBuffer::sDisableVBOMapping = LLVertexBuffer::sEnableVBOs && gSavedSettings.getBOOL("RenderVBOMappingDisable") ; + sBakeSunlight = gSavedSettings.getBOOL("RenderBakeSunlight"); + sNoAlpha = gSavedSettings.getBOOL("RenderNoAlpha"); + LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind"); - if (!LLViewerCamera::getInstance()->cameraUnderWater()) - { - shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 2.2); - } else { - shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 1.0); - } + LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping); - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1,-1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,3); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3,-1); - - gGL.end(); + LLVOPartGroup::restoreGL(); +} - unbindDeferredShader(*shader); +void LLPipeline::renderObjects(U32 type, U32 mask, bool texture, bool batch_texture) +{ + assertInitialized(); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; + mSimplePool->pushBatches(type, mask, texture, batch_texture); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; +} - if (multisample) - { - deferred_light_target->flush(); - } - } +void LLPipeline::renderMaskedObjects(U32 type, U32 mask, bool texture, bool batch_texture) +{ + assertInitialized(); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; + mAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; +} - if (multisample) - { - //bake out texture2D with RGBL for FXAA shader - mFXAABuffer.bindTarget(); - - S32 width = mScreen.getWidth(); - S32 height = mScreen.getHeight(); - glViewport(0, 0, width, height); - LLGLSLShader* shader = &gGlowCombineFXAAProgram; +void apply_cube_face_rotation(U32 face) +{ + switch (face) + { + case 0: + gGL.rotatef(90.f, 0, 1, 0); + gGL.rotatef(180.f, 1, 0, 0); + break; + case 2: + gGL.rotatef(-90.f, 1, 0, 0); + break; + case 4: + gGL.rotatef(180.f, 0, 1, 0); + gGL.rotatef(180.f, 0, 0, 1); + break; + case 1: + gGL.rotatef(-90.f, 0, 1, 0); + gGL.rotatef(180.f, 1, 0, 0); + break; + case 3: + gGL.rotatef(90, 1, 0, 0); + break; + case 5: + gGL.rotatef(180, 0, 0, 1); + break; + } +} - shader->bind(); - shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height); +void validate_framebuffer_object() +{ + GLenum status; + status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); + switch(status) + { + case GL_FRAMEBUFFER_COMPLETE: + //framebuffer OK, no error. + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + // frame buffer not OK: probably means unsupported depth buffer format + LL_ERRS() << "Framebuffer Incomplete Missing Attachment." << LL_ENDL; + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + // frame buffer not OK: probably means unsupported depth buffer format + LL_ERRS() << "Framebuffer Incomplete Attachment." << LL_ENDL; + break; + case GL_FRAMEBUFFER_UNSUPPORTED: + /* choose different formats */ + LL_ERRS() << "Framebuffer unsupported." << LL_ENDL; + break; + default: + LL_ERRS() << "Unknown framebuffer status." << LL_ENDL; + break; + } +} - S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, deferred_light_target->getUsage()); - if (channel > -1) - { - deferred_light_target->bindTexture(0, channel); - } - - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.vertex2f(-1,-1); - gGL.vertex2f(-1,3); - gGL.vertex2f(3,-1); - gGL.end(); +void LLPipeline::bindScreenToTexture() +{ + +} - gGL.flush(); +static LLTrace::BlockTimerStatHandle FTM_RENDER_BLOOM("Bloom"); - shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, deferred_light_target->getUsage()); - shader->unbind(); - - mFXAABuffer.flush(); +void LLPipeline::renderBloom(bool for_snapshot, F32 zoom_factor, int subfield) +{ + if (!(gPipeline.canUseVertexShaders() && + sRenderGlow)) + { + return; + } + + LLVertexBuffer::unbind(); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + + assertInitialized(); + + if (gUseWireframe) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } - shader = &gFXAAProgram; - shader->bind(); + LLVector2 tc1(0,0); + LLVector2 tc2((F32) mScreen.getWidth()*2, + (F32) mScreen.getHeight()*2); + + LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM); + gGL.color4f(1,1,1,1); + LLGLDepthTest depth(GL_FALSE); + LLGLDisable blend(GL_BLEND); + LLGLDisable cull(GL_CULL_FACE); + + enableLightsFullbright(LLColor4(1,1,1,1)); + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); + + LLGLDisable test(GL_ALPHA_TEST); + + gGL.setColorMask(true, true); + glClearColor(0,0,0,0); + + { + { + LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO); + mGlow[2].bindTarget(); + mGlow[2].clear(); + } + + gGlowExtractProgram.bind(); + F32 minLum = llmax((F32) RenderGlowMinLuminance, 0.0f); + F32 maxAlpha = RenderGlowMaxExtractAlpha; + F32 warmthAmount = RenderGlowWarmthAmount; + LLVector3 lumWeights = RenderGlowLumWeights; + LLVector3 warmthWeights = RenderGlowWarmthWeights; + + + gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, minLum); + gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha); + gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1], lumWeights.mV[2]); + gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1], warmthWeights.mV[2]); + gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount); + LLGLEnable blend_on(GL_BLEND); + LLGLEnable test(GL_ALPHA_TEST); + + gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); + + mScreen.bindTexture(0, 0); + + gGL.color4f(1,1,1,1); + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); + gGL.vertex2f(-1,-1); + + gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); + gGL.vertex2f(-1,3); + + gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); + gGL.vertex2f(3,-1); + + gGL.end(); + + gGL.getTexUnit(0)->unbind(mScreen.getUsage()); + + mGlow[2].flush(); + } - channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAABuffer.getUsage()); - if (channel > -1) - { - mFXAABuffer.bindTexture(0, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - } - - gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; - gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; - gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); - gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - - F32 scale_x = (F32) width/mFXAABuffer.getWidth(); - F32 scale_y = (F32) height/mFXAABuffer.getHeight(); - shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y); - shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f/width*scale_x, 1.f/height*scale_y); - shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f/width*scale_x, -0.5f/height*scale_y, 0.5f/width*scale_x, 0.5f/height*scale_y); - shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f/width*scale_x, -2.f/height*scale_y, 2.f/width*scale_x, 2.f/height*scale_y); - - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.vertex2f(-1,-1); - gGL.vertex2f(-1,3); - gGL.vertex2f(3,-1); - gGL.end(); - - gGL.flush(); - shader->unbind(); - } - } - else - { - U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1; - LLPointer buff = new LLVertexBuffer(mask, 0); - buff->allocateBuffer(3,0,TRUE); + tc1.setVec(0,0); + tc2.setVec(2,2); - LLStrider v; - LLStrider uv1; - LLStrider uv2; + // power of two between 1 and 1024 + U32 glowResPow = RenderGlowResolutionPow; + const U32 glow_res = llmax(1, + llmin(1024, 1 << glowResPow)); - buff->getVertexStrider(v); - buff->getTexCoord0Strider(uv1); - buff->getTexCoord1Strider(uv2); - - uv1[0] = LLVector2(0, 0); - uv1[1] = LLVector2(0, 2); - uv1[2] = LLVector2(2, 0); - - uv2[0] = LLVector2(0, 0); - uv2[1] = LLVector2(0, tc2.mV[1]*2.f); - uv2[2] = LLVector2(tc2.mV[0]*2.f, 0); - - v[0] = LLVector3(-1,-1,0); - v[1] = LLVector3(-1,3,0); - v[2] = LLVector3(3,-1,0); - - buff->flush(); + S32 kernel = RenderGlowIterations*2; + F32 delta = RenderGlowWidth / glow_res; + // Use half the glow width if we have the res set to less than 9 so that it looks + // almost the same in either case. + if (glowResPow < 9) + { + delta *= 0.5f; + } + F32 strength = RenderGlowStrength; - LLGLDisable blend(GL_BLEND); + gGlowProgram.bind(); + gGlowProgram.uniform1f(LLShaderMgr::GLOW_STRENGTH, strength); - if (LLGLSLShader::sNoFixedFunction) - { - gGlowCombineProgram.bind(); - } - else - { - //tex unit 0 - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR); - //tex unit 1 - gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); - } - - gGL.getTexUnit(0)->bind(&mGlow[1]); - gGL.getTexUnit(1)->bind(&mScreen); - - LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); - - buff->setBuffer(mask); - buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3); - - if (LLGLSLShader::sNoFixedFunction) - { - gGlowCombineProgram.unbind(); - } - else - { - gGL.getTexUnit(1)->disable(); - gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT); + for (S32 i = 0; i < kernel; i++) + { + { + LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO); + mGlow[i%2].bindTarget(); + mGlow[i%2].clear(); + } + + if (i == 0) + { + gGL.getTexUnit(0)->bind(&mGlow[2]); + } + else + { + gGL.getTexUnit(0)->bind(&mGlow[(i-1)%2]); + } + + if (i%2 == 0) + { + gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, delta, 0); + } + else + { + gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta); + } + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); + gGL.vertex2f(-1,-1); + + gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); + gGL.vertex2f(-1,3); + + gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); + gGL.vertex2f(3,-1); + + gGL.end(); + + mGlow[i%2].flush(); + } - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - } - - } + gGlowProgram.unbind(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); + /*if (LLRenderTarget::sUseFBO) + { + LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + }*/ - if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) - { - if (LLGLSLShader::sNoFixedFunction) - { - gSplatTextureRectProgram.bind(); - } + gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; + gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; + gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); + gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); + glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - gGL.setColorMask(true, false); + tc2.setVec((F32) mScreen.getWidth(), + (F32) mScreen.getHeight()); - LLVector2 tc1(0,0); - LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2, - (F32) gViewerWindow->getWorldViewHeightRaw()*2); + gGL.flush(); + + LLVertexBuffer::unbind(); - LLGLEnable blend(GL_BLEND); - gGL.color4f(1,1,1,0.75f); + if (LLPipeline::sRenderDeferred) + { - gGL.getTexUnit(0)->bind(&mPhysicsDisplay); + bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() && + (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) && + RenderDepthOfField; + + + bool multisample = RenderFSAASamples > 1 && mFXAABuffer.isComplete(); + + gViewerWindow->setup3DViewport(); + + if (dof_enabled) + { + LLGLSLShader* shader = &gDeferredPostProgram; + LLGLDisable blend(GL_BLEND); + + //depth of field focal plane calculations + static F32 current_distance = 16.f; + static F32 start_distance = 16.f; + static F32 transition_time = 1.f; + + LLVector3 focus_point; + + LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); + if (obj && obj->mDrawable && obj->isSelected()) + { //focus on selected media object + S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); + if (obj && obj->mDrawable) + { + LLFace* face = obj->mDrawable->getFace(face_idx); + if (face) + { + focus_point = face->getPositionAgent(); + } + } + } + + if (focus_point.isExactlyZero()) + { + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { //focus on point under cursor + focus_point.set(gDebugRaycastIntersection.getF32ptr()); + } + else if (gAgentCamera.cameraMouselook()) + { //focus on point under mouselook crosshairs + LLVector4a result; + result.clear(); + + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, + NULL, + &result); + + focus_point.set(result.getF32ptr()); + } + else + { + //focus on alt-zoom target + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + focus_point = LLVector3(gAgentCamera.getFocusGlobal()-region->getOriginGlobal()); + } + } + } + + LLVector3 eye = LLViewerCamera::getInstance()->getOrigin(); + F32 target_distance = 16.f; + if (!focus_point.isExactlyZero()) + { + target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point-eye); + } + + if (transition_time >= 1.f && + fabsf(current_distance-target_distance)/current_distance > 0.01f) + { //large shift happened, interpolate smoothly to new target distance + transition_time = 0.f; + start_distance = current_distance; + } + else if (transition_time < 1.f) + { //currently in a transition, continue interpolating + transition_time += 1.f/CameraFocusTransitionTime*gFrameIntervalSeconds.value(); + transition_time = llmin(transition_time, 1.f); + + F32 t = cosf(transition_time*F_PI+F_PI)*0.5f+0.5f; + current_distance = start_distance + (target_distance-start_distance)*t; + } + else + { //small or no change, just snap to target distance + current_distance = target_distance; + } + + //convert to mm + F32 subject_distance = current_distance*1000.f; + F32 fnumber = CameraFNumber; + F32 default_focal_length = CameraFocalLength; + + F32 fov = LLViewerCamera::getInstance()->getView(); + + const F32 default_fov = CameraFieldOfView * F_PI/180.f; + + //F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight(); + + F32 dv = 2.f*default_focal_length * tanf(default_fov/2.f); + + F32 focal_length = dv/(2*tanf(fov/2.f)); + + //F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle); + + // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f)) + // where N = fnumber + // s2 = dot distance + // s1 = subject distance + // f = focal length + // + + F32 blur_constant = focal_length*focal_length/(fnumber*(subject_distance-focal_length)); + blur_constant /= 1000.f; //convert to meters for shader + F32 magnification = focal_length/(subject_distance-focal_length); + + { //build diffuse+bloom+CoF + mDeferredLight.bindTarget(); + shader = &gDeferredCoFProgram; + + bindDeferredShader(*shader); + + S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); + if (channel > -1) + { + mScreen.bindTexture(0, channel); + } + + shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance/1000.f); + shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant); + shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f/LLDrawable::sCurPixelAngle)); + shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification); + shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); + shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); + gGL.vertex2f(-1,-1); + + gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); + gGL.vertex2f(-1,3); + + gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); + gGL.vertex2f(3,-1); + + gGL.end(); + + unbindDeferredShader(*shader); + mDeferredLight.flush(); + } + + U32 dof_width = (U32) (mScreen.getWidth()*CameraDoFResScale); + U32 dof_height = (U32) (mScreen.getHeight()*CameraDoFResScale); + + { //perform DoF sampling at half-res (preserve alpha channel) + mScreen.bindTarget(); + glViewport(0,0, dof_width, dof_height); + gGL.setColorMask(true, false); + + shader = &gDeferredPostProgram; + bindDeferredShader(*shader); + S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage()); + if (channel > -1) + { + mDeferredLight.bindTexture(0, channel); + } + + shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); + shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); + gGL.vertex2f(-1,-1); + + gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); + gGL.vertex2f(-1,3); + + gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); + gGL.vertex2f(3,-1); + + gGL.end(); + + unbindDeferredShader(*shader); + mScreen.flush(); + gGL.setColorMask(true, true); + } + + { //combine result based on alpha + if (multisample) + { + mDeferredLight.bindTarget(); + glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); + } + else + { + gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; + gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; + gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); + gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); + glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); + } + + shader = &gDeferredDoFCombineProgram; + bindDeferredShader(*shader); + + S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); + if (channel > -1) + { + mScreen.bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + if (!LLViewerCamera::getInstance()->cameraUnderWater()) + { + shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 2.2); + } else { + shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 1.0); + } + + shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); + shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + shader->uniform1f(LLShaderMgr::DOF_WIDTH, dof_width-1); + shader->uniform1f(LLShaderMgr::DOF_HEIGHT, dof_height-1); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); + gGL.vertex2f(-1,-1); + + gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); + gGL.vertex2f(-1,3); + + gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); + gGL.vertex2f(3,-1); + + gGL.end(); + + unbindDeferredShader(*shader); + + if (multisample) + { + mDeferredLight.flush(); + } + } + } + else + { + if (multisample) + { + mDeferredLight.bindTarget(); + } + LLGLSLShader* shader = &gDeferredPostNoDoFProgram; + + bindDeferredShader(*shader); + + S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); + if (channel > -1) + { + mScreen.bindTexture(0, channel); + } + + if (!LLViewerCamera::getInstance()->cameraUnderWater()) + { + shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 2.2); + } else { + shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 1.0); + } + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); + gGL.vertex2f(-1,-1); + + gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); + gGL.vertex2f(-1,3); + + gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); + gGL.vertex2f(3,-1); + + gGL.end(); + + unbindDeferredShader(*shader); + + if (multisample) + { + mDeferredLight.flush(); + } + } + + if (multisample) + { + //bake out texture2D with RGBL for FXAA shader + mFXAABuffer.bindTarget(); + + S32 width = mScreen.getWidth(); + S32 height = mScreen.getHeight(); + glViewport(0, 0, width, height); + + LLGLSLShader* shader = &gGlowCombineFXAAProgram; + + shader->bind(); + shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height); + + S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage()); + if (channel > -1) + { + mDeferredLight.bindTexture(0, channel); + } + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex2f(-1,-1); + gGL.vertex2f(-1,3); + gGL.vertex2f(3,-1); + gGL.end(); + + gGL.flush(); + + shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage()); + shader->unbind(); + + mFXAABuffer.flush(); + + shader = &gFXAAProgram; + shader->bind(); + + channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAABuffer.getUsage()); + if (channel > -1) + { + mFXAABuffer.bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; + gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; + gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); + gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); + glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); + + F32 scale_x = (F32) width/mFXAABuffer.getWidth(); + F32 scale_y = (F32) height/mFXAABuffer.getHeight(); + shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y); + shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f/width*scale_x, 1.f/height*scale_y); + shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f/width*scale_x, -0.5f/height*scale_y, 0.5f/width*scale_x, 0.5f/height*scale_y); + shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f/width*scale_x, -2.f/height*scale_y, 2.f/width*scale_x, 2.f/height*scale_y); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex2f(-1,-1); + gGL.vertex2f(-1,3); + gGL.vertex2f(3,-1); + gGL.end(); + + gGL.flush(); + shader->unbind(); + } + } + else + { + U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1; + LLPointer buff = new LLVertexBuffer(mask, 0); + buff->allocateBuffer(3,0,TRUE); + + LLStrider v; + LLStrider uv1; + LLStrider uv2; + + buff->getVertexStrider(v); + buff->getTexCoord0Strider(uv1); + buff->getTexCoord1Strider(uv2); + + uv1[0] = LLVector2(0, 0); + uv1[1] = LLVector2(0, 2); + uv1[2] = LLVector2(2, 0); + + uv2[0] = LLVector2(0, 0); + uv2[1] = LLVector2(0, tc2.mV[1]*2.f); + uv2[2] = LLVector2(tc2.mV[0]*2.f, 0); + + v[0] = LLVector3(-1,-1,0); + v[1] = LLVector3(-1,3,0); + v[2] = LLVector3(3,-1,0); + + buff->flush(); + + LLGLDisable blend(GL_BLEND); + + if (LLGLSLShader::sNoFixedFunction) + { + gGlowCombineProgram.bind(); + } + else + { + //tex unit 0 + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR); + //tex unit 1 + gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); + } + + gGL.getTexUnit(0)->bind(&mGlow[1]); + gGL.getTexUnit(1)->bind(&mScreen); + + LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + + buff->setBuffer(mask); + buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3); + + if (LLGLSLShader::sNoFixedFunction) + { + gGlowCombineProgram.unbind(); + } + else + { + gGL.getTexUnit(1)->disable(); + gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT); + + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } + + } - gGL.begin(LLRender::TRIANGLES); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1,-1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,3); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3,-1); - - gGL.end(); - gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); - if (LLGLSLShader::sNoFixedFunction) - { - gSplatTextureRectProgram.unbind(); - } - } + if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) + { + if (LLGLSLShader::sNoFixedFunction) + { + gSplatTextureRectProgram.bind(); + } + + gGL.setColorMask(true, false); + + LLVector2 tc1(0,0); + LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2, + (F32) gViewerWindow->getWorldViewHeightRaw()*2); + + LLGLEnable blend(GL_BLEND); + gGL.color4f(1,1,1,0.75f); + + gGL.getTexUnit(0)->bind(&mPhysicsDisplay); + + gGL.begin(LLRender::TRIANGLES); + gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); + gGL.vertex2f(-1,-1); + + gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); + gGL.vertex2f(-1,3); + + gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); + gGL.vertex2f(3,-1); + + gGL.end(); + gGL.flush(); + + if (LLGLSLShader::sNoFixedFunction) + { + gSplatTextureRectProgram.unbind(); + } + } - - if (LLRenderTarget::sUseFBO) - { //copy depth buffer from mScreen to framebuffer - LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), - 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); - } - + + if (LLRenderTarget::sUseFBO) + { //copy depth buffer from mScreen to framebuffer + LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), + 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); + } + - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); - LLVertexBuffer::unbind(); + LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); } @@ -8185,7 +8157,7 @@ static LLTrace::BlockTimerStatHandle FTM_BIND_DEFERRED("Bind Deferred"); void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target) { - LL_RECORD_BLOCK_TIME(FTM_BIND_DEFERRED); + LL_RECORD_BLOCK_TIME(FTM_BIND_DEFERRED); LLRenderTarget* deferred_target = &mDeferredScreen; LLRenderTarget* deferred_depth_target = &mDeferredDepth; @@ -8317,38 +8289,38 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ } } - F32 mat[16*6]; - for (U32 i = 0; i < 16; i++) - { - mat[i] = mSunShadowMatrix[0].m[i]; - mat[i+16] = mSunShadowMatrix[1].m[i]; - mat[i+32] = mSunShadowMatrix[2].m[i]; - mat[i+48] = mSunShadowMatrix[3].m[i]; - mat[i+64] = mSunShadowMatrix[4].m[i]; - mat[i+80] = mSunShadowMatrix[5].m[i]; - } + F32 mat[16*6]; + for (U32 i = 0; i < 16; i++) + { + mat[i] = mSunShadowMatrix[0].m[i]; + mat[i+16] = mSunShadowMatrix[1].m[i]; + mat[i+32] = mSunShadowMatrix[2].m[i]; + mat[i+48] = mSunShadowMatrix[3].m[i]; + mat[i+64] = mSunShadowMatrix[4].m[i]; + mat[i+80] = mSunShadowMatrix[5].m[i]; + } - shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_SHADOW_MATRIX, 6, FALSE, mat); + shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_SHADOW_MATRIX, 6, FALSE, mat); - stop_glerror(); + stop_glerror(); - channel = shader.enableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); - if (channel > -1) - { - LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; - if (cube_map) - { - cube_map->enable(channel); - cube_map->bind(); - F32* m = gGLModelView; - - F32 mat[] = { m[0], m[1], m[2], - m[4], m[5], m[6], - m[8], m[9], m[10] }; - - shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat); - } - } + channel = shader.enableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); + if (channel > -1) + { + LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; + if (cube_map) + { + cube_map->enable(channel); + cube_map->bind(); + F32* m = gGLModelView; + + F32 mat[] = { m[0], m[1], m[2], + m[4], m[5], m[6], + m[8], m[9], m[10] }; + + shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat); + } + } if (gAtmosphere) { @@ -8434,18 +8406,18 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ LLColor3 pow3f(LLColor3 v, F32 f) { - v.mV[0] = powf(v.mV[0], f); - v.mV[1] = powf(v.mV[1], f); - v.mV[2] = powf(v.mV[2], f); - return v; + v.mV[0] = powf(v.mV[0], f); + v.mV[1] = powf(v.mV[1], f); + v.mV[2] = powf(v.mV[2], f); + return v; } LLVector4 pow4fsrgb(LLVector4 v, F32 f) { - v.mV[0] = powf(v.mV[0], f); - v.mV[1] = powf(v.mV[1], f); - v.mV[2] = powf(v.mV[2], f); - return v; + v.mV[0] = powf(v.mV[0], f); + v.mV[1] = powf(v.mV[1], f); + v.mV[2] = powf(v.mV[2], f); + return v; } static LLTrace::BlockTimerStatHandle FTM_GI_TRACE("Trace"); @@ -9088,141 +9060,141 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep) { - //construct frustum - LLVOVolume* volume = drawablep->getVOVolume(); - LLVector3 params = volume->getSpotLightParams(); - - F32 fov = params.mV[0]; - F32 focus = params.mV[1]; + //construct frustum + LLVOVolume* volume = drawablep->getVOVolume(); + LLVector3 params = volume->getSpotLightParams(); - LLVector3 pos = drawablep->getPositionAgent(); - LLQuaternion quat = volume->getRenderRotation(); - LLVector3 scale = volume->getScale(); - - //get near clip plane - LLVector3 at_axis(0,0,-scale.mV[2]*0.5f); - at_axis *= quat; - - LLVector3 np = pos+at_axis; - at_axis.normVec(); + F32 fov = params.mV[0]; + F32 focus = params.mV[1]; - //get origin that has given fov for plane np, at_axis, and given scale - F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f); + LLVector3 pos = drawablep->getPositionAgent(); + LLQuaternion quat = volume->getRenderRotation(); + LLVector3 scale = volume->getScale(); + + //get near clip plane + LLVector3 at_axis(0,0,-scale.mV[2]*0.5f); + at_axis *= quat; - LLVector3 origin = np - at_axis*dist; + LLVector3 np = pos+at_axis; + at_axis.normVec(); - //matrix from volume space to agent space - LLMatrix4 light_mat(quat, LLVector4(origin,1.f)); + //get origin that has given fov for plane np, at_axis, and given scale + F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f); - glh::matrix4f light_to_agent((F32*) light_mat.mMatrix); - glh::matrix4f light_to_screen = get_current_modelview() * light_to_agent; + LLVector3 origin = np - at_axis*dist; - glh::matrix4f screen_to_light = light_to_screen.inverse(); + //matrix from volume space to agent space + LLMatrix4 light_mat(quat, LLVector4(origin,1.f)); - F32 s = volume->getLightRadius()*1.5f; - F32 near_clip = dist; - F32 width = scale.mV[VX]; - F32 height = scale.mV[VY]; - F32 far_clip = s+dist-scale.mV[VZ]; + glh::matrix4f light_to_agent((F32*) light_mat.mMatrix); + glh::matrix4f light_to_screen = get_current_modelview() * light_to_agent; - F32 fovy = fov * RAD_TO_DEG; - F32 aspect = width/height; + glh::matrix4f screen_to_light = light_to_screen.inverse(); - glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f, - 0.f, 0.5f, 0.f, 0.5f, - 0.f, 0.f, 0.5f, 0.5f, - 0.f, 0.f, 0.f, 1.f); + F32 s = volume->getLightRadius()*1.5f; + F32 near_clip = dist; + F32 width = scale.mV[VX]; + F32 height = scale.mV[VY]; + F32 far_clip = s+dist-scale.mV[VZ]; - glh::vec3f p1(0, 0, -(near_clip+0.01f)); - glh::vec3f p2(0, 0, -(near_clip+1.f)); + F32 fovy = fov * RAD_TO_DEG; + F32 aspect = width/height; - glh::vec3f screen_origin(0, 0, 0); + glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f, + 0.f, 0.5f, 0.f, 0.5f, + 0.f, 0.f, 0.5f, 0.5f, + 0.f, 0.f, 0.f, 1.f); - light_to_screen.mult_matrix_vec(p1); - light_to_screen.mult_matrix_vec(p2); - light_to_screen.mult_matrix_vec(screen_origin); + glh::vec3f p1(0, 0, -(near_clip+0.01f)); + glh::vec3f p2(0, 0, -(near_clip+1.f)); - glh::vec3f n = p2-p1; - n.normalize(); - - F32 proj_range = far_clip - near_clip; - glh::matrix4f light_proj = gl_perspective(fovy, aspect, near_clip, far_clip); - screen_to_light = trans * light_proj * screen_to_light; - shader.uniformMatrix4fv(LLShaderMgr::PROJECTOR_MATRIX, 1, FALSE, screen_to_light.m); - shader.uniform1f(LLShaderMgr::PROJECTOR_NEAR, near_clip); - shader.uniform3fv(LLShaderMgr::PROJECTOR_P, 1, p1.v); - shader.uniform3fv(LLShaderMgr::PROJECTOR_N, 1, n.v); - shader.uniform3fv(LLShaderMgr::PROJECTOR_ORIGIN, 1, screen_origin.v); - shader.uniform1f(LLShaderMgr::PROJECTOR_RANGE, proj_range); - shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIANCE, params.mV[2]); - S32 s_idx = -1; - - for (U32 i = 0; i < 2; i++) - { - if (mShadowSpotLight[i] == drawablep) - { - s_idx = i; - } - } + glh::vec3f screen_origin(0, 0, 0); - shader.uniform1i(LLShaderMgr::PROJECTOR_SHADOW_INDEX, s_idx); + light_to_screen.mult_matrix_vec(p1); + light_to_screen.mult_matrix_vec(p2); + light_to_screen.mult_matrix_vec(screen_origin); - if (s_idx >= 0) - { - shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f-mSpotLightFade[s_idx]); - } - else - { - shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f); - } + glh::vec3f n = p2-p1; + n.normalize(); + + F32 proj_range = far_clip - near_clip; + glh::matrix4f light_proj = gl_perspective(fovy, aspect, near_clip, far_clip); + screen_to_light = trans * light_proj * screen_to_light; + shader.uniformMatrix4fv(LLShaderMgr::PROJECTOR_MATRIX, 1, FALSE, screen_to_light.m); + shader.uniform1f(LLShaderMgr::PROJECTOR_NEAR, near_clip); + shader.uniform3fv(LLShaderMgr::PROJECTOR_P, 1, p1.v); + shader.uniform3fv(LLShaderMgr::PROJECTOR_N, 1, n.v); + shader.uniform3fv(LLShaderMgr::PROJECTOR_ORIGIN, 1, screen_origin.v); + shader.uniform1f(LLShaderMgr::PROJECTOR_RANGE, proj_range); + shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIANCE, params.mV[2]); + S32 s_idx = -1; - { - LLDrawable* potential = drawablep; - //determine if this is a good light for casting shadows - F32 m_pri = volume->getSpotLightPriority(); + for (U32 i = 0; i < 2; i++) + { + if (mShadowSpotLight[i] == drawablep) + { + s_idx = i; + } + } - for (U32 i = 0; i < 2; i++) - { - F32 pri = 0.f; + shader.uniform1i(LLShaderMgr::PROJECTOR_SHADOW_INDEX, s_idx); - if (mTargetShadowSpotLight[i].notNull()) - { - pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority(); - } + if (s_idx >= 0) + { + shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f-mSpotLightFade[s_idx]); + } + else + { + shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f); + } - if (m_pri > pri) - { - LLDrawable* temp = mTargetShadowSpotLight[i]; - mTargetShadowSpotLight[i] = potential; - potential = temp; - m_pri = pri; - } - } - } + { + LLDrawable* potential = drawablep; + //determine if this is a good light for casting shadows + F32 m_pri = volume->getSpotLightPriority(); + + for (U32 i = 0; i < 2; i++) + { + F32 pri = 0.f; + + if (mTargetShadowSpotLight[i].notNull()) + { + pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority(); + } + + if (m_pri > pri) + { + LLDrawable* temp = mTargetShadowSpotLight[i]; + mTargetShadowSpotLight[i] = potential; + potential = temp; + m_pri = pri; + } + } + } - LLViewerTexture* img = volume->getLightTexture(); + LLViewerTexture* img = volume->getLightTexture(); - if (img == NULL) - { - img = LLViewerFetchedTexture::sWhiteImagep; - } + if (img == NULL) + { + img = LLViewerFetchedTexture::sWhiteImagep; + } - S32 channel = shader.enableTexture(LLShaderMgr::DEFERRED_PROJECTION); + S32 channel = shader.enableTexture(LLShaderMgr::DEFERRED_PROJECTION); - if (channel > -1) - { - if (img) - { - gGL.getTexUnit(channel)->bind(img); + if (channel > -1) + { + if (img) + { + gGL.getTexUnit(channel)->bind(img); - F32 lod_range = logf(img->getWidth())/logf(2.f); + F32 lod_range = logf(img->getWidth())/logf(2.f); - shader.uniform1f(LLShaderMgr::PROJECTOR_FOCUS, focus); - shader.uniform1f(LLShaderMgr::PROJECTOR_LOD, lod_range); - shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIENT_LOD, llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f)); - } - } - + shader.uniform1f(LLShaderMgr::PROJECTOR_FOCUS, focus); + shader.uniform1f(LLShaderMgr::PROJECTOR_LOD, lod_range); + shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIENT_LOD, llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f)); + } + } + } void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) @@ -9555,68 +9527,68 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up) { - glh::matrix4f ret; + glh::matrix4f ret; - LLVector3 dirN; - LLVector3 upN; - LLVector3 lftN; + LLVector3 dirN; + LLVector3 upN; + LLVector3 lftN; - lftN = dir % up; - lftN.normVec(); - - upN = lftN % dir; - upN.normVec(); - - dirN = dir; - dirN.normVec(); + lftN = dir % up; + lftN.normVec(); + + upN = lftN % dir; + upN.normVec(); + + dirN = dir; + dirN.normVec(); - ret.m[ 0] = lftN[0]; - ret.m[ 1] = upN[0]; - ret.m[ 2] = -dirN[0]; - ret.m[ 3] = 0.f; + ret.m[ 0] = lftN[0]; + ret.m[ 1] = upN[0]; + ret.m[ 2] = -dirN[0]; + ret.m[ 3] = 0.f; - ret.m[ 4] = lftN[1]; - ret.m[ 5] = upN[1]; - ret.m[ 6] = -dirN[1]; - ret.m[ 7] = 0.f; + ret.m[ 4] = lftN[1]; + ret.m[ 5] = upN[1]; + ret.m[ 6] = -dirN[1]; + ret.m[ 7] = 0.f; - ret.m[ 8] = lftN[2]; - ret.m[ 9] = upN[2]; - ret.m[10] = -dirN[2]; - ret.m[11] = 0.f; + ret.m[ 8] = lftN[2]; + ret.m[ 9] = upN[2]; + ret.m[10] = -dirN[2]; + ret.m[11] = 0.f; - ret.m[12] = -(lftN*pos); - ret.m[13] = -(upN*pos); - ret.m[14] = dirN*pos; - ret.m[15] = 1.f; + ret.m[12] = -(lftN*pos); + ret.m[13] = -(upN*pos); + ret.m[14] = dirN*pos; + ret.m[15] = 1.f; - return ret; + return ret; } glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max) { - glh::matrix4f ret; - ret.m[ 0] = 2/(max[0]-min[0]); - ret.m[ 4] = 0; - ret.m[ 8] = 0; - ret.m[12] = -(max[0]+min[0])/(max[0]-min[0]); + glh::matrix4f ret; + ret.m[ 0] = 2/(max[0]-min[0]); + ret.m[ 4] = 0; + ret.m[ 8] = 0; + ret.m[12] = -(max[0]+min[0])/(max[0]-min[0]); - ret.m[ 1] = 0; - ret.m[ 5] = 2/(max[1]-min[1]); - ret.m[ 9] = 0; - ret.m[13] = -(max[1]+min[1])/(max[1]-min[1]); + ret.m[ 1] = 0; + ret.m[ 5] = 2/(max[1]-min[1]); + ret.m[ 9] = 0; + ret.m[13] = -(max[1]+min[1])/(max[1]-min[1]); - ret.m[ 2] = 0; - ret.m[ 6] = 0; - ret.m[10] = 2/(max[2]-min[2]); - ret.m[14] = -(max[2]+min[2])/(max[2]-min[2]); + ret.m[ 2] = 0; + ret.m[ 6] = 0; + ret.m[10] = 2/(max[2]-min[2]); + ret.m[14] = -(max[2]+min[2])/(max[2]-min[2]); - ret.m[ 3] = 0; - ret.m[ 7] = 0; - ret.m[11] = 0; - ret.m[15] = 1; + ret.m[ 3] = 0; + ret.m[ 7] = 0; + ret.m[11] = 0; + ret.m[15] = 1; - return ret; + return ret; } static LLTrace::BlockTimerStatHandle FTM_SHADOW_RENDER("Render Shadows"); @@ -9631,61 +9603,61 @@ static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_GRASS("Alpha Grass"); void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, bool use_shader, bool use_occlusion, U32 target_width) { - LL_RECORD_BLOCK_TIME(FTM_SHADOW_RENDER); - - //clip out geometry on the same side of water as the camera - S32 occlude = LLPipeline::sUseOcclusion; - if (!use_occlusion) - { - LLPipeline::sUseOcclusion = 0; - } - LLPipeline::sShadowRender = true; - - static const U32 types[] = { - LLRenderPass::PASS_SIMPLE, - LLRenderPass::PASS_FULLBRIGHT, - LLRenderPass::PASS_SHINY, - LLRenderPass::PASS_BUMP, - LLRenderPass::PASS_FULLBRIGHT_SHINY , - LLRenderPass::PASS_MATERIAL, - LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, - LLRenderPass::PASS_SPECMAP, - LLRenderPass::PASS_SPECMAP_EMISSIVE, - LLRenderPass::PASS_NORMMAP, - LLRenderPass::PASS_NORMMAP_EMISSIVE, - LLRenderPass::PASS_NORMSPEC, - LLRenderPass::PASS_NORMSPEC_EMISSIVE, - }; - - LLGLEnable cull(GL_CULL_FACE); - - //enable depth clamping if available - LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_RENDER); - if (use_shader) - { - gDeferredShadowCubeProgram.bind(); - } + //clip out geometry on the same side of water as the camera + S32 occlude = LLPipeline::sUseOcclusion; + if (!use_occlusion) + { + LLPipeline::sUseOcclusion = 0; + } + LLPipeline::sShadowRender = true; + + static const U32 types[] = { + LLRenderPass::PASS_SIMPLE, + LLRenderPass::PASS_FULLBRIGHT, + LLRenderPass::PASS_SHINY, + LLRenderPass::PASS_BUMP, + LLRenderPass::PASS_FULLBRIGHT_SHINY , + LLRenderPass::PASS_MATERIAL, + LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, + LLRenderPass::PASS_SPECMAP, + LLRenderPass::PASS_SPECMAP_EMISSIVE, + LLRenderPass::PASS_NORMMAP, + LLRenderPass::PASS_NORMMAP_EMISSIVE, + LLRenderPass::PASS_NORMSPEC, + LLRenderPass::PASS_NORMSPEC_EMISSIVE, + }; + + LLGLEnable cull(GL_CULL_FACE); + + //enable depth clamping if available + LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0); + + if (use_shader) + { + gDeferredShadowCubeProgram.bind(); + } - LLRenderTarget& occlusion_target = mShadowOcclusion[LLViewerCamera::sCurCameraID-1]; + LLRenderTarget& occlusion_target = mShadowOcclusion[LLViewerCamera::sCurCameraID-1]; - occlusion_target.bindTarget(); - updateCull(shadow_cam, result); - occlusion_target.flush(); + occlusion_target.bindTarget(); + updateCull(shadow_cam, result); + occlusion_target.flush(); - stateSort(shadow_cam, result); - - - //generate shadow map - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadMatrix(proj.m); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.loadMatrix(view.m); + stateSort(shadow_cam, result); + + + //generate shadow map + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadMatrix(proj.m); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadMatrix(view.m); - stop_glerror(); - gGLLastMatrix = NULL; + stop_glerror(); + gGLLastMatrix = NULL; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -9819,262 +9791,255 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera static LLTrace::BlockTimerStatHandle FTM_VISIBLE_CLOUD("Visible Cloud"); bool LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector& fp, LLVector3 light_dir) { - LL_RECORD_BLOCK_TIME(FTM_VISIBLE_CLOUD); - //get point cloud of intersection of frust and min, max - - if (getVisibleExtents(camera, min, max)) - { - return false; - } - - //get set of planes on bounding box - LLPlane bp[] = { - LLPlane(min, LLVector3(-1,0,0)), - LLPlane(min, LLVector3(0,-1,0)), - LLPlane(min, LLVector3(0,0,-1)), - LLPlane(max, LLVector3(1,0,0)), - LLPlane(max, LLVector3(0,1,0)), - LLPlane(max, LLVector3(0,0,1))}; - - //potential points - std::vector pp; - - //add corners of AABB - pp.push_back(LLVector3(min.mV[0], min.mV[1], min.mV[2])); - pp.push_back(LLVector3(max.mV[0], min.mV[1], min.mV[2])); - pp.push_back(LLVector3(min.mV[0], max.mV[1], min.mV[2])); - pp.push_back(LLVector3(max.mV[0], max.mV[1], min.mV[2])); - pp.push_back(LLVector3(min.mV[0], min.mV[1], max.mV[2])); - pp.push_back(LLVector3(max.mV[0], min.mV[1], max.mV[2])); - pp.push_back(LLVector3(min.mV[0], max.mV[1], max.mV[2])); - pp.push_back(LLVector3(max.mV[0], max.mV[1], max.mV[2])); - - //add corners of camera frustum - for (U32 i = 0; i < LLCamera::AGENT_FRUSTRUM_NUM; i++) - { - pp.push_back(camera.mAgentFrustum[i]); - } - - - //bounding box line segments - U32 bs[] = - { - 0,1, - 1,3, - 3,2, - 2,0, - - 4,5, - 5,7, - 7,6, - 6,4, - - 0,4, - 1,5, - 3,7, - 2,6 - }; - - for (U32 i = 0; i < 12; i++) - { //for each line segment in bounding box - for (U32 j = 0; j < LLCamera::AGENT_PLANE_NO_USER_CLIP_NUM; j++) - { //for each plane in camera frustum - const LLPlane& cp = camera.getAgentPlane(j); - const LLVector3& v1 = pp[bs[i*2+0]]; - const LLVector3& v2 = pp[bs[i*2+1]]; - LLVector3 n; - cp.getVector3(n); - - LLVector3 line = v1-v2; - - F32 d1 = line*n; - F32 d2 = -cp.dist(v2); - - F32 t = d2/d1; - - if (t > 0.f && t < 1.f) - { - LLVector3 intersect = v2+line*t; - pp.push_back(intersect); - } - } - } - - //camera frustum line segments - const U32 fs[] = - { - 0,1, - 1,2, - 2,3, - 3,0, - - 4,5, - 5,6, - 6,7, - 7,4, - - 0,4, - 1,5, - 2,6, - 3,7 - }; + LL_RECORD_BLOCK_TIME(FTM_VISIBLE_CLOUD); + //get point cloud of intersection of frust and min, max - for (U32 i = 0; i < 12; i++) - { - for (U32 j = 0; j < 6; ++j) - { - const LLVector3& v1 = pp[fs[i*2+0]+8]; - const LLVector3& v2 = pp[fs[i*2+1]+8]; - const LLPlane& cp = bp[j]; - LLVector3 n; - cp.getVector3(n); - - LLVector3 line = v1-v2; - - F32 d1 = line*n; - F32 d2 = -cp.dist(v2); - - F32 t = d2/d1; - - if (t > 0.f && t < 1.f) - { - LLVector3 intersect = v2+line*t; - pp.push_back(intersect); - } - } - } + if (getVisibleExtents(camera, min, max)) + { + return false; + } - LLVector3 ext[] = { min-LLVector3(0.05f,0.05f,0.05f), - max+LLVector3(0.05f,0.05f,0.05f) }; + //get set of planes on bounding box + LLPlane bp[] = { + LLPlane(min, LLVector3(-1,0,0)), + LLPlane(min, LLVector3(0,-1,0)), + LLPlane(min, LLVector3(0,0,-1)), + LLPlane(max, LLVector3(1,0,0)), + LLPlane(max, LLVector3(0,1,0)), + LLPlane(max, LLVector3(0,0,1))}; + + //potential points + std::vector pp; + + //add corners of AABB + pp.push_back(LLVector3(min.mV[0], min.mV[1], min.mV[2])); + pp.push_back(LLVector3(max.mV[0], min.mV[1], min.mV[2])); + pp.push_back(LLVector3(min.mV[0], max.mV[1], min.mV[2])); + pp.push_back(LLVector3(max.mV[0], max.mV[1], min.mV[2])); + pp.push_back(LLVector3(min.mV[0], min.mV[1], max.mV[2])); + pp.push_back(LLVector3(max.mV[0], min.mV[1], max.mV[2])); + pp.push_back(LLVector3(min.mV[0], max.mV[1], max.mV[2])); + pp.push_back(LLVector3(max.mV[0], max.mV[1], max.mV[2])); + + //add corners of camera frustum + for (U32 i = 0; i < LLCamera::AGENT_FRUSTRUM_NUM; i++) + { + pp.push_back(camera.mAgentFrustum[i]); + } - for (U32 i = 0; i < pp.size(); ++i) - { - bool found = true; - const F32* p = pp[i].mV; - - for (U32 j = 0; j < 3; ++j) - { - if (p[j] < ext[0].mV[j] || p[j] > ext[1].mV[j]) - { - found = false; - break; - } - } - - if (found) // don't bother testing user clip planes if we're already rejected... - { - for (U32 j = 0; j < LLCamera::AGENT_PLANE_NO_USER_CLIP_NUM; ++j) - { - const LLPlane& cp = camera.getAgentPlane(j); - F32 dist = cp.dist(pp[i]); - if (dist > 0.05f) //point is above some plane, not contained - { - found = false; - break; - } - } - } + //bounding box line segments + U32 bs[] = + { + 0,1, + 1,3, + 3,2, + 2,0, + + 4,5, + 5,7, + 7,6, + 6,4, + + 0,4, + 1,5, + 3,7, + 2,6 + }; + + for (U32 i = 0; i < 12; i++) + { //for each line segment in bounding box + for (U32 j = 0; j < LLCamera::AGENT_PLANE_NO_USER_CLIP_NUM; j++) + { //for each plane in camera frustum + const LLPlane& cp = camera.getAgentPlane(j); + const LLVector3& v1 = pp[bs[i*2+0]]; + const LLVector3& v2 = pp[bs[i*2+1]]; + LLVector3 n; + cp.getVector3(n); + + LLVector3 line = v1-v2; + + F32 d1 = line*n; + F32 d2 = -cp.dist(v2); + + F32 t = d2/d1; + + if (t > 0.f && t < 1.f) + { + LLVector3 intersect = v2+line*t; + pp.push_back(intersect); + } + } + } + + //camera frustum line segments + const U32 fs[] = + { + 0,1, + 1,2, + 2,3, + 3,0, + + 4,5, + 5,6, + 6,7, + 7,4, + + 0,4, + 1,5, + 2,6, + 3,7 + }; + + for (U32 i = 0; i < 12; i++) + { + for (U32 j = 0; j < 6; ++j) + { + const LLVector3& v1 = pp[fs[i*2+0]+8]; + const LLVector3& v2 = pp[fs[i*2+1]+8]; + const LLPlane& cp = bp[j]; + LLVector3 n; + cp.getVector3(n); + + LLVector3 line = v1-v2; + + F32 d1 = line*n; + F32 d2 = -cp.dist(v2); + + F32 t = d2/d1; + + if (t > 0.f && t < 1.f) + { + LLVector3 intersect = v2+line*t; + pp.push_back(intersect); + } + } + } - if (found) - { - fp.push_back(pp[i]); - } - } - - if (fp.empty()) - { - return false; - } - - return true; -} + LLVector3 ext[] = { min-LLVector3(0.05f,0.05f,0.05f), + max+LLVector3(0.05f,0.05f,0.05f) }; -void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade) -{ - BOOL shaders = canUseVertexShaders(); - if(shaders) + for (U32 i = 0; i < pp.size(); ++i) { - gHighlightProgram.bind(); + bool found = true; + + const F32* p = pp[i].mV; + + for (U32 j = 0; j < 3; ++j) + { + if (p[j] < ext[0].mV[j] || + p[j] > ext[1].mV[j]) + { + found = false; + break; + } + } + + for (U32 j = 0; j < LLCamera::AGENT_PLANE_NO_USER_CLIP_NUM; ++j) + { + const LLPlane& cp = camera.getAgentPlane(j); + F32 dist = cp.dist(pp[i]); + if (dist > 0.05f) //point is above some plane, not contained + { + found = false; + break; + } + } + + if (found) + { + fp.push_back(pp[i]); + } } - else + + if (fp.empty()) { - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + return false; } - - if (obj && obj->getVolume()) - { - for (LLViewerObject::child_list_t::const_iterator iter = obj->getChildren().begin(); iter != obj->getChildren().end(); ++iter) - { - renderHighlight(*iter, fade); - } - - LLDrawable* drawable = obj->mDrawable; - if (drawable) - { - for (S32 i = 0; i < drawable->getNumFaces(); ++i) - { - LLFace* face = drawable->getFace(i); - if (face) - { - face->renderSelected(LLViewerTexture::sNullImagep, LLColor4(1,1,1,fade)); - } - } - } - } + + return true; } -void LLPipeline::generateHighlight(LLCamera& camera) -{ - //render highlighted object as white into offscreen render target - if (mHighlightObject.notNull()) - { - mHighlightSet.insert(HighlightItem(mHighlightObject)); - } - - if (!mHighlightSet.empty()) - { - F32 transition = gFrameIntervalSeconds.value()/RenderHighlightFadeTime; - - LLGLDisable test(GL_ALPHA_TEST); - LLGLDepthTest depth(GL_FALSE); - mHighlight.bindTarget(); - disableLights(); - gGL.setColorMask(true, true); - mHighlight.clear(); - - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); - for (std::set::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ) - { - std::set::iterator cur_iter = iter++; - - if (cur_iter->mItem.isNull()) - { - mHighlightSet.erase(cur_iter); - continue; - } - - if (cur_iter->mItem == mHighlightObject) - { - cur_iter->incrFade(transition); - } - else - { - cur_iter->incrFade(-transition); - if (cur_iter->mFade <= 0.f) - { - mHighlightSet.erase(cur_iter); - continue; - } - } +void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade) +{ + if (obj && obj->getVolume()) + { + for (LLViewerObject::child_list_t::const_iterator iter = obj->getChildren().begin(); iter != obj->getChildren().end(); ++iter) + { + renderHighlight(*iter, fade); + } + + LLDrawable* drawable = obj->mDrawable; + if (drawable) + { + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + LLFace* face = drawable->getFace(i); + if (face) + { + face->renderSelected(LLViewerTexture::sNullImagep, LLColor4(1,1,1,fade)); + } + } + } + } +} - renderHighlight(cur_iter->mItem->getVObj(), cur_iter->mFade); - } +void LLPipeline::generateHighlight(LLCamera& camera) +{ + //render highlighted object as white into offscreen render target + if (mHighlightObject.notNull()) + { + mHighlightSet.insert(HighlightItem(mHighlightObject)); + } + + if (!mHighlightSet.empty()) + { + F32 transition = gFrameIntervalSeconds.value()/RenderHighlightFadeTime; - mHighlight.flush(); - gGL.setColorMask(true, false); - gViewerWindow->setup3DViewport(); - } + LLGLDisable test(GL_ALPHA_TEST); + LLGLDepthTest depth(GL_FALSE); + mHighlight.bindTarget(); + disableLights(); + gGL.setColorMask(true, true); + mHighlight.clear(); + + if (LLGLSLShader::sNoFixedFunction) + { + gHighlightProgram.bind(); + } + + gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); + for (std::set::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ) + { + std::set::iterator cur_iter = iter++; + + if (cur_iter->mItem.isNull()) + { + mHighlightSet.erase(cur_iter); + continue; + } + + if (cur_iter->mItem == mHighlightObject) + { + cur_iter->incrFade(transition); + } + else + { + cur_iter->incrFade(-transition); + if (cur_iter->mFade <= 0.f) + { + mHighlightSet.erase(cur_iter); + continue; + } + } + + renderHighlight(cur_iter->mItem->getVObj(), cur_iter->mFade); + } + + mHighlight.flush(); + gGL.setColorMask(true, false); + gViewerWindow->setup3DViewport(); + } } LLRenderTarget* LLPipeline::getShadowTarget(U32 i) @@ -10931,17 +10896,17 @@ void LLPipeline::generateSunShadow(LLCamera& camera) void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture) { - for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) - { - LLSpatialGroup* group = *i; - if (!group->isDead() && - (!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && - gPipeline.hasRenderType(group->getSpatialPartition()->mDrawableType) && - group->mDrawMap.find(type) != group->mDrawMap.end()) - { - pass->renderGroup(group,type,mask,texture); - } - } + for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) + { + LLSpatialGroup* group = *i; + if (!group->isDead() && + (!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && + gPipeline.hasRenderType(group->getSpatialPartition()->mDrawableType) && + group->mDrawMap.find(type) != group->mDrawMap.end()) + { + pass->renderGroup(group,type,mask,texture); + } + } } static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_MARK_VISIBLE("Impostor Mark Visible"); @@ -10952,364 +10917,364 @@ static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_RESIZE("Impostor Resize"); void LLPipeline::generateImpostor(LLVOAvatar* avatar) { - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); - static LLCullResult result; - result.clear(); - grabReferences(result); - - if (!avatar || !avatar->mDrawable) - { + static LLCullResult result; + result.clear(); + grabReferences(result); + + if (!avatar || !avatar->mDrawable) + { LL_WARNS_ONCE("AvatarRenderPipeline") << "Avatar is " << (avatar ? "not drawable" : "null") << LL_ENDL; - return; - } + return; + } LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " is drawable" << LL_ENDL; - assertInitialized(); + assertInitialized(); - bool visually_muted = avatar->isVisuallyMuted(); + bool visually_muted = avatar->isVisuallyMuted(); LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " is " << ( visually_muted ? "" : "not ") << "visually muted" << LL_ENDL; - bool too_complex = avatar->isTooComplex(); + bool too_complex = avatar->isTooComplex(); LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " is " << ( too_complex ? "" : "not ") << "too complex" << LL_ENDL; - pushRenderTypeMask(); - - if (visually_muted || too_complex) - { - andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); - } - else - { - andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA, - LLPipeline::RENDER_TYPE_FULLBRIGHT, - LLPipeline::RENDER_TYPE_VOLUME, - LLPipeline::RENDER_TYPE_GLOW, - LLPipeline::RENDER_TYPE_BUMP, - LLPipeline::RENDER_TYPE_PASS_SIMPLE, - LLPipeline::RENDER_TYPE_PASS_ALPHA, - LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK, - LLPipeline::RENDER_TYPE_PASS_BUMP, - LLPipeline::RENDER_TYPE_PASS_POST_BUMP, - LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, - LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK, - LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, - LLPipeline::RENDER_TYPE_PASS_GLOW, - LLPipeline::RENDER_TYPE_PASS_GRASS, - LLPipeline::RENDER_TYPE_PASS_SHINY, - LLPipeline::RENDER_TYPE_PASS_INVISIBLE, - LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY, - LLPipeline::RENDER_TYPE_AVATAR, - LLPipeline::RENDER_TYPE_ALPHA_MASK, - LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, - LLPipeline::RENDER_TYPE_INVISIBLE, - LLPipeline::RENDER_TYPE_SIMPLE, - END_RENDER_TYPES); - } - - S32 occlusion = sUseOcclusion; - sUseOcclusion = 0; - - sReflectionRender = ! sRenderDeferred; - - sShadowRender = true; - sImpostorRender = true; - - LLViewerCamera* viewer_camera = LLViewerCamera::getInstance(); - - { - LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_MARK_VISIBLE); - markVisible(avatar->mDrawable, *viewer_camera); - LLVOAvatar::sUseImpostors = false; // @TODO ??? - - LLVOAvatar::attachment_map_t::iterator iter; - for (iter = avatar->mAttachmentPoints.begin(); - iter != avatar->mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment *attachment = iter->second; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - if (LLViewerObject* attached_object = (*attachment_iter)) - { - markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera); - } - } - } - } - - stateSort(*LLViewerCamera::getInstance(), result); - - LLCamera camera = *viewer_camera; - LLVector2 tdim; - U32 resY = 0; - U32 resX = 0; - - { - LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_SETUP); - const LLVector4a* ext = avatar->mDrawable->getSpatialExtents(); - LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); - - camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis()); - - LLVector4a half_height; - half_height.setSub(ext[1], ext[0]); - half_height.mul(0.5f); - - LLVector4a left; - left.load3(camera.getLeftAxis().mV); - left.mul(left); - llassert(left.dot3(left).getF32() > F_APPROXIMATELY_ZERO); - left.normalize3fast(); - - LLVector4a up; - up.load3(camera.getUpAxis().mV); - up.mul(up); - llassert(up.dot3(up).getF32() > F_APPROXIMATELY_ZERO); - up.normalize3fast(); - - tdim.mV[0] = fabsf(half_height.dot3(left).getF32()); - tdim.mV[1] = fabsf(half_height.dot3(up).getF32()); - - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - - F32 distance = (pos-camera.getOrigin()).length(); - F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG; - F32 aspect = tdim.mV[0]/tdim.mV[1]; - glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f); - set_current_projection(persp); - gGL.loadMatrix(persp.m); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - glh::matrix4f mat; - camera.getOpenGLTransform(mat.m); - - mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat; + pushRenderTypeMask(); + + if (visually_muted || too_complex) + { + andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); + } + else + { + andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA, + LLPipeline::RENDER_TYPE_FULLBRIGHT, + LLPipeline::RENDER_TYPE_VOLUME, + LLPipeline::RENDER_TYPE_GLOW, + LLPipeline::RENDER_TYPE_BUMP, + LLPipeline::RENDER_TYPE_PASS_SIMPLE, + LLPipeline::RENDER_TYPE_PASS_ALPHA, + LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_BUMP, + LLPipeline::RENDER_TYPE_PASS_POST_BUMP, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, + LLPipeline::RENDER_TYPE_PASS_GLOW, + LLPipeline::RENDER_TYPE_PASS_GRASS, + LLPipeline::RENDER_TYPE_PASS_SHINY, + LLPipeline::RENDER_TYPE_PASS_INVISIBLE, + LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY, + LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_ALPHA_MASK, + LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, + LLPipeline::RENDER_TYPE_INVISIBLE, + LLPipeline::RENDER_TYPE_SIMPLE, + END_RENDER_TYPES); + } + + S32 occlusion = sUseOcclusion; + sUseOcclusion = 0; - gGL.loadMatrix(mat.m); - set_current_modelview(mat); + sReflectionRender = ! sRenderDeferred; - glClearColor(0.0f,0.0f,0.0f,0.0f); - gGL.setColorMask(true, true); - - // get the number of pixels per angle - F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView()); + sShadowRender = true; + sImpostorRender = true; - //get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing) - resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512); - resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512); + LLViewerCamera* viewer_camera = LLViewerCamera::getInstance(); - if (!avatar->mImpostor.isComplete()) - { - LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_ALLOCATE); - + { + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_MARK_VISIBLE); + markVisible(avatar->mDrawable, *viewer_camera); + LLVOAvatar::sUseImpostors = false; // @TODO ??? + + LLVOAvatar::attachment_map_t::iterator iter; + for (iter = avatar->mAttachmentPoints.begin(); + iter != avatar->mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment *attachment = iter->second; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + if (LLViewerObject* attached_object = (*attachment_iter)) + { + markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera); + } + } + } + } - if (LLPipeline::sRenderDeferred) - { - avatar->mImpostor.allocate(resX,resY,GL_SRGB8_ALPHA8,TRUE,FALSE); - addDeferredAttachments(avatar->mImpostor); - } - else - { - avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE); - } - - gGL.getTexUnit(0)->bind(&avatar->mImpostor); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - else if(resX != avatar->mImpostor.getWidth() || resY != avatar->mImpostor.getHeight()) - { - LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_RESIZE); - avatar->mImpostor.resize(resX,resY); - } + stateSort(*LLViewerCamera::getInstance(), result); + + LLCamera camera = *viewer_camera; + LLVector2 tdim; + U32 resY = 0; + U32 resX = 0; - avatar->mImpostor.bindTarget(); - } + { + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_SETUP); + const LLVector4a* ext = avatar->mDrawable->getSpatialExtents(); + LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); + + camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis()); + + LLVector4a half_height; + half_height.setSub(ext[1], ext[0]); + half_height.mul(0.5f); + + LLVector4a left; + left.load3(camera.getLeftAxis().mV); + left.mul(left); + llassert(left.dot3(left).getF32() > F_APPROXIMATELY_ZERO); + left.normalize3fast(); + + LLVector4a up; + up.load3(camera.getUpAxis().mV); + up.mul(up); + llassert(up.dot3(up).getF32() > F_APPROXIMATELY_ZERO); + up.normalize3fast(); + + tdim.mV[0] = fabsf(half_height.dot3(left).getF32()); + tdim.mV[1] = fabsf(half_height.dot3(up).getF32()); + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + + F32 distance = (pos-camera.getOrigin()).length(); + F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG; + F32 aspect = tdim.mV[0]/tdim.mV[1]; + glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f); + set_current_projection(persp); + gGL.loadMatrix(persp.m); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + glh::matrix4f mat; + camera.getOpenGLTransform(mat.m); + + mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat; + + gGL.loadMatrix(mat.m); + set_current_modelview(mat); + + glClearColor(0.0f,0.0f,0.0f,0.0f); + gGL.setColorMask(true, true); + + // get the number of pixels per angle + F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView()); + + //get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing) + resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512); + resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512); + + if (!avatar->mImpostor.isComplete()) + { + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_ALLOCATE); + + + if (LLPipeline::sRenderDeferred) + { + avatar->mImpostor.allocate(resX,resY,GL_SRGB8_ALPHA8,TRUE,FALSE); + addDeferredAttachments(avatar->mImpostor); + } + else + { + avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE); + } + + gGL.getTexUnit(0)->bind(&avatar->mImpostor); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + else if(resX != avatar->mImpostor.getWidth() || resY != avatar->mImpostor.getHeight()) + { + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_RESIZE); + avatar->mImpostor.resize(resX,resY); + } + + avatar->mImpostor.bindTarget(); + } - F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha; + F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha; - if (visually_muted || too_complex) - { //disable alpha masking for muted avatars (get whole skin silhouette) - LLDrawPoolAvatar::sMinimumAlpha = 0.f; - } + if (visually_muted || too_complex) + { //disable alpha masking for muted avatars (get whole skin silhouette) + LLDrawPoolAvatar::sMinimumAlpha = 0.f; + } - if (LLPipeline::sRenderDeferred) - { - avatar->mImpostor.clear(); - renderGeomDeferred(camera); + if (LLPipeline::sRenderDeferred) + { + avatar->mImpostor.clear(); + renderGeomDeferred(camera); - renderGeomPostDeferred(camera); + renderGeomPostDeferred(camera); - // Shameless hack time: render it all again, - // this time writing the depth - // values we need to generate the alpha mask below - // while preserving the alpha-sorted color rendering - // from the previous pass - // - sImpostorRenderAlphaDepthPass = true; - // depth-only here... - // - gGL.setColorMask(false,false); - renderGeomPostDeferred(camera); + // Shameless hack time: render it all again, + // this time writing the depth + // values we need to generate the alpha mask below + // while preserving the alpha-sorted color rendering + // from the previous pass + // + sImpostorRenderAlphaDepthPass = true; + // depth-only here... + // + gGL.setColorMask(false,false); + renderGeomPostDeferred(camera); - sImpostorRenderAlphaDepthPass = false; + sImpostorRenderAlphaDepthPass = false; - } - else - { - LLGLEnable scissor(GL_SCISSOR_TEST); - glScissor(0, 0, resX, resY); - avatar->mImpostor.clear(); - renderGeom(camera); - - // Shameless hack time: render it all again, - // this time writing the depth - // values we need to generate the alpha mask below - // while preserving the alpha-sorted color rendering - // from the previous pass - // - sImpostorRenderAlphaDepthPass = true; - - // depth-only here... - // - gGL.setColorMask(false,false); - renderGeom(camera); - - sImpostorRenderAlphaDepthPass = false; - } + } + else + { + LLGLEnable scissor(GL_SCISSOR_TEST); + glScissor(0, 0, resX, resY); + avatar->mImpostor.clear(); + renderGeom(camera); + + // Shameless hack time: render it all again, + // this time writing the depth + // values we need to generate the alpha mask below + // while preserving the alpha-sorted color rendering + // from the previous pass + // + sImpostorRenderAlphaDepthPass = true; + + // depth-only here... + // + gGL.setColorMask(false,false); + renderGeom(camera); + + sImpostorRenderAlphaDepthPass = false; + } - LLDrawPoolAvatar::sMinimumAlpha = old_alpha; + LLDrawPoolAvatar::sMinimumAlpha = old_alpha; - { //create alpha mask based on depth buffer (grey out if muted) - LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_BACKGROUND); - if (LLPipeline::sRenderDeferred) - { - GLuint buff = GL_COLOR_ATTACHMENT0; - glDrawBuffersARB(1, &buff); - } + { //create alpha mask based on depth buffer (grey out if muted) + LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_BACKGROUND); + if (LLPipeline::sRenderDeferred) + { + GLuint buff = GL_COLOR_ATTACHMENT0; + glDrawBuffersARB(1, &buff); + } - LLGLDisable blend(GL_BLEND); + LLGLDisable blend(GL_BLEND); - if (visually_muted || too_complex) - { - gGL.setColorMask(true, true); - } - else - { - gGL.setColorMask(false, true); - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + if (visually_muted || too_complex) + { + gGL.setColorMask(true, true); + } + else + { + gGL.setColorMask(false, true); + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); - gGL.flush(); + gGL.flush(); - gGL.pushMatrix(); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadIdentity(); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); - static const F32 clip_plane = 0.99999f; + static const F32 clip_plane = 0.99999f; - if (LLGLSLShader::sNoFixedFunction) - { - gDebugProgram.bind(); - } + if (LLGLSLShader::sNoFixedFunction) + { + gDebugProgram.bind(); + } - if (visually_muted) - { // Visually muted avatar + if (visually_muted) + { // Visually muted avatar LLColor4 muted_color(avatar->getMutedAVColor()); LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " MUTED set solid color " << muted_color << LL_ENDL; - gGL.diffuseColor4fv( muted_color.mV ); - } - else - { //grey muted avatar + gGL.diffuseColor4fv( muted_color.mV ); + } + else + { //grey muted avatar LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " MUTED set grey" << LL_ENDL; - gGL.diffuseColor4fv(LLColor4::pink.mV ); - } - - { - gGL.begin(LLRender::QUADS); - gGL.vertex3f(-1, -1, clip_plane); - gGL.vertex3f(1, -1, clip_plane); - gGL.vertex3f(1, 1, clip_plane); - gGL.vertex3f(-1, 1, clip_plane); - gGL.end(); - gGL.flush(); - } - - if (LLGLSLShader::sNoFixedFunction) - { - gDebugProgram.unbind(); - } - - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); - } + gGL.diffuseColor4fv(LLColor4::pink.mV ); + } + + { + gGL.begin(LLRender::QUADS); + gGL.vertex3f(-1, -1, clip_plane); + gGL.vertex3f(1, -1, clip_plane); + gGL.vertex3f(1, 1, clip_plane); + gGL.vertex3f(-1, 1, clip_plane); + gGL.end(); + gGL.flush(); + } + + if (LLGLSLShader::sNoFixedFunction) + { + gDebugProgram.unbind(); + } + + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + } - avatar->mImpostor.flush(); + avatar->mImpostor.flush(); - avatar->setImpostorDim(tdim); + avatar->setImpostorDim(tdim); - LLVOAvatar::sUseImpostors = (0 != LLVOAvatar::sMaxNonImpostors); - sUseOcclusion = occlusion; - sReflectionRender = false; - sImpostorRender = false; - sShadowRender = false; - popRenderTypeMask(); + LLVOAvatar::sUseImpostors = (0 != LLVOAvatar::sMaxNonImpostors); + sUseOcclusion = occlusion; + sReflectionRender = false; + sImpostorRender = false; + sShadowRender = false; + popRenderTypeMask(); - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); - avatar->mNeedsImpostorUpdate = FALSE; - avatar->cacheImpostorValues(); - avatar->mLastImpostorUpdateFrameTime = gFrameTimeSeconds; + avatar->mNeedsImpostorUpdate = FALSE; + avatar->cacheImpostorValues(); + avatar->mLastImpostorUpdateFrameTime = gFrameTimeSeconds; - LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + LLVertexBuffer::unbind(); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); } bool LLPipeline::hasRenderBatches(const U32 type) const { - return sCull->getRenderMapSize(type) > 0; + return sCull->getRenderMapSize(type) > 0; } LLCullResult::drawinfo_iterator LLPipeline::beginRenderMap(U32 type) { - return sCull->beginRenderMap(type); + return sCull->beginRenderMap(type); } LLCullResult::drawinfo_iterator LLPipeline::endRenderMap(U32 type) { - return sCull->endRenderMap(type); + return sCull->endRenderMap(type); } LLCullResult::sg_iterator LLPipeline::beginAlphaGroups() { - return sCull->beginAlphaGroups(); + return sCull->beginAlphaGroups(); } LLCullResult::sg_iterator LLPipeline::endAlphaGroups() { - return sCull->endAlphaGroups(); + return sCull->endAlphaGroups(); } bool LLPipeline::hasRenderType(const U32 type) const @@ -11317,277 +11282,277 @@ bool LLPipeline::hasRenderType(const U32 type) const // STORM-365 : LLViewerJointAttachment::setAttachmentVisibility() is setting type to 0 to actually mean "do not render" // We then need to test that value here and return false to prevent attachment to render (in mouselook for instance) // TODO: reintroduce RENDER_TYPE_NONE in LLRenderTypeMask and initialize its mRenderTypeEnabled[RENDER_TYPE_NONE] to false explicitely - return (type == 0 ? false : mRenderTypeEnabled[type]); + return (type == 0 ? false : mRenderTypeEnabled[type]); } void LLPipeline::setRenderTypeMask(U32 type, ...) { - va_list args; + va_list args; - va_start(args, type); - while (type < END_RENDER_TYPES) - { - mRenderTypeEnabled[type] = true; - type = va_arg(args, U32); - } - va_end(args); + va_start(args, type); + while (type < END_RENDER_TYPES) + { + mRenderTypeEnabled[type] = true; + type = va_arg(args, U32); + } + va_end(args); - if (type > END_RENDER_TYPES) - { - LL_ERRS() << "Invalid render type." << LL_ENDL; - } + if (type > END_RENDER_TYPES) + { + LL_ERRS() << "Invalid render type." << LL_ENDL; + } } bool LLPipeline::hasAnyRenderType(U32 type, ...) const { - va_list args; + va_list args; - va_start(args, type); - while (type < END_RENDER_TYPES) - { - if (mRenderTypeEnabled[type]) - { - return true; - } - type = va_arg(args, U32); - } - va_end(args); + va_start(args, type); + while (type < END_RENDER_TYPES) + { + if (mRenderTypeEnabled[type]) + { + return true; + } + type = va_arg(args, U32); + } + va_end(args); - if (type > END_RENDER_TYPES) - { - LL_ERRS() << "Invalid render type." << LL_ENDL; - } + if (type > END_RENDER_TYPES) + { + LL_ERRS() << "Invalid render type." << LL_ENDL; + } - return false; + return false; } void LLPipeline::pushRenderTypeMask() { - std::string cur_mask; - cur_mask.assign((const char*) mRenderTypeEnabled, sizeof(mRenderTypeEnabled)); - mRenderTypeEnableStack.push(cur_mask); + std::string cur_mask; + cur_mask.assign((const char*) mRenderTypeEnabled, sizeof(mRenderTypeEnabled)); + mRenderTypeEnableStack.push(cur_mask); } void LLPipeline::popRenderTypeMask() { - if (mRenderTypeEnableStack.empty()) - { - LL_ERRS() << "Depleted render type stack." << LL_ENDL; - } + if (mRenderTypeEnableStack.empty()) + { + LL_ERRS() << "Depleted render type stack." << LL_ENDL; + } - memcpy(mRenderTypeEnabled, mRenderTypeEnableStack.top().data(), sizeof(mRenderTypeEnabled)); - mRenderTypeEnableStack.pop(); + memcpy(mRenderTypeEnabled, mRenderTypeEnableStack.top().data(), sizeof(mRenderTypeEnabled)); + mRenderTypeEnableStack.pop(); } void LLPipeline::andRenderTypeMask(U32 type, ...) { - va_list args; + va_list args; - bool tmp[NUM_RENDER_TYPES]; - for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) - { - tmp[i] = false; - } + bool tmp[NUM_RENDER_TYPES]; + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + tmp[i] = false; + } - va_start(args, type); - while (type < END_RENDER_TYPES) - { - if (mRenderTypeEnabled[type]) - { - tmp[type] = true; - } + va_start(args, type); + while (type < END_RENDER_TYPES) + { + if (mRenderTypeEnabled[type]) + { + tmp[type] = true; + } - type = va_arg(args, U32); - } - va_end(args); + type = va_arg(args, U32); + } + va_end(args); - if (type > END_RENDER_TYPES) - { - LL_ERRS() << "Invalid render type." << LL_ENDL; - } + if (type > END_RENDER_TYPES) + { + LL_ERRS() << "Invalid render type." << LL_ENDL; + } - for (U32 i = 0; i < LLPipeline::NUM_RENDER_TYPES; ++i) - { - mRenderTypeEnabled[i] = tmp[i]; - } + for (U32 i = 0; i < LLPipeline::NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = tmp[i]; + } } void LLPipeline::clearRenderTypeMask(U32 type, ...) { - va_list args; + va_list args; - va_start(args, type); - while (type < END_RENDER_TYPES) - { - mRenderTypeEnabled[type] = false; - - type = va_arg(args, U32); - } - va_end(args); + va_start(args, type); + while (type < END_RENDER_TYPES) + { + mRenderTypeEnabled[type] = false; + + type = va_arg(args, U32); + } + va_end(args); - if (type > END_RENDER_TYPES) - { - LL_ERRS() << "Invalid render type." << LL_ENDL; - } + if (type > END_RENDER_TYPES) + { + LL_ERRS() << "Invalid render type." << LL_ENDL; + } } void LLPipeline::setAllRenderTypes() { - for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) - { - mRenderTypeEnabled[i] = true; - } + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = true; + } } void LLPipeline::clearAllRenderTypes() { - for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) - { - mRenderTypeEnabled[i] = false; - } + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = false; + } } void LLPipeline::addDebugBlip(const LLVector3& position, const LLColor4& color) { - DebugBlip blip(position, color); - mDebugBlips.push_back(blip); + DebugBlip blip(position, color); + mDebugBlips.push_back(blip); } void LLPipeline::hidePermanentObjects( std::vector& restoreList ) { - //This method is used to hide any vo's from the object list that may have - //the permanent flag set. - - U32 objCnt = gObjectList.getNumObjects(); - for (U32 i = 0; i < objCnt; ++i) - { - LLViewerObject* pObject = gObjectList.getObject(i); - if ( pObject && pObject->flagObjectPermanent() ) - { - LLDrawable *pDrawable = pObject->mDrawable; - - if ( pDrawable ) - { - restoreList.push_back( i ); - hideDrawable( pDrawable ); - } - } - } + //This method is used to hide any vo's from the object list that may have + //the permanent flag set. + + U32 objCnt = gObjectList.getNumObjects(); + for (U32 i = 0; i < objCnt; ++i) + { + LLViewerObject* pObject = gObjectList.getObject(i); + if ( pObject && pObject->flagObjectPermanent() ) + { + LLDrawable *pDrawable = pObject->mDrawable; + + if ( pDrawable ) + { + restoreList.push_back( i ); + hideDrawable( pDrawable ); + } + } + } - skipRenderingOfTerrain( true ); + skipRenderingOfTerrain( true ); } void LLPipeline::restorePermanentObjects( const std::vector& restoreList ) { - //This method is used to restore(unhide) any vo's from the object list that may have - //been hidden because their permanency flag was set. + //This method is used to restore(unhide) any vo's from the object list that may have + //been hidden because their permanency flag was set. - std::vector::const_iterator itCurrent = restoreList.begin(); - std::vector::const_iterator itEnd = restoreList.end(); - - U32 objCnt = gObjectList.getNumObjects(); + std::vector::const_iterator itCurrent = restoreList.begin(); + std::vector::const_iterator itEnd = restoreList.end(); + + U32 objCnt = gObjectList.getNumObjects(); - while ( itCurrent != itEnd ) - { - U32 index = *itCurrent; - LLViewerObject* pObject = NULL; - if ( index < objCnt ) - { - pObject = gObjectList.getObject( index ); - } - if ( pObject ) - { - LLDrawable *pDrawable = pObject->mDrawable; - if ( pDrawable ) - { - pDrawable->clearState( LLDrawable::FORCE_INVISIBLE ); - unhideDrawable( pDrawable ); - } - } - ++itCurrent; - } - - skipRenderingOfTerrain( false ); + while ( itCurrent != itEnd ) + { + U32 index = *itCurrent; + LLViewerObject* pObject = NULL; + if ( index < objCnt ) + { + pObject = gObjectList.getObject( index ); + } + if ( pObject ) + { + LLDrawable *pDrawable = pObject->mDrawable; + if ( pDrawable ) + { + pDrawable->clearState( LLDrawable::FORCE_INVISIBLE ); + unhideDrawable( pDrawable ); + } + } + ++itCurrent; + } + + skipRenderingOfTerrain( false ); } void LLPipeline::skipRenderingOfTerrain( bool flag ) { - pool_set_t::iterator iter = mPools.begin(); - while ( iter != mPools.end() ) - { - LLDrawPool* pPool = *iter; - U32 poolType = pPool->getType(); - if ( hasRenderType( pPool->getType() ) && poolType == LLDrawPool::POOL_TERRAIN ) - { - pPool->setSkipRenderFlag( flag ); - } - ++iter; - } + pool_set_t::iterator iter = mPools.begin(); + while ( iter != mPools.end() ) + { + LLDrawPool* pPool = *iter; + U32 poolType = pPool->getType(); + if ( hasRenderType( pPool->getType() ) && poolType == LLDrawPool::POOL_TERRAIN ) + { + pPool->setSkipRenderFlag( flag ); + } + ++iter; + } } void LLPipeline::hideObject( const LLUUID& id ) { - LLViewerObject *pVO = gObjectList.findObject( id ); - - if ( pVO ) - { - LLDrawable *pDrawable = pVO->mDrawable; - - if ( pDrawable ) - { - hideDrawable( pDrawable ); - } - } + LLViewerObject *pVO = gObjectList.findObject( id ); + + if ( pVO ) + { + LLDrawable *pDrawable = pVO->mDrawable; + + if ( pDrawable ) + { + hideDrawable( pDrawable ); + } + } } void LLPipeline::hideDrawable( LLDrawable *pDrawable ) { - pDrawable->setState( LLDrawable::FORCE_INVISIBLE ); - markRebuild( pDrawable, LLDrawable::REBUILD_ALL, TRUE ); - //hide the children - LLViewerObject::const_child_list_t& child_list = pDrawable->getVObj()->getChildren(); - for ( LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++ ) - { - LLViewerObject* child = *iter; - LLDrawable* drawable = child->mDrawable; - if ( drawable ) - { - drawable->setState( LLDrawable::FORCE_INVISIBLE ); - markRebuild( drawable, LLDrawable::REBUILD_ALL, TRUE ); - } - } + pDrawable->setState( LLDrawable::FORCE_INVISIBLE ); + markRebuild( pDrawable, LLDrawable::REBUILD_ALL, TRUE ); + //hide the children + LLViewerObject::const_child_list_t& child_list = pDrawable->getVObj()->getChildren(); + for ( LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++ ) + { + LLViewerObject* child = *iter; + LLDrawable* drawable = child->mDrawable; + if ( drawable ) + { + drawable->setState( LLDrawable::FORCE_INVISIBLE ); + markRebuild( drawable, LLDrawable::REBUILD_ALL, TRUE ); + } + } } void LLPipeline::unhideDrawable( LLDrawable *pDrawable ) { - pDrawable->clearState( LLDrawable::FORCE_INVISIBLE ); - markRebuild( pDrawable, LLDrawable::REBUILD_ALL, TRUE ); - //restore children - LLViewerObject::const_child_list_t& child_list = pDrawable->getVObj()->getChildren(); - for ( LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child = *iter; - LLDrawable* drawable = child->mDrawable; - if ( drawable ) - { - drawable->clearState( LLDrawable::FORCE_INVISIBLE ); - markRebuild( drawable, LLDrawable::REBUILD_ALL, TRUE ); - } - } + pDrawable->clearState( LLDrawable::FORCE_INVISIBLE ); + markRebuild( pDrawable, LLDrawable::REBUILD_ALL, TRUE ); + //restore children + LLViewerObject::const_child_list_t& child_list = pDrawable->getVObj()->getChildren(); + for ( LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + LLDrawable* drawable = child->mDrawable; + if ( drawable ) + { + drawable->clearState( LLDrawable::FORCE_INVISIBLE ); + markRebuild( drawable, LLDrawable::REBUILD_ALL, TRUE ); + } + } } void LLPipeline::restoreHiddenObject( const LLUUID& id ) { - LLViewerObject *pVO = gObjectList.findObject( id ); - - if ( pVO ) - { - LLDrawable *pDrawable = pVO->mDrawable; - if ( pDrawable ) - { - unhideDrawable( pDrawable ); - } - } + LLViewerObject *pVO = gObjectList.findObject( id ); + + if ( pVO ) + { + LLDrawable *pDrawable = pVO->mDrawable; + if ( pDrawable ) + { + unhideDrawable( pDrawable ); + } + } } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index a31f880fbf..b4a8ca004e 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -166,9 +166,6 @@ public: // if source's depth buffer cannot be bound for reading, a scratch space depth buffer must be provided void downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL); - // Downsample depth buffer with gather and find local min/max depth values. Writes to a 16F RG render target. - void downsampleMinMaxDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL); - void doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL); void doOcclusion(LLCamera& camera); void markNotCulled(LLSpatialGroup* group, LLCamera &camera); @@ -539,8 +536,7 @@ public: RENDER_DEBUG_ATTACHMENT_BYTES = 0x20000000, // not used RENDER_DEBUG_TEXEL_DENSITY = 0x40000000, RENDER_DEBUG_TRIANGLE_COUNT = 0x80000000, - RENDER_DEBUG_IMPOSTORS = 0x100000000, - RENDER_DEBUG_SH = 0x200000000, + RENDER_DEBUG_IMPOSTORS = 0x100000000 }; public: @@ -628,13 +624,12 @@ public: //sun shadow map LLRenderTarget mShadow[6]; LLRenderTarget mShadowOcclusion[6]; - - std::vector mShadowFrustPoints[4]; - LLVector4 mShadowError; - LLVector4 mShadowFOV; - LLVector3 mShadowFrustOrigin[4]; - LLCamera mShadowCamera[8]; - LLVector3 mShadowExtents[4][2]; + std::vector mShadowFrustPoints[4]; + LLVector4 mShadowError; + LLVector4 mShadowFOV; + LLVector3 mShadowFrustOrigin[4]; + LLCamera mShadowCamera[8]; + LLVector3 mShadowExtents[4][2]; glh::matrix4f mSunShadowMatrix[6]; glh::matrix4f mShadowModelview[6]; glh::matrix4f mShadowProjection[6]; -- cgit v1.3 From fb7c887a5e09024731038eef0a57e5f1e8e08b2e Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Tue, 26 Mar 2019 10:28:25 -0700 Subject: More consistent lighting across ALM/non-ALM/deferred/forward rendering. --- .../app_settings/shaders/class1/deferred/alphaF.glsl | 11 +++++++++-- .../shaders/class1/deferred/materialF.glsl | 19 ++++++++++++------- .../shaders/class1/lighting/lightFuncV.glsl | 2 +- .../shaders/class2/deferred/multiSpotLightF.glsl | 13 +++++-------- .../shaders/class2/deferred/spotLightF.glsl | 12 +++++------- indra/newview/llvovolume.cpp | 9 ++++++--- indra/newview/pipeline.cpp | 6 +++--- 7 files changed, 41 insertions(+), 31 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index fdbf5ec840..dac93cee3a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -100,12 +100,14 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec vec3 norm = normalize(n); da = max(0.0, dot(norm, lv)); + //da = min(da, shadow); da = clamp(da, 0.0, 1.0); //distance attenuation float dist = d/la; float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); dist_atten *= dist_atten; + dist_atten *= 2.0f; // spotlight coefficient. float spot = max(dot(-ln, lv), is_pointlight); @@ -113,12 +115,16 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec // to match spotLight (but not multiSpotLight) *sigh* float lit = max(da * dist_atten,0.0); + + // the shadowmap is wrong for alpha objects + // since we only have 2 maps but N spots + //col = lit * light_col * diffuse * shadow; col = lit * light_col * diffuse; float amb_da = ambiance; + amb_da += (da*0.5) * (1.0 - shadow) * ambiance; + amb_da += (da*da*0.5 + 0.5) * (1.0 - shadow) * ambiance; amb_da *= dist_atten; - amb_da += (da*0.5) * ambiance; - amb_da += (da*da*0.5 + 0.25) * ambiance; amb_da = min(amb_da, 1.0f - lit); col.rgb += amb_da * light_col * diffuse; @@ -189,6 +195,7 @@ void main() vec3 light_dir = (sun_up_factor == 1) ? sun_dir: moon_dir; float da = dot(norm.xyz, light_dir.xyz); da = clamp(da, 0.0, 1.0); + da = pow(da, 1.0 / 1.3); vec4 color = vec4(0,0,0,0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl index 9112b6afd3..c43b5b22bf 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl @@ -104,23 +104,28 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe float dist = d/la; float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); dist_atten *= dist_atten; - + dist_atten *= 2.0f; + // spotlight coefficient. float spot = max(dot(-ln, lv), is_pointlight); da *= spot*spot; // GL_SPOT_EXPONENT=2 //angular attenuation da = dot(n, lv); + //da = min(da, shadow); da *= clamp(da, 0.0, 1.0); - + float lit = max(da * dist_atten, 0.0); + // shadowmap is wrong for alpha-blended objs + // since we created shadowmaps for 2 but render N + //col = light_col*lit*diffuse*shadow; col = light_col*lit*diffuse; - + float amb_da = ambiance; + amb_da += (da*0.5) * (1.0 - shadow) * ambiance; + amb_da += (da*da*0.5 + 0.5) * (1.0 - shadow) * ambiance; amb_da *= dist_atten; - amb_da += (da*0.5) * ambiance; - amb_da += (da*da*0.5 + 0.25) * ambiance; amb_da = min(amb_da, 1.0f - lit); col.rgb += amb_da * light_col * diffuse; @@ -135,10 +140,10 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe float sa = nh; float fres = pow(1 - dot(h, npos), 5)*0.4+0.5; - float gtdenom = abs(2 * nh); + float gtdenom = 2 * nh; float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); - if (gtdenom > 0.0) + if (nh > 0.0) { float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da); vec3 speccol = lit*scol*light_col.rgb*spec.rgb; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl index a9288b3df6..8defcf9f52 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl @@ -28,7 +28,7 @@ float calcDirectionalLight(vec3 n, vec3 l) { - float a = max(dot(n,l),0.0); + float a = max(dot(n,normalize(l)),0.0); return a; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index c4f406aa76..05192e1737 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -143,11 +143,11 @@ void main() vec3 pos = getPosition(frag.xy).xyz; vec3 lv = center.xyz-pos.xyz; float dist = length(lv); - dist /= size; - if (dist > 1.0) - { - discard; - } + + if ((size > 0) && ((dist / size) > 1.0)) + { + discard; + } float shadow = 1.0; @@ -225,11 +225,8 @@ void main() vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); amb_da += (da*da*0.5+0.5)*(1.0-shadow)*proj_ambiance; - amb_da *= dist_atten * noise; - amb_da = min(amb_da, 1.0-lit); - col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index 67eb503e72..4a5f5e642b 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -143,11 +143,11 @@ void main() vec3 pos = getPosition(frag.xy).xyz; vec3 lv = trans_center.xyz-pos.xyz; float dist = length(lv); - dist /= size; - if (dist > 1.0) - { - discard; - } + + if ((size > 0) && ((dist / size) > 1.0)) + { + discard; + } float shadow = 1.0; @@ -224,9 +224,7 @@ void main() vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); amb_da += (da*da*0.5+0.5)*(1.0-shadow)*proj_ambiance; - amb_da *= dist_atten * noise; - amb_da = min(amb_da, 1.0-lit); col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 671f4d49a7..f97e0ff2e7 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3275,12 +3275,13 @@ F32 LLVOVolume::getSpotLightPriority() const void LLVOVolume::updateSpotLightPriority() { + F32 r = getLightRadius(); LLVector3 pos = mDrawable->getPositionAgent(); - LLVector3 at(0,0,-1); - at *= getRenderRotation(); + LLVector3 agent_pos = gAgent.getPositionAgent(); - F32 r = getLightRadius()*0.5f; + LLVector3 at(0,0,-1); + at *= getRenderRotation(); pos += at * r; at = LLViewerCamera::getInstance()->getAtAxis(); @@ -3289,6 +3290,8 @@ void LLVOVolume::updateSpotLightPriority() mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); + //mSpotLightPriority = (agent_pos - pos).length() + r; + if (mLightTexture.notNull()) { mLightTexture->addTextureStats(mSpotLightPriority); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4c93d16fb1..8bc68ac9ea 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8750,7 +8750,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); - gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); + gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()); gGL.syncMatrices(); mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); @@ -8809,7 +8809,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); - gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); + gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()); gGL.syncMatrices(); mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); @@ -8906,7 +8906,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); - gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); + gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()); mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); } -- cgit v1.3 From 92f79a7c102170011724430f30ce1aaf40031d21 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Tue, 26 Mar 2019 11:41:27 -0700 Subject: Fix unused var warn-error for Clang. --- indra/newview/llvovolume.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index f97e0ff2e7..afccc1c42c 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3277,20 +3277,17 @@ void LLVOVolume::updateSpotLightPriority() { F32 r = getLightRadius(); LLVector3 pos = mDrawable->getPositionAgent(); - LLVector3 agent_pos = gAgent.getPositionAgent(); LLVector3 at(0,0,-1); - at *= getRenderRotation(); pos += at * r; at = LLViewerCamera::getInstance()->getAtAxis(); - pos -= at * r; mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); - //mSpotLightPriority = (agent_pos - pos).length() + r; + //mSpotLightPriority = (gAgent.getPositionAgent() - pos).length() + r; if (mLightTexture.notNull()) { -- cgit v1.3 From 872b36488a7f3b1d9095e129e3973fefa11e85ba Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Tue, 26 Mar 2019 13:16:47 -0700 Subject: Modify spotlight prio calc to more stable version. --- indra/newview/llvovolume.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index afccc1c42c..4ddd9c4568 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3278,6 +3278,7 @@ void LLVOVolume::updateSpotLightPriority() F32 r = getLightRadius(); LLVector3 pos = mDrawable->getPositionAgent(); +#if OLD_SPOT_PRIO_CALC LLVector3 at(0,0,-1); at *= getRenderRotation(); pos += at * r; @@ -3286,8 +3287,9 @@ void LLVOVolume::updateSpotLightPriority() pos -= at * r; mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); - - //mSpotLightPriority = (gAgent.getPositionAgent() - pos).length() + r; +#else + mSpotLightPriority = (gAgent.getPositionAgent() - pos).length() + r; +#endif if (mLightTexture.notNull()) { -- cgit v1.3 From 03426a7ddbf1b3bb8349241d3b52962026f7504a Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Thu, 28 Mar 2019 13:23:59 -0700 Subject: SL-10829, SL-10830 Replace old spot prio calc. Replace fudge factors on light radius and falloff for deferred lights. --- .../shaders/class1/deferred/multiSpotLightF.glsl | 2 +- .../app_settings/shaders/class1/deferred/pointLightF.glsl | 2 +- .../app_settings/shaders/class1/deferred/spotLightF.glsl | 2 +- .../shaders/class2/deferred/multiSpotLightF.glsl | 4 ++-- .../app_settings/shaders/class2/deferred/spotLightF.glsl | 4 ++-- .../shaders/class3/deferred/multiSpotLightF.glsl | 2 +- .../app_settings/shaders/class3/deferred/spotLightF.glsl | 2 +- indra/newview/llvovolume.cpp | 6 +----- indra/newview/pipeline.cpp | 14 +++++++------- 9 files changed, 17 insertions(+), 21 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index 3364d5b5fc..57916eb3e5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -158,7 +158,7 @@ void main() proj_tc.xyz /= proj_tc.w; - float fa = (falloff * 0.5)+1.0; + float fa = falloff+1.0; float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0); dist_atten *= dist_atten; dist_atten *= 2.0; diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 55410c1ed7..f8264d971c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -89,7 +89,7 @@ void main() float noise = texture2D(noiseMap, frag.xy/128.0).b; vec3 col = texture2DRect(diffuseRect, frag.xy).rgb; - float fa = (falloff * 0.5)+1.0; + float fa = falloff+1.0; float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); dist_atten *= dist_atten; dist_atten *= 2.0; diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index b546519a7d..d09bc25334 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -155,7 +155,7 @@ void main() proj_tc.xyz /= proj_tc.w; - float fa = (falloff * 0.5)+1.0; + float fa = falloff+1.0; float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0); dist_atten *= dist_atten; dist_atten *= 2.0; diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index f817817f37..9e14c03a96 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -156,8 +156,8 @@ void main() { vec4 shd = texture2DRect(lightMap, frag.xy); shadow = (proj_shadow_idx==0)?shd.b:shd.a; - shadow = clamp(shadow, 0.0, 1.0); shadow += shadow_fade; + shadow = clamp(shadow, 0.0, 1.0); } vec3 norm = texture2DRect(normalMap, frag.xy).xyz; @@ -177,7 +177,7 @@ void main() proj_tc.xyz /= proj_tc.w; - float fa = (falloff * 0.5)+1.0; + float fa = falloff+1.0; float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0); dist_atten *= dist_atten; dist_atten *= 2.0; diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index 510d1ca9fd..93b55ab9c1 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -156,8 +156,8 @@ void main() { vec4 shd = texture2DRect(lightMap, frag.xy); shadow = (proj_shadow_idx == 0) ? shd.b : shd.a; - shadow = clamp(shadow, 0.0, 1.0); shadow += shadow_fade; + shadow = clamp(shadow, 0.0, 1.0); } vec3 norm = texture2DRect(normalMap, frag.xy).xyz; @@ -175,7 +175,7 @@ void main() proj_tc.xyz /= proj_tc.w; - float fa = (falloff * 0.5) + 1.0; + float fa = falloff + 1.0; float dist_atten = min(1.0 - (dist - 1.0 * (1.0 - fa)) / fa, 1.0); dist_atten *= dist_atten; dist_atten *= 2.0; diff --git a/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl index dec9afcfb7..abb6a3a5d8 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl @@ -157,8 +157,8 @@ void main() { vec4 shd = texture2DRect(lightMap, frag.xy); shadow = (proj_shadow_idx == 0) ? shd.b : shd.a; - shadow = clamp(shadow, 0.0, 1.0); shadow += shadow_fade; + shadow = clamp(shadow, 0.0, 1.0); } vec3 norm = texture2DRect(normalMap, frag.xy).xyz; diff --git a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl index 6a813cac15..afc542b8bc 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl @@ -157,8 +157,8 @@ void main() { vec4 shd = texture2DRect(lightMap, frag.xy); shadow = (proj_shadow_idx == 0) ? shd.b : shd.a; - shadow = clamp(shadow, 0.0, 1.0); shadow += shadow_fade; + shadow = clamp(shadow, 0.0, 1.0); } vec3 norm = texture2DRect(normalMap, frag.xy).xyz; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 4ddd9c4568..b4b3e19abc 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3278,18 +3278,14 @@ void LLVOVolume::updateSpotLightPriority() F32 r = getLightRadius(); LLVector3 pos = mDrawable->getPositionAgent(); -#if OLD_SPOT_PRIO_CALC LLVector3 at(0,0,-1); at *= getRenderRotation(); pos += at * r; at = LLViewerCamera::getInstance()->getAtAxis(); pos -= at * r; - + mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); -#else - mSpotLightPriority = (gAgent.getPositionAgent() - pos).length() + r; -#endif if (mLightTexture.notNull()) { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 658410fd3d..4c93d16fb1 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8703,7 +8703,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) LLVector4a center; center.load3(drawablep->getPositionAgent().mV); const F32* c = center.getF32ptr(); - F32 s = volume->getLightRadius(); + F32 s = volume->getLightRadius()*1.5f; LLColor3 col = volume->getLightColor(); @@ -8750,7 +8750,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); - gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()); + gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); gGL.syncMatrices(); mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); @@ -8770,7 +8770,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) mat.mult_matrix_vec(tc); fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s)); - light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff())); + light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); } } unbindDeferredShader(gDeferredLightProgram); @@ -8795,7 +8795,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) LLVector4a center; center.load3(drawablep->getPositionAgent().mV); const F32* c = center.getF32ptr(); - F32 s = volume->getLightRadius(); + F32 s = volume->getLightRadius()*1.5f; sVisibleLightCount++; @@ -8809,7 +8809,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); - gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()); + gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); gGL.syncMatrices(); mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); @@ -8888,7 +8888,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) LLVector3 center = drawablep->getPositionAgent(); F32* c = center.mV; - F32 s = volume->getLightRadius(); + F32 s = volume->getLightRadius()*1.5f; sVisibleLightCount++; @@ -8906,7 +8906,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); - gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()); + gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3); } -- cgit v1.3 From 57d88a8a98ef8663b9064b12143beb4068e58f86 Mon Sep 17 00:00:00 2001 From: Geenz Date: Fri, 29 Mar 2019 08:11:56 -0700 Subject: Gamma correction pass 2: Make sure lights are in the correct color space. Bonus: cache the sRGB color in setLightColor on point and spot lights. Frees up a pow and some multiplies on the CPU every frame. --- indra/llmath/v3color.h | 8 ++++++++ indra/llmath/v4color.h | 11 +++++++++++ indra/llmath/v4math.h | 12 ++++++++++++ indra/llprimitive/llprimitive.h | 4 +++- indra/llrender/llrender.cpp | 2 +- indra/newview/lldrawpoolwlsky.cpp | 17 ++++++++++++++--- indra/newview/llvosky.cpp | 3 +++ indra/newview/llvovolume.cpp | 13 +++++++++++++ indra/newview/llvovolume.h | 1 + indra/newview/pipeline.cpp | 21 ++++----------------- 10 files changed, 70 insertions(+), 22 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h index 43910a1bbe..ac78197510 100644 --- a/indra/llmath/v3color.h +++ b/indra/llmath/v3color.h @@ -475,5 +475,13 @@ inline LLColor3 lerp(const LLColor3 &a, const LLColor3 &b, F32 u) a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u); } +inline const LLColor3 srgbColor3(const LLColor3 &a) { + LLColor3 srgbColor; + srgbColor.mV[0] = linearTosRGB(a.mV[0]); + srgbColor.mV[1] = linearTosRGB(a.mV[1]); + srgbColor.mV[2] = linearTosRGB(a.mV[2]); + + return srgbColor; +} #endif diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index 614cdc9f3e..d9dd28ec54 100644 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -656,5 +656,16 @@ void LLColor4::clamp() } } +inline const LLColor4 srgbColor4(const LLColor4 &a) { + LLColor4 srgbColor; + + srgbColor.mV[0] = linearTosRGB(a.mV[0]); + srgbColor.mV[1] = linearTosRGB(a.mV[1]); + srgbColor.mV[2] = linearTosRGB(a.mV[2]); + srgbColor.mV[3] = a.mV[3]; + + return srgbColor; +} + #endif diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h index 3f6d480ed9..00baeefa5c 100644 --- a/indra/llmath/v4math.h +++ b/indra/llmath/v4math.h @@ -534,6 +534,18 @@ inline F32 LLVector4::normVec(void) return (mag); } +// Because apparently some parts of the viewer use this for color info. +inline const LLVector4 srgbVector4(const LLVector4 &a) { + LLVector4 srgbColor; + + srgbColor.mV[0] = linearTosRGB(a.mV[0]); + srgbColor.mV[1] = linearTosRGB(a.mV[1]); + srgbColor.mV[2] = linearTosRGB(a.mV[2]); + srgbColor.mV[3] = a.mV[3]; + + return srgbColor; +} + #endif diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index c138c2ac2b..677606abd1 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -133,6 +133,7 @@ class LLLightParams : public LLNetworkData { protected: LLColor4 mColor; // alpha = intensity + LLColor4 msRGBColor; // Only used in deferred (for now?) F32 mRadius; F32 mFalloff; F32 mCutoff; @@ -150,12 +151,13 @@ public: bool fromLLSD(LLSD& sd); - void setColor(const LLColor4& color) { mColor = color; mColor.clamp(); } + void setColor(const LLColor4& color) { mColor = color; mColor.clamp(); msRGBColor = srgbColor4(mColor); } void setRadius(F32 radius) { mRadius = llclamp(radius, LIGHT_MIN_RADIUS, LIGHT_MAX_RADIUS); } void setFalloff(F32 falloff) { mFalloff = llclamp(falloff, LIGHT_MIN_FALLOFF, LIGHT_MAX_FALLOFF); } void setCutoff(F32 cutoff) { mCutoff = llclamp(cutoff, LIGHT_MIN_CUTOFF, LIGHT_MAX_CUTOFF); } LLColor4 getColor() const { return mColor; } + LLColor4 getsRGBColor() const { return msRGBColor; } F32 getRadius() const { return mRadius; } F32 getFalloff() const { return mFalloff; } F32 getCutoff() const { return mCutoff; } diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 2bf7ad9902..fe6010fabd 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1193,7 +1193,7 @@ void LLRender::syncLightState() shader->uniform3fv(LLShaderMgr::LIGHT_DIRECTION, 8, direction[0].mV); shader->uniform4fv(LLShaderMgr::LIGHT_ATTENUATION, 8, attenuation[0].mV); shader->uniform3fv(LLShaderMgr::LIGHT_DIFFUSE, 8, diffuse[0].mV); - shader->uniform4fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV); + shader->uniform4fv(LLShaderMgr::LIGHT_AMBIENT, 1, srgbColor4(mAmbientLightColor).mV); shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_primary[0] ? 1 : 0); shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, diffuse_b[0].mV); } diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index e608f6eaf2..7f59852b62 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -503,7 +503,12 @@ void LLDrawPoolWLSky::renderHeavenlyBodies() LLColor4 color(gSky.mVOSkyp->getSun().getInterpColor()); - sun_shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, color.mV); + if (LLPipeline::RenderDeferred) { + sun_shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, srgbColor4(color).mV); + } + else { + sun_shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, color.mV); + } sun_shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); LLFacePool::LLOverrideFaceColor color_override(this, color); @@ -554,9 +559,15 @@ void LLDrawPoolWLSky::renderHeavenlyBodies() F32 moon_brightness = (float)psky->getMoonBrightness(); moon_shader->uniform1f(LLShaderMgr::MOON_BRIGHTNESS, moon_brightness); - moon_shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, gSky.mVOSkyp->getMoon().getColor().mV); - moon_shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, color.mV); + if (LLPipeline::RenderDeferred) { + moon_shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, srgbColor4(gSky.mVOSkyp->getMoon().getColor()).mV); + moon_shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, srgbColor4(color).mV); + } + else { + moon_shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, gSky.mVOSkyp->getMoon().getColor().mV); + moon_shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, color.mV); + } moon_shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); LLFacePool::LLOverrideFaceColor color_override(this, color); diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 8bcd875d90..954a590682 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -210,6 +210,9 @@ void LLSkyTex::createGLImage(S32 which) if (LLPipeline::RenderDeferred) { mTexture[which]->setExplicitFormat(GL_SRGB8_ALPHA8, GL_RGBA); } + else { + mTexture[which]->setExplicitFormat(GL_RGBA8, GL_RGBA); + } mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLGLTexture::LOCAL); mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP); } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 4ddd9c4568..85bc1ba845 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3239,6 +3239,19 @@ LLColor3 LLVOVolume::getLightColor() const } } +LLColor3 LLVOVolume::getLightsRGBColor() const +{ + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return LLColor3(param_block->getsRGBColor()) * param_block->getsRGBColor().mV[3]; + } + else + { + return LLColor3(1, 1, 1); + } +} + LLUUID LLVOVolume::getLightTextureID() const { if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 0882fc095d..aeabcda911 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -251,6 +251,7 @@ public: BOOL getIsLight() const; LLColor3 getLightBaseColor() const; // not scaled by intensity LLColor3 getLightColor() const; // scaled by intensity + LLColor3 getLightsRGBColor() const; // Used to get the (cached) light color in sRGB color space. Also scaled by intensity. LLUUID getLightTextureID() const; bool isLightSpotlight() const; LLVector3 getSpotLightParams() const; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 658410fd3d..2a7cac3eda 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8368,7 +8368,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff); shader.uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, mSunDiffuse.mV); - shader.uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, mMoonDiffuse.mV); + shader.uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, srgbColor4(mMoonDiffuse).mV); LLEnvironment& environment = LLEnvironment::instance(); shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); @@ -8705,7 +8705,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) const F32* c = center.getF32ptr(); F32 s = volume->getLightRadius(); - LLColor3 col = volume->getLightColor(); + LLColor3 col = volume->getLightsRGBColor(); if (col.magVecSquared() < 0.001f) { @@ -8742,10 +8742,6 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) continue; } - /*col.mV[0] = powf(col.mV[0], 2.2f); - col.mV[1] = powf(col.mV[1], 2.2f); - col.mV[2] = powf(col.mV[2], 2.2f);*/ - LL_RECORD_BLOCK_TIME(FTM_LOCAL_LIGHTS); gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); @@ -8801,7 +8797,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) setupSpotLight(gDeferredSpotLightProgram, drawablep); - LLColor3 col = volume->getLightColor(); + LLColor3 col = volume->getLightsRGBColor(); /*col.mV[0] = powf(col.mV[0], 2.2f); col.mV[1] = powf(col.mV[1], 2.2f); col.mV[2] = powf(col.mV[2], 2.2f);*/ @@ -8850,12 +8846,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) col[count] = light_colors.front(); light_colors.pop_front(); - /*col[count].mV[0] = powf(col[count].mV[0], 2.2f); - col[count].mV[1] = powf(col[count].mV[1], 2.2f); - col[count].mV[2] = powf(col[count].mV[2], 2.2f);*/ - far_z = llmin(light[count].mV[2]-light[count].mV[3], far_z); - //col[count] = pow4fsrgb(col[count], 2.2f); count++; if (count == max_count || fullscreen_lights.empty()) { @@ -8897,11 +8888,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) setupSpotLight(gDeferredMultiSpotLightProgram, drawablep); - LLColor3 col = volume->getLightColor(); - - /*col.mV[0] = powf(col.mV[0], 2.2f); - col.mV[1] = powf(col.mV[1], 2.2f); - col.mV[2] = powf(col.mV[2], 2.2f);*/ + LLColor3 col = volume->getLightsRGBColor(); gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); -- cgit v1.3 From 0272c47e5a31cf972e02fbf14cb2642f86f75d78 Mon Sep 17 00:00:00 2001 From: Geenz Date: Fri, 29 Mar 2019 11:57:45 -0700 Subject: Tweaked naming a bit, also white space. Will wait for a response from @graham_linden regarding moving the sRGB conversion functions in llmath.h to llrender. --- indra/llmath/llmath.h | 24 +++--- indra/llmath/v4color.h | 12 +-- indra/llmath/v4math.h | 12 +-- indra/llprimitive/llprimitive.h | 10 +-- indra/llrender/llcubemap.cpp | 6 +- indra/llrender/llimagegl.cpp | 176 +++++++++++++++++++------------------- indra/llrender/llrender.cpp | 2 +- indra/newview/lldrawpoolwlsky.cpp | 8 +- indra/newview/llvosky.cpp | 18 ++-- indra/newview/llvovolume.cpp | 20 ++--- indra/newview/llvovolume.h | 2 +- indra/newview/pipeline.cpp | 11 +-- 12 files changed, 149 insertions(+), 152 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index bb19248f1f..57f2489a2d 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -540,21 +540,21 @@ inline void ll_remove_outliers(std::vector& data, F32 k) // This converts from a non-linear sRGB floating point value (0..1) to a linear value. // Useful for gamma correction and such. Note: any values passed through this should not be serialized. You should also ideally cache the output of this. inline float sRGBtoLinear(const float val) { - if (val < 0.0031308f) { - return val * 12.92f; - } - else { - return 1.055f * pow(val, 1.0f / 2.4f) - 0.055f; - } + if (val < 0.0031308f) { + return val * 12.92f; + } + else { + return 1.055f * pow(val, 1.0f / 2.4f) - 0.055f; + } } inline float linearTosRGB(const float val) { - if (val < 0.04045f) { - return val / 12.92f; - } - else { - return pow((val + 0.055f) / 1.055f, 2.4f); - } + if (val < 0.04045f) { + return val / 12.92f; + } + else { + return pow((val + 0.055f) / 1.055f, 2.4f); + } } // Include simd math header diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index d9dd28ec54..6b91b4f191 100644 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -657,14 +657,14 @@ void LLColor4::clamp() } inline const LLColor4 srgbColor4(const LLColor4 &a) { - LLColor4 srgbColor; + LLColor4 srgbColor; - srgbColor.mV[0] = linearTosRGB(a.mV[0]); - srgbColor.mV[1] = linearTosRGB(a.mV[1]); - srgbColor.mV[2] = linearTosRGB(a.mV[2]); - srgbColor.mV[3] = a.mV[3]; + srgbColor.mV[0] = linearTosRGB(a.mV[0]); + srgbColor.mV[1] = linearTosRGB(a.mV[1]); + srgbColor.mV[2] = linearTosRGB(a.mV[2]); + srgbColor.mV[3] = a.mV[3]; - return srgbColor; + return srgbColor; } #endif diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h index 00baeefa5c..b8835ba2e4 100644 --- a/indra/llmath/v4math.h +++ b/indra/llmath/v4math.h @@ -536,14 +536,14 @@ inline F32 LLVector4::normVec(void) // Because apparently some parts of the viewer use this for color info. inline const LLVector4 srgbVector4(const LLVector4 &a) { - LLVector4 srgbColor; + LLVector4 srgbColor; - srgbColor.mV[0] = linearTosRGB(a.mV[0]); - srgbColor.mV[1] = linearTosRGB(a.mV[1]); - srgbColor.mV[2] = linearTosRGB(a.mV[2]); - srgbColor.mV[3] = a.mV[3]; + srgbColor.mV[0] = linearTosRGB(a.mV[0]); + srgbColor.mV[1] = linearTosRGB(a.mV[1]); + srgbColor.mV[2] = linearTosRGB(a.mV[2]); + srgbColor.mV[3] = a.mV[3]; - return srgbColor; + return srgbColor; } diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 677606abd1..619a9f8ca5 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -133,7 +133,7 @@ class LLLightParams : public LLNetworkData { protected: LLColor4 mColor; // alpha = intensity - LLColor4 msRGBColor; // Only used in deferred (for now?) + LLColor4 mSRGBColor; // Only used in deferred (for now?) F32 mRadius; F32 mFalloff; F32 mCutoff; @@ -150,14 +150,14 @@ public: operator LLSD() const { return asLLSD(); } bool fromLLSD(LLSD& sd); - - void setColor(const LLColor4& color) { mColor = color; mColor.clamp(); msRGBColor = srgbColor4(mColor); } + + void setColor(const LLColor4& color) { mColor = color; mColor.clamp(); mSRGBColor = srgbColor4(mColor); } void setRadius(F32 radius) { mRadius = llclamp(radius, LIGHT_MIN_RADIUS, LIGHT_MAX_RADIUS); } void setFalloff(F32 falloff) { mFalloff = llclamp(falloff, LIGHT_MIN_FALLOFF, LIGHT_MAX_FALLOFF); } void setCutoff(F32 cutoff) { mCutoff = llclamp(cutoff, LIGHT_MIN_CUTOFF, LIGHT_MAX_CUTOFF); } - LLColor4 getColor() const { return mColor; } - LLColor4 getsRGBColor() const { return msRGBColor; } + LLColor4 getColor() const { return mColor; } + LLColor4 getSRGBColor() const { return mSRGBColor; } F32 getRadius() const { return mRadius; } F32 getFalloff() const { return mFalloff; } F32 getCutoff() const { return mCutoff; } diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index fcac016ed7..14d0a744bb 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -87,9 +87,9 @@ void LLCubeMap::initGL() for (int i = 0; i < 6; i++) { mImages[i] = new LLImageGL(RESOLUTION, RESOLUTION, 4, FALSE); - if (mIssRGB) { - mImages[i]->setExplicitFormat(GL_SRGB8_ALPHA8, GL_RGBA); - } + if (mIssRGB) { + mImages[i]->setExplicitFormat(GL_SRGB8_ALPHA8, GL_RGBA); + } mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP); mRawImages[i] = new LLImageRaw(RESOLUTION, RESOLUTION, 4); mImages[i]->createGLTexture(0, mRawImages[i], texname); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index d3f8431654..2d526a2113 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -184,47 +184,47 @@ void LLImageGL::cleanupClass() //static S32 LLImageGL::dataFormatBits(S32 dataformat) { - switch (dataformat) - { - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 4; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 4; - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 8; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 8; - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 8; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 8; - case GL_LUMINANCE: return 8; - case GL_ALPHA: return 8; - case GL_COLOR_INDEX: return 8; - case GL_LUMINANCE_ALPHA: return 16; - case GL_RGB: return 24; - case GL_SRGB: return 24; - case GL_RGB8: return 24; - case GL_RGBA: return 32; - case GL_SRGB_ALPHA: return 32; - case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac - default: - LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL; - return 0; - } + switch (dataformat) + { + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 4; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 4; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 8; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 8; + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 8; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 8; + case GL_LUMINANCE: return 8; + case GL_ALPHA: return 8; + case GL_COLOR_INDEX: return 8; + case GL_LUMINANCE_ALPHA: return 16; + case GL_RGB: return 24; + case GL_SRGB: return 24; + case GL_RGB8: return 24; + case GL_RGBA: return 32; + case GL_SRGB_ALPHA: return 32; + case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac + default: + LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL; + return 0; + } } //static S32 LLImageGL::dataFormatBytes(S32 dataformat, S32 width, S32 height) { - switch (dataformat) - { - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - if (width < 4) width = 4; - if (height < 4) height = 4; - break; - default: - break; - } + switch (dataformat) + { + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + if (width < 4) width = 4; + if (height < 4) height = 4; + break; + default: + break; + } S32 bytes ((width*height*dataFormatBits(dataformat)+7)>>3); S32 aligned = (bytes+3)&~3; return aligned; @@ -669,19 +669,19 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) LL_RECORD_BLOCK_TIME(FTM_SET_IMAGE); bool is_compressed = false; - switch (mFormatPrimary) - { - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - is_compressed = true; - break; - default: - break; - } + switch (mFormatPrimary) + { + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + is_compressed = true; + break; + default: + break; + } @@ -1255,18 +1255,18 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt case GL_RGB8: intformat = GL_COMPRESSED_RGB; break; - case GL_SRGB: - case GL_SRGB8: - intformat = GL_COMPRESSED_SRGB; - break; + case GL_SRGB: + case GL_SRGB8: + intformat = GL_COMPRESSED_SRGB; + break; case GL_RGBA: case GL_RGBA8: intformat = GL_COMPRESSED_RGBA; break; - case GL_SRGB_ALPHA: - case GL_SRGB8_ALPHA8: - intformat = GL_COMPRESSED_SRGB_ALPHA; - break; + case GL_SRGB_ALPHA: + case GL_SRGB8_ALPHA8: + intformat = GL_COMPRESSED_SRGB_ALPHA; + break; case GL_LUMINANCE: case GL_LUMINANCE8: intformat = GL_COMPRESSED_LUMINANCE; @@ -1824,30 +1824,30 @@ void LLImageGL::calcAlphaChannelOffsetAndStride() } mAlphaStride = -1 ; - switch (mFormatPrimary) - { - case GL_LUMINANCE: - case GL_ALPHA: - mAlphaStride = 1; - break; - case GL_LUMINANCE_ALPHA: - mAlphaStride = 2; - break; - case GL_RGB: - case GL_SRGB: - mNeedsAlphaAndPickMask = FALSE ; - mIsMask = FALSE; - return ; //no alpha channel. - case GL_RGBA: - case GL_SRGB_ALPHA: - mAlphaStride = 4; - break; - case GL_BGRA_EXT: - mAlphaStride = 4; - break; - default: - break; - } + switch (mFormatPrimary) + { + case GL_LUMINANCE: + case GL_ALPHA: + mAlphaStride = 1; + break; + case GL_LUMINANCE_ALPHA: + mAlphaStride = 2; + break; + case GL_RGB: + case GL_SRGB: + mNeedsAlphaAndPickMask = FALSE; + mIsMask = FALSE; + return; //no alpha channel. + case GL_RGBA: + case GL_SRGB_ALPHA: + mAlphaStride = 4; + break; + case GL_BGRA_EXT: + mAlphaStride = 4; + break; + default: + break; + } mAlphaOffset = -1 ; if (mFormatType == GL_UNSIGNED_BYTE) @@ -2030,13 +2030,13 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) freePickMask(); - if (mFormatType != GL_UNSIGNED_BYTE || - mFormatPrimary != GL_RGBA || - mFormatPrimary != GL_SRGB_ALPHA) - { - //cannot generate a pick mask for this texture - return; - } + if (mFormatType != GL_UNSIGNED_BYTE || + mFormatPrimary != GL_RGBA || + mFormatPrimary != GL_SRGB_ALPHA) + { + //cannot generate a pick mask for this texture + return; + } #ifdef SHOW_ASSERT const U32 pickSize = createPickMask(width, height); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index fe6010fabd..2bf7ad9902 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1193,7 +1193,7 @@ void LLRender::syncLightState() shader->uniform3fv(LLShaderMgr::LIGHT_DIRECTION, 8, direction[0].mV); shader->uniform4fv(LLShaderMgr::LIGHT_ATTENUATION, 8, attenuation[0].mV); shader->uniform3fv(LLShaderMgr::LIGHT_DIFFUSE, 8, diffuse[0].mV); - shader->uniform4fv(LLShaderMgr::LIGHT_AMBIENT, 1, srgbColor4(mAmbientLightColor).mV); + shader->uniform4fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV); shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_primary[0] ? 1 : 0); shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, diffuse_b[0].mV); } diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index f674766935..a3aa0e289f 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -503,7 +503,7 @@ void LLDrawPoolWLSky::renderHeavenlyBodies() LLColor4 color(gSky.mVOSkyp->getSun().getInterpColor()); - sun_shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, color.mV); + sun_shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, color.mV); sun_shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); LLFacePool::LLOverrideFaceColor color_override(this, color); @@ -553,9 +553,9 @@ void LLDrawPoolWLSky::renderHeavenlyBodies() F32 moon_brightness = (float)psky->getMoonBrightness(); - moon_shader->uniform1f(LLShaderMgr::MOON_BRIGHTNESS, moon_brightness); - moon_shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, gSky.mVOSkyp->getMoon().getColor().mV); - moon_shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, color.mV); + moon_shader->uniform1f(LLShaderMgr::MOON_BRIGHTNESS, moon_brightness); + moon_shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, gSky.mVOSkyp->getMoon().getColor().mV); + moon_shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, color.mV); moon_shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); LLFacePool::LLOverrideFaceColor color_override(this, color); diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 954a590682..a181fdaf50 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -207,12 +207,12 @@ void LLSkyTex::create(const F32 brightness) void LLSkyTex::createGLImage(S32 which) { - if (LLPipeline::RenderDeferred) { - mTexture[which]->setExplicitFormat(GL_SRGB8_ALPHA8, GL_RGBA); - } - else { - mTexture[which]->setExplicitFormat(GL_RGBA8, GL_RGBA); - } + if (LLPipeline::RenderDeferred) { + mTexture[which]->setExplicitFormat(GL_SRGB8_ALPHA8, GL_RGBA); + } + else { + mTexture[which]->setExplicitFormat(GL_RGBA8, GL_RGBA); + } mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLGLTexture::LOCAL); mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP); } @@ -619,10 +619,10 @@ void LLVOSky::initCubeMap() } else if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) { - bool wantsRGB = LLPipeline::RenderDeferred; + bool wantsRGB = LLPipeline::RenderDeferred; - mCubeMap = new LLCubeMap(wantsRGB); - mCubeMap->init(images); + mCubeMap = new LLCubeMap(wantsRGB); + mCubeMap->init(images); } gGL.getTexUnit(0)->disable(); } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 16fca58f8c..1fd7c7d3ce 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3239,17 +3239,17 @@ LLColor3 LLVOVolume::getLightColor() const } } -LLColor3 LLVOVolume::getLightsRGBColor() const +LLColor3 LLVOVolume::getLightSRGBColor() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return LLColor3(param_block->getsRGBColor()) * param_block->getsRGBColor().mV[3]; - } - else - { - return LLColor3(1, 1, 1); - } + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return LLColor3(param_block->getSRGBColor()) * param_block->getSRGBColor().mV[3]; + } + else + { + return LLColor3(1, 1, 1); + } } LLUUID LLVOVolume::getLightTextureID() const diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index aeabcda911..da2b086f4a 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -251,7 +251,7 @@ public: BOOL getIsLight() const; LLColor3 getLightBaseColor() const; // not scaled by intensity LLColor3 getLightColor() const; // scaled by intensity - LLColor3 getLightsRGBColor() const; // Used to get the (cached) light color in sRGB color space. Also scaled by intensity. + LLColor3 getLightSRGBColor() const; // Used to get the (cached) light color in sRGB color space. Also scaled by intensity. LLUUID getLightTextureID() const; bool isLightSpotlight() const; LLVector3 getSpotLightParams() const; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index b8c8a42125..f84cd594c9 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8368,7 +8368,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff); shader.uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, mSunDiffuse.mV); - shader.uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, srgbColor4(mMoonDiffuse).mV); + shader.uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, mMoonDiffuse.mV); LLEnvironment& environment = LLEnvironment::instance(); shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); @@ -8705,7 +8705,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) const F32* c = center.getF32ptr(); F32 s = volume->getLightRadius()*1.5f; - LLColor3 col = volume->getLightsRGBColor(); + LLColor3 col = volume->getLightSRGBColor(); if (col.magVecSquared() < 0.001f) { @@ -8797,10 +8797,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) setupSpotLight(gDeferredSpotLightProgram, drawablep); - LLColor3 col = volume->getLightsRGBColor(); - /*col.mV[0] = powf(col.mV[0], 2.2f); - col.mV[1] = powf(col.mV[1], 2.2f); - col.mV[2] = powf(col.mV[2], 2.2f);*/ + LLColor3 col = volume->getLightSRGBColor(); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); @@ -8888,7 +8885,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) setupSpotLight(gDeferredMultiSpotLightProgram, drawablep); - LLColor3 col = volume->getLightsRGBColor(); + LLColor3 col = volume->getLightSRGBColor(); gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); -- cgit v1.3 From e4bac71ac38f04eca96f4e3c932b51bd0d7432a1 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Tue, 2 Apr 2019 14:14:19 -0700 Subject: Fix shader link fail from forward decl of wrong soft clip func in class 1. Fix trying to bind diffuse maps for shader without uniform in shadow shaders. Clean up merge fail around mShaderLevel namechange. --- .../shaders/class1/deferred/softenLightF.glsl | 5 +-- indra/newview/lldrawpoolavatar.cpp | 39 ++++++++++++++++++---- indra/newview/lldrawpoolavatar.h | 4 +-- indra/newview/lldrawpoolterrain.cpp | 2 +- indra/newview/llviewershadermgr.cpp | 6 ++-- indra/newview/llvovolume.cpp | 2 +- 6 files changed, 39 insertions(+), 19 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 2df55f6cfc..e22240727c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -73,8 +73,7 @@ vec3 fullbrightAtmosTransportFrag(vec3 l, vec3 additive, vec3 atten); void calcFragAtmospherics(vec3 inPositionEye, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten); -vec3 scaleSoftClip(vec3 l); -vec3 fullbrightScaleSoftClip(vec3 l); +vec3 scaleSoftClipFrag(vec3 l); vec4 getPositionWithDepth(vec2 pos_screen, float depth); @@ -145,8 +144,6 @@ void main() if (norm.w < 0.5) { - //col = mix(atmosFragLighting(col, additive, atten), fullbrightAtmosTransportFrag(col, additive, atten), diffuse.a); - //col = mix(scaleSoftClipFrag(col), fullbrightScaleSoftClipFrag(col, additive, atten), diffuse.a); col = atmosFragLighting(col, additive, atten); col = scaleSoftClipFrag(col); } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 4b6ddf153d..19b5b4af30 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -455,8 +455,13 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) sVertexProgram = &gDeferredAvatarAlphaShadowProgram; // bind diffuse tex so we can reference the alpha channel... - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - + S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP); + sDiffuseChannel = 0; + if (loc != -1) + { + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + } + if ((sShaderLevel > 0)) // for hardware blending { sRenderingSkinned = TRUE; @@ -470,8 +475,13 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) sVertexProgram = &gDeferredAvatarAlphaMaskShadowProgram; // bind diffuse tex so we can reference the alpha channel... - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - + S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP); + sDiffuseChannel = 0; + if (loc != -1) + { + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + } + if ((sShaderLevel > 0)) // for hardware blending { sRenderingSkinned = TRUE; @@ -485,7 +495,12 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) sVertexProgram = &gDeferredAttachmentAlphaShadowProgram; // bind diffuse tex so we can reference the alpha channel... - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP); + sDiffuseChannel = 0; + if (loc != -1) + { + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + } if ((sShaderLevel > 0)) // for hardware blending { @@ -500,7 +515,12 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) sVertexProgram = &gDeferredAttachmentAlphaMaskShadowProgram; // bind diffuse tex so we can reference the alpha channel... - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP); + sDiffuseChannel = 0; + if (loc != -1) + { + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + } if ((sShaderLevel > 0)) // for hardware blending { @@ -513,7 +533,12 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) else // SHADOW_PASS_ATTACHMENT_OPAQUE { sVertexProgram = &gDeferredAttachmentShadowProgram; - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP); + sDiffuseChannel = 0; + if (loc != -1) + { + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + } sVertexProgram->bind(); } } diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 3392381e11..e8add0e1d8 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -58,8 +58,6 @@ public: ~LLDrawPoolAvatar(); /*virtual*/ BOOL isDead(); - virtual S32 getShaderLevel() const; - typedef enum { RIGGED_MATERIAL=0, @@ -178,7 +176,7 @@ typedef enum virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } - virtual S32 getVertexShaderLevel() const; + virtual S32 getShaderLevel() const; LLDrawPoolAvatar(); diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index b5b2fd5e00..d852eb33d8 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -249,7 +249,7 @@ void LLDrawPoolTerrain::renderDeferred(S32 pass) // Special-case for land ownership feedback if (gSavedSettings.getBOOL("ShowParcelOwners")) { - hilightParcelOwners(); + hilightParcelOwners(true); } } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 5cf9a74f8a..bcc3f83694 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -1300,7 +1300,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredHighlightProgram.mShaderFiles.clear(); gDeferredHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredHighlightProgram.mShaderFiles.push_back(make_pair("deferred/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredHighlightProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gDeferredHighlightProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gDeferredHighlightProgram.createShader(NULL, NULL); } @@ -1310,7 +1310,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredHighlightNormalProgram.mShaderFiles.clear(); gDeferredHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightNormV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredHighlightNormalProgram.mShaderFiles.push_back(make_pair("deferred/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredHighlightNormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gDeferredHighlightNormalProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gHighlightNormalProgram.createShader(NULL, NULL); } @@ -1320,7 +1320,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredHighlightSpecularProgram.mShaderFiles.clear(); gDeferredHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightSpecV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredHighlightSpecularProgram.mShaderFiles.push_back(make_pair("deferred/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredHighlightSpecularProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + gDeferredHighlightSpecularProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gDeferredHighlightSpecularProgram.createShader(NULL, NULL); } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index d6bd9c3b66..7e7bc1112d 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4974,7 +4974,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, if ( type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT) - && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1) + && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1) { LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL; } -- cgit v1.3 From 605c9c19661702755171669e2af846abe77d2a51 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Wed, 8 May 2019 11:42:31 -0700 Subject: Fix merge fail. --- indra/llui/llmenugl.h | 7 ++++++- indra/newview/llinventorybridge.cpp | 5 ++++- indra/newview/llinventorypanel.cpp | 3 --- indra/newview/llmeshrepository.cpp | 13 ------------- indra/newview/llviewerfloaterreg.cpp | 2 +- indra/newview/llviewermenufile.cpp | 2 +- indra/newview/llviewermessage.cpp | 28 ++++++---------------------- indra/newview/llviewertexture.cpp | 4 ++-- indra/newview/llviewertexture.h | 2 +- indra/newview/llvovolume.cpp | 4 ++-- 10 files changed, 23 insertions(+), 47 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index aa87329020..1f11f26192 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -175,7 +175,12 @@ protected: // This function appends the character string representation of // the current accelerator key and mask to the provided string. void appendAcceleratorString( std::string& st ) const; - + + virtual std::string _getSearchText() const + { + return mLabel.getString(); + } + protected: KEY mAcceleratorKey; MASK mAcceleratorMask; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 50c4fdc870..ee9dfbc376 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -81,6 +81,10 @@ #include "llwearableitemslist.h" #include "lllandmarkactions.h" #include "llpanellandmarks.h" +#include "llviewerparcelmgr.h" +#include "llparcel.h" + +#include "llenvironment.h" #include @@ -4058,7 +4062,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items } } getClipboardEntries(false, items, disabled_items, flags); - } else { diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 4eb42950b7..dd541defa1 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1726,9 +1726,6 @@ bool LLInventoryPanel::isSelectionRemovable() /************************************************************************/ /* Recent Inventory Panel related class */ /************************************************************************/ -class LLInventoryRecentItemsPanel; -static LLDefaultChildRegistry::Register t_recent_inventory_panel("recent_inventory_panel"); - static const LLRecentInventoryBridgeBuilder RECENT_ITEMS_BUILDER; class LLInventoryRecentItemsPanel : public LLInventoryPanel { diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 4e9ebec0f2..127d04c34d 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -2190,7 +2190,6 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) std::map mesh_index; std::string model_name; - std::string model_metric; S32 instance_num = 0; @@ -2220,11 +2219,6 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) model_name = data.mBaseModel->getName(); } - if (model_metric.empty()) - { - model_metric = data.mBaseModel->getMetric(); - } - std::stringstream ostr; LLModel::Decomposition& decomp = @@ -2379,11 +2373,6 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) model_name = data.mBaseModel->getName(); } - if (model_metric.empty()) - { - model_metric = data.mBaseModel->getMetric(); - } - std::stringstream ostr; LLModel::Decomposition& decomp = @@ -2514,8 +2503,6 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) if (model_name.empty()) model_name = "mesh model"; result["name"] = model_name; - if (model_metric.empty()) model_metric = "MUT_Unspecified"; - res["metric"] = model_metric; result["asset_resources"] = res; dump_llsd_to_file(result,make_dump_name("whole_model_",dump_num)); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index ad016d0817..ffc21e8f14 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -90,7 +90,7 @@ #include "llfloatermemleak.h" #include "llfloatermodelpreview.h" #include "llfloatermyscripts.h" -"llfloatermyenvironment.h" +#include "llfloatermyenvironment.h" #include "llfloaternamedesc.h" #include "llfloaternotificationsconsole.h" #include "llfloaternotificationstabbed.h" diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 693d2ab60a..07873f482f 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -812,7 +812,7 @@ void upload_done_callback( LLStringUtil::trim(asset_name); std::string display_name = LLStringUtil::null; - LLAssetStorage::LLStoreAssetCallback callback = NULL; + LLAssetStorage::LLStoreAssetCallback callback; void *userdata = NULL; upload_new_resource( next_file, diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 982f1980f1..c22be25f1f 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3760,6 +3760,7 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data) void process_time_synch(LLMessageSystem *mesgsys, void **user_data) { LLVector3 sun_direction; + LLVector3 moon_direction; LLVector3 sun_ang_velocity; F32 phase; U64 space_time_usec; @@ -3781,12 +3782,10 @@ void process_time_synch(LLMessageSystem *mesgsys, void **user_data) LL_DEBUGS("WindlightSync") << "Sun phase: " << phase << " rad = " << fmodf(phase / F_TWO_PI + 0.25, 1.f) * 24.f << " h" << LL_ENDL; - gSky.setSunPhase(phase); - gSky.setSunTargetDirection(sun_direction, sun_ang_velocity); - if ( !(gSavedSettings.getBOOL("SkyOverrideSimSunPosition") || gSky.getOverrideSun()) ) - { - gSky.setSunDirection(sun_direction, sun_ang_velocity); - } + /* LAPRAS + We decode these parts of the message but ignore them + as the real values are provided elsewhere. */ + (void)sun_direction, (void)moon_direction, (void)phase; } void process_sound_trigger(LLMessageSystem *msg, void **) @@ -5531,17 +5530,6 @@ void notify_cautioned_script_question(const LLSD& notification, const LLSD& resp void script_question_mute(const LLUUID& item_id, const std::string& object_name); -bool unknown_script_question_cb(const LLSD& notification, const LLSD& response) -{ - // Only care if they muted the object here. - if ( response["Mute"] ) // mute - { - LLUUID task_id = notification["payload"]["task_id"].asUUID(); - script_question_mute(task_id,notification["payload"]["object_name"].asString()); - } - return false; -} - void experiencePermissionBlock(LLUUID experience, LLSD result) { LLSD permission; @@ -5647,8 +5635,7 @@ void script_question_mute(const LLUUID& task_id, const std::string& object_name) bool matches(const LLNotificationPtr notification) const { if (notification->getName() == "ScriptQuestionCaution" - || notification->getName() == "ScriptQuestion" - /*|| notification->getName() == "UnknownScriptQuestion"*/) + || notification->getName() == "ScriptQuestion") { return (notification->getPayload()["task_id"].asUUID() == blocked_id); } @@ -5665,7 +5652,6 @@ void script_question_mute(const LLUUID& task_id, const std::string& object_name) static LLNotificationFunctorRegistration script_question_cb_reg_1("ScriptQuestion", script_question_cb); static LLNotificationFunctorRegistration script_question_cb_reg_2("ScriptQuestionCaution", script_question_cb); static LLNotificationFunctorRegistration script_question_cb_reg_3("ScriptQuestionExperience", script_question_cb); -//static LLNotificationFunctorRegistration unknown_script_question_cb_reg("UnknownScriptQuestion", unknown_script_question_cb); void process_script_experience_details(const LLSD& experience_details, LLSD args, LLSD payload) { @@ -5775,8 +5761,6 @@ void process_script_question(LLMessageSystem *msg, void **user_data) } } - script_question += "\n"; - args["QUESTIONS"] = script_question; if (known_questions != questions) diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 68a9994bee..5bd60c6b94 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -98,8 +98,8 @@ const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64; const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez; const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128; const S32 DEFAULT_ICON_DIMENTIONS = 32; -S32 LLViewerTexture::sMinLargeImageSize = 65536; //256 * 256. -S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA; +U32 LLViewerTexture::sMinLargeImageSize = 65536; //256 * 256. +U32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA; bool LLViewerTexture::sFreezeImageUpdates = false; F32 LLViewerTexture::sCurrentTime = 0.0f; F32 LLViewerTexture::sTexelPixelRatio = 1.0f; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 78bebb542a..69568cc825 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -125,7 +125,7 @@ public: virtual BOOL isMissingAsset() const ; virtual void dump(); // debug info to LL_INFOS() - virtual BOOL isViewerMediaTexture() const { return false; } + virtual bool isViewerMediaTexture() const { return false; } /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ; /*virtual*/ bool bindDebugImage(const S32 stage = 0) ; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 08798d81b7..664615d4eb 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4981,7 +4981,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, if ( type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT) - && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1) + && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1) { LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL; } @@ -5882,7 +5882,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) spec_mask = spec_mask | LLVertexBuffer::MAP_EMISSIVE; } - BOOL batch_textures = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1; + BOOL batch_textures = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1; if (batch_textures) { -- cgit v1.3 From 4abb342e9564a7740475c3abe60cd62ae5bbc34d Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Tue, 18 Jun 2019 13:14:27 -0700 Subject: SL-10969 Remove ambiance handling from alpha and blended materials objects for now. Still too many setups where they get blown out due to attenuation mismatches with deferred. --- .../app_settings/shaders/class1/deferred/alphaF.glsl | 20 +++++++++++--------- .../shaders/class1/deferred/materialF.glsl | 16 ++++++++++++---- indra/newview/llvovolume.cpp | 2 +- indra/newview/pipeline.cpp | 12 ++++++------ 4 files changed, 30 insertions(+), 20 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index 7dc2fb4cc0..241857dd92 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -96,12 +96,12 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec float dist = length(lv); float da = 1.0; - if (dist > la) + /*if (dist > la) { return col; } - /* clip to projector bounds + clip to projector bounds vec4 proj_tc = proj_mat * lp; if (proj_tc.z < 0 @@ -116,15 +116,15 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec if (dist > 0.0 && la > 0.0) { - dist /= la; + dist /= la; //normalize light vector lv = normalize(lv); //distance attenuation + fa += 1.0f; float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); dist_atten *= dist_atten; - //dist_atten *= 2.0f; if (dist_atten <= 0.0) { @@ -137,10 +137,11 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec //angular attenuation da *= dot(n, lv); + da = max(0.0, da); float lit = 0.0f; - float amb_da = ambiance; + float amb_da = 0.0;//ambiance; if (da > 0) { lit = max(da * dist_atten,0.0); @@ -151,7 +152,8 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec amb_da *= dist_atten; amb_da = min(amb_da, 1.0f - lit); - col.rgb += amb_da * light_col * diffuse; + // SL-10969 ... need to work out why this blows out in many setups... + //col.rgb += amb_da * light_col * diffuse; // no spec for alpha shader... } @@ -174,13 +176,14 @@ void main() #endif #ifdef USE_DIFFUSE_TEX - vec4 diffuse_srgb = texture2D(diffuseMap,vary_texcoord0.xy); + vec4 diffuse_tap = texture2D(diffuseMap,vary_texcoord0.xy); #endif #ifdef USE_INDEXED_TEX - vec4 diffuse_srgb = diffuseLookup(vary_texcoord0.xy); + vec4 diffuse_tap = diffuseLookup(vary_texcoord0.xy); #endif + vec4 diffuse_srgb = diffuse_tap; vec4 diffuse_linear = vec4(srgb_to_linear(diffuse_srgb.rgb), diffuse_srgb.a); #ifdef FOR_IMPOSTOR @@ -205,7 +208,6 @@ void main() #ifdef USE_VERTEX_COLOR float final_alpha = diffuse_linear.a * vertex_color.a; - diffuse_srgb.rgb *= vertex_color.rgb; diffuse_linear.rgb *= vertex_color.rgb; #else float final_alpha = diffuse_linear.a; diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl index 571d0dd17a..8ebb2f44d3 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl @@ -117,6 +117,7 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe lv = normalize(lv); //distance attenuation + fa += 1.0f; float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); dist_atten *= dist_atten; //dist_atten *= 2.0f; @@ -136,7 +137,7 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe float lit = 0.0f; float amb_da = ambiance; - if (da > 0) + if (da >= 0) { lit = max(da * dist_atten,0.0); col = lit * light_col * diffuse; @@ -146,7 +147,8 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe amb_da *= dist_atten; amb_da = min(amb_da, 1.0f - lit); - col.rgb += amb_da * light_col * diffuse; + // SL-10969 need to see why these are blown out + //col.rgb += amb_da * light_col * diffuse; if (spec.a > 0.0) { @@ -225,8 +227,14 @@ void main() vec2 pos_screen = vary_texcoord0.xy; vec4 diffuse_tap = texture2D(diffuseMap, vary_texcoord0.xy); + +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) + vec4 diffuse_srgb = diffuse_tap; + vec4 diffuse_linear = vec4(srgb_to_linear(diffuse_srgb.rgb), diffuse_srgb.a); +#else vec4 diffuse_linear = diffuse_tap; - vec4 diffuse_srgb = vec4(linear_to_srgb(diffuse_linear.rgb), diffuse_tap.a); + vec4 diffuse_srgb = vec4(linear_to_srgb(diffuse_linear.rgb), diffuse_linear.a); +#endif #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK) if (diffuse_linear.a < minimum_alpha) @@ -338,7 +346,7 @@ vec3 post_ambient = color.rgb; vec3 post_sunlight = color.rgb; - color.rgb *= diffuse_linear.rgb; + color.rgb *= diffuse_srgb.rgb; vec3 post_diffuse = color.rgb; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 664615d4eb..61eb6f18a2 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3370,7 +3370,7 @@ F32 LLVOVolume::getLightFalloff() const const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); if (param_block) { - return param_block->getFalloff(); + return param_block->getFalloff() * 0.5f; } else { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index d13b0634cf..d1a6fd12f2 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6346,11 +6346,11 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) continue; } - F32 x = (3.f * (1.f + light->getLightFalloff())); // why this magic? probably trying to match a historic behavior. + F32 x = (3.f * (1.f + (light->getLightFalloff() * 2.0f))); // why this magic? probably trying to match a historic behavior. F32 linatten = x / (light_radius); // % of brightness at radius // get falloff to match for forward deferred rendering lights - F32 falloff = light->getLightFalloff() * 0.5f + (sRenderDeferred ? 0.0 : 1.f); + F32 falloff = light->getLightFalloff() + (sRenderDeferred ? 0.0 : 1.f); mHWLightColors[cur_light] = light_color; LLLightState* light_state = gGL.getLight(cur_light); @@ -8784,7 +8784,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); - gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); + gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()); gGL.syncMatrices(); mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); @@ -8804,7 +8804,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) mat.mult_matrix_vec(tc); fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s)); - light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); + light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff())); } } unbindDeferredShader(gDeferredLightProgram); @@ -8840,7 +8840,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); - gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); + gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()); gGL.syncMatrices(); mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); @@ -8915,7 +8915,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) LLVector3 center = drawablep->getPositionAgent(); F32* c = center.mV; F32 light_size_final = volume->getLightRadius()*1.5f; - F32 light_falloff_final = volume->getLightFalloff()*0.5f; + F32 light_falloff_final = volume->getLightFalloff(); sVisibleLightCount++; -- cgit v1.3 From 0728a31a8ff3d2f9272c2d8c47420cf46ce5ad82 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Tue, 18 Jun 2019 15:31:22 -0700 Subject: SL-11051 Make genDrawInfo pay more attention to faces with 100% transparency that are not invisiprims. --- .../shaders/class1/deferred/shadowAlphaMaskF.glsl | 4 +- indra/newview/llvovolume.cpp | 195 +++++++++++---------- 2 files changed, 106 insertions(+), 93 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl index b2fbd8b86c..0d028d2729 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl @@ -43,8 +43,6 @@ void main() { float alpha = diffuseLookup(vary_texcoord0.xy).a; - alpha *= vertex_color.a; - // mask cutoff 0 -> no shadow SL-11051 if (minimum_alpha == 0) { @@ -64,6 +62,8 @@ void main() } } + alpha *= vertex_color.a; + frag_color = vec4(1,1,1,1); #if !defined(DEPTH_CLAMP) diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 61eb6f18a2..edd5f5e2cb 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4977,6 +4977,12 @@ static LLTrace::BlockTimerStatHandle FTM_REGISTER_FACE("Register Face"); void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) { + + //const LLTextureEntry* te = facep->getTextureEntry(); + //F32 te_alpha = te->getColor().mV[VW]; + // we should not attempt to render anything that's 100% transparent except invisiprims... + //llassert(te_alpha > 0.0f || type == LLRenderPass::PASS_ALPHA_INVISIBLE); + LL_RECORD_BLOCK_TIME(FTM_REGISTER_FACE); if ( type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() @@ -5516,6 +5522,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) LLViewerTexture* tex = facep->getTexture(); U32 type = gPipeline.getPoolTypeFromTE(te, tex); + F32 te_alpha = te->getColor().mV[3]; if (te->getGlow()) { @@ -5527,17 +5534,24 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (mat && LLPipeline::sRenderDeferred) { U8 alpha_mode = mat->getDiffuseAlphaMode(); + + + // don't bother with 100% transparent faces... + if (te_alpha <= 0.0f) + { + continue; + } bool is_alpha = type == LLDrawPool::POOL_ALPHA && (alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND || - te->getColor().mV[3] < 0.999f); + te_alpha < 0.999f); if (is_alpha) { //this face needs alpha blending, override alpha mode alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; } - if (!is_alpha || te->getColor().mV[3] > 0.f) // //only add the face if it will actually be visible + if (!is_alpha || te_alpha > 0.f) // //only add the face if it will actually be visible { U32 mask = mat->getShaderMask(alpha_mode); pool->addRiggedFace(facep, mask); @@ -5551,35 +5565,33 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) bool can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; - if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && te->getColor().mV[3] >= 0.999f) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); - } - else if (is_alpha || (te->getColor().mV[3] < 0.999f)) - { - if (te->getColor().mV[3] > 0.f) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA : LLDrawPoolAvatar::RIGGED_ALPHA); - } - } - else if (gPipeline.canUseVertexShaders() - && LLPipeline::sRenderBump - && te->getShiny() - && can_be_shiny) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY : LLDrawPoolAvatar::RIGGED_SHINY); - } - else - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); - } + if (te_alpha > 0.f) + { + if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && te_alpha >= 0.999f) + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); + } + else if (is_alpha || (te_alpha < 0.999f)) + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA : LLDrawPoolAvatar::RIGGED_ALPHA); + } + else if (gPipeline.canUseVertexShaders() + && LLPipeline::sRenderBump + && te->getShiny() + && can_be_shiny) + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY : LLDrawPoolAvatar::RIGGED_SHINY); + } + else + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); + } + } } - else - { - if (type == LLDrawPool::POOL_ALPHA) - { - if (te->getColor().mV[3] > 0.f) - { + else if (te_alpha > 0.0f) + { + if (type == LLDrawPool::POOL_ALPHA) + { if (te->getFullbright()) { pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); @@ -5588,54 +5600,52 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); } - } - } - else if (te->getShiny()) - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); - } - else - { - if (LLPipeline::sRenderDeferred) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); - } - } - } - else - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); - } - } - - - if (LLPipeline::sRenderDeferred) - { - if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) - { - if (te->getBumpmap()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); - } - } - } - } + } + else if (te->getShiny()) + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); + } + else + { + if (LLPipeline::sRenderDeferred) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); + } + } + } + else + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + } + + if (LLPipeline::sRenderDeferred) + { + if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) + { + if (te->getBumpmap()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); + } + } + } + } } continue; @@ -6450,10 +6460,13 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; } + F32 te_alpha = te->getColor().mV[3]; bool use_legacy_bump = te->getBumpmap() && (te->getBumpmap() < 18) && (!mat || mat->getNormalID().isNull()); - bool opaque = te->getColor().mV[3] >= 0.999f; + bool opaque = te_alpha >= 0.999f; + bool transparent = te_alpha < 0.999f; + bool invisible = te_alpha <= 0.0f; - if (mat && LLPipeline::sRenderDeferred && !hud_group) + if (mat && LLPipeline::sRenderDeferred && !hud_group && !invisible) { bool material_pass = false; @@ -6485,7 +6498,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { material_pass = true; } - else + else if (!invisible) { registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); } @@ -6495,7 +6508,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } - else if (te->getColor().mV[3] < 0.999f) + else if (transparent) { registerFace(group, facep, LLRenderPass::PASS_ALPHA); } @@ -6540,10 +6553,10 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace registerFace(group, facep, pass[mask]); } } - else if (mat) + else if (mat && !invisible) { U8 mode = mat->getDiffuseAlphaMode(); - if (te->getColor().mV[3] < 0.999f) + if (transparent) { mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; } @@ -6571,7 +6584,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace else if (is_alpha) { // can we safely treat this as an alpha mask? - if (facep->getFaceColor().mV[3] <= 0.f) + if (invisible) { //100% transparent, don't render unless we're highlighting transparent registerFace(group, facep, LLRenderPass::PASS_ALPHA_INVISIBLE); } @@ -6594,7 +6607,8 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace else if (gPipeline.canUseVertexShaders() && LLPipeline::sRenderBump && te->getShiny() - && can_be_shiny) + && can_be_shiny + && !invisible) { //shiny if (tex->getPrimaryFormat() == GL_ALPHA) { //invisiprim+shiny @@ -6630,7 +6644,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace registerFace(group, facep, LLRenderPass::PASS_SHINY); } } - else + else if (!invisible) { //not alpha and not shiny if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) { //invisiprim @@ -6668,9 +6682,8 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } + } } - } - if (!gPipeline.canUseVertexShaders() && !is_alpha && @@ -6682,7 +6695,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace } //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 - if (!is_alpha && (hud_group || !LLPipeline::sRenderDeferred)) + if (!invisible && !is_alpha && (hud_group || !LLPipeline::sRenderDeferred)) { llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); @@ -6693,7 +6706,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace } } - if (!is_alpha && LLPipeline::sRenderGlow && te->getGlow() > 0.f) + if (!invisible && !is_alpha && LLPipeline::sRenderGlow && te->getGlow() > 0.f) { registerFace(group, facep, LLRenderPass::PASS_GLOW); } -- cgit v1.3 From 7f24395889832c9ce51bae69054c7d081d77f65a Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Wed, 19 Jun 2019 08:31:43 -0700 Subject: SL-11318 Make alpha pass start with no shader bound. Make diffuse mode alpha-blended fullbrights get into alpha pass properly. --- indra/newview/lldrawpoolalpha.cpp | 3 +++ indra/newview/llvovolume.cpp | 16 +++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index d671a5968f..da0467315f 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -226,6 +226,9 @@ void LLDrawPoolAlpha::beginRenderPass(S32 pass) } } gPipeline.enableLightsDynamic(); + + LLGLSLShader::bindNoShader(); + current_shader = NULL; } void LLDrawPoolAlpha::endRenderPass( S32 pass ) diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index edd5f5e2cb..3866045b1d 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -6493,14 +6493,20 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace } else { - if (mat->getEnvironmentIntensity() > 0 || - te->getShiny() > 0) + if (mat->getEnvironmentIntensity() > 0 || te->getShiny() > 0) { material_pass = true; } - else if (!invisible) + else { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + if (opaque) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } } } } @@ -6565,7 +6571,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK : LLRenderPass::PASS_ALPHA_MASK); } - else if (is_alpha || (te->getColor().mV[3] < 0.999f)) + else if (is_alpha || transparent) { registerFace(group, facep, LLRenderPass::PASS_ALPHA); } -- cgit v1.3 From b659e5596e6612d83ce41dd6ce44228103851875 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Fri, 28 Jun 2019 08:45:07 -0700 Subject: SL-11514 Convince Geenzo code to get a little DeMorgan in it. Trophy Unlocked: make all alpha textures partcipate in picking. --- indra/llrender/llimagegl.cpp | 4 ++-- indra/newview/lltoolpie.cpp | 20 -------------------- indra/newview/llvovolume.cpp | 8 +++----- 3 files changed, 5 insertions(+), 27 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 790ba25112..ff74380217 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -2049,8 +2049,8 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) freePickMask(); if (mFormatType != GL_UNSIGNED_BYTE || - mFormatPrimary != GL_RGBA || - mFormatPrimary != GL_SRGB_ALPHA) + ((mFormatPrimary != GL_RGBA) + && (mFormatPrimary != GL_SRGB_ALPHA))) { //cannot generate a pick mask for this texture return; diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index d5ffdef4c9..f184b22ccb 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -112,26 +112,6 @@ BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask) mMouseDownX = x; mMouseDownY = y; -#if 0 - LLTimer pick_timer; - BOOL pick_rigged = false; //gSavedSettings.getBOOL("AnimatedObjectsAllowLeftClick"); - mPick = gViewerWindow->pickImmediate(x, y, FALSE, pick_rigged); - LLViewerObject *object = mPick.getObject(); - LLViewerObject *parent = object ? object->getRootEdit() : NULL; - if (!object - || object->isAttachment() - || object->getClickAction() == CLICK_ACTION_DISABLED - || (!useClickAction(mask, object, parent) && !object->flagHandleTouch() && !(parent && parent->flagHandleTouch()))) - { - // Unless we are hovering over actionable visible object - // left mouse down always picks transparent (but see handleMouseUp). - // Also see LLToolPie::handleHover() - priorities are a bit different there. - // Todo: we need a more consistent set of rules to work with - mPick = gViewerWindow->pickImmediate(x, y, TRUE /*transparent*/, pick_rigged); - } - LL_INFOS() << "pick_rigged is " << (S32) pick_rigged << " pick time elapsed " << pick_timer.getElapsedTimeF32() << LL_ENDL; -#endif - //left mouse down always picks transparent (but see handleMouseUp) mPick = gViewerWindow->pickImmediate(x, y, TRUE, FALSE); mPick.mKeyMask = mask; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 3866045b1d..dcefa22e75 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4579,12 +4579,10 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& } } + BOOL no_texture = !face->getTexture() || !face->getTexture()->hasGLTexture(); + BOOL mask = no_texture ? FALSE : face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)); if (face && - (ignore_alpha || - pick_transparent || - !face->getTexture() || - !face->getTexture()->hasGLTexture() || - face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)))) + (ignore_alpha || pick_transparent || no_texture || mask)) { local_end = p; if (face_hitp != NULL) -- cgit v1.3 From 21536f412edab7f3c1d6a9eb93f47015a0c8ad5c Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Fri, 28 Jun 2019 15:49:42 -0700 Subject: SL-11521 Make llvovolume submit completely transparent yet still glowy faces again. --- indra/newview/llvovolume.cpp | 177 ++++++++++++++++++++----------------------- 1 file changed, 84 insertions(+), 93 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index dcefa22e75..8aaf678aba 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4975,12 +4975,6 @@ static LLTrace::BlockTimerStatHandle FTM_REGISTER_FACE("Register Face"); void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) { - - //const LLTextureEntry* te = facep->getTextureEntry(); - //F32 te_alpha = te->getColor().mV[VW]; - // we should not attempt to render anything that's 100% transparent except invisiprims... - //llassert(te_alpha > 0.0f || type == LLRenderPass::PASS_ALPHA_INVISIBLE); - LL_RECORD_BLOCK_TIME(FTM_REGISTER_FACE); if ( type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() @@ -5532,13 +5526,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (mat && LLPipeline::sRenderDeferred) { U8 alpha_mode = mat->getDiffuseAlphaMode(); - - - // don't bother with 100% transparent faces... - if (te_alpha <= 0.0f) - { - continue; - } bool is_alpha = type == LLDrawPool::POOL_ALPHA && (alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND || @@ -5563,33 +5550,35 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) bool can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; - if (te_alpha > 0.f) - { - if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && te_alpha >= 0.999f) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); - } - else if (is_alpha || (te_alpha < 0.999f)) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA : LLDrawPoolAvatar::RIGGED_ALPHA); - } - else if (gPipeline.canUseVertexShaders() - && LLPipeline::sRenderBump - && te->getShiny() - && can_be_shiny) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY : LLDrawPoolAvatar::RIGGED_SHINY); - } - else - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); - } - } + if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && te->getColor().mV[3] >= 0.999f) + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); + } + else if (is_alpha || (te->getColor().mV[3] < 0.999f)) + { + if (te->getColor().mV[3] > 0.f) + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA : LLDrawPoolAvatar::RIGGED_ALPHA); + } + } + else if (gPipeline.canUseVertexShaders() + && LLPipeline::sRenderBump + && te->getShiny() + && can_be_shiny) + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY : LLDrawPoolAvatar::RIGGED_SHINY); + } + else + { + pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); + } } - else if (te_alpha > 0.0f) - { - if (type == LLDrawPool::POOL_ALPHA) - { + else + { + if (type == LLDrawPool::POOL_ALPHA) + { + if (te->getColor().mV[3] > 0.f) + { if (te->getFullbright()) { pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); @@ -5598,52 +5587,54 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); } - } - else if (te->getShiny()) - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); - } - else - { - if (LLPipeline::sRenderDeferred) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); - } - } - } - else - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); - } - } - - if (LLPipeline::sRenderDeferred) - { - if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) - { - if (te->getBumpmap()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); - } - } - } - } + } + } + else if (te->getShiny()) + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); + } + else + { + if (LLPipeline::sRenderDeferred) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); + } + } + } + else + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + } + + + if (LLPipeline::sRenderDeferred) + { + if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) + { + if (te->getBumpmap()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); + } + } + } + } } continue; @@ -6464,7 +6455,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace bool transparent = te_alpha < 0.999f; bool invisible = te_alpha <= 0.0f; - if (mat && LLPipeline::sRenderDeferred && !hud_group && !invisible) + if (mat && LLPipeline::sRenderDeferred && !hud_group) { bool material_pass = false; @@ -6557,7 +6548,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace registerFace(group, facep, pass[mask]); } } - else if (mat && !invisible) + else if (mat) { U8 mode = mat->getDiffuseAlphaMode(); if (transparent) @@ -6611,8 +6602,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace else if (gPipeline.canUseVertexShaders() && LLPipeline::sRenderBump && te->getShiny() - && can_be_shiny - && !invisible) + && can_be_shiny) { //shiny if (tex->getPrimaryFormat() == GL_ALPHA) { //invisiprim+shiny @@ -6648,7 +6638,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace registerFace(group, facep, LLRenderPass::PASS_SHINY); } } - else if (!invisible) + else { //not alpha and not shiny if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) { //invisiprim @@ -6686,8 +6676,9 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } - } } + } + if (!gPipeline.canUseVertexShaders() && !is_alpha && @@ -6699,7 +6690,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace } //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 - if (!invisible && !is_alpha && (hud_group || !LLPipeline::sRenderDeferred)) + if (!is_alpha && (hud_group || !LLPipeline::sRenderDeferred)) { llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); @@ -6710,7 +6701,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace } } - if (!invisible && !is_alpha && LLPipeline::sRenderGlow && te->getGlow() > 0.f) + if (!is_alpha && LLPipeline::sRenderGlow && te->getGlow() > 0.f) { registerFace(group, facep, LLRenderPass::PASS_GLOW); } -- cgit v1.3 From 576f1cdd7e16e44c43b39618f715753160045468 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Mon, 1 Jul 2019 17:23:59 -0700 Subject: SL-11521, SL-10625 Try aligning data used for glReadPixels to see if we can coax the Intel driver stack into being a less souciant pile of detritus. Replace face color based test replaced with other logic in error. --- indra/llappearance/llpolymorph.cpp | 4 ++-- indra/llappearance/lltexlayer.cpp | 26 +++++++++++++++++++++----- indra/newview/llvovolume.cpp | 12 ++++++++---- 3 files changed, 31 insertions(+), 11 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 2cb4c65d7c..ce7010984a 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -816,8 +816,8 @@ void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, U32 s = llclamp((U32)(uvCoords.mV[VX] * (F32)(width - 1)), (U32)0, (U32)width - 1); U32 t = llclamp((U32)(uvCoords.mV[VY] * (F32)(height - 1)), (U32)0, (U32)height - 1); - mWeights[index] = ((F32) maskTextureData[((t * width + s) * num_components) + (num_components - 1)]) / 255.f; - + mWeights[index] = maskTextureData ? ((F32) maskTextureData[((t * width + s) * num_components) + (num_components - 1)]) / 255.f : 0.0f; + if (invert) { mWeights[index] = 1.f - mWeights[index]; diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 3f2fcce429..22b3364559 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -1575,14 +1575,30 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC delete [] alpha_data; mAlphaCache.erase(iter2); } - alpha_data = new U8[width * height]; + + // GPUs tend to be very uptight about memory alignment as the DMA used to convey + // said data to the card works better when well-aligned so plain old default-aligned heap mem is a no-no + //new U8[width * height]; + size_t mem_size = (width * height); + size_t rem = (mem_size & 0x3F); + mem_size += rem > 0 ? (mem_size + (32 - rem)) : 0; + + alpha_data = (U8*)ll_aligned_malloc_32(mem_size); + mAlphaCache[cache_index] = alpha_data; - - // nSight doesn't support use of glReadPixels - if (!LLRender::sNsightDebugSupport) + + bool skip_readback = LLRender::sNsightDebugSupport; // nSight doesn't support use of glReadPixels + // || gGLManager.mIsIntel; SL-10625? + + if (!skip_readback) { - glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); + glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); } + else + { + ll_aligned_free_32(alpha_data); + alpha_data = nullptr; + } } getTexLayerSet()->getAvatarAppearance()->dirtyMesh(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 8aaf678aba..3740caa53f 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -6453,7 +6453,8 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace bool use_legacy_bump = te->getBumpmap() && (te->getBumpmap() < 18) && (!mat || mat->getNormalID().isNull()); bool opaque = te_alpha >= 0.999f; bool transparent = te_alpha < 0.999f; - bool invisible = te_alpha <= 0.0f; + + is_alpha = (is_alpha || transparent) ? TRUE : FALSE; if (mat && LLPipeline::sRenderDeferred && !hud_group) { @@ -6551,7 +6552,10 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace else if (mat) { U8 mode = mat->getDiffuseAlphaMode(); - if (transparent) + + is_alpha = (is_alpha || (mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)); + + if (is_alpha) { mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; } @@ -6560,7 +6564,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK : LLRenderPass::PASS_ALPHA_MASK); } - else if (is_alpha || transparent) + else if (is_alpha ) { registerFace(group, facep, LLRenderPass::PASS_ALPHA); } @@ -6579,7 +6583,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace else if (is_alpha) { // can we safely treat this as an alpha mask? - if (invisible) + if (facep->getFaceColor().mV[3] <= 0.f) { //100% transparent, don't render unless we're highlighting transparent registerFace(group, facep, LLRenderPass::PASS_ALPHA_INVISIBLE); } -- cgit v1.3 From 11331604767b2dcf50c7a84f24843ce8e531a409 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Fri, 12 Jul 2019 13:26:02 -0700 Subject: SL-11109 Make shadowAlphaMask shader ignore vertex alpha before discards iff we're a fullbright object. Keep llappearance from stuffing dangling pointers into the alpha cache (crash iff you're using nSight debugging and disable readbacks). --- indra/llappearance/lltexlayer.cpp | 6 ++--- indra/llrender/llvertexbuffer.cpp | 26 +++++++++++----------- .../shaders/class1/deferred/shadowAlphaMaskF.glsl | 6 +++-- indra/newview/llviewershadermgr.cpp | 22 ++++++++++++++++++ indra/newview/llviewershadermgr.h | 1 + indra/newview/llvovolume.cpp | 2 +- indra/newview/pipeline.cpp | 21 +++++++++++++++-- indra/newview/pipeline.h | 1 + 8 files changed, 64 insertions(+), 21 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index ca0d102b74..19a4f3e12d 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -1586,8 +1586,6 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC alpha_data = (U8*)ll_aligned_malloc_32(mem_size); - mAlphaCache[cache_index] = alpha_data; - bool skip_readback = LLRender::sNsightDebugSupport || gGLManager.mIsIntel; // nSight doesn't support use of glReadPixels if (!skip_readback) @@ -1598,7 +1596,9 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC { ll_aligned_free_32(alpha_data); alpha_data = nullptr; - } + } + + mAlphaCache[cache_index] = alpha_data; } getTexLayerSet()->getAvatarAppearance()->dirtyMesh(); diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 1312f6afda..0c53d48c08 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -942,15 +942,15 @@ S32 LLVertexBuffer::determineUsage(S32 usage) { //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default if (ret_usage != GL_DYNAMIC_COPY_ARB) { - if (sDisableVBOMapping) - { //always use stream draw if VBO mapping is disabled - ret_usage = GL_STREAM_DRAW_ARB; - } - else - { - ret_usage = GL_DYNAMIC_DRAW_ARB; - } - } + if (sDisableVBOMapping) + { //always use stream draw if VBO mapping is disabled + ret_usage = GL_STREAM_DRAW_ARB; + } + else + { + ret_usage = GL_DYNAMIC_DRAW_ARB; + } + } } return ret_usage; @@ -1506,10 +1506,10 @@ bool LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) llassert(newnverts >= 0); llassert(newnindices >= 0); - bool sucsess = true; + bool success = true; - sucsess &= updateNumVerts(newnverts); - sucsess &= updateNumIndices(newnindices); + success &= updateNumVerts(newnverts); + success &= updateNumIndices(newnindices); if (useVBOs()) { @@ -1521,7 +1521,7 @@ bool LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) } } - return sucsess; + return success; } bool LLVertexBuffer::useVBOs() const diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl index 0d028d2729..9b8df0a5a4 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl @@ -49,6 +49,10 @@ void main() discard; } +#if !defined(IS_FULLBRIGHT) + alpha *= vertex_color.a; +#endif + if (alpha < 0.05) // treat as totally transparent { discard; @@ -62,8 +66,6 @@ void main() } } - alpha *= vertex_color.a; - frag_color = vec4(1,1,1,1); #if !defined(DEPTH_CLAMP) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index bd8064999f..5297e59e18 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -215,6 +215,7 @@ LLGLSLShader gDeferredSoftenWaterProgram; LLGLSLShader gDeferredShadowProgram; LLGLSLShader gDeferredShadowCubeProgram; LLGLSLShader gDeferredShadowAlphaMaskProgram; +LLGLSLShader gDeferredShadowFullbrightAlphaMaskProgram; LLGLSLShader gDeferredAvatarShadowProgram; LLGLSLShader gDeferredAvatarAlphaShadowProgram; LLGLSLShader gDeferredAvatarAlphaMaskShadowProgram; @@ -1293,6 +1294,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredShadowProgram.unload(); gDeferredShadowCubeProgram.unload(); gDeferredShadowAlphaMaskProgram.unload(); + gDeferredShadowFullbrightAlphaMaskProgram.unload(); gDeferredAvatarShadowProgram.unload(); gDeferredAvatarAlphaShadowProgram.unload(); gDeferredAvatarAlphaMaskShadowProgram.unload(); @@ -2401,6 +2403,26 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() } if (success) + { + gDeferredShadowFullbrightAlphaMaskProgram.mName = "Deferred Shadow Fullbright Alpha Mask Shader"; + gDeferredShadowFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + + gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.clear(); + gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB)); + + gDeferredShadowFullbrightAlphaMaskProgram.clearPermutations(); + if (gGLManager.mHasDepthClamp) + { + gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1"); + } + gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("IS_FULLBRIGHT", "1"); + gDeferredShadowFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredShadowFullbrightAlphaMaskProgram.createShader(NULL, NULL); + llassert(success); + } + + if (success) { gDeferredShadowAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader"; gDeferredShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 18be3c22aa..081221f15b 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -301,6 +301,7 @@ extern LLGLSLShader gDeferredSoftenWaterProgram; extern LLGLSLShader gDeferredShadowProgram; extern LLGLSLShader gDeferredShadowCubeProgram; extern LLGLSLShader gDeferredShadowAlphaMaskProgram; +extern LLGLSLShader gDeferredShadowFullbrightAlphaMaskProgram; extern LLGLSLShader gDeferredPostProgram; extern LLGLSLShader gDeferredCoFProgram; extern LLGLSLShader gDeferredDoFCombineProgram; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 3740caa53f..d149a61d89 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -6680,7 +6680,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } - } + } } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 6f3e6819c4..863785889f 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -7452,6 +7452,15 @@ void LLPipeline::renderMaskedObjects(U32 type, U32 mask, bool texture, bool batc gGLLastMatrix = NULL; } +void LLPipeline::renderFullbrightMaskedObjects(U32 type, U32 mask, bool texture, bool batch_texture) +{ + assertInitialized(); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; + mFullbrightAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; +} void apply_cube_face_rotation(U32 face) { @@ -9608,6 +9617,7 @@ static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_MASKED("Alpha Masked"); static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_BLEND("Alpha Blend"); static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_TREE("Alpha Tree"); static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_GRASS("Alpha Grass"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED("Fullbright Alpha Masked"); void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, bool use_shader, bool use_occlusion, U32 target_width) { @@ -9740,8 +9750,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera { LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_MASKED); - renderMaskedObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE); - renderMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE); + renderMaskedObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE); } { @@ -9750,6 +9759,14 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera renderObjects(LLRenderPass::PASS_ALPHA, mask, TRUE, TRUE); } + { + LL_RECORD_BLOCK_TIME(FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED); + gDeferredShadowFullbrightAlphaMaskProgram.bind(); + gDeferredShadowFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); + gDeferredShadowFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); + renderFullbrightMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE); + } + mask = mask & ~LLVertexBuffer::MAP_TEXTURE_INDEX; { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index fe81ae91e8..b0c40d145b 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -261,6 +261,7 @@ public: void renderObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false); void renderMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false); + void renderFullbrightMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false); void renderGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture); -- cgit v1.3 From aa4b24beee1d6451370983517d7ac3755429e26f Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Mon, 22 Jul 2019 12:21:24 -0700 Subject: SL-11443 Make fullbright rigged objects with alpha mode none use fullbright shader instead of incorrectly using the material shader. Increase effect of variance in cloud shaders. --- .../app_settings/shaders/class1/deferred/cloudShadowF.glsl | 4 ++-- .../newview/app_settings/shaders/class1/deferred/cloudsF.glsl | 4 ++-- .../app_settings/shaders/class1/windlight/cloudShadowF.glsl | 4 ++-- .../newview/app_settings/shaders/class2/windlight/cloudsF.glsl | 4 ++-- .../app_settings/shaders/class3/deferred/cloudShadowF.glsl | 4 ++-- .../newview/app_settings/shaders/class3/deferred/cloudsF.glsl | 6 +++--- indra/newview/llvovolume.cpp | 10 +++++++--- 7 files changed, 20 insertions(+), 16 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudShadowF.glsl index 0efde5f949..0157d166e0 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/cloudShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/cloudShadowF.glsl @@ -82,12 +82,12 @@ void main() vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f); // Offset texture coords - uv1 += cloud_pos_density1.xy + (disturbance * 0.02); //large texture, visible density + uv1 += cloud_pos_density1.xy + (disturbance * 0.2); //large texture, visible density uv2 += cloud_pos_density1.xy; //large texture, self shadow uv3 += cloud_pos_density2.xy; //small texture, visible density uv4 += cloud_pos_density2.xy; //small texture, self shadow - float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y)); + float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y) * 4.0); cloudDensity *= 1.0 - (density_variance * density_variance); diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl index d6bd0a7917..f6694aae2a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl @@ -85,12 +85,12 @@ void main() vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f); // Offset texture coords - uv1 += cloud_pos_density1.xy + (disturbance * 0.02); //large texture, visible density + uv1 += cloud_pos_density1.xy + (disturbance * 0.2); //large texture, visible density uv2 += cloud_pos_density1.xy; //large texture, self shadow uv3 += cloud_pos_density2.xy; //small texture, visible density uv4 += cloud_pos_density2.xy; //small texture, self shadow - float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y)); + float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y) * 4.0); cloudDensity *= 1.0 - (density_variance * density_variance); diff --git a/indra/newview/app_settings/shaders/class1/windlight/cloudShadowF.glsl b/indra/newview/app_settings/shaders/class1/windlight/cloudShadowF.glsl index 1d004b2b3e..82fad4db5a 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/cloudShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/cloudShadowF.glsl @@ -82,12 +82,12 @@ void main() vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f); // Offset texture coords - uv1 += cloud_pos_density1.xy + (disturbance * 0.02); //large texture, visible density + uv1 += cloud_pos_density1.xy + (disturbance * 0.2); //large texture, visible density uv2 += cloud_pos_density1.xy; //large texture, self shadow uv3 += cloud_pos_density2.xy; //small texture, visible density uv4 += cloud_pos_density2.xy; //small texture, self shadow - float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y)); + float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y) * 4.0); cloudDensity *= 1.0 - (density_variance * density_variance); diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl index e7ae2d52e3..3ac0fc224b 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl @@ -86,12 +86,12 @@ void main() vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f); // Offset texture coords - uv1 += cloud_pos_density1.xy + (disturbance * 0.02); //large texture, visible density + uv1 += cloud_pos_density1.xy + (disturbance * 0.2); //large texture, visible density uv2 += cloud_pos_density1.xy; //large texture, self shadow uv3 += cloud_pos_density2.xy; //small texture, visible density uv4 += cloud_pos_density2.xy; //small texture, self shadow - float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y)); + float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y) * 4.0); cloudDensity *= 1.0 - (density_variance * density_variance); diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl index ae521afdad..32210f60dc 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl @@ -79,12 +79,12 @@ void main() vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f); // Offset texture coords - uv1 += cloud_pos_density1.xy + (disturbance * 0.02); //large texture, visible density + uv1 += cloud_pos_density1.xy + (disturbance * 0.2); //large texture, visible density uv2 += cloud_pos_density1.xy; //large texture, self shadow uv3 += cloud_pos_density2.xy; //small texture, visible density uv4 += cloud_pos_density2.xy; //small texture, self shadow - float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y)); + float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y) * 4.0); cloudDensity *= 1.0 - (density_variance * density_variance); diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl index 1abe2fab63..e40d7e7c75 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl @@ -95,12 +95,12 @@ void main() vec2 disturbance = vec2(cloudNoise(uv1 / 16.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f); // Offset texture coords - uv1 += cloud_pos_density1.xy + disturbance; //large texture, visible density + uv1 += cloud_pos_density1.xy + (disturbance * 0.2); //large texture, visible density uv2 += cloud_pos_density1.xy; //large texture, self shadow - uv3 += cloud_pos_density2.xy + disturbance; //small texture, visible density + uv3 += cloud_pos_density2.xy; //small texture, visible density uv4 += cloud_pos_density2.xy; //small texture, self shadow - float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0)); + float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0) * 4.0); cloudDensity *= 1.0 - (density_variance * density_variance); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index d149a61d89..02ef7612a7 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5522,6 +5522,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } LLMaterial* mat = te->getMaterialParams().get(); + bool fullbright = te->getFullbright(); if (mat && LLPipeline::sRenderDeferred) { @@ -5536,15 +5537,18 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; } - if (!is_alpha || te_alpha > 0.f) // //only add the face if it will actually be visible + if (fullbright && (alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE)) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); + } + else if (!is_alpha || te_alpha > 0.f) // //only add the face if it will actually be visible { U32 mask = mat->getShaderMask(alpha_mode); pool->addRiggedFace(facep, mask); } } else if (mat) - { - bool fullbright = te->getFullbright(); + { bool is_alpha = type == LLDrawPool::POOL_ALPHA; U8 mode = mat->getDiffuseAlphaMode(); bool can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || -- cgit v1.3 From 71af0a2a9e9f90d1e336f8a30f642bb5e19ef658 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Tue, 6 Aug 2019 14:41:55 -0700 Subject: Fix shutdown crash in teardown of joint heirarchy. Ifdef'd code for potential skinning speed up to avoid lots of int<->float conversions (expensive and static for min space investment) as updating rigged VBs shows up as a profiling bottleneck for Low rendering (where we actually use CPU skinning). --- indra/llcharacter/lljoint.cpp | 17 ++--- indra/llmath/llvolume.cpp | 39 +++++++---- indra/llmath/llvolume.h | 4 ++ indra/newview/lldrawpoolavatar.cpp | 133 +++++++++++++++++++++++++++++-------- indra/newview/lldrawpoolavatar.h | 2 +- indra/newview/llskinningutil.cpp | 71 ++++++++++++++++---- indra/newview/llskinningutil.h | 29 +++++++- indra/newview/llvovolume.cpp | 48 ++++++++++--- 8 files changed, 270 insertions(+), 73 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index 36ecf8cb4b..a685df5925 100644 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -303,16 +303,17 @@ void LLJoint::removeChild(LLJoint* joint) //-------------------------------------------------------------------- void LLJoint::removeAllChildren() { - for (joints_t::iterator iter = mChildren.begin(); - iter != mChildren.end();) + for (LLJoint* joint : mChildren) { - joints_t::iterator curiter = iter++; - LLJoint* joint = *curiter; - mChildren.erase(curiter); - joint->mXform.setParent(NULL); - joint->mParent = NULL; - joint->touch(); + if (joint) + { + joint->mXform.setParent(NULL); + joint->mParent = NULL; + joint->touch(); + //delete joint; + } } + mChildren.clear(); } diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 9d0cf1e119..df867b332d 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2526,7 +2526,6 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) if (mdl[i].has("Weights")) { face.allocateWeights(num_verts); - face.allocateJointIndices(num_verts); LLSD::Binary weights = mdl[i]["Weights"]; @@ -2567,13 +2566,6 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) { wght = LLVector4(0.999f,0.f,0.f,0.f); } - if (face.mJointIndices) - { - for (U32 k=0; k<4; k++) - { - face.mJointIndices[cur_vertex * 4 + k] = llclamp((U8)joints[k], (U8)0, (U8)110); - } - } for (U32 k=0; k<4; k++) { F32 f_combined = (F32) joints[k] + wght[k]; @@ -4664,7 +4656,10 @@ LLVolumeFace::LLVolumeFace() : mTexCoords(NULL), mIndices(NULL), mWeights(NULL), +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + mJustWeights(NULL), mJointIndices(NULL), +#endif mWeightsScrubbed(FALSE), mOctree(NULL), mOptimized(FALSE) @@ -4691,7 +4686,10 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) mTexCoords(NULL), mIndices(NULL), mWeights(NULL), +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + mJustWeights(NULL), mJointIndices(NULL), +#endif mWeightsScrubbed(FALSE), mOctree(NULL) { @@ -4768,19 +4766,22 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) mWeightsScrubbed = FALSE; } + #if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS if (src.mJointIndices) { llassert(!mJointIndices); // don't orphan an old alloc here accidentally allocateJointIndices(src.mNumVertices); LLVector4a::memcpyNonAliased16((F32*) mJointIndices, (F32*) src.mJointIndices, src.mNumVertices * sizeof(U8) * 4); } - else + else*/ { ll_aligned_free_16(mJointIndices); mJointIndices = NULL; } - } + #endif + } + if (mNumIndices) { S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF; @@ -4823,8 +4824,13 @@ void LLVolumeFace::freeData() mTangents = NULL; ll_aligned_free_16(mWeights); mWeights = NULL; + +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS ll_aligned_free_16(mJointIndices); mJointIndices = NULL; + ll_aligned_free_16(mJustWeights); + mJustWeights = NULL; +#endif delete mOctree; mOctree = NULL; @@ -5479,13 +5485,17 @@ bool LLVolumeFace::cacheOptimize() // DO NOT free mNormals and mTexCoords as they are part of mPositions buffer ll_aligned_free_16(mWeights); ll_aligned_free_16(mTangents); +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS ll_aligned_free_16(mJointIndices); + ll_aligned_free_16(mJustWeights); + mJustWeights = NULL; + mJointIndices = NULL; // filled in later as necessary by skinning code for acceleration +#endif mPositions = pos; mNormals = norm; mTexCoords = tc; - mWeights = wght; - mJointIndices = NULL; // filled in later as necessary by skinning code for acceleration + mWeights = wght; mTangents = binorm; //std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks); @@ -6401,8 +6411,13 @@ void LLVolumeFace::allocateWeights(S32 num_verts) void LLVolumeFace::allocateJointIndices(S32 num_verts) { +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS ll_aligned_free_16(mJointIndices); + ll_aligned_free_16(mJustWeights); + mJointIndices = (U8*)ll_aligned_malloc_16(sizeof(U8) * 4 * num_verts); + mJustWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a) * num_verts); +#endif } void LLVolumeFace::resizeIndices(S32 num_indices) diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index ed2cd9cde0..a77e8c08c6 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -956,7 +956,11 @@ public: // format is mWeights[vertex_index].mV[influence] = . // mWeights.size() should be empty or match mVertices.size() LLVector4a* mWeights; + +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + LLVector4a* mJustWeights; U8* mJointIndices; +#endif mutable BOOL mWeightsScrubbed; diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 15a0595179..789a254389 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -38,6 +38,7 @@ #include "lldrawable.h" #include "lldrawpoolbump.h" #include "llface.h" +#include "llvolume.h" #include "llmeshrepository.h" #include "llsky.h" #include "llviewercamera.h" @@ -1833,15 +1834,13 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, - const LLVolumeFace& vol_face) + LLVolumeFace& vol_face) { LLVector4a* weights = vol_face.mWeights; if (!weights) { return; } - // FIXME ugly const cast - LLSkinningUtil::scrubInvalidJoints(avatar, const_cast(skin)); LLPointer buffer = face->getVertexBuffer(); LLDrawable* drawable = face->getDrawable(); @@ -1851,6 +1850,48 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( return; } + const U32 max_joints = LLSkinningUtil::getMaxJointCount(); + +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + #define CONDITION_WEIGHT(f) ((U8)llclamp((S32)f, (S32)0, (S32)max_joints-1)) + LLVector4a* just_weights = vol_face.mJustWeights; + // we need to calculate the separated indices and store just the matrix weights for this vol... + if (!vol_face.mJointIndices) + { + // not very consty after all... + vol_face.allocateJointIndices(vol_face.mNumVertices); + just_weights = vol_face.mJustWeights; + + U8* joint_indices_cursor = vol_face.mJointIndices; + for (int i = 0; i < vol_face.mNumVertices; i++) + { + F32* w = weights[i].getF32ptr(); + F32* w_ = just_weights[i].getF32ptr(); + + F32 w0 = floorf(w[0]); + F32 w1 = floorf(w[1]); + F32 w2 = floorf(w[2]); + F32 w3 = floorf(w[3]); + + joint_indices_cursor[0] = CONDITION_WEIGHT(w0); + joint_indices_cursor[1] = CONDITION_WEIGHT(w1); + joint_indices_cursor[2] = CONDITION_WEIGHT(w2); + joint_indices_cursor[3] = CONDITION_WEIGHT(w3); + + // remove joint portion of combined weight + w_[0] = w[0] - w0; + w_[1] = w[1] - w1; + w_[2] = w[2] - w2; + w_[3] = w[3] - w3; + + joint_indices_cursor += 4; + } + } +#endif + + // FIXME ugly const cast + LLSkinningUtil::scrubInvalidJoints(avatar, const_cast(skin)); + U32 data_mask = face->getRiggedVertexBufferDataMask(); if (!vol_face.mWeightsScrubbed) @@ -1927,29 +1968,67 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( LLMatrix4a bind_shape_matrix; bind_shape_matrix.loadu(skin->mBindShapeMatrix); - const U32 max_joints = LLSkinningUtil::getMaxJointCount(); - for (U32 j = 0; j < buffer->getNumVerts(); ++j) - { - LLMatrix4a final_mat; - LLSkinningUtil::getPerVertexSkinMatrix(weights[j].getF32ptr(), mat, false, final_mat, max_joints); - - LLVector4a& v = vol_face.mPositions[j]; - - LLVector4a t; - LLVector4a dst; - bind_shape_matrix.affineTransform(v, t); - final_mat.affineTransform(t, dst); - pos[j] = dst; - - if (norm) - { - LLVector4a& n = vol_face.mNormals[j]; - bind_shape_matrix.rotate(n, t); - final_mat.rotate(t, dst); - dst.normalize3fast(); - norm[j] = dst; - } - } +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + U8* joint_indices_cursor = vol_face.mJointIndices; + // fast path with joint indices separate from weights + if (joint_indices_cursor) + { + LLMatrix4a src[4]; + for (U32 j = 0; j < buffer->getNumVerts(); ++j) + { + LLMatrix4a final_mat; + //LLMatrix4a final_mat_correct; + + F32* jw = just_weights[j].getF32ptr(); + + LLSkinningUtil::getPerVertexSkinMatrixWithIndices(jw, joint_indices_cursor, mat, final_mat, src); + + joint_indices_cursor += 4; + + LLVector4a& v = vol_face.mPositions[j]; + + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + + if (norm) + { + LLVector4a& n = vol_face.mNormals[j]; + bind_shape_matrix.rotate(n, t); + final_mat.rotate(t, dst); + dst.normalize3fast(); + norm[j] = dst; + } + } + } + // slow path with joint indices calculated from weights + else +#endif + { + for (U32 j = 0; j < buffer->getNumVerts(); ++j) + { + LLMatrix4a final_mat; + LLSkinningUtil::getPerVertexSkinMatrix(weights[j].getF32ptr(), mat, false, final_mat, max_joints); + + LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + + if (norm) + { + LLVector4a& n = vol_face.mNormals[j]; + bind_shape_matrix.rotate(n, t); + final_mat.rotate(t, dst); + //dst.normalize3fast(); + norm[j] = dst; + } + } + } } } @@ -2301,7 +2380,7 @@ void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar) stop_glerror(); - const LLVolumeFace& vol_face = volume->getVolumeFace(te); + LLVolumeFace& vol_face = volume->getVolumeFace(te); updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face); } } diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index e8add0e1d8..cb09eb18e2 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -257,7 +257,7 @@ typedef enum LLFace* facep, const LLMeshSkinInfo* skin, LLVolume* volume, - const LLVolumeFace& vol_face); + LLVolumeFace& vol_face); void updateRiggedVertexBuffers(LLVOAvatar* avatar); void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false); diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index 0fa4c2b114..83b9c8971a 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -34,8 +34,12 @@ #include "llvolume.h" #include "llrigginginfo.h" +#define DEBUG_SKINNING LL_DEBUG +#define MAT_USE_SSE 1 + void dump_avatar_and_skin_state(const std::string& reason, LLVOAvatar *avatar, const LLMeshSkinInfo *skin) { +#if DEBUG_SKINNING static S32 dump_count = 0; const S32 max_dump = 10; @@ -81,16 +85,16 @@ void dump_avatar_and_skin_state(const std::string& reason, LLVOAvatar *avatar, c dump_count++; } +#endif } void LLSkinningUtil::initClass() { } -U32 LLSkinningUtil::getMaxJointCount() +S32 LLSkinningUtil::getMaxJointCount() { - U32 result = LL_MAX_JOINTS_PER_MESH_OBJECT; - return result; + return (S32)LL_MAX_JOINTS_PER_MESH_OBJECT; } U32 LLSkinningUtil::getMeshJointCount(const LLMeshSkinInfo *skin) @@ -120,6 +124,8 @@ void LLSkinningUtil::scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin skin->mInvalidJointsScrubbed = true; } +#define MAT_USE_SSE 1 + void LLSkinningUtil::initSkinningMatrixPalette( LLMatrix4* mat, S32 count, @@ -130,9 +136,9 @@ void LLSkinningUtil::initSkinningMatrixPalette( for (U32 j = 0; j < count; ++j) { LLJoint *joint = avatar->getJoint(skin->mJointNums[j]); + llassert(joint); if (joint) { -#define MAT_USE_SSE #ifdef MAT_USE_SSE LLMatrix4a bind, world, res; bind.loadu(skin->mInvBindMatrix[j]); @@ -147,6 +153,7 @@ void LLSkinningUtil::initSkinningMatrixPalette( else { mat[j] = skin->mInvBindMatrix[j]; +#if DEBUG_SKINNING // This shouldn't happen - in mesh upload, skinned // rendering should be disabled unless all joints are // valid. In other cases of skinned rendering, invalid @@ -157,16 +164,15 @@ void LLSkinningUtil::initSkinningMatrixPalette( LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " avatar build state: isBuilt() " << avatar->isBuilt() << " mInitFlags " << avatar->mInitFlags << LL_ENDL; -#if 0 - dump_avatar_and_skin_state("initSkinningMatrixPalette joint not found", avatar, skin); #endif + dump_avatar_and_skin_state("initSkinningMatrixPalette joint not found", avatar, skin); } } } void LLSkinningUtil::checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) { -#ifdef SHOW_ASSERT // same condition that controls llassert() +#if DEBUG_SKINNING const S32 max_joints = skin->mJointNames.size(); for (U32 j=0; jmJointNames.size(); ++j) { + #if DEBUG_SKINNING LLJoint *joint = NULL; if (skin->mJointNums[j] == -1) { @@ -282,11 +289,16 @@ void LLSkinningUtil::initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar) { LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " unable to find joint " << skin->mJointNames[j] << LL_ENDL; LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " avatar build state: isBuilt() " << avatar->isBuilt() << " mInitFlags " << avatar->mInitFlags << LL_ENDL; -#if 0 dump_avatar_and_skin_state("initJointNums joint not found", avatar, skin); -#endif + skin->mJointNums[j] = 0; } } + #else + LLJoint *joint = (skin->mJointNums[j] == -1) ? avatar->getJoint(skin->mJointNames[j]) : avatar->getJoint(skin->mJointNums[j]); + skin->mJointNums[j] = joint ? joint->getJointNum() : 0; + #endif + // insure we have *a* valid joint to reference + llassert(skin->mJointNums[j] >= 0); } skin->mJointNumsInitialized = true; } @@ -344,14 +356,17 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a // FIXME could precompute these matMuls. LLMatrix4a bind_shape; - bind_shape.loadu(skin->mBindShapeMatrix); LLMatrix4a inv_bind; - inv_bind.loadu(skin->mInvBindMatrix[joint_index]); LLMatrix4a mat; - matMul(bind_shape, inv_bind, mat); LLVector4a pos_joint_space; + + bind_shape.loadu(skin->mBindShapeMatrix); + inv_bind.loadu(skin->mInvBindMatrix[joint_index]); + matMul(bind_shape, inv_bind, mat); + mat.affineTransform(pos, pos_joint_space); pos_joint_space.mul(wght[k]); + LLVector4a *extents = rig_info_tab[joint_num].getRiggedExtents(); update_min_max(extents[0], extents[1], pos_joint_space); } @@ -366,6 +381,8 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a vol_face.mJointRiggingInfoTab.setNeedsUpdate(false); } } + +#if DEBUG_SKINNING if (vol_face.mJointRiggingInfoTab.size()!=0) { LL_DEBUGS("RigSpammish") << "we have rigging info for vf " << &vol_face @@ -376,10 +393,40 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a LL_DEBUGS("RigSpammish") << "no rigging info for vf " << &vol_face << " num_verts " << vol_face.mNumVertices << LL_ENDL; } +#endif } } +void LLSkinningUtil::updateRiggingInfo_(LLMeshSkinInfo* skin, LLVOAvatar *avatar, S32 num_verts, LLVector4a* weights, LLVector4a* positions, U8* joint_indices, LLJointRiggingInfoTab &rig_info_tab) +{ + LL_RECORD_BLOCK_TIME(FTM_FACE_RIGGING_INFO); + for (S32 i=0; i < num_verts; i++) + { + LLVector4a& pos = positions[i]; + LLVector4a& wght = weights[i]; + for (U32 k=0; k<4; ++k) + { + S32 joint_num = skin->mJointNums[joint_indices[k]]; + llassert(joint_num >= 0 && joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS); + { + rig_info_tab[joint_num].setIsRiggedTo(true); + LLMatrix4a bind_shape; + bind_shape.loadu(skin->mBindShapeMatrix); + LLMatrix4a inv_bind; + inv_bind.loadu(skin->mInvBindMatrix[joint_indices[k]]); + LLMatrix4a mat; + matMul(bind_shape, inv_bind, mat); + LLVector4a pos_joint_space; + mat.affineTransform(pos, pos_joint_space); + pos_joint_space.mul(wght[k]); + LLVector4a *extents = rig_info_tab[joint_num].getRiggedExtents(); + update_min_max(extents[0], extents[1], pos_joint_space); + } + } + } +} + // This is used for extracting rotation from a bind shape matrix that // already has scales baked in LLQuaternion LLSkinningUtil::getUnscaledQuaternion(const LLMatrix4& mat4) diff --git a/indra/newview/llskinningutil.h b/indra/newview/llskinningutil.h index ccc501adc0..d39356451d 100644 --- a/indra/newview/llskinningutil.h +++ b/indra/newview/llskinningutil.h @@ -27,23 +27,48 @@ #ifndef LLSKINNINGUTIL_H #define LLSKINNINGUTIL_H +#include "v2math.h" +#include "v4math.h" +#include "llvector4a.h" +#include "llmatrix4a.h" + class LLVOAvatar; class LLMeshSkinInfo; -class LLMatrix4a; class LLVolumeFace; +class LLJointRiggingInfoTab; namespace LLSkinningUtil { void initClass(); - U32 getMaxJointCount(); + S32 getMaxJointCount(); U32 getMeshJointCount(const LLMeshSkinInfo *skin); void scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin); void initSkinningMatrixPalette(LLMatrix4* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar); void checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); void scrubSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints); + + LL_FORCE_INLINE void getPerVertexSkinMatrixWithIndices( + F32* weights, + U8* idx, + LLMatrix4a* mat, + LLMatrix4a& final_mat, + LLMatrix4a* src) + { + final_mat.clear(); + src[0].setMul(mat[idx[0]], weights[0]); + src[1].setMul(mat[idx[1]], weights[1]); + final_mat.add(src[0]); + final_mat.add(src[1]); + src[2].setMul(mat[idx[2]], weights[2]); + src[3].setMul(mat[idx[3]], weights[3]); + final_mat.add(src[2]); + final_mat.add(src[3]); + } + void initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar); void updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *avatar, LLVolumeFace& vol_face); + void updateRiggingInfo_(LLMeshSkinInfo* skin, LLVOAvatar *avatar, S32 num_verts, LLVector4a* weights, LLVector4a* positions, U8* joint_indices, LLJointRiggingInfoTab &rig_info_tab); LLQuaternion getUnscaledQuaternion(const LLMatrix4& mat4); }; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 02ef7612a7..706e2c6895 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4787,18 +4787,44 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons U32 max_joints = LLSkinningUtil::getMaxJointCount(); rigged_vert_count += dst_face.mNumVertices; rigged_face_count++; - for (U32 j = 0; j < dst_face.mNumVertices; ++j) - { - LLMatrix4a final_mat; - LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); + + #if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + if (vol_face.mJointIndices) // fast path with preconditioned joint indices + { + LLMatrix4a src[4]; + U8* joint_indices_cursor = vol_face.mJointIndices; + LLVector4a* just_weights = vol_face.mJustWeights; + for (U32 j = 0; j < dst_face.mNumVertices; ++j) + { + LLMatrix4a final_mat; + F32* w = just_weights[j].getF32ptr(); + LLSkinningUtil::getPerVertexSkinMatrixWithIndices(w, joint_indices_cursor, mat, final_mat, src); + joint_indices_cursor += 4; + + LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + } + } + else + #endif + { + for (U32 j = 0; j < dst_face.mNumVertices; ++j) + { + LLMatrix4a final_mat; + LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); - LLVector4a& v = vol_face.mPositions[j]; - LLVector4a t; - LLVector4a dst; - bind_shape_matrix.affineTransform(v, t); - final_mat.affineTransform(t, dst); - pos[j] = dst; - } + LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + } + } //update bounding box // VFExtents change -- cgit v1.3 From d756e185730f46fd78e88215e0b4b9fd282fd1d7 Mon Sep 17 00:00:00 2001 From: Runitai Linden Date: Thu, 26 Mar 2020 16:48:33 -0500 Subject: SL-12902 Fix for doing the technically correct but compatibility wrong thing WRT light color values. --- indra/llmath/llmath.h | 17 +++++++++++++---- indra/llmath/v3color.h | 9 +++++++++ indra/llmath/v4color.h | 11 +++++++++++ indra/llprimitive/llprimitive.h | 14 ++++++++++---- indra/newview/llvovolume.cpp | 14 ++++---------- indra/newview/llvovolume.h | 17 ++++++++++++++--- indra/newview/pipeline.cpp | 13 ++++++++----- 7 files changed, 69 insertions(+), 26 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index 57f2489a2d..8f01ad6c1c 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -537,9 +537,12 @@ inline void ll_remove_outliers(std::vector& data, F32 k) } } -// This converts from a non-linear sRGB floating point value (0..1) to a linear value. -// Useful for gamma correction and such. Note: any values passed through this should not be serialized. You should also ideally cache the output of this. -inline float sRGBtoLinear(const float val) { +// Converts given value from a linear RGB floating point value (0..1) to a gamma corrected (sRGB) value. +// Some shaders require color values in linear space, while others require color values in gamma corrected (sRGB) space. +// Note: in our code, values labeled as sRGB are ALWAYS gamma corrected linear values, NOT linear values with monitor gamma applied +// Note: stored color values should always be gamma corrected linear (i.e. the values returned from an on-screen color swatch) +// Note: DO NOT cache the conversion. This leads to error prone synchronization and is actually slower in the typical case due to cache misses +inline float linearTosRGB(const float val) { if (val < 0.0031308f) { return val * 12.92f; } @@ -548,7 +551,13 @@ inline float sRGBtoLinear(const float val) { } } -inline float linearTosRGB(const float val) { +// Converts given value from a gamma corrected (sRGB) floating point value (0..1) to a linear color value. +// Some shaders require color values in linear space, while others require color values in gamma corrected (sRGB) space. +// Note: In our code, values labeled as sRGB are gamma corrected linear values, NOT linear values with monitor gamma applied +// Note: Stored color values should generally be gamma corrected sRGB. +// If you're serializing the return value of this function, you're probably doing it wrong. +// Note: DO NOT cache the conversion. This leads to error prone synchronization and is actually slower in the typical case due to cache misses. +inline float sRGBtoLinear(const float val) { if (val < 0.04045f) { return val / 12.92f; } diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h index ac78197510..43a632408c 100644 --- a/indra/llmath/v3color.h +++ b/indra/llmath/v3color.h @@ -484,4 +484,13 @@ inline const LLColor3 srgbColor3(const LLColor3 &a) { return srgbColor; } +inline const LLColor3 linearColor3(const LLColor3 &a) { + LLColor3 linearColor; + linearColor.mV[0] = sRGBtoLinear(a.mV[0]); + linearColor.mV[1] = sRGBtoLinear(a.mV[1]); + linearColor.mV[2] = sRGBtoLinear(a.mV[2]); + + return linearColor; +} + #endif diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index 6b91b4f191..00fc955384 100644 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -656,6 +656,7 @@ void LLColor4::clamp() } } +// Return the given linear space color value in gamma corrected (sRGB) space inline const LLColor4 srgbColor4(const LLColor4 &a) { LLColor4 srgbColor; @@ -667,5 +668,15 @@ inline const LLColor4 srgbColor4(const LLColor4 &a) { return srgbColor; } +// Return the given gamma corrected (sRGB) color in linear space +inline const LLColor4 linearColor4(const LLColor4 &a) +{ + LLColor4 linearColor; + linearColor.mV[0] = sRGBtoLinear(a.mV[0]); + linearColor.mV[1] = sRGBtoLinear(a.mV[1]); + linearColor.mV[2] = sRGBtoLinear(a.mV[2]); + linearColor.mV[3] = a.mV[3]; +} + #endif diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 20b5ad8eff..ed89462e5a 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -132,8 +132,7 @@ extern const F32 LIGHT_MAX_CUTOFF; class LLLightParams : public LLNetworkData { protected: - LLColor4 mColor; // alpha = intensity - LLColor4 mSRGBColor; // Only used in deferred (for now?) + LLColor4 mColor; // gamma corrected color (sRGB), alpha = intensity F32 mRadius; F32 mFalloff; F32 mCutoff; @@ -151,13 +150,20 @@ public: bool fromLLSD(LLSD& sd); - void setColor(const LLColor4& color) { mColor = color; mColor.clamp(); mSRGBColor = srgbColor4(mColor); } + // set the color + // color - gamma corrected color value (directly taken from an on-screen color swatch) + void setColor(const LLColor4& color) { mColor = color; mColor.clamp(); } void setRadius(F32 radius) { mRadius = llclamp(radius, LIGHT_MIN_RADIUS, LIGHT_MAX_RADIUS); } void setFalloff(F32 falloff) { mFalloff = llclamp(falloff, LIGHT_MIN_FALLOFF, LIGHT_MAX_FALLOFF); } void setCutoff(F32 cutoff) { mCutoff = llclamp(cutoff, LIGHT_MIN_CUTOFF, LIGHT_MAX_CUTOFF); } + // same as getSRGBColor LLColor4 getColor() const { return mColor; } - LLColor4 getSRGBColor() const { return mSRGBColor; } + // get the sRGB (gamma corrected) color of this light + LLColor4 getSRGBColor() const { return mColor; } + // get the linear space color of this light + LLColor4 getLinearColor() const { return linearColor4(mColor); } + F32 getRadius() const { return mRadius; } F32 getFalloff() const { return mFalloff; } F32 getCutoff() const { return mCutoff; } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index c1dd356586..586d3b66b0 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3234,17 +3234,11 @@ LLColor3 LLVOVolume::getLightBaseColor() const } } -LLColor3 LLVOVolume::getLightColor() const +LLColor3 LLVOVolume::getLightLinearColor() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return LLColor3(param_block->getColor()) * param_block->getColor().mV[3]; - } - else - { - return LLColor3(1,1,1); - } + LLColor3 ret = getLightSRGBColor(); + ret = linearColor3(ret); + return ret; } LLColor3 LLVOVolume::getLightSRGBColor() const diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index bbe911f488..bf19a01d57 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -251,9 +251,20 @@ public: void setSpotLightParams(LLVector3 params); BOOL getIsLight() const; - LLColor3 getLightBaseColor() const; // not scaled by intensity - LLColor3 getLightColor() const; // scaled by intensity - LLColor3 getLightSRGBColor() const; // Used to get the (cached) light color in sRGB color space. Also scaled by intensity. + + + // Get the light color in sRGB color space NOT scaled by intensity. + LLColor3 getLightBaseColor() const; + + //same as getLightSRGBColor() + LLColor3 getLightColor() const { return getLightSRGBColor(); } + + // Same as linearColor3(getLightSRGBColor) + LLColor3 getLightLinearColor() const; + + // Get the light color in sRGB color space scaled by intensity. + LLColor3 getLightSRGBColor() const; + LLUUID getLightTextureID() const; bool isLightSpotlight() const; LLVector3 getSpotLightParams() const; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index fda79984ab..1765ba227f 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6325,7 +6325,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) mLightMovingMask |= (1<getLightSRGBColor() : light->getLightColor(); + //NOTE: for legacy reasons, send sRGB color to light shader for both deferred and non-deferred path + LLColor4 light_color = light->getLightColor(); light_color.mV[3] = 0.0f; F32 fade = iter->fade; @@ -8767,7 +8768,8 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) const F32* c = center.getF32ptr(); F32 s = volume->getLightRadius()*1.5f; - LLColor3 col = volume->getLightSRGBColor(); + //NOTE: for legacy reasons, send sRGB color to light shader + LLColor3 col = volume->getLightColor(); if (col.magVecSquared() < 0.001f) { @@ -8859,7 +8861,8 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) setupSpotLight(gDeferredSpotLightProgram, drawablep); - LLColor3 col = volume->getLightSRGBColor(); + //NOTE: for legacy reasons, send sRGB color to light shader + LLColor3 col = volume->getLightColor(); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); @@ -8948,8 +8951,8 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) setupSpotLight(gDeferredMultiSpotLightProgram, drawablep); - LLColor3 col = volume->getLightSRGBColor(); - + //NOTE: for legacy reasons, send sRGB color to light shader + LLColor3 col = volume->getLightColor(); gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, light_size_final); -- cgit v1.3 From e468d8018634b51f329eae17485c3358c0a3630b Mon Sep 17 00:00:00 2001 From: Runitai Linden Date: Fri, 27 Mar 2020 17:32:01 -0500 Subject: SL-12902 Better fix for light color values in color swatch not matching light color values inworld. --- indra/llprimitive/llprimitive.cpp | 6 +++--- indra/llprimitive/llprimitive.h | 25 ++++++++++++----------- indra/newview/llpanelvolume.cpp | 8 ++++---- indra/newview/llviewerwindow.cpp | 2 +- indra/newview/llvovolume.cpp | 42 ++++++++++++++++++++++++--------------- indra/newview/llvovolume.h | 17 ++++++++++------ indra/newview/pipeline.cpp | 16 +++++++-------- 7 files changed, 66 insertions(+), 50 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index bc5dd62f45..53b83a40d7 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -1659,7 +1659,7 @@ BOOL LLLightParams::unpack(LLDataPacker &dp) { LLColor4U color; dp.unpackColor4U(color, "color"); - setColor(LLColor4(color)); + setLinearColor(LLColor4(color)); F32 radius; dp.unpackF32(radius, "radius"); @@ -1707,7 +1707,7 @@ LLSD LLLightParams::asLLSD() const { LLSD sd; - sd["color"] = ll_sd_from_color4(getColor()); + sd["color"] = ll_sd_from_color4(getLinearColor()); sd["radius"] = getRadius(); sd["falloff"] = getFalloff(); sd["cutoff"] = getCutoff(); @@ -1721,7 +1721,7 @@ bool LLLightParams::fromLLSD(LLSD& sd) w = "color"; if (sd.has(w)) { - setColor( ll_color4_from_sd(sd["color"]) ); + setLinearColor( ll_color4_from_sd(sd["color"]) ); } else goto fail; w = "radius"; if (sd.has(w)) diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index ed89462e5a..b1f8112223 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -131,8 +131,8 @@ extern const F32 LIGHT_MAX_CUTOFF; class LLLightParams : public LLNetworkData { -protected: - LLColor4 mColor; // gamma corrected color (sRGB), alpha = intensity +private: + LLColor4 mColor; // linear color (not gamma corrected), alpha = intensity F32 mRadius; F32 mFalloff; F32 mCutoff; @@ -149,21 +149,22 @@ public: operator LLSD() const { return asLLSD(); } bool fromLLSD(LLSD& sd); - - // set the color + // set the color by gamma corrected color value // color - gamma corrected color value (directly taken from an on-screen color swatch) - void setColor(const LLColor4& color) { mColor = color; mColor.clamp(); } + void setSRGBColor(const LLColor4& color) { setLinearColor(linearColor4(color)); } + + // set the color by linear color value + // color - linear color value (value as it appears in shaders) + void setLinearColor(const LLColor4& color) { mColor = color; mColor.clamp(); } void setRadius(F32 radius) { mRadius = llclamp(radius, LIGHT_MIN_RADIUS, LIGHT_MAX_RADIUS); } void setFalloff(F32 falloff) { mFalloff = llclamp(falloff, LIGHT_MIN_FALLOFF, LIGHT_MAX_FALLOFF); } void setCutoff(F32 cutoff) { mCutoff = llclamp(cutoff, LIGHT_MIN_CUTOFF, LIGHT_MAX_CUTOFF); } - // same as getSRGBColor - LLColor4 getColor() const { return mColor; } - // get the sRGB (gamma corrected) color of this light - LLColor4 getSRGBColor() const { return mColor; } - // get the linear space color of this light - LLColor4 getLinearColor() const { return linearColor4(mColor); } - + // get the linear space color of this light. This value can be fed directly to shaders + LLColor4 getLinearColor() const { return mColor; } + // get the sRGB (gamma corrected) color of this light, this is the value that should be displayed in the UI + LLColor4 getSRGBColor() const { return srgbColor4(mColor); } + F32 getRadius() const { return mRadius; } F32 getFalloff() const { return mFalloff; } F32 getCutoff() const { return mCutoff; } diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 2b531b6acc..ae727e409f 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -300,7 +300,7 @@ void LLPanelVolume::getState( ) { LightColorSwatch->setEnabled( TRUE ); LightColorSwatch->setValid( TRUE ); - LightColorSwatch->set(volobjp->getLightBaseColor()); + LightColorSwatch->set(volobjp->getLightSRGBBaseColor()); } LLTextureCtrl* LightTextureCtrl = getChild("light texture control"); @@ -328,7 +328,7 @@ void LLPanelVolume::getState( ) getChild("Light Focus")->setValue(params.mV[1]); getChild("Light Ambiance")->setValue(params.mV[2]); - mLightSavedColor = volobjp->getLightColor(); + mLightSavedColor = volobjp->getLightSRGBColor(); } else { @@ -807,7 +807,7 @@ void LLPanelVolume::onLightSelectColor(const LLSD& data) { LLColor4 clr = LightColorSwatch->get(); LLColor3 clr3( clr ); - volobjp->setLightColor(clr3); + volobjp->setLightSRGBColor(clr3); mLightSavedColor = clr; } } @@ -881,7 +881,7 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata ) if(LightColorSwatch) { LLColor4 clr = LightColorSwatch->get(); - volobjp->setLightColor(LLColor3(clr)); + volobjp->setLightSRGBColor(LLColor3(clr)); } LLTextureCtrl* LightTextureCtrl = self->getChild("light texture control"); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index b238256b7f..ae1eec81e0 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -3871,7 +3871,7 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, F32 scale = vovolume->getLightRadius(); gGL.scalef(scale, scale, scale); - LLColor4 color(vovolume->getLightColor(), .5f); + LLColor4 color(vovolume->getLightSRGBColor(), .5f); gGL.color4fv(color.mV); //F32 pixel_area = 100000.f; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 586d3b66b0..bd7ad399f9 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3147,14 +3147,19 @@ void LLVOVolume::setIsLight(BOOL is_light) } } -void LLVOVolume::setLightColor(const LLColor3& color) +void LLVOVolume::setLightSRGBColor(const LLColor3& color) +{ + setLightLinearColor(linearColor3(color)); +} + +void LLVOVolume::setLightLinearColor(const LLColor3& color) { LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); if (param_block) { - if (param_block->getColor() != color) + if (param_block->getLinearColor() != color) { - param_block->setColor(LLColor4(color, param_block->getColor().mV[3])); + param_block->setLinearColor(LLColor4(color, param_block->getLinearColor().mV[3])); parameterChanged(LLNetworkData::PARAMS_LIGHT, true); gPipeline.markTextured(mDrawable); mFaceMappingChanged = TRUE; @@ -3167,9 +3172,9 @@ void LLVOVolume::setLightIntensity(F32 intensity) LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); if (param_block) { - if (param_block->getColor().mV[3] != intensity) + if (param_block->getLinearColor().mV[3] != intensity) { - param_block->setColor(LLColor4(LLColor3(param_block->getColor()), intensity)); + param_block->setLinearColor(LLColor4(LLColor3(param_block->getLinearColor()), intensity)); parameterChanged(LLNetworkData::PARAMS_LIGHT, true); } } @@ -3221,12 +3226,17 @@ BOOL LLVOVolume::getIsLight() const return getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT); } -LLColor3 LLVOVolume::getLightBaseColor() const +LLColor3 LLVOVolume::getLightSRGBBaseColor() const +{ + return srgbColor3(getLightLinearColor()); +} + +LLColor3 LLVOVolume::getLightLinearBaseColor() const { const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); if (param_block) { - return LLColor3(param_block->getColor()); + return LLColor3(param_block->getLinearColor()); } else { @@ -3235,18 +3245,11 @@ LLColor3 LLVOVolume::getLightBaseColor() const } LLColor3 LLVOVolume::getLightLinearColor() const -{ - LLColor3 ret = getLightSRGBColor(); - ret = linearColor3(ret); - return ret; -} - -LLColor3 LLVOVolume::getLightSRGBColor() const { const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); if (param_block) { - return LLColor3(param_block->getSRGBColor()) * param_block->getSRGBColor().mV[3]; + return LLColor3(param_block->getLinearColor()) * param_block->getLinearColor().mV[3]; } else { @@ -3254,6 +3257,13 @@ LLColor3 LLVOVolume::getLightSRGBColor() const } } +LLColor3 LLVOVolume::getLightSRGBColor() const +{ + LLColor3 ret = getLightLinearColor(); + ret = srgbColor3(ret); + return ret; +} + LLUUID LLVOVolume::getLightTextureID() const { if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) @@ -3345,7 +3355,7 @@ F32 LLVOVolume::getLightIntensity() const const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); if (param_block) { - return param_block->getColor().mV[3]; + return param_block->getLinearColor().mV[3]; } else { diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index bf19a01d57..776b6a16b0 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -242,7 +242,11 @@ public: // For Lights void setIsLight(BOOL is_light); - void setLightColor(const LLColor3& color); + //set the gamma-corrected (sRGB) color of this light + void setLightSRGBColor(const LLColor3& color); + //set the linear color of this light + void setLightLinearColor(const LLColor3& color); + void setLightIntensity(F32 intensity); void setLightRadius(F32 radius); void setLightFalloff(F32 falloff); @@ -254,12 +258,13 @@ public: // Get the light color in sRGB color space NOT scaled by intensity. - LLColor3 getLightBaseColor() const; - - //same as getLightSRGBColor() - LLColor3 getLightColor() const { return getLightSRGBColor(); } + LLColor3 getLightSRGBBaseColor() const; - // Same as linearColor3(getLightSRGBColor) + // Get the light color in linear color space NOT scaled by intensity. + LLColor3 getLightLinearBaseColor() const; + + // Get the light color in linear color space scaled by intensity + // this is the value that should be fed into shaders LLColor3 getLightLinearColor() const; // Get the light color in sRGB color space scaled by intensity. diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 1765ba227f..563b45273e 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6325,8 +6325,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) mLightMovingMask |= (1<getLightColor(); + //send linear light color to shader + LLColor4 light_color = light->getLightLinearColor(); light_color.mV[3] = 0.0f; F32 fade = iter->fade; @@ -8768,8 +8768,8 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) const F32* c = center.getF32ptr(); F32 s = volume->getLightRadius()*1.5f; - //NOTE: for legacy reasons, send sRGB color to light shader - LLColor3 col = volume->getLightColor(); + //send light color to shader in linear space + LLColor3 col = volume->getLightLinearColor(); if (col.magVecSquared() < 0.001f) { @@ -8861,8 +8861,8 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) setupSpotLight(gDeferredSpotLightProgram, drawablep); - //NOTE: for legacy reasons, send sRGB color to light shader - LLColor3 col = volume->getLightColor(); + //send light color to shader in linear space + LLColor3 col = volume->getLightLinearColor(); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); @@ -8951,8 +8951,8 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) setupSpotLight(gDeferredMultiSpotLightProgram, drawablep); - //NOTE: for legacy reasons, send sRGB color to light shader - LLColor3 col = volume->getLightColor(); + //send light color to shader in linear space + LLColor3 col = volume->getLightLinearColor(); gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, light_size_final); -- cgit v1.3 From 8e436fc3964c6dada4c071cc1390358116291358 Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Mon, 30 Mar 2020 10:39:10 -0400 Subject: Fix editing light color corrupting intensity and color values --- indra/newview/llpanelvolume.cpp | 2 +- indra/newview/llvovolume.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index ae727e409f..05d9346f89 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -328,7 +328,7 @@ void LLPanelVolume::getState( ) getChild("Light Focus")->setValue(params.mV[1]); getChild("Light Ambiance")->setValue(params.mV[2]); - mLightSavedColor = volobjp->getLightSRGBColor(); + mLightSavedColor = volobjp->getLightSRGBBaseColor(); } else { diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index bd7ad399f9..fe9d770f39 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3228,7 +3228,7 @@ BOOL LLVOVolume::getIsLight() const LLColor3 LLVOVolume::getLightSRGBBaseColor() const { - return srgbColor3(getLightLinearColor()); + return srgbColor3(getLightLinearBaseColor()); } LLColor3 LLVOVolume::getLightLinearBaseColor() const -- cgit v1.3 From 3dc71d1ce97f2a4017f7a0eff056856b02742911 Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Mon, 30 Mar 2020 10:30:38 -0400 Subject: Fix light falloff being corrupted when editing value via build floater spinner --- indra/newview/llvovolume.cpp | 2 +- indra/newview/pipeline.cpp | 15 ++++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index bd7ad399f9..29be841847 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3381,7 +3381,7 @@ F32 LLVOVolume::getLightFalloff() const const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); if (param_block) { - return param_block->getFalloff() * 0.5f; + return param_block->getFalloff(); } else { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 563b45273e..1f5aa644fd 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6363,12 +6363,9 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) continue; } - F32 x = (3.f * (1.f + (light->getLightFalloff() * 2.0f))); // why this magic? probably trying to match a historic behavior. + F32 x = (3.f * (1.f + ((light->getLightFalloff() * 0.5f) * 2.0f))); // why this magic? probably trying to match a historic behavior. F32 linatten = x / (light_radius); // % of brightness at radius - // get falloff to match for forward deferred rendering lights - F32 falloff = light->getLightFalloff() + (sRenderDeferred ? 1.0 : 0.f); - mHWLightColors[cur_light] = light_color; LLLightState* light_state = gGL.getLight(cur_light); @@ -6379,7 +6376,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) if (sRenderDeferred) { light_state->setLinearAttenuation(size); - light_state->setQuadraticAttenuation(falloff); + light_state->setQuadraticAttenuation(light->getLightFalloff() * 0.5f + 1.f); // get falloff to match for forward deferred rendering lights } else { @@ -8810,7 +8807,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); - gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()); + gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); gGL.syncMatrices(); mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); @@ -8830,7 +8827,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) mat.mult_matrix_vec(tc); fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s)); - light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff())); + light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); } } unbindDeferredShader(gDeferredLightProgram); @@ -8867,7 +8864,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); - gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()); + gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); gGL.syncMatrices(); mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); @@ -8942,7 +8939,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) LLVector3 center = drawablep->getPositionAgent(); F32* c = center.mV; F32 light_size_final = volume->getLightRadius()*1.5f; - F32 light_falloff_final = volume->getLightFalloff(); + F32 light_falloff_final = volume->getLightFalloff()*0.5f; sVisibleLightCount++; -- cgit v1.3 From 516ca236597e9e76193dd597edddc6a2fd7b0912 Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Mon, 30 Mar 2020 23:27:04 -0400 Subject: Update falloff fix with changes requested in review. --- indra/newview/llvovolume.cpp | 4 ++-- indra/newview/llvovolume.h | 2 +- indra/newview/pipeline.cpp | 13 +++++++------ 3 files changed, 10 insertions(+), 9 deletions(-) (limited to 'indra/newview/llvovolume.cpp') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 29be841847..ec10d3e22c 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3376,12 +3376,12 @@ F32 LLVOVolume::getLightRadius() const } } -F32 LLVOVolume::getLightFalloff() const +F32 LLVOVolume::getLightFalloff(const F32 fudge_factor) const { const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); if (param_block) { - return param_block->getFalloff(); + return param_block->getFalloff() * fudge_factor; } else { diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 776b6a16b0..de00ef494e 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -279,7 +279,7 @@ public: LLViewerTexture* getLightTexture(); F32 getLightIntensity() const; F32 getLightRadius() const; - F32 getLightFalloff() const; + F32 getLightFalloff(const F32 fudge_factor = 1.f) const; F32 getLightCutoff() const; // Flexible Objects diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 1f5aa644fd..f0ed303f66 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -211,6 +211,7 @@ LLTrace::EventStatHandle LLPipeline::sStatBatchSize("renderbatchsize"); const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f; const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f; +const F32 DEFERRED_LIGHT_FALLOFF = 0.5f; const U32 DEFERRED_VB_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1; extern S32 gBoxFrame; @@ -6363,7 +6364,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) continue; } - F32 x = (3.f * (1.f + ((light->getLightFalloff() * 0.5f) * 2.0f))); // why this magic? probably trying to match a historic behavior. + F32 x = (3.f * (1.f + (light->getLightFalloff() * 2.0f))); // why this magic? probably trying to match a historic behavior. F32 linatten = x / (light_radius); // % of brightness at radius mHWLightColors[cur_light] = light_color; @@ -6376,7 +6377,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) if (sRenderDeferred) { light_state->setLinearAttenuation(size); - light_state->setQuadraticAttenuation(light->getLightFalloff() * 0.5f + 1.f); // get falloff to match for forward deferred rendering lights + light_state->setQuadraticAttenuation(light->getLightFalloff(DEFERRED_LIGHT_FALLOFF) + 1.f); // get falloff to match for forward deferred rendering lights } else { @@ -8807,7 +8808,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); - gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); + gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF)); gGL.syncMatrices(); mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); @@ -8827,7 +8828,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) mat.mult_matrix_vec(tc); fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s)); - light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); + light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF))); } } unbindDeferredShader(gDeferredLightProgram); @@ -8864,7 +8865,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); - gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); + gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF)); gGL.syncMatrices(); mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); @@ -8939,7 +8940,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target) LLVector3 center = drawablep->getPositionAgent(); F32* c = center.mV; F32 light_size_final = volume->getLightRadius()*1.5f; - F32 light_falloff_final = volume->getLightFalloff()*0.5f; + F32 light_falloff_final = volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF); sVisibleLightCount++; -- cgit v1.3