diff options
| author | Cosmic Linden <cosmic@lindenlab.com> | 2023-10-13 10:39:03 -0700 | 
|---|---|---|
| committer | Cosmic Linden <cosmic@lindenlab.com> | 2023-10-13 10:39:03 -0700 | 
| commit | ab3b4edac7809008cfed6d1b77e5a4debb22c88e (patch) | |
| tree | 312c2d96a9b803c04ea5ddac64b1a2586b45d8f4 /indra | |
| parent | 7f7431891661668b898e03345c8023b4bbd0d9d9 (diff) | |
DRTVWR-592: Fix broken minimap loading, improve minimap view of PBR materials (still not accurate, but better...)
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llimage/llimage.cpp | 53 | ||||
| -rw-r--r-- | indra/llimage/llimage.h | 6 | ||||
| -rw-r--r-- | indra/newview/llfetchedgltfmaterial.cpp | 5 | ||||
| -rw-r--r-- | indra/newview/llfetchedgltfmaterial.h | 9 | ||||
| -rw-r--r-- | indra/newview/llgltfmateriallist.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llsurfacepatch.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llvlcomposition.cpp | 125 | ||||
| -rw-r--r-- | indra/newview/llvlcomposition.h | 2 | 
8 files changed, 179 insertions, 27 deletions
| diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index a96b6601bd..acfc254b65 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -31,6 +31,7 @@  #include "llmath.h"  #include "v4coloru.h" +#include "v3color.h"  #include "llimagebmp.h"  #include "llimagetga.h" @@ -1026,6 +1027,34 @@ bool LLImageRaw::optimizeAwayAlpha()      return false;  } +bool LLImageRaw::makeAlpha() +{ +    if (getComponents() == 3) +    { +        U8* data = getData(); +        U32 pixels = getWidth() * getHeight(); + +        // alpha channel doesn't exist, make a new copy of data with alpha channel +        U8* new_data = (U8*) ll_aligned_malloc_16(getWidth() * getHeight() * 4); + +        for (U32 i = 0; i < pixels; ++i) +        { +            U32 di = i * 4; +            U32 si = i * 3; +            for (U32 j = 0; j < 3; ++j) +            { +                new_data[di+j] = data[si+j]; +            } +        } + +        setDataAndSize(new_data, getWidth(), getHeight(), 3); + +        return true; +    } + +    return false; +} +  void LLImageRaw::expandToPowerOfTwo(S32 max_dim, bool scale_image)  {  	// Find new sizes @@ -1268,6 +1297,30 @@ void LLImageRaw::fill( const LLColor4U& color )  	}  } +void LLImageRaw::tint( const LLColor3& color ) +{ +	llassert( (3 == getComponents()) || (4 == getComponents()) ); +	if (isBufferInvalid()) +	{ +		LL_WARNS() << "Invalid image buffer" << LL_ENDL; +		return; +	} + +	S32 pixels = getWidth() * getHeight(); +    const S32 components = getComponents(); +    U8* data = getData(); +    for( S32 i = 0; i < pixels; i++ ) +    { +        const float c0 = data[0] * color.mV[0]; +        const float c1 = data[1] * color.mV[1]; +        const float c2 = data[2] * color.mV[2]; +        data[0] = llclamp((U8)c0, 0, 255); +        data[1] = llclamp((U8)c1, 0, 255); +        data[2] = llclamp((U8)c2, 0, 255); +        data += components; +    } +} +  LLPointer<LLImageRaw> LLImageRaw::duplicate()  {  	if(getNumRefs() < 2) diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 8f9e1b3c54..77b5f0b7bc 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -71,6 +71,7 @@ const S32 HTTP_PACKET_SIZE = 1496;  class LLImageFormatted;  class LLImageRaw;  class LLColor4U; +class LLColor3;  typedef enum e_image_codec  { @@ -212,6 +213,8 @@ public:      // if the alpha channel is all 100% opaque, delete it      // returns true if alpha channel was deleted      bool optimizeAwayAlpha(); +    // Create an alpha channel if this image doesn't have one +    bool makeAlpha();      static S32 biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);      static S32 expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE); @@ -225,6 +228,9 @@ public:  	// Fill the buffer with a constant color  	void fill( const LLColor4U& color ); +    // Multiply this raw image by the given color +    void tint( const LLColor3& color ); +  	// Copy operations  	//duplicate this raw image if refCount > 1. diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index 1fb3577dd7..c870d4778c 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -35,8 +35,6 @@  LLFetchedGLTFMaterial::LLFetchedGLTFMaterial()      : LLGLTFMaterial()      , mExpectedFlusTime(0.f) -    , mActive(true) -    , mFetching(false)  {  } @@ -163,10 +161,11 @@ void LLFetchedGLTFMaterial::onMaterialComplete(std::function<void()> material_co      materialCompleteCallbacks.push_back(material_complete);  } -void LLFetchedGLTFMaterial::materialComplete() +void LLFetchedGLTFMaterial::materialComplete(bool success)  {      llassert(mFetching);      mFetching = false; +    mFetchSuccess = success;      for (std::function<void()> material_complete : materialCompleteCallbacks)      { diff --git a/indra/newview/llfetchedgltfmaterial.h b/indra/newview/llfetchedgltfmaterial.h index ce4d33a213..c5f6f6ca94 100644 --- a/indra/newview/llfetchedgltfmaterial.h +++ b/indra/newview/llfetchedgltfmaterial.h @@ -49,7 +49,7 @@ public:      void bind(LLViewerTexture* media_tex = nullptr);      bool isFetching() const { return mFetching; } -    bool isLoaded() const { return !mFetching; } +    bool isLoaded() const { return !mFetching && mFetchSuccess; }      // Textures used for fetching/rendering      LLPointer<LLViewerFetchedTexture> mBaseColorTexture; @@ -61,11 +61,12 @@ protected:      // Lifetime management      void materialBegin(); -    void materialComplete(); +    void materialComplete(bool success);      F64 mExpectedFlusTime; // since epoch in seconds -    bool mActive; -    bool mFetching; +    bool mActive = true; +    bool mFetching = false; +    bool mFetchSuccess = false;      std::vector<std::function<void()>> materialCompleteCallbacks;  }; diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index 99a052f719..7994515b61 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -549,7 +549,7 @@ void LLGLTFMaterialList::onAssetLoadComplete(const LLUUID& id, LLAssetType::ETyp      if (status != LL_ERR_NOERR)      {          LL_WARNS("GLTF") << "Error getting material asset data: " << LLAssetStorage::getErrorString(status) << " (" << status << ")" << LL_ENDL; -        asset_data->mMaterial->materialComplete(); +        asset_data->mMaterial->materialComplete(false);          delete asset_data;      }      else @@ -634,7 +634,7 @@ void LLGLTFMaterialList::onAssetLoadComplete(const LLUUID& id, LLAssetType::ETyp                  LL_DEBUGS("GLTF") << "Failed to get material " << id << LL_ENDL;              } -            asset_data->mMaterial->materialComplete(); +            asset_data->mMaterial->materialComplete(true);              delete asset_data;          }); diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index b4daf71ce2..a6370e9ec2 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -741,7 +741,7 @@ void LLSurfacePatch::updateGL()  	updateCompositionStats();  	F32 tex_patch_size = meters_per_grid*grids_per_patch_edge; -	if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY], +	if (comp->generateMinimapTileLand((F32)origin_region[VX], (F32)origin_region[VY],  							  tex_patch_size, tex_patch_size))  	{  		mSTexUpdate = FALSE; diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index fa19bcae87..f645023217 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -129,26 +129,28 @@ LLTerrainMaterials::Type LLTerrainMaterials::getMaterialType()  BOOL LLTerrainMaterials::texturesReady(BOOL boost)  { +    BOOL ready = TRUE;  	for (S32 i = 0; i < ASSET_COUNT; i++)  	{          if (!textureReady(mDetailTextures[i], boost))          { -            return FALSE; +            ready = FALSE;          }  	} -    return TRUE; +    return ready;  }  BOOL LLTerrainMaterials::materialsReady(BOOL boost)  { +    BOOL ready = TRUE;  	for (S32 i = 0; i < ASSET_COUNT; i++)  	{          if (!materialReady(mDetailMaterials[i], mMaterialTexturesSet[i], boost))          { -            return FALSE; +            ready = FALSE;          }      } -    return TRUE; +    return ready;  }  // Boost the texture loading priority @@ -188,6 +190,10 @@ BOOL LLTerrainMaterials::textureReady(LLPointer<LLViewerFetchedTexture>& tex, BO          }          return FALSE;      } +    if (tex->getComponents() == 0) +    { +        return FALSE; +    }      return TRUE;  } @@ -381,8 +387,7 @@ BOOL LLVLComposition::generateComposition()      return LLTerrainMaterials::generateMaterials();  } -// *TODO: Re-evaluate usefulness of this function in the PBR case. There is currently a hack here to treat the material base color like a legacy terrain texture, but I'm not sure if that's useful. -BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, +BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,  									  const F32 width, const F32 height)  {  	LL_PROFILE_ZONE_SCOPED @@ -390,8 +395,6 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,  	llassert(x >= 0.f);  	llassert(y >= 0.f); -	LLTimer gen_timer; -  	///////////////////////////  	//  	// Generate raw data arrays for surface textures @@ -403,6 +406,17 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,  	S32 st_data_size[ASSET_COUNT]; // for debugging      const bool use_textures = getMaterialType() != LLTerrainMaterials::Type::PBR; +    // *TODO: Remove this as it is reduandant computation (first and foremost +    // because getMaterialType() does something similar, but also... shouldn't +    // the textures/materials already be loaded by now?) +    if (use_textures) +    { +        if (!texturesReady()) { return FALSE; } +    } +    else +    { +        if (!materialsReady()) { return FALSE; } +    }  	for (S32 i = 0; i < ASSET_COUNT; i++)  	{ @@ -410,16 +424,37 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,  		{  			// Read back a raw image for this discard level, if it exists              LLViewerFetchedTexture* tex; +            LLViewerFetchedTexture* tex_emissive; // Can be null +            bool has_base_color_factor; +            bool has_emissive_factor; +            LLColor3 base_color_factor; +            LLColor3 emissive_factor;              if (use_textures)              {                  tex = mDetailTextures[i]; +                tex_emissive = nullptr; +                has_base_color_factor = false; +                has_emissive_factor = false; +                llassert(tex);              }              else              {                  tex = mDetailMaterials[i]->mBaseColorTexture; +                tex_emissive = mDetailMaterials[i]->mEmissiveTexture; +                base_color_factor = LLColor3(mDetailMaterials[i]->mBaseColor); +                // *HACK: Treat alpha as black +                base_color_factor *= (mDetailMaterials[i]->mBaseColor.mV[VW]); +                emissive_factor = mDetailMaterials[i]->mEmissiveColor; +                has_base_color_factor = (base_color_factor.mV[VX] != 1.f || +                                         base_color_factor.mV[VY] != 1.f || +                                         base_color_factor.mV[VZ] != 1.f); +                has_emissive_factor = (emissive_factor.mV[VX] != 1.f || +                                       emissive_factor.mV[VY] != 1.f || +                                       emissive_factor.mV[VZ] != 1.f);              } -			// *TODO: Why are terrain textures (not terrain materials) not loading? (that is why there is a getComponents() check here) -			if (!tex || tex->getComponents() == 0) { tex = LLViewerFetchedTexture::sWhiteImagep; } + +            if (!tex) { tex = LLViewerFetchedTexture::sWhiteImagep; } +            // tex_emissive can be null, and then will be ignored  			S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight());  			S32 ddiscard = 0; @@ -430,8 +465,9 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,  			}  			BOOL delete_raw = (tex->reloadRawImage(ddiscard) != NULL) ; -			if(tex->getRawImageLevel() != ddiscard)//raw iamge is not ready, will enter here again later. +			if(tex->getRawImageLevel() != ddiscard)  			{ +                // Raw image is not ready, will enter here again later.                  if (tex->getFetchPriority() <= 0.0f && !tex->hasSavedRawImage())                  {                      tex->setBoostLevel(LLGLTexture::BOOST_MAP); @@ -442,21 +478,78 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,  				{  					tex->destroyRawImage() ;  				} -				LL_DEBUGS("Terrain") << "cached raw data for terrain detail texture is not ready yet: " << tex->getID() << " Discard: " << ddiscard << LL_ENDL;  				return FALSE;  			} +            if (tex_emissive) +            { +                if(tex_emissive->getRawImageLevel() != ddiscard) +                { +                    // Raw image is not ready, will enter here again later. +                    if (tex_emissive->getFetchPriority() <= 0.0f && !tex_emissive->hasSavedRawImage()) +                    { +                        tex_emissive->setBoostLevel(LLGLTexture::BOOST_MAP); +                        tex_emissive->forceToRefetchTexture(ddiscard); +                    } + +                    if(delete_raw) +                    { +                        tex_emissive->destroyRawImage() ; +                    } +                    return FALSE; +                } +            }  			mRawImages[i] = tex->getRawImage() ;  			if(delete_raw)  			{  				tex->destroyRawImage() ;  			} -			if (tex->getWidth(ddiscard) != BASE_SIZE || + +            // *TODO: This isn't quite right for PBR: +            // 1) It does not convert the color images from SRGB to linear +            // before mixing (which will always require copying the image). +            // 2) It mixes emissive and base color before mixing terrain +            // materials, but it should be the other way around +            // 3) The composite function used to put emissive into base color +            // is not an alpha blend. +            // Long-term, we should consider a method that is more +            // maintainable. Shaders, perhaps? Bake shaders to textures? +            LLPointer<LLImageRaw> raw_emissive; +            if (tex_emissive) +            { +                raw_emissive = tex_emissive->getRawImage(); +                if (has_emissive_factor || +                    tex_emissive->getWidth(ddiscard) != BASE_SIZE || +                    tex_emissive->getHeight(ddiscard) != BASE_SIZE || +                    tex_emissive->getComponents() != 4) +                { +                    LLPointer<LLImageRaw> newraw_emissive = new LLImageRaw(BASE_SIZE, BASE_SIZE, 4); +                    // Copy RGB, leave alpha alone (set to opaque by default) +                    newraw_emissive->copy(mRawImages[i]); +                    if (has_emissive_factor) +                    { +                        newraw_emissive->tint(emissive_factor); +                    } +                    raw_emissive = newraw_emissive; // deletes old +                } +            } +			if (has_base_color_factor || +                raw_emissive || +                tex->getWidth(ddiscard) != BASE_SIZE ||  				tex->getHeight(ddiscard) != BASE_SIZE ||  				tex->getComponents() != 3)  			{  				LLPointer<LLImageRaw> newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3);  				newraw->composite(mRawImages[i]); +                if (has_base_color_factor) +                { +                    newraw->tint(base_color_factor); +                } +                // Apply emissive texture +                if (raw_emissive) +                { +                    newraw->composite(raw_emissive); +                }  				mRawImages[i] = newraw; // deletes old  			}  		} @@ -478,12 +571,12 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,  	if (x_end > mWidth)  	{ -		LL_WARNS("Terrain") << "x end > width" << LL_ENDL; +        llassert(false);  		x_end = mWidth;  	}  	if (y_end > mWidth)  	{ -		LL_WARNS("Terrain") << "y end > width" << LL_ENDL; +        llassert(false);  		y_end = mWidth;  	} @@ -513,7 +606,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,  	if (tex_comps != st_comps)  	{ -		LL_WARNS("Terrain") << "Base texture comps != input texture comps" << LL_ENDL; +        llassert(false);  		return FALSE;  	} diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index 882c3d89b2..d59c0f95bb 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -87,7 +87,7 @@ public:  	BOOL generateHeights(const F32 x, const F32 y, const F32 width, const F32 height);  	BOOL generateComposition();  	// Generate texture from composition values. -	BOOL generateTexture(const F32 x, const F32 y, const F32 width, const F32 height);		 +	BOOL generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height);		  	// Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc.  	// So we need to compress heights into this range. | 
