summaryrefslogtreecommitdiff
path: root/indra/newview/llfetchedgltfmaterial.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llfetchedgltfmaterial.cpp')
-rw-r--r--indra/newview/llfetchedgltfmaterial.cpp308
1 files changed, 308 insertions, 0 deletions
diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp
new file mode 100644
index 0000000000..46b9dffae9
--- /dev/null
+++ b/indra/newview/llfetchedgltfmaterial.cpp
@@ -0,0 +1,308 @@
+/**
+ * @file llfetchedgltfmaterial.cpp
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, 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 "llfetchedgltfmaterial.h"
+
+#include "llviewertexturelist.h"
+#include "llavatarappearancedefines.h"
+#include "llviewerobject.h"
+#include "llselectmgr.h"
+#include "llshadermgr.h"
+#include "pipeline.h"
+
+LLFetchedGLTFMaterial::LLFetchedGLTFMaterial()
+ : LLGLTFMaterial()
+ , mExpectedFlusTime(0.f)
+ , mActive(true)
+ , mFetching(false)
+{
+
+}
+
+LLFetchedGLTFMaterial::~LLFetchedGLTFMaterial()
+{
+
+}
+
+LLFetchedGLTFMaterial& LLFetchedGLTFMaterial::operator=(const LLFetchedGLTFMaterial& rhs)
+{
+ LLGLTFMaterial::operator =(rhs);
+
+ mBaseColorTexture = rhs.mBaseColorTexture;
+ mNormalTexture = rhs.mNormalTexture;
+ mMetallicRoughnessTexture = rhs.mMetallicRoughnessTexture;
+ mEmissiveTexture = rhs.mEmissiveTexture;
+
+ return *this;
+}
+
+void LLFetchedGLTFMaterial::bind(LLViewerTexture* media_tex)
+{
+ // glTF 2.0 Specification 3.9.4. Alpha Coverage
+ // mAlphaCutoff is only valid for LLGLTFMaterial::ALPHA_MODE_MASK
+ F32 min_alpha = -1.0;
+
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+
+ // override emissive and base color textures with media tex if present
+ LLViewerTexture* baseColorTex = media_tex ? media_tex : mBaseColorTexture;
+ LLViewerTexture* emissiveTex = media_tex ? media_tex : mEmissiveTexture;
+
+ if (!LLPipeline::sShadowRender || (mAlphaMode == LLGLTFMaterial::ALPHA_MODE_MASK))
+ {
+ if (mAlphaMode == LLGLTFMaterial::ALPHA_MODE_MASK)
+ {
+ // dividing the alpha cutoff by transparency here allows the shader to compare against
+ // the alpha value of the texture without needing the transparency value
+ min_alpha = mAlphaCutoff/mBaseColor.mV[3];
+ }
+ shader->uniform1f(LLShaderMgr::MINIMUM_ALPHA, min_alpha);
+ }
+
+ if (baseColorTex != nullptr)
+ {
+ shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, baseColorTex);
+ }
+ else
+ {
+ shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, LLViewerFetchedTexture::sWhiteImagep);
+ }
+
+ F32 base_color_packed[8];
+ mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].getPacked(base_color_packed);
+ shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, (F32*)base_color_packed);
+
+ if (!LLPipeline::sShadowRender)
+ {
+ if (mNormalTexture.notNull() && mNormalTexture->getDiscardLevel() <= 4)
+ {
+ shader->bindTexture(LLShaderMgr::BUMP_MAP, mNormalTexture);
+ }
+ else
+ {
+ shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);
+ }
+
+ if (mMetallicRoughnessTexture.notNull())
+ {
+ shader->bindTexture(LLShaderMgr::SPECULAR_MAP, mMetallicRoughnessTexture); // PBR linear packed Occlusion, Roughness, Metal.
+ }
+ else
+ {
+ shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep);
+ }
+
+ if (emissiveTex != nullptr)
+ {
+ shader->bindTexture(LLShaderMgr::EMISSIVE_MAP, emissiveTex); // PBR sRGB Emissive
+ }
+ else
+ {
+ shader->bindTexture(LLShaderMgr::EMISSIVE_MAP, LLViewerFetchedTexture::sWhiteImagep);
+ }
+
+ // NOTE: base color factor is baked into vertex stream
+
+ shader->uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, mRoughnessFactor);
+ shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, mMetallicFactor);
+ shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, mEmissiveColor.mV);
+
+ F32 normal_packed[8];
+ mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed);
+ shader->uniform4fv(LLShaderMgr::TEXTURE_NORMAL_TRANSFORM, 2, (F32*)normal_packed);
+
+ F32 metallic_roughness_packed[8];
+ mTextureTransform[GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].getPacked(metallic_roughness_packed);
+ shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, 2, (F32*)metallic_roughness_packed);
+
+ F32 emissive_packed[8];
+ mTextureTransform[GLTF_TEXTURE_INFO_EMISSIVE].getPacked(emissive_packed);
+ shader->uniform4fv(LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM, 2, (F32*)emissive_packed);
+ }
+
+}
+
+LLViewerFetchedTexture* fetch_texture(const LLUUID& id)
+{
+ LLViewerFetchedTexture* img = nullptr;
+ if (id.notNull())
+ {
+ img = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ img->addTextureStats(64.f * 64.f, TRUE);
+ }
+ return img;
+};
+
+bool LLFetchedGLTFMaterial::replaceLocalTexture(const LLUUID& tracking_id, const LLUUID& old_id, const LLUUID& new_id)
+{
+ bool res = false;
+ if (mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] == old_id)
+ {
+ mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] = new_id;
+ mBaseColorTexture = fetch_texture(new_id);
+ res = true;
+ }
+ if (mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] == old_id)
+ {
+ mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] = new_id;
+ mNormalTexture = fetch_texture(new_id);
+ res = true;
+ }
+ if (mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] == old_id)
+ {
+ mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] = new_id;
+ mMetallicRoughnessTexture = fetch_texture(new_id);
+ res = true;
+ }
+ if (mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] == old_id)
+ {
+ mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] = new_id;
+ mEmissiveTexture = fetch_texture(new_id);
+ res = true;
+ }
+
+ for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
+ {
+ if (mTextureId[i] == new_id)
+ {
+ res = true;
+ }
+ }
+
+ if (res)
+ {
+ mTrackingIdToLocalTexture[tracking_id] = new_id;
+ }
+ else
+ {
+ mTrackingIdToLocalTexture.erase(tracking_id);
+ }
+
+ return res;
+}
+
+void LLFetchedGLTFMaterial::addTextureEntry(LLTextureEntry* te)
+{
+ mTextureEntires.insert(te);
+}
+
+void LLFetchedGLTFMaterial::removeTextureEntry(LLTextureEntry* te)
+{
+ mTextureEntires.erase(te);
+}
+
+void LLFetchedGLTFMaterial::updateTextureTracking()
+{
+ for (local_tex_map_t::value_type &val : mTrackingIdToLocalTexture)
+ {
+ LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(val.first, this);
+ }
+}
+
+void LLFetchedGLTFMaterial::materialBegin()
+{
+ llassert(!mFetching);
+ mFetching = true;
+}
+
+void LLFetchedGLTFMaterial::onMaterialComplete(std::function<void()> material_complete)
+{
+ if (!material_complete) { return; }
+
+ if (!mFetching)
+ {
+ material_complete();
+ return;
+ }
+
+ materialCompleteCallbacks.push_back(material_complete);
+}
+
+void LLFetchedGLTFMaterial::materialComplete()
+{
+ llassert(mFetching);
+ mFetching = false;
+
+ for (std::function<void()> material_complete : materialCompleteCallbacks)
+ {
+ material_complete();
+ }
+ 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;
+}