diff options
Diffstat (limited to 'indra/newview/llvlcomposition.cpp')
-rw-r--r-- | indra/newview/llvlcomposition.cpp | 423 |
1 files changed, 12 insertions, 411 deletions
diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index ba255f2b24..077e6e6cb1 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -312,12 +312,23 @@ bool LLTerrainMaterials::makeMaterialsReady(bool boost, bool strict) return one_ready; } +LLViewerTexture* LLTerrainMaterials::getPaintMap() +{ + return mPaintMap.get(); +} + +void LLTerrainMaterials::setPaintMap(LLViewerTexture* paint_map) +{ + llassert(!paint_map || mPaintType == TERRAIN_PAINT_TYPE_PBR_PAINTMAP); + mPaintMap = paint_map; +} + // Boost the texture loading priority // Return true when ready to use (i.e. texture is sufficiently loaded) // static bool LLTerrainMaterials::makeTextureReady(LLPointer<LLViewerFetchedTexture>& tex, bool boost) { - llassert(tex); + //llassert(tex); ??? maybe ok ??? if (!tex) { return false; } if (tex->getDiscardLevel() < 0) @@ -571,416 +582,6 @@ bool LLVLComposition::generateComposition() return LLTerrainMaterials::generateMaterials(); } -namespace -{ - void prepare_fallback_image(LLImageRaw* raw_image) - { - raw_image->resize(BASE_SIZE, BASE_SIZE, 4); - raw_image->fill(LLColor4U::white); - } - - // Check if the raw image is loaded for this texture at a discard - // level the minimap can use, and if not then try to get it loaded. - bool prepare_raw_image(LLPointer<LLImageRaw>& raw_image, bool emissive, LLViewerFetchedTexture* tex, bool& delete_raw_post) - { - if (!tex) - { - if (!emissive) - { - prepare_fallback_image(raw_image); - } - else - { - llassert(!raw_image); - raw_image = nullptr; - } - return true; - } - if (raw_image) - { - // Callback already initiated - if (raw_image->getDataSize() > 0) - { - // Callback finished - delete_raw_post = true; - return true; - } - else - { - return false; - } - } - - raw_image = new LLImageRaw(); - - S32 ddiscard = 0; - { - S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight()); - while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL) - { - ddiscard++; - min_dim /= 2; - } - } - - struct PendingImage - { - LLImageRaw* mRawImage; - S32 mDesiredDiscard; - LLUUID mTextureId; - PendingImage(LLImageRaw* raw_image, S32 ddiscard, const LLUUID& texture_id) - : mRawImage(raw_image) - , mDesiredDiscard(ddiscard) - , mTextureId(texture_id) - { - mRawImage->ref(); - } - ~PendingImage() - { - mRawImage->unref(); - } - }; - PendingImage* pending_image = new PendingImage(raw_image, ddiscard, tex->getID()); - - loaded_callback_func cb = [](bool success, LLViewerFetchedTexture * src_vi, LLImageRaw * src, LLImageRaw * src_aux, S32 discard_level, bool is_final, void* userdata) { - PendingImage* pending = (PendingImage*)userdata; - // Owning LLVLComposition still exists - - // Assume mRawImage only used by single LLVLComposition for now - const bool in_use_by_composition = pending->mRawImage->getNumRefs() > 1; - llassert(pending->mRawImage->getNumRefs()); - llassert(pending->mRawImage->getNumRefs() <= 2); - const bool needs_data = !pending->mRawImage->getDataSize(); - if (in_use_by_composition && needs_data) - { - if (success && pending->mDesiredDiscard == discard_level) - { - pending->mRawImage->resize(BASE_SIZE, BASE_SIZE, src->getComponents()); - pending->mRawImage->copyScaled(src); - } - else if (is_final) - { - prepare_fallback_image(pending->mRawImage); - } - } - - if (is_final) { delete pending; } - }; - tex->setLoadedCallback(cb, ddiscard, true, false, pending_image, nullptr); - tex->forceToSaveRawImage(ddiscard); - - return false; - } -}; - -bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, - const F32 width, const F32 height) -{ - LL_PROFILE_ZONE_SCOPED - llassert(mSurfacep); - llassert(x >= 0.f); - llassert(y >= 0.f); - - /////////////////////////// - // - // Generate raw data arrays for surface textures - // - // - - // These have already been validated by generateComposition. - U8* st_data[ASSET_COUNT]; - S32 st_data_size[ASSET_COUNT]; // for debugging - - const bool use_textures = getMaterialType() != LLTerrainMaterials::Type::PBR; - if (use_textures) - { - if (!makeTexturesReady(true, true)) { return false; } - } - else - { - if (!makeMaterialsReady(true, true)) { return false; } - } - - for (S32 i = 0; i < ASSET_COUNT; i++) - { - if (mRawImages[i].isNull()) - { - // 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; - bool has_alpha; - 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; - has_alpha = false; - llassert(tex); - } - else - { - LLPointer<LLFetchedGLTFMaterial>& mat = mDetailRenderMaterials[i]; - tex = mat->mBaseColorTexture; - tex_emissive = mat->mEmissiveTexture; - base_color_factor = LLColor3(mat->mBaseColor); - // *HACK: Treat alpha as black - base_color_factor *= (mat->mBaseColor.mV[VW]); - emissive_factor = mat->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); - has_alpha = mat->mAlphaMode != LLGLTFMaterial::ALPHA_MODE_OPAQUE; - } - - if (!tex) { tex = LLViewerFetchedTexture::sWhiteImagep; } - - bool delete_raw_post = false; - bool delete_raw_post_emissive = false; - if (!prepare_raw_image(mRawImagesBaseColor[i], false, tex, delete_raw_post)) { return false; } - if (tex_emissive && !prepare_raw_image(mRawImagesEmissive[i], true, tex_emissive, delete_raw_post_emissive)) { return false; } - // tex_emissive can be null, and then will be ignored - - // In the simplest case, the minimap image is just the base color. - // This will be replaced if we need to do any tinting/compositing. - mRawImages[i] = mRawImagesBaseColor[i]; - - // *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 - // 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 = mRawImagesEmissive[i]; - if (has_emissive_factor || - tex_emissive->getWidth(tex_emissive->getRawImageLevel()) != BASE_SIZE || - tex_emissive->getHeight(tex_emissive->getRawImageLevel()) != 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(mRawImagesEmissive[i]); - if (has_emissive_factor) - { - newraw_emissive->tint(emissive_factor); - } - raw_emissive = newraw_emissive; - } - } - if (has_base_color_factor || - raw_emissive || - has_alpha || - tex->getWidth(tex->getRawImageLevel()) != BASE_SIZE || - tex->getHeight(tex->getRawImageLevel()) != BASE_SIZE || - tex->getComponents() != 3) - { - LLPointer<LLImageRaw> newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3); - if (has_alpha) - { - // Approximate the water underneath terrain alpha with solid water color - newraw->clear( - MAX_WATER_COLOR.mV[VX], - MAX_WATER_COLOR.mV[VY], - MAX_WATER_COLOR.mV[VZ], - 255); - } - newraw->composite(mRawImagesBaseColor[i]); - if (has_base_color_factor) - { - newraw->tint(base_color_factor); - } - // Apply emissive texture - if (raw_emissive) - { - newraw->addEmissive(raw_emissive); - } - - mRawImages[i] = newraw; // deletes old - } - - if (delete_raw_post) - { - tex->destroyRawImage(); - } - if (delete_raw_post_emissive) - { - tex_emissive->destroyRawImage(); - } - - // Remove intermediary image references - mRawImagesBaseColor[i] = nullptr; - mRawImagesEmissive[i] = nullptr; - } - st_data[i] = mRawImages[i]->getData(); - st_data_size[i] = mRawImages[i]->getDataSize(); - } - - /////////////////////////////////////// - // - // Generate and clamp x/y bounding box. - // - // - - S32 x_begin, y_begin, x_end, y_end; - x_begin = (S32)(x * mScaleInv); - y_begin = (S32)(y * mScaleInv); - x_end = ll_round( (x + width) * mScaleInv ); - y_end = ll_round( (y + width) * mScaleInv ); - - if (x_end > mWidth) - { - llassert(false); - x_end = mWidth; - } - if (y_end > mWidth) - { - llassert(false); - y_end = mWidth; - } - - - /////////////////////////////////////////// - // - // Generate target texture information, stride ratios. - // - // - - LLViewerTexture *texturep; - U32 tex_width, tex_height, tex_comps; - U32 tex_stride; - F32 tex_x_scalef, tex_y_scalef; - S32 tex_x_begin, tex_y_begin, tex_x_end, tex_y_end; - F32 tex_x_ratiof, tex_y_ratiof; - - texturep = mSurfacep->getSTexture(); - tex_width = texturep->getWidth(); - tex_height = texturep->getHeight(); - tex_comps = texturep->getComponents(); - tex_stride = tex_width * tex_comps; - - U32 st_comps = 3; - U32 st_width = BASE_SIZE; - U32 st_height = BASE_SIZE; - - if (tex_comps != st_comps) - { - llassert(false); - return false; - } - - tex_x_scalef = (F32)tex_width / (F32)mWidth; - tex_y_scalef = (F32)tex_height / (F32)mWidth; - tex_x_begin = (S32)((F32)x_begin * tex_x_scalef); - tex_y_begin = (S32)((F32)y_begin * tex_y_scalef); - tex_x_end = (S32)((F32)x_end * tex_x_scalef); - tex_y_end = (S32)((F32)y_end * tex_y_scalef); - - tex_x_ratiof = (F32)mWidth*mScale / (F32)tex_width; - tex_y_ratiof = (F32)mWidth*mScale / (F32)tex_height; - - LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps); - U8 *rawp = raw->getData(); - - F32 st_x_stride, st_y_stride; - st_x_stride = ((F32)st_width / (F32)mTexScaleX)*((F32)mWidth / (F32)tex_width); - st_y_stride = ((F32)st_height / (F32)mTexScaleY)*((F32)mWidth / (F32)tex_height); - - llassert(st_x_stride > 0.f); - llassert(st_y_stride > 0.f); - //////////////////////////////// - // - // Iterate through the target texture, striding through the - // subtextures and interpolating appropriately. - // - // - - F32 sti, stj; - S32 st_offset; - sti = (tex_x_begin * st_x_stride) - st_width*(llfloor((tex_x_begin * st_x_stride)/st_width)); - stj = (tex_y_begin * st_y_stride) - st_height*(llfloor((tex_y_begin * st_y_stride)/st_height)); - - st_offset = (llfloor(stj * st_width) + llfloor(sti)) * st_comps; - for (S32 j = tex_y_begin; j < tex_y_end; j++) - { - U32 offset = j * tex_stride + tex_x_begin * tex_comps; - sti = (tex_x_begin * st_x_stride) - st_width*((U32)(tex_x_begin * st_x_stride)/st_width); - for (S32 i = tex_x_begin; i < tex_x_end; i++) - { - S32 tex0, tex1; - F32 composition = getValueScaled(i*tex_x_ratiof, j*tex_y_ratiof); - - tex0 = llfloor( composition ); - tex0 = llclamp(tex0, 0, 3); - composition -= tex0; - tex1 = tex0 + 1; - tex1 = llclamp(tex1, 0, 3); - - st_offset = (lltrunc(sti) + lltrunc(stj)*st_width) * st_comps; - for (U32 k = 0; k < tex_comps; k++) - { - // Linearly interpolate based on composition. - if (st_offset >= st_data_size[tex0] || st_offset >= st_data_size[tex1]) - { - // SJB: This shouldn't be happening, but does... Rounding error? - //LL_WARNS() << "offset 0 [" << tex0 << "] =" << st_offset << " >= size=" << st_data_size[tex0] << LL_ENDL; - //LL_WARNS() << "offset 1 [" << tex1 << "] =" << st_offset << " >= size=" << st_data_size[tex1] << LL_ENDL; - } - else - { - F32 a = *(st_data[tex0] + st_offset); - F32 b = *(st_data[tex1] + st_offset); - rawp[ offset ] = (U8)lltrunc( a + composition * (b - a) ); - } - offset++; - st_offset++; - } - - sti += st_x_stride; - if (sti >= st_width) - { - sti -= st_width; - } - } - - stj += st_y_stride; - if (stj >= st_height) - { - stj -= st_height; - } - } - - if (!texturep->hasGLTexture()) - { - texturep->createGLTexture(0, raw); - } - texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin); - - // Un-boost detail textures (will get re-boosted if rendering in high detail) - for (S32 i = 0; i < ASSET_COUNT; i++) - { - unboost_minimap_texture(mDetailTextures[i]); - } - - // Un-boost textures for each detail material (will get re-boosted if rendering in high detail) - for (S32 i = 0; i < ASSET_COUNT; i++) - { - unboost_minimap_material(mDetailMaterials[i]); - } - - return true; -} - F32 LLVLComposition::getStartHeight(S32 corner) { return mStartHeight[corner]; |