diff options
| author | cosmic-linden <111533034+cosmic-linden@users.noreply.github.com> | 2024-01-22 09:16:12 -0800 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-22 09:16:12 -0800 | 
| commit | 2adecc6fac9852974e44e3d58ccf2619b45642a9 (patch) | |
| tree | 0465739323a25c7d1457ed17e13a6db8a612ea0b | |
| parent | 09ee84f675cf08f98cbd49516c5e01c289b42a20 (diff) | |
| parent | 42623ad81142f93290b31b380cc0f888a1c3c3b6 (diff) | |
Merge pull request #658 from secondlife/SL-20606
SL-20606: PBR swatches in build floater should show entire material
| -rw-r--r-- | indra/llmath/llcamera.h | 1 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 4 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.h | 5 | ||||
| -rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/newview/lldrawpool.cpp | 17 | ||||
| -rw-r--r-- | indra/newview/lldrawpool.h | 12 | ||||
| -rw-r--r-- | indra/newview/lldrawpoolterrain.cpp | 15 | ||||
| -rw-r--r-- | indra/newview/lldrawpooltree.cpp | 13 | ||||
| -rw-r--r-- | indra/newview/lldynamictexture.cpp | 29 | ||||
| -rw-r--r-- | indra/newview/llfetchedgltfmaterial.cpp | 52 | ||||
| -rw-r--r-- | indra/newview/llfetchedgltfmaterial.h | 5 | ||||
| -rw-r--r-- | indra/newview/llgltfmaterialpreviewmgr.cpp | 555 | ||||
| -rw-r--r-- | indra/newview/llgltfmaterialpreviewmgr.h | 82 | ||||
| -rw-r--r-- | indra/newview/llreflectionmapmanager.cpp | 39 | ||||
| -rw-r--r-- | indra/newview/llreflectionmapmanager.h | 5 | ||||
| -rw-r--r-- | indra/newview/lltexturectrl.cpp | 93 | ||||
| -rw-r--r-- | indra/newview/lltexturectrl.h | 3 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 28 | ||||
| -rw-r--r-- | indra/newview/pipeline.h | 4 | 
19 files changed, 818 insertions, 146 deletions
| diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index c4d04f5d02..e1d3536f66 100644 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -65,7 +65,6 @@ class LLCamera  : 	public LLCoordFrame  {  public: -	  	LLCamera(const LLCamera& rhs)  	{  		*this = rhs; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index de27636c33..4f5f30d7c2 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1319,6 +1319,10 @@ bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, U32 index,  {  	return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count);  } +bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector4a>& strider, U32 index, S32 count) +{ +    return VertexBufferStrider<LLVector4a, TYPE_NORMAL>::get(*this, strider, index, count); +}  bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector3>& strider, U32 index, S32 count)  {  	return VertexBufferStrider<LLVector3,TYPE_TANGENT>::get(*this, strider, index, count); diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index f2d146d4bb..cc59e322ed 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -180,6 +180,7 @@ public:  	bool getTexCoord1Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);  	bool getTexCoord2Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);  	bool getNormalStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1); +	bool getNormalStrider(LLStrider<LLVector4a>& strider, U32 index = 0, S32 count = -1);  	bool getTangentStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);  	bool getTangentStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);  	bool getColorStrider(LLStrider<LLColor4U>& strider, U32 index=0, S32 count = -1); @@ -187,10 +188,6 @@ public:  	bool getWeightStrider(LLStrider<F32>& strider, U32 index=0, S32 count = -1);  	bool getWeight4Strider(LLStrider<LLVector4>& strider, U32 index=0, S32 count = -1);  	bool getClothWeightStrider(LLStrider<LLVector4>& strider, U32 index=0, S32 count = -1); -    bool getBasecolorTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1); -    bool getNormalTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1); -    bool getMetallicRoughnessTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1); -    bool getEmissiveTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);      void setPositionData(const LLVector4a* data);      void setTexCoordData(const LLVector2* data); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 7a70d0b6e6..8268fb3d97 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -310,6 +310,7 @@ set(viewer_SOURCE_FILES      llgiveinventory.cpp      llglsandbox.cpp      llgltfmateriallist.cpp +    llgltfmaterialpreviewmgr.cpp      llgroupactions.cpp      llgroupiconctrl.cpp      llgrouplist.cpp @@ -963,6 +964,7 @@ set(viewer_HEADER_FILES      llgesturemgr.h      llgiveinventory.h      llgltfmateriallist.h +    llgltfmaterialpreviewmgr.h      llgroupactions.h      llgroupiconctrl.h      llgrouplist.h diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 50210b06c4..556760632a 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -567,14 +567,19 @@ void LLRenderPass::pushRiggedMaskBatches(U32 type, bool texture, bool batch_text  void LLRenderPass::applyModelMatrix(const LLDrawInfo& params)  { -	if (params.mModelMatrix != gGLLastMatrix) +	applyModelMatrix(params.mModelMatrix); +} + +void LLRenderPass::applyModelMatrix(const LLMatrix4* model_matrix) +{ +	if (model_matrix != gGLLastMatrix)  	{ -		gGLLastMatrix = params.mModelMatrix; +		gGLLastMatrix = model_matrix;  		gGL.matrixMode(LLRender::MM_MODELVIEW);  		gGL.loadMatrix(gGLModelView); -		if (params.mModelMatrix) +		if (model_matrix)  		{ -			gGL.multMatrix((GLfloat*) params.mModelMatrix->mMatrix); +			gGL.multMatrix((GLfloat*) model_matrix->mMatrix);  		}  		gPipeline.mMatrixOpCount++;  	} @@ -746,6 +751,7 @@ void LLRenderPass::pushUntexturedGLTFBatches(U32 type)      }  } +// static  void LLRenderPass::pushGLTFBatch(LLDrawInfo& params)  {      auto& mat = params.mGLTFMaterial; @@ -764,6 +770,7 @@ void LLRenderPass::pushGLTFBatch(LLDrawInfo& params)      teardown_texture_matrix(params);  } +// static  void LLRenderPass::pushUntexturedGLTFBatch(LLDrawInfo& params)  {      auto& mat = params.mGLTFMaterial; @@ -825,6 +832,7 @@ void LLRenderPass::pushUntexturedRiggedGLTFBatches(U32 type)  } +// static  void LLRenderPass::pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId)  {      if (params.mAvatar.notNull() && (lastAvatar != params.mAvatar || lastMeshId != params.mSkinInfo->mHash)) @@ -837,6 +845,7 @@ void LLRenderPass::pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvat      pushGLTFBatch(params);  } +// static  void LLRenderPass::pushUntexturedRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId)  {      if (params.mAvatar.notNull() && (lastAvatar != params.mAvatar || lastMeshId != params.mSkinInfo->mHash)) diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 0925a01439..0a9c2cc420 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -349,8 +349,8 @@ public:  	void resetDrawOrders() { }  	static void applyModelMatrix(const LLDrawInfo& params); -    // Use before a non-GLTF batch if it is interleaved with GLTF batches that share the same shader -    static void resetGLTFTextureTransform(); +    // For rendering that doesn't use LLDrawInfo for some reason +	static void applyModelMatrix(const LLMatrix4* model_matrix);  	void pushBatches(U32 type, bool texture = true, bool batch_textures = false);      void pushUntexturedBatches(U32 type); @@ -374,10 +374,10 @@ public:      void pushUntexturedRiggedGLTFBatches(U32 type);      // push a single GLTF draw call -    void pushGLTFBatch(LLDrawInfo& params); -    void pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId); -    void pushUntexturedGLTFBatch(LLDrawInfo& params); -    void pushUntexturedRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId); +    static void pushGLTFBatch(LLDrawInfo& params); +    static void pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId); +    static void pushUntexturedGLTFBatch(LLDrawInfo& params); +    static void pushUntexturedRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId);  	void pushMaskBatches(U32 type, bool texture = true, bool batch_textures = false);      void pushRiggedMaskBatches(U32 type, bool texture = true, bool batch_textures = false); diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 77189dceae..43f7587591 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -204,19 +204,8 @@ void LLDrawPoolTerrain::drawLoop()  		{  			LLFace *facep = *iter; -			LLMatrix4* model_matrix = &(facep->getDrawable()->getRegion()->mRenderMatrix); - -			if (model_matrix != gGLLastMatrix) -			{ -				llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); -				gGLLastMatrix = model_matrix; -				gGL.loadMatrix(gGLModelView); -				if (model_matrix) -				{ -					gGL.multMatrix((GLfloat*) model_matrix->mMatrix); -				} -				gPipeline.mMatrixOpCount++; -			} +            llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); +            LLRenderPass::applyModelMatrix(&facep->getDrawable()->getRegion()->mRenderMatrix);  			facep->renderIndexed();  		} diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 9dcbc48697..50c4a2c1b3 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -85,17 +85,8 @@ void LLDrawPoolTree::renderDeferred(S32 pass)          {              LLMatrix4* model_matrix = &(face->getDrawable()->getRegion()->mRenderMatrix); -            if (model_matrix != gGLLastMatrix) -            { -                gGLLastMatrix = model_matrix; -                gGL.loadMatrix(gGLModelView); -                if (model_matrix) -                { -                    llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); -                    gGL.multMatrix((GLfloat*)model_matrix->mMatrix); -                } -                gPipeline.mMatrixOpCount++; -            } +            llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); +            LLRenderPass::applyModelMatrix(model_matrix);              buff->setBuffer();              buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts() - 1, buff->getNumIndices(), 0); diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 425acd3392..a66c3876fc 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -181,19 +181,26 @@ void LLViewerDynamicTexture::postRender(BOOL success)  //-----------------------------------------------------------------------------  BOOL LLViewerDynamicTexture::updateAllInstances()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; +  	sNumRenders = 0;  	if (gGLManager.mIsDisabled)  	{  		return TRUE;  	} -	bool use_fbo = gPipeline.mBake.isComplete() && !gGLManager.mIsAMD; +    LLRenderTarget& bake_target = gPipeline.mAuxillaryRT.deferredScreen; -	if (use_fbo) -	{ -		gPipeline.mBake.bindTarget(); -        gPipeline.mBake.clear(); -	} +	if (!bake_target.isComplete()) +    { +        llassert(false); +		return FALSE; +    } +    llassert(bake_target.getWidth() >= LLPipeline::MAX_BAKE_WIDTH); +    llassert(bake_target.getHeight() >= LLPipeline::MAX_BAKE_WIDTH); + +    bake_target.bindTarget(); +    bake_target.clear();  	LLGLSLShader::unbind();  	LLVertexBuffer::unbind(); @@ -208,11 +215,14 @@ BOOL LLViewerDynamicTexture::updateAllInstances()  			LLViewerDynamicTexture *dynamicTexture = *iter;  			if (dynamicTexture->needsRender())  			{				 +                llassert(dynamicTexture->getFullWidth() <= LLPipeline::MAX_BAKE_WIDTH); +                llassert(dynamicTexture->getFullHeight() <= LLPipeline::MAX_BAKE_WIDTH); +  				glClear(GL_DEPTH_BUFFER_BIT);  				gDepthDirty = TRUE;  				gGL.color4f(1,1,1,1); -                dynamicTexture->setBoundTarget(use_fbo ? &gPipeline.mBake : nullptr); +                dynamicTexture->setBoundTarget(&bake_target);  				dynamicTexture->preRender();	// Must be called outside of startRender()  				result = FALSE;  				if (dynamicTexture->render()) @@ -229,10 +239,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances()  		}  	} -	if (use_fbo) -	{ -		gPipeline.mBake.flush(); -	} +	bake_target.flush();      gGL.flush(); diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index 46b9dffae9..90ec08391d 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -254,55 +254,3 @@ void LLFetchedGLTFMaterial::materialComplete()      materialCompleteCallbacks.clear();      materialCompleteCallbacks.shrink_to_fit();  } - -LLPointer<LLViewerFetchedTexture> LLFetchedGLTFMaterial::getUITexture() -{ -    if (mFetching) -    { -        return nullptr; -    } - -    auto fetch_texture_for_ui = [](LLPointer<LLViewerFetchedTexture>& img, const LLUUID& id) -    { -        if (id.notNull()) -        { -            if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(id)) -            { -                LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); -                if (obj) -                { -                    LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(id); -                    img = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL; -                } - -            } -            else -            { -                img = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); -            } -        } -        if (img) -        { -            img->setBoostLevel(LLGLTexture::BOOST_PREVIEW); -            img->forceToSaveRawImage(0); -        } -    }; - -    fetch_texture_for_ui(mBaseColorTexture, mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]); -    fetch_texture_for_ui(mNormalTexture, mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]); -    fetch_texture_for_ui(mMetallicRoughnessTexture, mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]); -    fetch_texture_for_ui(mEmissiveTexture, mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]); - -    if ((mBaseColorTexture && (mBaseColorTexture->getRawImageLevel() != 0)) || -        (mNormalTexture && (mNormalTexture->getRawImageLevel() != 0)) || -        (mMetallicRoughnessTexture && (mMetallicRoughnessTexture->getRawImageLevel() != 0)) || -        (mEmissiveTexture && (mEmissiveTexture->getRawImageLevel() != 0))) -    { -        return nullptr; -    } - -    // *HACK: Use one of the PBR texture components as the preview texture for now -    mPreviewTexture = mBaseColorTexture; - -    return mPreviewTexture; -} diff --git a/indra/newview/llfetchedgltfmaterial.h b/indra/newview/llfetchedgltfmaterial.h index a9e539633d..2559aa46cc 100644 --- a/indra/newview/llfetchedgltfmaterial.h +++ b/indra/newview/llfetchedgltfmaterial.h @@ -50,8 +50,6 @@ public:      bool isFetching() const { return mFetching; } -    LLPointer<LLViewerFetchedTexture> getUITexture(); -      void addTextureEntry(LLTextureEntry* te) override;      void removeTextureEntry(LLTextureEntry* te) override;      virtual bool replaceLocalTexture(const LLUUID& tracking_id, const LLUUID& old_id, const LLUUID& new_id) override; @@ -65,9 +63,6 @@ public:      std::set<LLTextureEntry*> mTextureEntires; -    // Texture used for previewing the material in the UI -    LLPointer<LLViewerFetchedTexture> mPreviewTexture; -  protected:      // Lifetime management diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp new file mode 100644 index 0000000000..a8ea3429f4 --- /dev/null +++ b/indra/newview/llgltfmaterialpreviewmgr.cpp @@ -0,0 +1,555 @@ +/** + * @file llgltfmaterialpreviewmgr.cpp + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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 "llgltfmaterialpreviewmgr.h" + +#include <memory> +#include <vector> + +#include "llavatarappearancedefines.h" +#include "llenvironment.h" +#include "llselectmgr.h" +#include "llviewercamera.h" +#include "llviewerobject.h" +#include "llviewershadermgr.h" +#include "llviewertexturelist.h" +#include "llviewerwindow.h" +#include "llvolumemgr.h" +#include "pipeline.h" + +LLGLTFMaterialPreviewMgr gGLTFMaterialPreviewMgr; + +namespace +{ +    constexpr S32 FULLY_LOADED = 0; +    constexpr S32 NOT_LOADED = 99; +}; + +LLGLTFPreviewTexture::MaterialLoadLevels::MaterialLoadLevels() +{ +    for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i) +    { +        levels[i] = NOT_LOADED; +    } +} + +S32& LLGLTFPreviewTexture::MaterialLoadLevels::operator[](size_t i) +{ +    llassert(i >= 0 && i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT); +    return levels[i]; +} + +const S32& LLGLTFPreviewTexture::MaterialLoadLevels::operator[](size_t i) const +{ +    llassert(i >= 0 && i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT); +    return levels[i]; +} + +bool LLGLTFPreviewTexture::MaterialLoadLevels::operator<(const MaterialLoadLevels& other) const +{ +    bool less = false; +    for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i) +    { +        if (((*this)[i] > other[i])) { return false; } +        less = less || ((*this)[i] < other[i]); +    } +    return less; +} + +bool LLGLTFPreviewTexture::MaterialLoadLevels::operator>(const MaterialLoadLevels& other) const +{ +    bool great = false; +    for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i) +    { +        if (((*this)[i] < other[i])) { return false; } +        great = great || ((*this)[i] > other[i]); +    } +    return great; +} + +namespace +{ +    void fetch_texture_for_ui(LLPointer<LLViewerFetchedTexture>& img, const LLUUID& id) +    { +        if (id.notNull()) +        { +            if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(id)) +            { +                LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); +                if (obj) +                { +                    LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(id); +                    img = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL; +                } +            } +            else +            { +                img = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); +            } +        } +        if (img) +        { +            img->setBoostLevel(LLGLTexture::BOOST_PREVIEW); +            img->forceToSaveRawImage(0); +        } +    }; + +    // *NOTE: Does not use the same conventions as texture discard level. Lower is better. +    S32 get_texture_load_level(const LLPointer<LLViewerFetchedTexture>& texture) +    { +        if (!texture) { return FULLY_LOADED; } +        const S32 raw_level = texture->getDiscardLevel(); +        if (raw_level < 0) { return NOT_LOADED; } +        return raw_level; +    } + +    LLGLTFPreviewTexture::MaterialLoadLevels get_material_load_levels(LLFetchedGLTFMaterial& material) +    { +        using MaterialTextures = LLPointer<LLViewerFetchedTexture>*[LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT]; + +        MaterialTextures textures; + +        textures[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] = &material.mBaseColorTexture; +        textures[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] = &material.mNormalTexture; +        textures[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] = &material.mMetallicRoughnessTexture; +        textures[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] = &material.mEmissiveTexture; + +        LLGLTFPreviewTexture::MaterialLoadLevels levels; + +        for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i) +        { +            fetch_texture_for_ui(*textures[i], material.mTextureId[i]); +            levels[i] = get_texture_load_level(*textures[i]); +        } + +        return levels; +    } + +    // Is the material loaded enough to start rendering a preview? +    bool is_material_loaded_enough_for_ui(LLFetchedGLTFMaterial& material) +    { +        if (material.isFetching()) +        { +            return false; +        } + +        LLGLTFPreviewTexture::MaterialLoadLevels levels = get_material_load_levels(material); + +        for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i) +        { +            if (levels[i] == NOT_LOADED) +            { +                return false; +            } +        } + +        return true; +    } + +};  // namespace + +LLGLTFPreviewTexture::LLGLTFPreviewTexture(LLPointer<LLFetchedGLTFMaterial> material, S32 width) +    : LLViewerDynamicTexture(width, width, 4, EOrder::ORDER_MIDDLE, FALSE) +    , mGLTFMaterial(material) +{ +} + +// static +LLPointer<LLGLTFPreviewTexture> LLGLTFPreviewTexture::create(LLPointer<LLFetchedGLTFMaterial> material) +{ +    return new LLGLTFPreviewTexture(material, LLPipeline::MAX_BAKE_WIDTH); +} + +void LLGLTFPreviewTexture::preRender(BOOL clear_depth) +{ +    LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; + +    MaterialLoadLevels current_load = get_material_load_levels(*mGLTFMaterial.get()); +    if (current_load < mBestLoad) +    { +        mShouldRender = true; +        mBestLoad = current_load; +    } + +    if (!mShouldRender) { return; } + +    LLViewerDynamicTexture::preRender(clear_depth); +} + + +namespace { + +struct GLTFPreviewModel +{ +    GLTFPreviewModel(LLPointer<LLDrawInfo>& info, const LLMatrix4& mat) +    : mDrawInfo(info) +    , mModelMatrix(mat) +    { +        mDrawInfo->mModelMatrix = &mModelMatrix; +    } +    GLTFPreviewModel(GLTFPreviewModel&) = delete; +    ~GLTFPreviewModel() +    { +        // No model matrix necromancy +        llassert(gGLLastMatrix != &mModelMatrix); +        gGLLastMatrix = nullptr; +    } +    LLPointer<LLDrawInfo> mDrawInfo; +    LLMatrix4 mModelMatrix; // Referenced by mDrawInfo +}; + +using PreviewSpherePart = std::unique_ptr<GLTFPreviewModel>; +using PreviewSphere = std::vector<PreviewSpherePart>; + +// Like LLVolumeGeometryManager::registerFace but without batching or too-many-indices/vertices checking. +PreviewSphere create_preview_sphere(LLPointer<LLFetchedGLTFMaterial>& material, const LLMatrix4& model_matrix) +{ +    LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; + +    const LLColor4U vertex_color(material->mBaseColor); + +    LLPrimitive prim; +    prim.init_primitive(LL_PCODE_VOLUME); +    LLVolumeParams params; +    params.setType(LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE); +    params.setBeginAndEndS(0.f, 1.f); +    params.setBeginAndEndT(0.f, 1.f); +    params.setRatio(1, 1); +    params.setShear(0, 0); +    constexpr auto MAX_LOD = LLVolumeLODGroup::NUM_LODS - 1; +    prim.setVolume(params, MAX_LOD); + +    LLVolume* volume = prim.getVolume(); +    llassert(volume); +    for (LLVolumeFace& face : volume->getVolumeFaces()) +    { +        face.createTangents(); +    } + +    PreviewSphere preview_sphere; +    preview_sphere.reserve(volume->getNumFaces()); + +    LLPointer<LLVertexBuffer> buf = new LLVertexBuffer( +        LLVertexBuffer::MAP_VERTEX | +        LLVertexBuffer::MAP_NORMAL | +        LLVertexBuffer::MAP_TEXCOORD0 | +        LLVertexBuffer::MAP_COLOR | +        LLVertexBuffer::MAP_TANGENT +    ); +    U32 nv = 0; +    U32 ni = 0; +    for (LLVolumeFace& face : volume->getVolumeFaces()) +    { +        nv += face.mNumVertices; +        ni += face.mNumIndices; +    } +    buf->allocateBuffer(nv, ni); + +    // UV hacks +    // Higher factor helps to see more details on the preview sphere +    const LLVector2 uv_factor(2.0f, 2.0f); +    // Offset places center of material in center of view +    const LLVector2 uv_offset(-0.5f, -0.5f); + +    LLStrider<U16> indices; +    LLStrider<LLVector4a> positions; +    LLStrider<LLVector4a> normals; +    LLStrider<LLVector2> texcoords; +    LLStrider<LLColor4U> colors; +    LLStrider<LLVector4a> tangents; +	buf->getIndexStrider(indices); +	buf->getVertexStrider(positions); +	buf->getNormalStrider(normals); +	buf->getTexCoord0Strider(texcoords); +	buf->getColorStrider(colors); +	buf->getTangentStrider(tangents); +    U32 index_offset = 0; +    U32 vertex_offset = 0; +    for (const LLVolumeFace& face : volume->getVolumeFaces()) +    { +        for (S32 i = 0; i < face.mNumIndices; ++i) +        { +            *indices++ = face.mIndices[i] + vertex_offset; +        } +        for (S32 v = 0; v < face.mNumVertices; ++v) +        { +            *positions++ = face.mPositions[v]; +            *normals++ = face.mNormals[v]; +            LLVector2 uv(face.mTexCoords[v]); +            uv.scaleVec(uv_factor); +            uv += uv_offset; +            *texcoords++ = uv; +            *colors++ = vertex_color; +            *tangents++ = face.mTangents[v]; +        } + +        constexpr LLViewerTexture* no_media = nullptr; +        LLPointer<LLDrawInfo> info = new LLDrawInfo(U16(vertex_offset), U16(vertex_offset + face.mNumVertices - 1), face.mNumIndices, index_offset, no_media, buf.get()); +        info->mGLTFMaterial = material; +        preview_sphere.emplace_back(std::make_unique<GLTFPreviewModel>(info, model_matrix)); +        index_offset += face.mNumIndices; +        vertex_offset += face.mNumVertices; +    } + +    buf->unmapBuffer(); + +    return preview_sphere; +} + +void set_preview_sphere_material(PreviewSphere& preview_sphere, LLPointer<LLFetchedGLTFMaterial>& material) +{ +    llassert(!preview_sphere.empty()); +    if (preview_sphere.empty()) { return; } + +    const LLColor4U vertex_color(material->mBaseColor); + +    // See comments about unmapBuffer in llvertexbuffer.h +    for (PreviewSpherePart& part : preview_sphere) +    { +        LLDrawInfo* info = part->mDrawInfo.get(); +        info->mGLTFMaterial = material; +        LLVertexBuffer* buf = info->mVertexBuffer.get(); +        LLStrider<LLColor4U> colors; +        const S32 count = info->mEnd - info->mStart; +        buf->getColorStrider(colors, info->mStart, count); +        for (S32 i = 0; i < count; ++i) +        { +            *colors++ = vertex_color; +        } +        buf->unmapBuffer(); +    } +} + +PreviewSphere& get_preview_sphere(LLPointer<LLFetchedGLTFMaterial>& material, const LLMatrix4& model_matrix) +{ +    static PreviewSphere preview_sphere; +    if (preview_sphere.empty()) +    { +        preview_sphere = create_preview_sphere(material, model_matrix); +    } +    else +    { +        set_preview_sphere_material(preview_sphere, material); +    } +    return preview_sphere; +} + +// Final, direct modifications to shader constants, just before render +void fixup_shader_constants(LLGLSLShader& shader) +{ +    // Sunlight intensity of 0 no matter what +    shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, 1); +    shader.uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, 1, LLColor3::white.mV); +    shader.uniform1f(LLShaderMgr::DENSITY_MULTIPLIER, 0.0f); + +    // Ignore sun shadow (if enabled) +    for (U32 i = 0; i < 6; i++) +    { +        const S32 channel = shader.getTextureChannel(LLShaderMgr::DEFERRED_SHADOW0+i); +        if (channel != -1) +        { +            gGL.getTexUnit(channel)->bind(LLViewerFetchedTexture::sWhiteImagep, TRUE); +        } +    } +} + +// Set a variable to a value temporarily, and restor the variable's old value +// when this object leaves scope. +template<typename T> +struct SetTemporarily +{ +    T* mRef; +    T mOldVal; +    SetTemporarily(T* var, T temp_val) +    { +        mRef = var; +        mOldVal = *mRef; +        *mRef = temp_val; +    } +    ~SetTemporarily() +    { +        *mRef = mOldVal; +    } +}; + +}; // namespace + +BOOL LLGLTFPreviewTexture::render() +{ +    LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; + +    if (!mShouldRender) { return FALSE; } + +    glClearColor(0, 0, 0, 0); +    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +     +    LLGLDepthTest(GL_FALSE); +    LLGLDisable stencil(GL_STENCIL_TEST); +    LLGLDisable scissor(GL_SCISSOR_TEST); +    SetTemporarily<bool> no_dof(&LLPipeline::RenderDepthOfField, false); +    SetTemporarily<bool> no_glow(&LLPipeline::sRenderGlow, false); +    SetTemporarily<bool> no_ssr(&LLPipeline::RenderScreenSpaceReflections, false); +    SetTemporarily<U32> no_fxaa(&LLPipeline::RenderFSAASamples, U32(0)); +    SetTemporarily<LLPipeline::RenderTargetPack*> use_auxiliary_render_target(&gPipeline.mRT, &gPipeline.mAuxillaryRT); + +    LLVector3 light_dir3(1.0f, 1.0f, 1.0f); +    light_dir3.normalize(); +    const LLVector4 light_dir = LLVector4(light_dir3, 0); +    SetTemporarily<S32> sun_light_only(&LLPipeline::RenderLocalLightCount, 0); + +    gPipeline.mReflectionMapManager.forceDefaultProbeAndUpdateUniforms(); + +    LLViewerCamera camera; + +    // Calculate the object distance at which the object of a given radius will +    // span the partial width of the screen given by fill_ratio. +    // Assume the primitive has a scale of 1 (this is the default). +    constexpr F32 fill_ratio = 0.8f; +    constexpr F32 object_radius = 0.5f; +    const F32 object_distance = (object_radius / fill_ratio) * tan(camera.getDefaultFOV()); +    // Negative coordinate shows the textures on the sphere right-side up, when +    // combined with the UV hacks in create_preview_sphere +    const LLVector3 object_position(0.0, -object_distance, 0.0); +    LLMatrix4 object_transform; +    object_transform.translate(object_position); + +    // Set up camera and viewport +    const LLVector3 origin(0.0, 0.0, 0.0); +    camera.lookAt(origin, object_position); +    camera.setAspect(mFullHeight / mFullWidth); +    const LLRect texture_rect(0, mFullHeight, mFullWidth, 0); +    camera.setPerspective(NOT_FOR_SELECTION, texture_rect.mLeft, texture_rect.mBottom, texture_rect.getWidth(), texture_rect.getHeight(), FALSE, camera.getNear(), MAX_FAR_CLIP*2.f); + +    // Generate sphere object on-the-fly. Discard afterwards. (Vertex buffer is +    // discarded, but the sphere should be cached in LLVolumeMgr.) +    PreviewSphere& preview_sphere = get_preview_sphere(mGLTFMaterial, object_transform); + +    gPipeline.setupHWLights(); +    glh::matrix4f mat = copy_matrix(gGLModelView); +    glh::vec4f transformed_light_dir(light_dir.mV); +    mat.mult_matrix_vec(transformed_light_dir); +    SetTemporarily<LLVector4> force_sun_direction_high_graphics(&gPipeline.mTransformedSunDir, LLVector4(transformed_light_dir.v)); +    // Override lights to ensure the sun is always shining from a certain direction (low graphics) +    // See also force_sun_direction_high_graphics and fixup_shader_constants +    { +        LLLightState* light = gGL.getLight(0); +        light->setPosition(light_dir); +        constexpr bool sun_up = true; +        light->setSunPrimary(sun_up); +    } + +    LLRenderTarget& screen = gPipeline.mAuxillaryRT.screen; + +    // *HACK: Force reset of the model matrix +    gGLLastMatrix = nullptr; + +#if 0 +    if (mGLTFMaterial->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_OPAQUE || mGLTFMaterial->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_MASK) +    { +        // *TODO: Opaque/alpha mask rendering +    } +    else +#endif +    { +        // Alpha blend rendering + +        screen.bindTarget(); +        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + +        LLGLSLShader& shader = gDeferredPBRAlphaProgram; + +        gPipeline.bindDeferredShader(shader); +        fixup_shader_constants(shader); + +        for (PreviewSpherePart& part : preview_sphere) +        { +            LLRenderPass::pushGLTFBatch(*part->mDrawInfo); +        } + +        gPipeline.unbindDeferredShader(shader); + +        screen.flush(); +    } + +    gPipeline.copyScreenSpaceReflections(&screen, &gPipeline.mSceneMap); +    gPipeline.generateLuminance(&screen, &gPipeline.mLuminanceMap); +    gPipeline.generateExposure(&gPipeline.mLuminanceMap, &gPipeline.mExposureMap); +    gPipeline.gammaCorrect(&screen, &gPipeline.mPostMap); +    LLVertexBuffer::unbind(); +    gPipeline.generateGlow(&gPipeline.mPostMap); +    gPipeline.combineGlow(&gPipeline.mPostMap, &screen); +	gPipeline.renderDoF(&screen, &gPipeline.mPostMap); +	gPipeline.applyFXAA(&gPipeline.mPostMap, &screen); + +    // Final render + +	gDeferredPostNoDoFProgram.bind(); + +	// From LLPipeline::renderFinalize: "Whatever is last in the above post processing chain should _always_ be rendered directly here.  If not, expect problems." +	gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &screen); +	gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, mBoundTarget, true); + +	{ +		LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); +		gPipeline.mScreenTriangleVB->setBuffer(); +		gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); +	} + +	gDeferredPostNoDoFProgram.unbind(); + +    // Clean up +    gPipeline.setupHWLights(); +    gPipeline.mReflectionMapManager.forceDefaultProbeAndUpdateUniforms(false); + +    return TRUE; +} + +void LLGLTFPreviewTexture::postRender(BOOL success) +{ +    LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; + +    if (!mShouldRender) { return; } +    mShouldRender = false; + +    LLViewerDynamicTexture::postRender(success); +} + +// static +LLPointer<LLViewerTexture> LLGLTFMaterialPreviewMgr::getPreview(LLPointer<LLFetchedGLTFMaterial> &material) +{ +    if (!material) +    { +        return nullptr; +    } + +    if (!is_material_loaded_enough_for_ui(*material)) +    { +        return nullptr; +    } + +    return LLGLTFPreviewTexture::create(material); +} diff --git a/indra/newview/llgltfmaterialpreviewmgr.h b/indra/newview/llgltfmaterialpreviewmgr.h new file mode 100644 index 0000000000..cc40a6f2e2 --- /dev/null +++ b/indra/newview/llgltfmaterialpreviewmgr.h @@ -0,0 +1,82 @@ +/** + * @file llgltfmaterialpreviewmgr.h + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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$ + */ + +#pragma once + +#include "lldrawpool.h" +#include "lldynamictexture.h" +#include "llfetchedgltfmaterial.h" +#include "llsingleton.h" +#include "lltexture.h" + +class LLGLTFPreviewTexture : public LLViewerDynamicTexture +{ +protected: +    LLGLTFPreviewTexture(LLPointer<LLFetchedGLTFMaterial> material, S32 width); + +public: +    // Width scales with size of material's textures +    static LLPointer<LLGLTFPreviewTexture> create(LLPointer<LLFetchedGLTFMaterial> material); + +    BOOL needsRender() override { return mNeedsRender; } +    void preRender(BOOL clear_depth = TRUE) override; +    BOOL render() override; +    void postRender(BOOL success) override; + +    struct MaterialLoadLevels +    { +        S32 levels[LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT]; + +        MaterialLoadLevels(); + +        S32& operator[](size_t i); + +        const S32& operator[](size_t i) const; + +        // Less is better +        // Returns false if lhs is not strictly less or equal for all levels +        bool operator<(const MaterialLoadLevels& other) const; + +        // Less is better +        // Returns false if lhs is not strictly greater or equal for all levels +        bool operator>(const MaterialLoadLevels& other) const; +    }; + +private: +    LLPointer<LLFetchedGLTFMaterial> mGLTFMaterial; +    bool mNeedsRender = true; +    bool mShouldRender = true; +    MaterialLoadLevels mBestLoad; +}; + +class LLGLTFMaterialPreviewMgr +{ +  public: +    // Returns null if the material is not loaded yet. +    // *NOTE: User should cache the texture if the same material is being previewed +    LLPointer<LLViewerTexture> getPreview(LLPointer<LLFetchedGLTFMaterial> &material); +}; + +extern LLGLTFMaterialPreviewMgr gGLTFMaterialPreviewMgr; diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 69674417c1..2b6985b214 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -27,6 +27,9 @@  #include "llviewerprecompiledheaders.h"  #include "llreflectionmapmanager.h" + +#include <vector> +  #include "llviewercamera.h"  #include "llspatialpartition.h"  #include "llviewerregion.h" @@ -1383,3 +1386,39 @@ void LLReflectionMapManager::doOcclusion()          }      }  } + +void LLReflectionMapManager::forceDefaultProbeAndUpdateUniforms(bool force) +{ +    static std::vector<bool> mProbeWasOccluded; + +    if (force) +    { +        llassert(mProbeWasOccluded.empty()); + +        for (size_t i = 0; i < mProbes.size(); ++i) +        { +            auto& probe = mProbes[i]; +            mProbeWasOccluded.push_back(probe->mOccluded); +            if (probe != nullptr && probe != mDefaultProbe) +            { +                probe->mOccluded = true; +            } +        } + +        updateUniforms(); +    } +    else +    { +        llassert(mProbes.size() == mProbeWasOccluded.size()); + +        const size_t n = llmin(mProbes.size(), mProbeWasOccluded.size()); +        for (size_t i = 0; i < n; ++i) +        { +            auto& probe = mProbes[i]; +            llassert(probe->mOccluded == (probe != mDefaultProbe)); +            probe->mOccluded = mProbeWasOccluded[i]; +        } +        mProbeWasOccluded.clear(); +        mProbeWasOccluded.shrink_to_fit(); +    } +} diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index b77a33da89..dd641452ae 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -106,6 +106,11 @@ public:      // perform occlusion culling on all active reflection probes      void doOcclusion(); +    // *HACK: "cull" all reflection probes except the default one. Only call +    // this if you don't intend to call updateUniforms directly. Call again +    // with false when done. +    void forceDefaultProbeAndUpdateUniforms(bool force = true); +  private:      friend class LLPipeline; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 233b864fba..b9cb00b561 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -72,6 +72,7 @@  #include "llradiogroup.h"  #include "llfloaterreg.h" +#include "llgltfmaterialpreviewmgr.h"  #include "lllocalbitmaps.h"  #include "lllocalgltfmaterials.h"  #include "llerror.h" @@ -657,6 +658,7 @@ void LLFloaterTexturePicker::draw()  	if( mOwner )   	{  		mTexturep = NULL; +        LLPointer<LLFetchedGLTFMaterial> old_material = mGLTFMaterial;          mGLTFMaterial = NULL;          if (mImageAssetID.notNull())          { @@ -664,10 +666,23 @@ void LLFloaterTexturePicker::draw()              {                  mGLTFMaterial = (LLFetchedGLTFMaterial*) gGLTFMaterialList.getMaterial(mImageAssetID);                  llassert(mGLTFMaterial == nullptr || dynamic_cast<LLFetchedGLTFMaterial*>(gGLTFMaterialList.getMaterial(mImageAssetID)) != nullptr); +                if (mGLTFPreview.isNull() || mGLTFMaterial.isNull() || (old_material.notNull() && (*old_material.get() != *mGLTFMaterial.get()))) +                { +                    // Only update the preview if needed, since gGLTFMaterialPreviewMgr does not cache the preview. +                    if (mGLTFMaterial.isNull()) +                    { +                        mGLTFPreview = nullptr; +                    } +                    else +                    { +                        mGLTFPreview = gGLTFMaterialPreviewMgr.getPreview(mGLTFMaterial); +                    } +                }              }              else              {                  LLPointer<LLViewerFetchedTexture> texture = NULL; +                mGLTFPreview = nullptr;                  if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))                  { @@ -677,7 +692,7 @@ void LLFloaterTexturePicker::draw()                      if (obj)                      {                          LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID); -                        texture = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL; +						texture = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL;                      }                  } @@ -718,27 +733,29 @@ void LLFloaterTexturePicker::draw()  		// If the floater is focused, don't apply its alpha to the texture (STORM-677).  		const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); -        LLViewerTexture* texture = nullptr; +        LLViewerTexture* preview = nullptr;          if (mGLTFMaterial)          { -            texture = mGLTFMaterial->getUITexture(); +            preview = mGLTFPreview.get();          }          else          { -            texture = mTexturep.get(); +            preview = mTexturep.get(); +            if (mTexturep) +            { +                // Pump the priority +				mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); +            }          } -		if( texture ) +		if( preview )  		{ -			if( texture->getComponents() == 4 ) +			if( preview->getComponents() == 4 )  			{  				gl_rect_2d_checkerboard( interior, alpha );  			} -			gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), texture, UI_VERTEX_COLOR % alpha ); - -			// Pump the priority -			texture->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); +			gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), preview, UI_VERTEX_COLOR % alpha );  		}  		else if (!mFallbackImage.isNull())  		{ @@ -2156,48 +2173,69 @@ void LLTextureCtrl::draw()  {  	mBorder->setKeyboardFocusHighlight(hasFocus()); +    LLPointer<LLViewerTexture> preview = NULL; +  	if (!mValid)  	{  		mTexturep = NULL; +        mGLTFMaterial = NULL; +        mGLTFPreview = NULL;  	}  	else if (!mImageAssetID.isNull())  	{ -		LLPointer<LLViewerFetchedTexture> texture = NULL; -  		if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))  		{  			LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();  			if (obj)  			{  				LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID); -				texture = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL; +				mTexturep = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL; +				mGLTFMaterial = NULL; +				mGLTFPreview = NULL; + +                preview = mTexturep;  			}  		} -		if (texture.isNull()) +		if (preview.isNull())  		{ +            LLPointer<LLFetchedGLTFMaterial> old_material = mGLTFMaterial; +            mGLTFMaterial = NULL; +            mTexturep = NULL;              if (mInventoryPickType == PICK_MATERIAL)              { -                LLPointer<LLFetchedGLTFMaterial> material = gGLTFMaterialList.getMaterial(mImageAssetID); -                if (material) +                mGLTFMaterial = gGLTFMaterialList.getMaterial(mImageAssetID); +                if (mGLTFPreview.isNull() || mGLTFMaterial.isNull() || (old_material.notNull() && (*old_material.get() != *mGLTFMaterial.get())))                  { -                    texture = material->getUITexture(); +                    // Only update the preview if needed, since gGLTFMaterialPreviewMgr does not cache the preview. +                    if (mGLTFMaterial.isNull()) +                    { +                        mGLTFPreview = nullptr; +                    } +                    else +                    { +                        mGLTFPreview = gGLTFMaterialPreviewMgr.getPreview(mGLTFMaterial); +                    }                  } + +                preview = mGLTFPreview;              }              else              { -                texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); -                texture->setBoostLevel(LLGLTexture::BOOST_PREVIEW); -                texture->forceToSaveRawImage(0); +				mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); +				mTexturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW); +				mTexturep->forceToSaveRawImage(0); + +				preview = mTexturep;              }  		} - -		mTexturep = texture;  	}  	else//mImageAssetID == LLUUID::null  	{  		mTexturep = NULL;  +        mGLTFMaterial = NULL; +        mGLTFPreview = NULL;  	}  	// Border @@ -2210,15 +2248,18 @@ void LLTextureCtrl::draw()  	// If we're in a focused floater, don't apply the floater's alpha to the texture (STORM-677).  	const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); -	if( mTexturep ) +	if( preview )  	{ -		if( mTexturep->getComponents() == 4 ) +		if( preview->getComponents() == 4 )  		{  			gl_rect_2d_checkerboard( interior, alpha );  		} -		gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha); -		mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); +		gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), preview, UI_VERTEX_COLOR % alpha); +        if (mTexturep) +        { +            mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); +        }  	}  	else if (!mFallbackImage.isNull())  	{ diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index cb6ce636e0..77919637ac 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -250,6 +250,8 @@ private:  	commit_callback_t		 	mOnCloseCallback;  	texture_selected_callback	mOnTextureSelectedCallback;  	LLPointer<LLViewerFetchedTexture> mTexturep; +	LLPointer<LLFetchedGLTFMaterial> mGLTFMaterial; +	LLPointer<LLViewerTexture> mGLTFPreview;  	LLUIColor				 	mBorderColor;  	LLUUID					 	mImageItemID;  	LLUUID					 	mImageAssetID; @@ -382,6 +384,7 @@ protected:  	LLPointer<LLViewerTexture> mTexturep;      LLPointer<LLFetchedGLTFMaterial> mGLTFMaterial; +    LLPointer<LLViewerTexture> mGLTFPreview;  	LLView*				mOwner;  	LLUUID				mImageAssetID; // Currently selected texture diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index f740fa60be..53be4c135e 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -163,6 +163,7 @@ F32 LLPipeline::CameraFocusTransitionTime;  F32 LLPipeline::CameraFNumber;  F32 LLPipeline::CameraFocalLength;  F32 LLPipeline::CameraFieldOfView; +S32 LLPipeline::RenderLocalLightCount;  F32 LLPipeline::RenderShadowNoise;  F32 LLPipeline::RenderShadowBlurSize;  F32 LLPipeline::RenderSSAOScale; @@ -200,6 +201,8 @@ S32 LLPipeline::RenderScreenSpaceReflectionGlossySamples;  S32 LLPipeline::RenderBufferVisualization;  LLTrace::EventStatHandle<S64> LLPipeline::sStatBatchSize("renderbatchsize"); +const U32 LLPipeline::MAX_BAKE_WIDTH = 512; +  const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;  const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;  const F32 ALPHA_BLEND_CUTOFF = 0.598f; @@ -521,6 +524,7 @@ void LLPipeline::init()  	connectRefreshCachedSettingsSafe("CameraFNumber");  	connectRefreshCachedSettingsSafe("CameraFocalLength");  	connectRefreshCachedSettingsSafe("CameraFieldOfView"); +	connectRefreshCachedSettingsSafe("RenderLocalLightCount");  	connectRefreshCachedSettingsSafe("RenderShadowNoise");  	connectRefreshCachedSettingsSafe("RenderShadowBlurSize");  	connectRefreshCachedSettingsSafe("RenderSSAOScale"); @@ -764,10 +768,13 @@ LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY)  bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; -    if (mRT == &mMainRT && sReflectionProbesEnabled) +    if (mRT == &mMainRT)      { // hacky -- allocate auxillary buffer -        gCubeSnapshot = TRUE; -        mReflectionMapManager.initReflectionMaps(); +        if (sReflectionProbesEnabled) +        { +            gCubeSnapshot = TRUE; +            mReflectionMapManager.initReflectionMaps(); +        }          mRT = &mAuxillaryRT;          U32 res = mReflectionMapManager.mProbeResolution * 4;  //multiply by 4 because probes will be 16x super sampled          allocateScreenBuffer(res, res, samples); @@ -1009,6 +1016,7 @@ void LLPipeline::refreshCachedSettings()  	CameraFNumber = gSavedSettings.getF32("CameraFNumber");  	CameraFocalLength = gSavedSettings.getF32("CameraFocalLength");  	CameraFieldOfView = gSavedSettings.getF32("CameraFieldOfView"); +	RenderLocalLightCount = gSavedSettings.getS32("RenderLocalLightCount");  	RenderShadowNoise = gSavedSettings.getF32("RenderShadowNoise");  	RenderShadowBlurSize = gSavedSettings.getF32("RenderShadowBlurSize");  	RenderSSAOScale = gSavedSettings.getF32("RenderSSAOScale"); @@ -1072,7 +1080,6 @@ void LLPipeline::releaseGLBuffers()  	releaseLUTBuffers();  	mWaterDis.release(); -    mBake.release();      mSceneMap.release(); @@ -1151,9 +1158,6 @@ void LLPipeline::createGLBuffers()      stop_glerror();  	assertInitialized(); -    // Use FBO for bake tex -    mBake.allocate(512, 512, GL_RGBA, true); // SL-12781 Build > Upload > Model; 3D Preview -  	stop_glerror();  	GLuint resX = gViewerWindow->getWorldViewWidthRaw(); @@ -5227,7 +5231,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)  		return;  	} -    static LLCachedControl<S32> local_light_count(gSavedSettings, "RenderLocalLightCount", 256); +    const S32 local_light_count = LLPipeline::RenderLocalLightCount;  	if (local_light_count >= 1)  	{ @@ -5496,7 +5500,7 @@ void LLPipeline::setupHWLights()  	mLightMovingMask = 0; -    static LLCachedControl<S32> local_light_count(gSavedSettings, "RenderLocalLightCount", 256); +    const S32 local_light_count = LLPipeline::RenderLocalLightCount;  	if (local_light_count >= 1)  	{ @@ -6536,7 +6540,7 @@ void LLPipeline::renderAlphaObjects(bool rigged)                  LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up);                  LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);                  LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF); -                mSimplePool->pushRiggedGLTFBatch(*pparams, lastAvatar, lastMeshId); +                LLRenderPass::pushRiggedGLTFBatch(*pparams, lastAvatar, lastMeshId);              }              else              { @@ -6562,7 +6566,7 @@ void LLPipeline::renderAlphaObjects(bool rigged)                  LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up);                  LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);                  LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF); -                mSimplePool->pushGLTFBatch(*pparams); +                LLRenderPass::pushGLTFBatch(*pparams);              }              else              { @@ -7930,7 +7934,7 @@ void LLPipeline::renderDeferredLighting()              unbindDeferredShader(gDeferredSoftenProgram);          } -        static LLCachedControl<S32> local_light_count(gSavedSettings, "RenderLocalLightCount", 256); +        const S32 local_light_count = LLPipeline::RenderLocalLightCount;          if (local_light_count > 0)          { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 88a7eab813..dd5040f76e 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -694,6 +694,7 @@ public:      RenderTargetPack mMainRT;      // auxillary 512x512 render target pack +    // used by reflection probes and dynamic texture bakes      RenderTargetPack mAuxillaryRT;      // currently used render target pack @@ -754,7 +755,7 @@ public:  	//water distortion texture (refraction)  	LLRenderTarget				mWaterDis; -    LLRenderTarget				mBake; +    static const U32 MAX_BAKE_WIDTH;  	//texture for making the glow  	LLRenderTarget				mGlow[3]; @@ -1012,6 +1013,7 @@ public:  	static F32 CameraFNumber;  	static F32 CameraFocalLength;  	static F32 CameraFieldOfView; +	static S32 RenderLocalLightCount;  	static F32 RenderShadowNoise;  	static F32 RenderShadowBlurSize;  	static F32 RenderSSAOScale; | 
