diff --git a/autobuild.xml b/autobuild.xml index 3394878f08..4d13b5d7e6 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -1381,65 +1381,17 @@ glext platforms - darwin64 + common archive hash - c5e9a59c7cf03c88a5cb4ab0a9c21091 + 4f8dc85863fec36e8d872c31f4abcd05 url - https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/99835/880141/glext-68-darwin64-571812.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101480/892402/glext-68-common-572829.tar.bz2 name - darwin64 - - linux - - archive - - hash - da432b959ccd920adca1030ad7f1b6cf - url - http://3p.firestormviewer.org/glext-68-linux-180871251.tar.bz2 - - name - linux - - linux64 - - archive - - hash - 12b2d643a013be8297bbbe37743abe94 - url - http://3p.firestormviewer.org/glext-68-linux64-180841554.tar.bz2 - - name - linux64 - - windows - - archive - - hash - 6a311615bce59b01cf73ee65012a9b38 - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54951/511711/glext-68-windows-538965.tar.bz2 - - name - windows - - windows64 - - archive - - hash - daf619dab1cf7518af6532b18800c4b0 - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54924/511490/glext-68-windows64-538965.tar.bz2 - - name - windows64 + common version @@ -3773,6 +3725,62 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors version 3.0.16.565299 + vulkan_gltf + + canonical_repo + https://bitbucket.org/lindenlab/3p-vulkan-gltf-pbr + copyright + Copyright (c) 2018 Sascha Willems + description + Vulkan GLTF Sample Implementation + license + Copyright (c) 2018 Sascha Willems + license_file + LICENSES/vulkan_gltf.txt + name + vulkan_gltf + platforms + + darwin64 + + archive + + hash + 8cff2060843db3db788511ee34a8e8cc + url + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101316/891509/vulkan_gltf-1-darwin64-572743.tar.bz2 + + name + darwin64 + + windows + + archive + + hash + 58eea384be49ba756ce9c5e66669540b + url + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101318/891520/vulkan_gltf-1-windows-572743.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 79b6a11622c2f83cfc2b7cd1fafb867b + url + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101319/891521/vulkan_gltf-1-windows64-572743.tar.bz2 + + name + windows64 + + + version + 1 + xmlrpc-epi copyright diff --git a/indra/cmake/GLEXT.cmake b/indra/cmake/GLEXT.cmake index 9fd3923bfd..a749644202 100644 --- a/indra/cmake/GLEXT.cmake +++ b/indra/cmake/GLEXT.cmake @@ -2,9 +2,7 @@ include(Prebuilt) if (NOT USESYSTEMLIBS) - if (WINDOWS OR LINUX) - use_prebuilt_binary(glext) - endif (WINDOWS OR LINUX) + use_prebuilt_binary(glext) use_prebuilt_binary(glh_linear) set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) endif (NOT USESYSTEMLIBS) diff --git a/indra/cmake/LLRender.cmake b/indra/cmake/LLRender.cmake index 868922451f..2d9d3725ad 100644 --- a/indra/cmake/LLRender.cmake +++ b/indra/cmake/LLRender.cmake @@ -3,10 +3,12 @@ include(Variables) include(FreeType) include(GLH) +include(GLEXT) set(LLRENDER_INCLUDE_DIRS ${LIBS_OPEN_DIR}/llrender ${GLH_INCLUDE_DIR} + ${GLEXT_INCLUDE_DIR} ) if (BUILD_HEADLESS) diff --git a/indra/cmake/VulkanGltf.cmake b/indra/cmake/VulkanGltf.cmake new file mode 100644 index 0000000000..94541d5307 --- /dev/null +++ b/indra/cmake/VulkanGltf.cmake @@ -0,0 +1,5 @@ +# -*- cmake -*- +include(Prebuilt) + +use_prebuilt_binary(vulkan_gltf) + diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 0bb1f1a0fd..f08cc18036 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -96,7 +96,7 @@ LLAssetDictionary::LLAssetDictionary() addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false)); addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false)); addEntry(LLAssetType::AT_SETTINGS, new AssetEntry("SETTINGS", "settings", "settings blob", true, true, true)); - addEntry(LLAssetType::AT_MATERIAL, new AssetEntry("MATERIAL", "material", "render material", true, true, true)); + addEntry(LLAssetType::AT_MATERIAL, new AssetEntry("MATERIAL", "material", "render material", true, true, true)); addEntry(LLAssetType::AT_UNKNOWN, new AssetEntry("UNKNOWN", "invalid", NULL, false, false, false)); addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE)); diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 455bc654f9..bb5e224a7b 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -834,6 +834,15 @@ LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components) ++sRawImageCount; } +LLImageRaw::LLImageRaw(const U8* data, U16 width, U16 height, S8 components) + : LLImageBase() +{ + if (allocateDataSize(width, height, components)) + { + memcpy(getData(), data, width * height * components); + } +} + LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy) : LLImageBase() { diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index e23c40e0d5..5f4d74c191 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -191,6 +191,7 @@ protected: public: LLImageRaw(); LLImageRaw(U16 width, U16 height, S8 components); + LLImageRaw(const U8* data, U16 width, U16 height, S8 components); LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy = false); // Construct using createFromFile (used by tools) //LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false); diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index a40bf67abb..8da73e8c38 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -87,6 +87,7 @@ LLInventoryDictionary::LLInventoryDictionary() addEntry(LLInventoryType::IT_WIDGET, new InventoryEntry("widget", "widget", 1, LLAssetType::AT_WIDGET)); addEntry(LLInventoryType::IT_PERSON, new InventoryEntry("person", "person", 1, LLAssetType::AT_PERSON)); addEntry(LLInventoryType::IT_SETTINGS, new InventoryEntry("settings", "settings", 1, LLAssetType::AT_SETTINGS)); + addEntry(LLInventoryType::IT_MATERIAL, new InventoryEntry("material", "render material", 1, LLAssetType::AT_MATERIAL)); } diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp index 7f901c41ed..335cb52deb 100644 --- a/indra/llinventory/llsettingssky.cpp +++ b/indra/llinventory/llsettingssky.cpp @@ -131,6 +131,8 @@ const std::string LLSettingsSky::SETTING_SKY_MOISTURE_LEVEL("moisture_level"); const std::string LLSettingsSky::SETTING_SKY_DROPLET_RADIUS("droplet_radius"); const std::string LLSettingsSky::SETTING_SKY_ICE_LEVEL("ice_level"); +const std::string LLSettingsSky::SETTING_REFLECTION_PROBE_AMBIANCE("reflection_probe_ambiance"); + const LLUUID LLSettingsSky::DEFAULT_ASSET_ID("3ae23978-ac82-bcf3-a9cb-ba6e52dcb9ad"); static const LLUUID DEFAULT_SUN_ID("32bfbcea-24b1-fb9d-1ef9-48a28a63730f"); // dataserver @@ -634,6 +636,9 @@ LLSettingsSky::validation_list_t LLSettingsSky::validationList() validation.push_back(Validator(SETTING_SKY_ICE_LEVEL, false, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f))))); + validation.push_back(Validator(SETTING_REFLECTION_PROBE_AMBIANCE, false, LLSD::TypeReal, + boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f))))); + validation.push_back(Validator(SETTING_RAYLEIGH_CONFIG, true, LLSD::TypeArray, &validateRayleighLayers)); validation.push_back(Validator(SETTING_ABSORPTION_CONFIG, true, LLSD::TypeArray, &validateAbsorptionLayers)); validation.push_back(Validator(SETTING_MIE_CONFIG, true, LLSD::TypeArray, &validateMieLayers)); @@ -759,6 +764,8 @@ LLSD LLSettingsSky::defaults(const LLSettingsBase::TrackPosition& position) dfltsetting[SETTING_SKY_DROPLET_RADIUS] = 800.0f; dfltsetting[SETTING_SKY_ICE_LEVEL] = 0.0f; + dfltsetting[SETTING_REFLECTION_PROBE_AMBIANCE] = 0.0f; + dfltsetting[SETTING_RAYLEIGH_CONFIG] = rayleighConfigDefault(); dfltsetting[SETTING_MIE_CONFIG] = mieConfigDefault(); dfltsetting[SETTING_ABSORPTION_CONFIG] = absorptionConfigDefault(); @@ -1136,6 +1143,11 @@ void LLSettingsSky::setSkyIceLevel(F32 ice_level) setValue(SETTING_SKY_ICE_LEVEL, ice_level); } +void LLSettingsSky::setReflectionProbeAmbiance(F32 ambiance) +{ + setValue(SETTING_REFLECTION_PROBE_AMBIANCE, ambiance); +} + void LLSettingsSky::setAmbientColor(const LLColor3 &val) { mSettings[SETTING_LEGACY_HAZE][SETTING_AMBIENT] = val.getValue(); @@ -1424,6 +1436,11 @@ F32 LLSettingsSky::getSkyIceLevel() const return mSettings[SETTING_SKY_ICE_LEVEL].asReal(); } +F32 LLSettingsSky::getReflectionProbeAmbiance() const +{ + return mSettings[SETTING_REFLECTION_PROBE_AMBIANCE].asReal(); +} + F32 LLSettingsSky::getSkyBottomRadius() const { return mSettings[SETTING_SKY_BOTTOM_RADIUS].asReal(); diff --git a/indra/llinventory/llsettingssky.h b/indra/llinventory/llsettingssky.h index fa9326f006..715d31518b 100644 --- a/indra/llinventory/llsettingssky.h +++ b/indra/llinventory/llsettingssky.h @@ -97,6 +97,8 @@ public: static const std::string SETTING_SKY_DROPLET_RADIUS; static const std::string SETTING_SKY_ICE_LEVEL; + static const std::string SETTING_REFLECTION_PROBE_AMBIANCE; + static const std::string SETTING_LEGACY_HAZE; static const LLUUID DEFAULT_ASSET_ID; @@ -131,6 +133,8 @@ public: F32 getSkyDropletRadius() const; F32 getSkyIceLevel() const; + F32 getReflectionProbeAmbiance() const; + // Return first (only) profile layer represented in LLSD LLSD getRayleighConfig() const; LLSD getMieConfig() const; @@ -159,6 +163,8 @@ public: void setSkyDropletRadius(F32 radius); void setSkyIceLevel(F32 ice_level); + void setReflectionProbeAmbiance(F32 ambiance); + //--------------------------------------------------------------------- LLColor3 getAmbientColor() const; void setAmbientColor(const LLColor3 &val); diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index b63bda7b0b..3426b12c14 100644 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -58,6 +58,7 @@ set(llprimitive_HEADER_FILES CMakeLists.txt lldaeloader.h llgltfloader.h + llgltfmaterial.h legacy_object_types.h llmaterial.h llmaterialid.h diff --git a/indra/llprimitive/llgltfloader.cpp b/indra/llprimitive/llgltfloader.cpp index 3ec11f70c6..6041c9c273 100644 --- a/indra/llprimitive/llgltfloader.cpp +++ b/indra/llprimitive/llgltfloader.cpp @@ -24,7 +24,7 @@ * $/LicenseInfo$ */ -#include "LLGLTFLoader.h" +#include "llgltfloader.h" // Import & define single-header gltf import/export lib #define TINYGLTF_IMPLEMENTATION @@ -43,7 +43,7 @@ // Additionally, disable inclusion of STB header files entirely with // TINYGLTF_NO_INCLUDE_STB_IMAGE // TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE -#include "tinygltf\tiny_gltf.h" +#include "tinygltf/tiny_gltf.h" // TODO: includes inherited from dae loader. Validate / prune @@ -68,7 +68,6 @@ static const std::string lod_suffix[LLModel::NUM_LODS] = "_PHYS", }; -const U32 LIMIT_MATERIALS_OUTPUT = 12; LLGLTFLoader::LLGLTFLoader(std::string filename, S32 lod, @@ -94,7 +93,6 @@ LLGLTFLoader::LLGLTFLoader(std::string filename, jointsFromNodes, jointAliasMap, maxJointsPerMesh ), - mGeneratedModelLimit(modelLimit), //mPreprocessGLTF(preprocess), mMeshesLoaded(false), mMaterialsLoaded(false) diff --git a/indra/llprimitive/llgltfloader.h b/indra/llprimitive/llgltfloader.h index 91389b5845..b4d6ca1940 100644 --- a/indra/llprimitive/llgltfloader.h +++ b/indra/llprimitive/llgltfloader.h @@ -158,7 +158,6 @@ private: bool populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh); LLUUID imageBufferToTextureUUID(const gltf_texture& tex); - U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels // bool mPreprocessGLTF; /* Below inherited from dae loader - unknown if/how useful here diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h new file mode 100644 index 0000000000..2df4883a3c --- /dev/null +++ b/indra/llprimitive/llgltfmaterial.h @@ -0,0 +1,89 @@ +/** + * @file llgltfmaterial.h + * @brief Material definition + * + * $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$ + */ + +#pragma once + +#include "llrefcount.h" +#include "v4color.h" +#include "v3color.h" +#include "lluuid.h" +#include "llmd5.h" + +class LLGLTFMaterial : public LLRefCount +{ +public: + + enum AlphaMode + { + ALPHA_MODE_OPAQUE = 0, + ALPHA_MODE_BLEND, + ALPHA_MODE_MASK + }; + + LLUUID mAlbedoId; + LLUUID mNormalId; + LLUUID mMetallicRoughnessId; + LLUUID mEmissiveId; + + LLColor4 mAlbedoColor = LLColor4(1,1,1,1); + LLColor3 mEmissiveColor = LLColor3(0,0,0); + + F32 mMetallicFactor = 0.f; + F32 mRoughnessFactor = 0.f; + bool mDoubleSided = false; + AlphaMode mAlphaMode = ALPHA_MODE_OPAQUE; + + // get a UUID based on a hash of this LLGLTFMaterial + LLUUID getHash() const + { + LLMD5 md5; + md5.update((unsigned char*) this, sizeof(this)); + LLUUID id; + md5.raw_digest(id.mData); + return id; + } + + // set mAlphaMode from string. + // Anything otherthan "MASK" or "BLEND" sets mAlphaMode to ALPHA_MODE_OPAQUE + void setAlphaMode(const std::string& mode) + { + if (mode == "MASK") + { + mAlphaMode = ALPHA_MODE_MASK; + } + else if (mode == "BLEND") + { + mAlphaMode = ALPHA_MODE_BLEND; + } + else + { + mAlphaMode = ALPHA_MODE_OPAQUE; + } + } +}; + + + diff --git a/indra/llprimitive/llmaterialid.cpp b/indra/llprimitive/llmaterialid.cpp index f88a607c4f..340a83801c 100644 --- a/indra/llprimitive/llmaterialid.cpp +++ b/indra/llprimitive/llmaterialid.cpp @@ -155,6 +155,13 @@ std::string LLMaterialID::asString() const return materialIDString; } +LLUUID LLMaterialID::asUUID() const +{ + LLUUID ret; + memcpy(ret.mData, mID, MATERIAL_ID_SIZE); + return ret; +} + std::ostream& operator<<(std::ostream& s, const LLMaterialID &material_id) { s << material_id.asString(); diff --git a/indra/llprimitive/llmaterialid.h b/indra/llprimitive/llmaterialid.h index ee663f8f99..e6165dfc91 100644 --- a/indra/llprimitive/llmaterialid.h +++ b/indra/llprimitive/llmaterialid.h @@ -61,6 +61,7 @@ public: LLSD asLLSD() const; std::string asString() const; + LLUUID asUUID() const; friend std::ostream& operator<<(std::ostream& s, const LLMaterialID &material_id); diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h index dc2e201044..1549b2ce87 100644 --- a/indra/llprimitive/lltextureentry.h +++ b/indra/llprimitive/lltextureentry.h @@ -32,6 +32,7 @@ #include "llsd.h" #include "llmaterialid.h" #include "llmaterial.h" +#include "llgltfmaterial.h" // These bits are used while unpacking TEM messages to tell which aspects of // the texture entry changed. @@ -134,6 +135,10 @@ public: S32 setMaterialID(const LLMaterialID& pMaterialID); S32 setMaterialParams(const LLMaterialPtr pMaterialParams); + void setGLTFMaterial(LLGLTFMaterial* material) { mGLTFMaterial = material; } + LLGLTFMaterial* getGLTFMaterial() { return mGLTFMaterial; } + + virtual const LLUUID &getID() const { return mID; } const LLColor4 &getColor() const { return mColor; } const F32 getAlpha() const { return mColor.mV[VALPHA]; } @@ -162,6 +167,8 @@ public: const LLMaterialID& getMaterialID() const { return mMaterialID; }; const LLMaterialPtr getMaterialParams() const { return mMaterial; }; + LLGLTFMaterial* getGLTFMaterial() const { return mGLTFMaterial; } + // *NOTE: it is possible for hasMedia() to return true, but getMediaData() to return NULL. // CONVERSELY, it is also possible for hasMedia() to return false, but getMediaData() // to NOT return NULL. @@ -219,6 +226,7 @@ protected: bool mMaterialUpdatePending; LLMaterialID mMaterialID; LLMaterialPtr mMaterial; + LLPointer mGLTFMaterial; // if present, ignore mMaterial // Note the media data is not sent via the same message structure as the rest of the TE LLMediaEntry* mMediaEntry; // The media data for the face diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp index e4081c1154..438d92cdba 100644 --- a/indra/llrender/llcubemaparray.cpp +++ b/indra/llrender/llcubemaparray.cpp @@ -53,6 +53,50 @@ GLenum LLCubeMapArray::sTargets[6] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB }; +LLVector3 LLCubeMapArray::sLookVecs[6] = +{ + LLVector3(1, 0, 0), + LLVector3(-1, 0, 0), + LLVector3(0, 1, 0), + LLVector3(0, -1, 0), + LLVector3(0, 0, 1), + LLVector3(0, 0, -1) +}; + +LLVector3 LLCubeMapArray::sUpVecs[6] = +{ + LLVector3(0, -1, 0), + LLVector3(0, -1, 0), + LLVector3(0, 0, 1), + LLVector3(0, 0, -1), + LLVector3(0, -1, 0), + LLVector3(0, -1, 0) +}; + +LLVector3 LLCubeMapArray::sClipToCubeLookVecs[6] = +{ + LLVector3(0, 0, -1), //GOOD + LLVector3(0, 0, 1), //GOOD + + LLVector3(1, 0, 0), // GOOD + LLVector3(1, 0, 0), // GOOD + + LLVector3(1, 0, 0), + LLVector3(-1, 0, 0), +}; + +LLVector3 LLCubeMapArray::sClipToCubeUpVecs[6] = +{ + LLVector3(-1, 0, 0), //GOOD + LLVector3(1, 0, 0), //GOOD + + LLVector3(0, 1, 0), // GOOD + LLVector3(0, -1, 0), // GOOD + + LLVector3(0, 0, -1), + LLVector3(0, 0, 1) +}; + LLCubeMapArray::LLCubeMapArray() : mTextureStage(0) { diff --git a/indra/llrender/llcubemaparray.h b/indra/llrender/llcubemaparray.h index 52e21f1dda..cbc0692afb 100644 --- a/indra/llrender/llcubemaparray.h +++ b/indra/llrender/llcubemaparray.h @@ -32,13 +32,20 @@ class LLVector3; -// Environment map hack! class LLCubeMapArray : public LLRefCount { public: LLCubeMapArray(); static GLenum sTargets[6]; + + // look and up vectors for each cube face (agent space) + static LLVector3 sLookVecs[6]; + static LLVector3 sUpVecs[6]; + + // look and up vectors for each cube face (clip space) + static LLVector3 sClipToCubeLookVecs[6]; + static LLVector3 sClipToCubeUpVecs[6]; // allocate a cube map array // res - resolution of each cube face diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index c3d86af649..16b93a1a44 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -455,6 +455,7 @@ LLGLManager::LLGLManager() : mHasAnisotropic(FALSE), mHasARBEnvCombine(FALSE), mHasCubeMap(FALSE), + mHasCubeMapArray(FALSE), mHasDebugOutput(FALSE), mIsAMD(FALSE), @@ -1074,6 +1075,7 @@ void LLGLManager::initExtensions() mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts); mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE; mHasUniformBufferObject = ExtensionExists("GL_ARB_uniform_buffer_object", gGLHExts.mSysExts); + mHasCubeMapArray = ExtensionExists("GL_ARB_texture_cube_map_array", gGLHExts.mSysExts); #if !LL_DARWIN mHasPointParameters = ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); #endif @@ -1186,6 +1188,10 @@ void LLGLManager::initExtensions() { LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_draw_buffers" << LL_ENDL; } + if (!mHasCubeMapArray) + { + LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_texture_cube_map_array" << LL_ENDL; + } // Disable certain things due to known bugs if (mIsIntel && mHasMipMapGeneration) diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 7ecc998428..08b1cffca5 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -124,6 +124,7 @@ public: BOOL mHasAnisotropic; BOOL mHasARBEnvCombine; BOOL mHasCubeMap; + BOOL mHasCubeMapArray; BOOL mHasDebugOutput; BOOL mHassRGBTexture; BOOL mHassRGBFramebuffer; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index 4cdf1593a7..863b4f3a6f 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -577,11 +577,13 @@ extern PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding; //---------------------------------------------------------------------------- // LL_DARWIN +#define GL_GLEXT_LEGACY #include #include #define GL_EXT_separate_specular_color 1 -#include +#define GL_GLEXT_PROTOTYPES +#include "GL/glext.h" #include "GL/glh_extensions.h" diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 35424d716e..f0dace6287 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -460,7 +460,7 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, #ifdef GL_INTERLEAVED_ATTRIBS if (varying_count > 0 && varyings) { - glTransformFeedbackVaryings(mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS); + glTransformFeedbackVaryings((GLuint64) mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS); } #endif diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 15705d0ac3..4cb546fea1 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -793,7 +793,14 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade extra_code_text[extra_code_count++] = strdup("#define shadow2DRect(a,b) vec2(texture(a,b))\n"); } } - + + // Use alpha float to store bit flags + // See: C++: addDeferredAttachment(), shader: frag_data[2] + extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_SKIP_ATMOS 0.0 \n"); // atmo kill + extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_ATMOS 0.25\n"); // bit 0 + extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_PBR 0.50\n"); // bit 1 + extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (mod(floor(norm.w/flag),2.0)>0.5)\n"); + if (defines) { for (std::unordered_map::iterator iter = defines->begin(); iter != defines->end(); ++iter) @@ -1169,14 +1176,19 @@ void LLShaderMgr::initAttribsAndUniforms() llassert(mReservedUniforms.size() == LLShaderMgr::PROJECTOR_AMBIENT_LOD+1); mReservedUniforms.push_back("color"); - + mReservedUniforms.push_back("emissiveColor"); + mReservedUniforms.push_back("metallicFactor"); + mReservedUniforms.push_back("roughnessFactor"); + mReservedUniforms.push_back("diffuseMap"); mReservedUniforms.push_back("altDiffuseMap"); mReservedUniforms.push_back("specularMap"); + mReservedUniforms.push_back("emissiveMap"); mReservedUniforms.push_back("bumpMap"); mReservedUniforms.push_back("bumpMap2"); mReservedUniforms.push_back("environmentMap"); mReservedUniforms.push_back("reflectionProbes"); + mReservedUniforms.push_back("irradianceProbes"); mReservedUniforms.push_back("cloud_noise_texture"); mReservedUniforms.push_back("cloud_noise_texture_next"); mReservedUniforms.push_back("fullbright"); @@ -1223,6 +1235,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("minimum_alpha"); mReservedUniforms.push_back("emissive_brightness"); + // Deferred mReservedUniforms.push_back("shadow_matrix"); mReservedUniforms.push_back("env_mat"); mReservedUniforms.push_back("shadow_clip"); @@ -1247,8 +1260,9 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("depth_cutoff"); mReservedUniforms.push_back("norm_cutoff"); mReservedUniforms.push_back("shadow_target_width"); + mReservedUniforms.push_back("view_dir"); // DEFERRED_VIEW_DIR - llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH+1); + llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_VIEW_DIR+1); mReservedUniforms.push_back("tc_scale"); mReservedUniforms.push_back("rcp_screen_res"); @@ -1361,6 +1375,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("halo_map"); mReservedUniforms.push_back("moon_brightness"); mReservedUniforms.push_back("cloud_variance"); + mReservedUniforms.push_back("reflection_probe_ambiance"); mReservedUniforms.push_back("sh_input_r"); mReservedUniforms.push_back("sh_input_g"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 24c29e31b4..a9517b39ba 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -74,13 +74,18 @@ public: PROJECTOR_LOD, // "proj_lod" PROJECTOR_AMBIENT_LOD, // "proj_ambient_lod" DIFFUSE_COLOR, // "color" + EMISSIVE_COLOR, // "emissiveColor" + METALLIC_FACTOR, // "metallicFactor" + ROUGHNESS_FACTOR, // "roughnessFactor" DIFFUSE_MAP, // "diffuseMap" ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap" SPECULAR_MAP, // "specularMap" + EMISSIVE_MAP, // "emissiveMap" BUMP_MAP, // "bumpMap" BUMP_MAP2, // "bumpMap2" ENVIRONMENT_MAP, // "environmentMap" REFLECTION_PROBES, // "reflectionProbes" + IRRADIANCE_PROBES, // "irradianceProbes" CLOUD_NOISE_MAP, // "cloud_noise_texture" CLOUD_NOISE_MAP_NEXT, // "cloud_noise_texture_next" FULLBRIGHT, // "fullbright" @@ -143,6 +148,7 @@ public: DEFERRED_DEPTH_CUTOFF, // "depth_cutoff" DEFERRED_NORM_CUTOFF, // "norm_cutoff" DEFERRED_SHADOW_TARGET_WIDTH, // "shadow_target_width" + DEFERRED_VIEW_DIR, // "view_dir" FXAA_TC_SCALE, // "tc_scale" FXAA_RCP_SCREEN_RES, // "rcp_screen_res" @@ -257,6 +263,7 @@ public: CLOUD_VARIANCE, // "cloud_variance" + REFLECTION_PROBE_AMBIANCE, // "reflection_probe_ambiance" SH_INPUT_L1R, // "sh_input_r" SH_INPUT_L1G, // "sh_input_g" SH_INPUT_L1B, // "sh_input_b" diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0ff1250f0d..d588f778d5 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -56,6 +56,7 @@ include(UnixInstall) include(ViewerMiscLibs) #include(ViewerManager) # Remove VMP include(VisualLeakDetector) +include(VulkanGltf) include(URIPARSER) include(Growl) include(ColladaDom) @@ -519,6 +520,7 @@ set(viewer_SOURCE_FILES llmaniptranslate.cpp llmarketplacefunctions.cpp llmarketplacenotifications.cpp + llmaterialeditor.cpp llmaterialmgr.cpp llmediactrl.cpp llmediadataclient.cpp @@ -1300,6 +1302,7 @@ set(viewer_HEADER_FILES llmaniptranslate.h llmarketplacefunctions.h llmarketplacenotifications.h + llmaterialeditor.h llmaterialmgr.h llmediactrl.h llmediadataclient.h diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index 60d83cc623..22b3bd1463 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -52,6 +52,6 @@ void main() frag_data[0] = vec4(diff.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index b5677a07ee..749ec3a6ac 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -64,5 +64,5 @@ void main() frag_data[1] = vertex_color.aaaa; // spec //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested vec3 nvn = normalize(tnorm); - frag_data[2] = vec4(encode_normal(nvn), vertex_color.a, 0.0); + frag_data[2] = vec4(encode_normal(nvn), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl index ae1ac5de7f..348e0f5228 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl @@ -124,7 +124,7 @@ void main() /// Gamma correct for WL (soft clip effect). frag_data[0] = vec4(color.rgb, alpha1); frag_data[1] = vec4(0.0,0.0,0.0,0.0); - frag_data[2] = vec4(0,0,0,1); + frag_data[2] = vec4(0,0,0,GBUFFER_FLAG_SKIP_ATMOS); gl_FragDepth = 0.99995f; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl index b328ee9483..3bf148502c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl @@ -53,6 +53,6 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); // spec vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl index fc5c86b4d6..e15239b59d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl @@ -52,5 +52,5 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl index 1bb8eb8bd0..b0ff233414 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl @@ -52,6 +52,6 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); // spec vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 8319e61242..b2d2e2fa71 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -46,6 +46,6 @@ void main() frag_data[1] = vertex_color.aaaa; // spec //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, 0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl index ccd1df84f9..b4bc114dd5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl @@ -48,5 +48,5 @@ void main() frag_data[0] = vec4(col, 0.0); frag_data[1] = vec4(spec, vertex_color.a); // spec vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, 0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/highlightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/highlightF.glsl index 90566393d2..75f914cb02 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/highlightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/highlightF.glsl @@ -38,5 +38,5 @@ void main() { frag_data[0] = color*texture2D(diffuseMap, vary_texcoord0.xy); frag_data[1] = vec4(0.0); - frag_data[2] = vec4(0.0, 1.0, 0.0, 1.0); + frag_data[2] = vec4(0.0, 1.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl index a58cc3d12d..67f4c59c3f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -56,5 +56,5 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = spec; - frag_data[2] = norm; + frag_data[2] = norm; // TODO: Should .w be set? } diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl index 02d83925ea..6f087632a5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl @@ -277,10 +277,10 @@ void main() vec4 final_specular = spec; #ifdef HAS_SPECULAR_MAP - vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, 0.0); + vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, GBUFFER_FLAG_HAS_ATMOS); final_specular.a = specular_color.a * norm.a; #else - vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, 0.0); + vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, GBUFFER_FLAG_HAS_ATMOS); final_specular.a = specular_color.a; #endif @@ -444,10 +444,10 @@ void main() #else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer - // deferred path - frag_data[0] = final_color; //gbuffer is sRGB + // deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl + frag_data[0] = final_color; // gbuffer is sRGB frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent. - frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity. + frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog) #endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl index 35068899ee..a513d60388 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl @@ -66,7 +66,7 @@ void main() frag_data[0] = vec4(c.rgb, c.a); frag_data[1] = vec4(0.0); - frag_data[2] = vec4(0.0f); + frag_data[2] = vec4(0.0, 0.0, 0.0, GBUFFER_FLAG_HAS_ATMOS); gl_FragDepth = 0.999985f; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl index cb9cc4958a..e4be88926f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl @@ -25,85 +25,120 @@ /*[EXTRA_CODE_HERE]*/ -#define DEBUG_BASIC 1 -#define DEBUG_COLOR 0 -#define DEBUG_NORMAL 0 +#define DEBUG_BASIC 0 +#define DEBUG_VERTEX 0 +#define DEBUG_NORMAL_RAW 0 // Output packed normal map "as is" to diffuse +#define DEBUG_NORMAL_OUT 0 // Output unpacked normal to diffuse #define DEBUG_POSITION 0 -#define DEBUG_REFLECT_VEC 0 -#define DEBUG_REFLECT_COLOR 0 + +uniform sampler2D diffuseMap; //always in sRGB space + +uniform float metallicFactor; +uniform float roughnessFactor; +uniform vec3 emissiveColor; + +#ifdef HAS_NORMAL_MAP + uniform sampler2D bumpMap; +#endif + +#ifdef HAS_EMISSIVE_MAP + uniform sampler2D emissiveMap; +#endif #ifdef HAS_SPECULAR_MAP -uniform sampler2D specularMap; + uniform sampler2D specularMap; // Packed: Occlusion, Metal, Roughness #endif + uniform samplerCube environmentMap; uniform mat3 env_mat; #ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_data[3]; +out vec4 frag_data[4]; #else #define frag_data gl_FragData #endif VARYING vec3 vary_position; -VARYING vec3 vary_normal; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +#ifdef HAS_NORMAL_MAP +VARYING vec3 vary_normal; +VARYING vec3 vary_mat0; +VARYING vec3 vary_mat1; +VARYING vec3 vary_mat2; +VARYING vec2 vary_texcoord1; +#endif + #ifdef HAS_SPECULAR_MAP -VARYING vec2 vary_texcoord2; + VARYING vec2 vary_texcoord2; #endif vec2 encode_normal(vec3 n); vec3 linear_to_srgb(vec3 c); -struct PBR -{ - float LdotH; // Light and Half - float NdotL; // Normal and Light - float NdotH; // Normal and Half - float VdotH; // View and Half -}; - const float M_PI = 3.141592653589793; void main() { - vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb; +// IF .mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; +// vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb; +// else + vec3 col = vertex_color.rgb * texture2D(diffuseMap, vary_texcoord0.xy).rgb; + +#ifdef HAS_NORMAL_MAP + vec4 norm = texture2D(bumpMap, vary_texcoord1.xy); + norm.xyz = norm.xyz * 2 - 1; + + vec3 tnorm = vec3(dot(norm.xyz,vary_mat0), + dot(norm.xyz,vary_mat1), + dot(norm.xyz,vary_mat2)); +#else + vec4 norm = vec4(0,0,0,1.0); +// vec3 tnorm = vary_normal; + vec3 tnorm = vec3(0,0,1); +#endif + + tnorm = normalize(tnorm.xyz); -//#ifdef HAS_SPECULAR_MAP -//#else - vec4 norm = vec4(0,0,0,1.0); - vec3 tnorm = vary_normal; -//#endif norm.xyz = normalize(tnorm.xyz); + // RGB = Occlusion, Roughness, Metal + // default values + // occlusion ? + // roughness 1.0 + // metal 1.0 +#ifdef HAS_SPECULAR_MAP + vec3 spec = texture2D(specularMap, vary_texcoord2.xy).rgb; +#else + vec3 spec = vec3(1,1,1); +#endif + + spec.g *= roughnessFactor; + spec.b *= metallicFactor; - vec3 spec; - spec.rgb = vec3(vertex_color.a); + vec3 emissive = emissiveColor; +#ifdef HAS_EMISSIVE_MAP + emissive *= texture2D(emissiveMap, vary_texcoord0.xy).rgb; +#endif - vec3 pos = vary_position; - vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); - vec3 env_vec = env_mat * refnormpersp; - vec3 reflected_color = textureCube(environmentMap, env_vec).rgb; #if DEBUG_BASIC - col.rgb = vec3( 1, 0, 1 ); // DEBUG + col.rgb = vec3( 1, 0, 1 ); #endif -#if DEBUG_COLOR +#if DEBUG_VERTEX col.rgb = vertex_color.rgb; #endif -#if DEBUG_NORMAL +#if DEBUG_NORMAL_RAW + col.rgb = texture2D(bumpMap, vary_texcoord1.xy).rgb; +#endif +#if DEBUG_NORMAL_OUT col.rgb = vary_normal; #endif #if DEBUG_POSITION col.rgb = vary_position.xyz; #endif -#if DEBUG_REFLECT_VEC - col.rgb = refnormpersp; -#endif -#if DEBUG_REFLECT_COLOR - col.rgb = reflected_color; -#endif - frag_data[0] = vec4(col, 0.0); - frag_data[1] = vec4(spec, vertex_color.a); // spec - frag_data[2] = vec4(encode_normal(norm.xyz), vertex_color.a, 0.0); + frag_data[0] = vec4(col, 0.0); // Diffuse + frag_data[1] = vec4(spec.rgb, vertex_color.a); // Occlusion, Roughness, Metal + frag_data[2] = vec4(encode_normal(tnorm), vertex_color.a, GBUFFER_FLAG_HAS_PBR); // normal, environment intensity, flags + frag_data[3] = vec4(emissive,0); // Emissive } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl index 72bae808e0..a2606ed771 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl @@ -23,32 +23,122 @@ * $/LicenseInfo$ */ -uniform mat3 normal_matrix; -uniform mat4 texture_matrix0; +#define DIFFUSE_ALPHA_MODE_IGNORE 0 +#define DIFFUSE_ALPHA_MODE_BLEND 1 +#define DIFFUSE_ALPHA_MODE_MASK 2 +#define DIFFUSE_ALPHA_MODE_EMISSIVE 3 + +#ifdef HAS_SKIN uniform mat4 modelview_matrix; +uniform mat4 projection_matrix; +mat4 getObjectSkinnedTransform(); +#else +uniform mat3 normal_matrix; uniform mat4 modelview_projection_matrix; +#endif + +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) + +#if !defined(HAS_SKIN) +uniform mat4 modelview_matrix; +#endif + +VARYING vec3 vary_position; + +#endif + +uniform mat4 texture_matrix0; ATTRIBUTE vec3 position; ATTRIBUTE vec4 diffuse_color; ATTRIBUTE vec3 normal; ATTRIBUTE vec2 texcoord0; -VARYING vec3 vary_position; + +#ifdef HAS_NORMAL_MAP +ATTRIBUTE vec4 tangent; +ATTRIBUTE vec2 texcoord1; + +VARYING vec3 vary_mat0; +VARYING vec3 vary_mat1; +VARYING vec3 vary_mat2; + +VARYING vec2 vary_texcoord1; +#else VARYING vec3 vary_normal; +#endif + +#ifdef HAS_SPECULAR_MAP +ATTRIBUTE vec2 texcoord2; +VARYING vec2 vary_texcoord2; +#endif + VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -void passTextureIndex(); - void main() { - //transform vertex - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); - vary_position = (modelview_matrix * vec4(position.xyz,1.0)).xyz; - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); - passTextureIndex(); - vary_normal = normalize(normal_matrix * normal); + mat = modelview_matrix * mat; - vertex_color = diffuse_color; + vec3 pos = (mat*vec4(position.xyz,1.0)).xyz; + +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) + vary_position = pos; +#endif + + gl_Position = projection_matrix*vec4(pos,1.0); + +#else + //transform vertex + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + +#endif + + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + +#ifdef HAS_NORMAL_MAP + vary_texcoord1 = (texture_matrix0 * vec4(texcoord1,0,1)).xy; +#endif + +#ifdef HAS_SPECULAR_MAP + vary_texcoord2 = (texture_matrix0 * vec4(texcoord2,0,1)).xy; +#endif + +#ifdef HAS_SKIN + vec3 n = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz); +#ifdef HAS_NORMAL_MAP + vec3 t = normalize((mat*vec4(tangent.xyz+position.xyz,1.0)).xyz-pos.xyz); + vec3 b = cross(n, t)*tangent.w; + + vary_mat0 = vec3(t.x, b.x, n.x); + vary_mat1 = vec3(t.y, b.y, n.y); + vary_mat2 = vec3(t.z, b.z, n.z); +#else //HAS_NORMAL_MAP +vary_normal = n; +#endif //HAS_NORMAL_MAP +#else //HAS_SKIN + vec3 n = normalize(normal_matrix * normal); +#ifdef HAS_NORMAL_MAP + vec3 t = normalize(normal_matrix * tangent.xyz); + vec3 b = cross(n,t)*tangent.w; + //vec3 t = cross(b,n) * binormal.w; + + vary_mat0 = vec3(t.x, b.x, n.x); + vary_mat1 = vec3(t.y, b.y, n.y); + vary_mat2 = vec3(t.z, b.z, n.z); +#else //HAS_NORMAL_MAP + vary_normal = n; +#endif //HAS_NORMAL_MAP +#endif //HAS_SKIN + + vertex_color = diffuse_color; + +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) +#if !defined(HAS_SKIN) + vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; +#endif +#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl index 331249dc33..ecb0c43518 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl @@ -57,7 +57,7 @@ void main() /// Gamma correct for WL (soft clip effect). frag_data[0] = vec4(color.rgb, 0.0); frag_data[1] = vec4(0.0,0.0,0.0,0.0); - frag_data[2] = vec4(0.0,0.0,0.0,1.0); //1.0 in norm.w masks off fog + frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_SKIP_ATMOS); //1.0 in norm.w masks off fog gl_FragDepth = 0.99999f; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 5a49a9da3c..c5e7753c09 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -143,7 +143,7 @@ void main() color = mix(color.rgb, reflected_color, envIntensity); } - if (norm.w < 0.5) + if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { color = mix(atmosFragLighting(color, additive, atten), fullbrightAtmosTransportFrag(color, additive, atten), diffuse.a); color = mix(scaleSoftClipFrag(color), fullbrightScaleSoftClip(color), diffuse.a); diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl index bac79a9fdc..ef9cee3fa0 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl @@ -60,7 +60,7 @@ void main() frag_data[0] = col; frag_data[1] = vec4(0.0f); - frag_data[2] = vec4(0.0, 1.0, 0.0, 1.0); + frag_data[2] = vec4(0.0, 1.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS); gl_FragDepth = 0.99995f; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl index b2fa5d8a25..4ab8747629 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl @@ -57,7 +57,7 @@ void main() frag_data[0] = c; frag_data[1] = vec4(0.0f); - frag_data[2] = vec4(0.0, 1.0, 0.0, 1.0); + frag_data[2] = vec4(0.0, 1.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS); gl_FragDepth = 0.999988f; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index 6b6eed9db8..d6c14c48c9 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -63,6 +63,6 @@ void main() frag_data[0] = outColor; frag_data[1] = vec4(0.0,0.0,0.0,-1.0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index 89e354558a..dc0e5b0ce3 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -52,5 +52,5 @@ void main() frag_data[0] = vec4(vertex_color.rgb*col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0); + frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl index 9a5debb3c1..14c337e608 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl @@ -78,5 +78,5 @@ void main() frag_data[0] = vec4(fb.rgb, 1.0); // diffuse frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec - frag_data[2] = vec4(encode_normal(wavef), 0.0, 0.0); // normalxyz, env intens, atmo kill + frag_data[2] = vec4(encode_normal(wavef), 0.0, GBUFFER_FLAG_HAS_ATMOS); // normalxyz, env intens, flags (atmo kill) } diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index a157e9c017..03896f4c51 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -180,5 +180,5 @@ void main() frag_data[1] = vec4(0); // speccolor, spec - frag_data[2] = vec4(encode_normal(screenspacewavef.xyz), 0.05, 0);// normalxy, 0, 0 + frag_data[2] = vec4(encode_normal(screenspacewavef.xyz), 0.05, GBUFFER_FLAG_HAS_ATMOS);// normalxy, env intens, flags (atmo kill) } diff --git a/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl new file mode 100644 index 0000000000..4d91395a1b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl @@ -0,0 +1,100 @@ +/** + * @file irradianceGenF.glsl + * + * $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$ + */ + + +/*[EXTRA_CODE_HERE]*/ + + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +uniform samplerCubeArray reflectionProbes; +uniform int sourceIdx; + +VARYING vec3 vary_dir; + +// ============================================================================================================= +// Parts of this file are (c) 2018 Sascha Willems +// SNIPPED FROM https://github.com/SaschaWillems/Vulkan-glTF-PBR/blob/master/data/shaders/irradiancecube.frag +/* +MIT License + +Copyright (c) 2018 Sascha Willems + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +// ============================================================================================================= + + + +#define PI 3.1415926535897932384626433832795 + +void main() +{ + float deltaPhi = (2.0 * PI) / 11.25; + float deltaTheta = (0.5 * PI) / 4.0; + float mipLevel = 2; + + vec3 N = normalize(vary_dir); + vec3 up = vec3(0.0, 1.0, 0.0); + vec3 right = normalize(cross(up, N)); + up = cross(N, right); + + const float TWO_PI = PI * 2.0; + const float HALF_PI = PI * 0.5; + + vec3 color = vec3(0.0); + uint sampleCount = 0u; + for (float phi = 0.0; phi < TWO_PI; phi += deltaPhi) { + for (float theta = 0.0; theta < HALF_PI; theta += deltaTheta) { + vec3 tempVec = cos(phi) * right + sin(phi) * up; + vec3 sampleVector = cos(theta) * N + sin(theta) * tempVec; + color += textureLod(reflectionProbes, vec4(sampleVector, sourceIdx), mipLevel).rgb * cos(theta) * sin(theta); + sampleCount++; + } + } + frag_color = vec4(PI * color / float(sampleCount), 1.0); +} +// ============================================================================================================= + diff --git a/indra/newview/app_settings/shaders/class1/interface/irradianceGenV.glsl b/indra/newview/app_settings/shaders/class1/interface/irradianceGenV.glsl new file mode 100644 index 0000000000..5190abf17c --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/irradianceGenV.glsl @@ -0,0 +1,38 @@ +/** + * @file irradianceGenV.glsl + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform mat4 modelview_matrix; + +ATTRIBUTE vec3 position; + +VARYING vec3 vary_dir; + +void main() +{ + gl_Position = vec4(position, 1.0); + + vary_dir = vec3(modelview_matrix * vec4(position, 1.0)).xyz; +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl new file mode 100644 index 0000000000..94fedce243 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl @@ -0,0 +1,168 @@ +/** + * @file radianceGenF.glsl + * + * $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$ + */ + + +/*[EXTRA_CODE_HERE]*/ + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +uniform samplerCubeArray reflectionProbes; +uniform int sourceIdx; + +VARYING vec3 vary_dir; + +// ============================================================================================================= +// Parts of this file are (c) 2018 Sascha Willems +// SNIPPED FROM https://github.com/SaschaWillems/Vulkan-glTF-PBR/blob/master/data/shaders/prefilterenvmap.frag +/* +MIT License + +Copyright (c) 2018 Sascha Willems + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +// ============================================================================================================= + + +uniform float roughness; + +uniform float mipLevel; + +const float PI = 3.1415926536; + +// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ +float random(vec2 co) +{ + float a = 12.9898; + float b = 78.233; + float c = 43758.5453; + float dt= dot(co.xy ,vec2(a,b)); + float sn= mod(dt,3.14); + return fract(sin(sn) * c); +} + +vec2 hammersley2d(uint i, uint N) +{ + // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html + uint bits = (i << 16u) | (i >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + float rdi = float(bits) * 2.3283064365386963e-10; + return vec2(float(i) /float(N), rdi); +} + +// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf +vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal) +{ + // Maps a 2D point to a hemisphere with spread based on roughness + float alpha = roughness * roughness; + float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta * cosTheta); + vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); + + // Tangent space + vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangentX = normalize(cross(up, normal)); + vec3 tangentY = normalize(cross(normal, tangentX)); + + // Convert to world Space + return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); +} + +// Normal Distribution function +float D_GGX(float dotNH, float roughness) +{ + float alpha = roughness * roughness; + float alpha2 = alpha * alpha; + float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; + return (alpha2)/(PI * denom*denom); +} + +vec3 prefilterEnvMap(vec3 R, float roughness) +{ + vec3 N = R; + vec3 V = R; + vec3 color = vec3(0.0); + float totalWeight = 0.0; + float envMapDim = 256.0; + int numSamples = 32/max(int(mipLevel), 1); + + for(uint i = 0u; i < numSamples; i++) { + vec2 Xi = hammersley2d(i, numSamples); + vec3 H = importanceSample_GGX(Xi, roughness, N); + vec3 L = 2.0 * dot(V, H) * H - V; + float dotNL = clamp(dot(N, L), 0.0, 1.0); + if(dotNL > 0.0) { + // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/ + + float dotNH = clamp(dot(N, H), 0.0, 1.0); + float dotVH = clamp(dot(V, H), 0.0, 1.0); + + // Probability Distribution Function + float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001; + // Slid angle of current smple + float omegaS = 1.0 / (float(numSamples) * pdf); + // Solid angle of 1 pixel across all cube faces + float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim); + // Biased (+1.0) mip level for better result + //float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f); + color += textureLod(reflectionProbes, vec4(L,sourceIdx), mipLevel).rgb * dotNL; + totalWeight += dotNL; + + } + } + return (color / totalWeight); +} + +void main() +{ + vec3 N = normalize(vary_dir); + frag_color = vec4(prefilterEnvMap(N, roughness), 1.0); +} +// ============================================================================================================= + diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenV.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenV.glsl new file mode 100644 index 0000000000..5f5d9396ff --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenV.glsl @@ -0,0 +1,38 @@ +/** + * @file radianceGenV.glsl + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform mat4 modelview_matrix; + +ATTRIBUTE vec3 position; + +VARYING vec3 vary_dir; + +void main() +{ + gl_Position = vec4(position, 1.0); + + vary_dir = vec3(modelview_matrix * vec4(position, 1.0)).xyz; +} + diff --git a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl index 8c1323ba1a..ab5badf538 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl @@ -473,4 +473,5 @@ void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 no fresnel = min(fresnel+envIntensity, 1.0); reflected_color *= (envIntensity*fresnel)*brighten(spec.rgb); color = mix(color.rgb, reflected_color, envIntensity); - } \ No newline at end of file + } + diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl index 6841a8194f..4379024680 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl @@ -195,5 +195,5 @@ void main() // Gamma correct for WL (soft clip effect). frag_data[0] = vec4(color.rgb, 1.0); frag_data[1] = vec4(0.0, 0.0, 0.0, 0.0); - frag_data[2] = vec4(0.0, 0.0, 0.0, 1.0); // 1.0 in norm.w masks off fog + frag_data[2] = vec4(0.0, 0.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS); // 1.0 in norm.w masks off fog } diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 7700d16007..dfb93c17dc 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -139,7 +139,7 @@ void main() color = mix(color.rgb, reflected_color, envIntensity); } - if (norm.w < 0.5) + if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { color = mix(atmosFragLighting(color, additive, atten), fullbrightAtmosTransportFrag(color, additive, atten), diffuse.a); color = mix(scaleSoftClipFrag(color), fullbrightScaleSoftClip(color), diffuse.a); diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index c5b1937cfb..13369d09fd 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -446,10 +446,10 @@ void main() #else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer - // deferred path - frag_data[0] = final_color; //gbuffer is sRGB + // deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl + frag_data[0] = final_color; // gbuffer is sRGB frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent. - frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity. + frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog) #endif } diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index b3396baeba..83348077d7 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -31,6 +31,7 @@ #define REF_SAMPLE_COUNT 64 //maximum number of samples to consider uniform samplerCubeArray reflectionProbes; +uniform samplerCubeArray irradianceProbes; layout (std140, binding = 1) uniform ReflectionProbes { @@ -308,7 +309,7 @@ vec3 boxIntersect(vec3 origin, vec3 dir, int i) -// Tap a sphere based reflection probe +// Tap a reflection probe // pos - position of pixel // dir - pixel normal // lod - which mip to bias towards (lower is higher res, sharper reflections) @@ -334,9 +335,36 @@ vec3 tapRefMap(vec3 pos, vec3 dir, float lod, vec3 c, float r2, int i) v -= c; v = env_mat * v; { - float min_lod = textureQueryLod(reflectionProbes,v).y; // lower is higher res - return textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), max(min_lod, lod)).rgb; - //return texture(reflectionProbes, vec4(v.xyz, refIndex[i].x)).rgb; + return textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod).rgb; + } +} + +// Tap an irradiance map +// pos - position of pixel +// dir - pixel normal +// c - center of probe +// r2 - radius of probe squared +// i - index of probe +// vi - point at which reflection vector struck the influence volume, in clip space +vec3 tapIrradianceMap(vec3 pos, vec3 dir, vec3 c, float r2, int i) +{ + //lod = max(lod, 1); + // parallax adjustment + + vec3 v; + if (refIndex[i].w < 0) + { + v = boxIntersect(pos, dir, i); + } + else + { + v = sphereIntersect(pos, dir, c, r2); + } + + v -= c; + v = env_mat * v; + { + return texture(irradianceProbes, vec4(v.xyz, refIndex[i].x)).rgb * refParams[i].x; } } @@ -349,7 +377,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight) for (int idx = 0; idx < probeInfluences; ++idx) { int i = probeIndex[idx]; - if (refIndex[i].w < max_priority) + if (abs(refIndex[i].w) < max_priority) { continue; } @@ -370,7 +398,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight) float atten = 1.0-max(d2-r2, 0.0)/(rr-r2); w *= atten; //w *= p; // boost weight based on priority - col += refcol*w*max(minweight, refParams[i].x); + col += refcol*w; wsum += w; } @@ -393,7 +421,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight) float w = 1.0/d2; w *= w; - col += refcol*w*max(minweight, refParams[i].x); + col += refcol*w; wsum += w; } } @@ -407,24 +435,75 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight) return col; } -vec3 sampleProbeAmbient(vec3 pos, vec3 dir, float lod) +vec3 sampleProbeAmbient(vec3 pos, vec3 dir) { - vec3 col = sampleProbes(pos, dir, lod, 0.f); + // modified copy/paste of sampleProbes follows, will likely diverge from sampleProbes further + // as irradiance map mixing is tuned independently of radiance map mixing + float wsum = 0.0; + vec3 col = vec3(0,0,0); + float vd2 = dot(pos,pos); // view distance squared - //desaturate - vec3 hcol = col *0.5; - - col *= 2.0; - col = vec3( - col.r + hcol.g + hcol.b, - col.g + hcol.r + hcol.b, - col.b + hcol.r + hcol.g - ); - - col *= 0.333333; + float minweight = 1.0; + for (int idx = 0; idx < probeInfluences; ++idx) + { + int i = probeIndex[idx]; + if (abs(refIndex[i].w) < max_priority) + { + continue; + } + float r = refSphere[i].w; // radius of sphere volume + float p = float(abs(refIndex[i].w)); // priority + + float rr = r*r; // radius squred + float r1 = r * 0.1; // 75% of radius (outer sphere to start interpolating down) + vec3 delta = pos.xyz-refSphere[i].xyz; + float d2 = dot(delta,delta); + float r2 = r1*r1; + + { + vec3 refcol = tapIrradianceMap(pos, dir, refSphere[i].xyz, rr, i); + + float w = 1.0/d2; + + float atten = 1.0-max(d2-r2, 0.0)/(rr-r2); + w *= atten; + //w *= p; // boost weight based on priority + col += refcol*w; + + wsum += w; + } + } + + if (probeInfluences <= 1) + { //edge-of-scene probe or no probe influence, mix in with embiggened version of probes closest to camera + for (int idx = 0; idx < 8; ++idx) + { + if (refIndex[idx].w < 0) + { // don't fallback to box probes, they are *very* specific + continue; + } + int i = idx; + vec3 delta = pos.xyz-refSphere[i].xyz; + float d2 = dot(delta,delta); + + { + vec3 refcol = tapIrradianceMap(pos, dir, refSphere[i].xyz, d2, i); + + float w = 1.0/d2; + w *= w; + col += refcol*w; + wsum += w; + } + } + } + + if (wsum > 0.0) + { + col *= 1.0/wsum; + } + return col; - } // brighten a color so that at least one component is 1 @@ -450,7 +529,7 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 l vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - ambenv = sampleProbeAmbient(pos, norm, reflection_lods-1); + ambenv = sampleProbeAmbient(pos, norm); if (glossiness > 0.0) { diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 61757882bb..243f1c4498 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -1,5 +1,5 @@ /** - * @file class2/deferred/softenLightF.glsl + * @file class3/deferred/softenLightF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code @@ -23,6 +23,31 @@ * $/LicenseInfo$ */ +#define DEBUG_PBR_PACKORM0 0 // Rough=0, Metal=0 +#define DEBUG_PBR_PACKORM1 0 // Rough=1, Metal=1 +#define DEBUG_PBR_TANGENT1 1 // Tangent = 1,0,0 + +#define DEBUG_PBR_RAW_DIFF 0 // Output: use diffuse in G-Buffer +#define DEBUG_PBR_RAW_SPEC 0 // Output: use spec in G-Buffer +#define DEBUG_PBR_IRRADIANCE 0 // Output: Diffuse Irradiance +#define DEBUG_PBR_DIFFUSE 0 // Output: Radiance Lambertian +#define DEBUG_PBR_ORM 0 // Output: Packed Occlusion Roughness Metal +#define DEBUG_PBR_ROUGH_PERCEPTUAL 0 // Output: grayscale Perceptual Roughenss +#define DEBUG_PBR_ROUGH_ALPHA 0 // Output: grayscale Alpha Roughness +#define DEBUG_PBR_METAL 0 // Output: grayscale metal +#define DEBUG_PBR_REFLECTANCE 0 // Output: diffuse reflectance +#define DEBUG_PBR_BRDF_UV 0 // Output: red green BRDF UV (GGX input) +#define DEBUG_PBR_BRDF_SCALE_BIAS 0 // Output: red green BRDF Scale Bias (GGX output) +#define DEBUG_PBR_SPEC 0 // Output: Final spec +#define DEBUG_PBR_SPEC_REFLECTION 0 // Output: reflection +#define DEBUG_PBR_NORMAL 0 // Output: passed in normal. To see raw normal map: set DEBUG_PBR_RAW_DIFF 1, and in pbropaqueF set DEBUG_NORMAL_RAW +#define DEBUG_PBR_VIEW 0 // Output: view_dir +#define DEBUG_PBR_BRDF 0 // Output: Environment BRDF +#define DEBUG_PBR_DOT_NV 0 // Output: grayscale dot(Normal,ViewDir) +#define DEBUG_PBR_DOT_TV 0 // Output: +#define DEBUG_PBR_DOT_BV 0 // Output: +#define DEBUG_PBR_FRESNEL 0 // Output: roughness dependent fresnel + #extension GL_ARB_texture_rectangle : enable #extension GL_ARB_shader_texture_lod : enable @@ -85,6 +110,34 @@ vec3 srgb_to_linear(vec3 c); vec4 applyWaterFogView(vec3 pos, vec4 color); #endif +uniform vec3 view_dir; // PBR + +#define getDiffuseLightPBR(n) ambenv +#define getSpecularPBR(reflection) glossenv + +// Approximate Environment BRDF +vec2 getGGXApprox( vec2 uv ) +{ + vec2 st = vec2(1.) - uv; + float d = (st.x * st.x * 0.5) * (st.y * st.y); + float scale = 1.0 - d; + float bias = d; + return vec2( scale, bias ); +} + +vec2 getGGX( vec2 brdfPoint ) +{ + // TODO: use GGXLUT + // texture2D(GGXLUT, brdfPoint).rg; + return getGGXApprox( brdfPoint); +} + +vec3 calcBaseReflect0(float ior) +{ + vec3 reflect0 = vec3(pow((ior - 1.0) / (ior + 1.0), 2.0)); + return reflect0; +} + void main() { vec2 tc = vary_fragcoord.xy; @@ -131,6 +184,142 @@ void main() vec3 legacyenv; sampleReflectionProbes(ambenv, glossenv, legacyenv, pos.xyz, norm.xyz, spec.a, envIntensity); + bool hasPBR = GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR); + if (hasPBR) + { + vec3 colorDiffuse = vec3(0); + vec3 colorEmissive = vec3(0); + vec3 colorSpec = vec3(0); +// vec3 colorClearCoat = vec3(0); +// vec3 colorSheen = vec3(0); +// vec3 colorTransmission = vec3(0); + + vec3 packedORM = spec.rgb; // Packed: Occlusion Roughness Metal +#if DEBUG_PBR_PACK_ORM0 + packedORM = vec3(0,0,0); +#endif +#if DEBUG_PBR_PACK_ORM1 + packedORM = vec3(1,1,1); +#endif + float IOR = 1.5; // default Index Of Reflection 1.5 + vec3 reflect0 = vec3(0.04); // -> incidence reflectance 0.04 + + IOR = 0.0; // TODO: Set from glb + reflect0 = calcBaseReflect0(IOR); + + float metal = packedORM.b; + vec3 reflect90 = vec3(0); + vec3 v = view_dir; + vec3 n = norm.xyz; +// vec3 t = texture2DRect(tangentMap, tc).rgb; +#if DEBUG_PBR_TANGENT1 + vec3 t = vec3(1,0,0); +#endif + vec3 b = cross( n,t); + vec3 reflectVN = normalize(reflect(-v,n)); + + float dotNV = clamp(dot(n,v),0,1); + float dotTV = clamp(dot(n,t),0,1); + float dotBV = clamp(dot(n,b),0,1); + + // Reference: getMetallicRoughnessInfo + float perceptualRough = packedORM.g; + float alphaRough = perceptualRough * perceptualRough; + vec3 colorDiff = mix( diffuse.rgb, vec3(0) , metal); + reflect0 = mix( reflect0 , diffuse.rgb, metal); // reflect at 0 degrees + reflect90 = vec3(1); // reflect at 90 degrees + float reflectance = max( max( reflect0.r, reflect0.g ), reflect0.b ); + + // Common to RadianceGGX and RadianceLambertian + float specWeight = 1.0; + vec2 brdfPoint = clamp(vec2(dotNV, perceptualRough), vec2(0,0), vec2(1,1)); + vec2 vScaleBias = getGGX( brdfPoint); // Environment BRDF: scale and bias applied to reflect0 + vec3 fresnelR = max(vec3(1.0 - perceptualRough), reflect0) - reflect0; // roughness dependent fresnel + vec3 kSpec = reflect0 + fresnelR*pow(1.0 - dotNV, 5.0); + + // Reference: getIBLRadianceGGX + vec3 specLight = getSpecularPBR(reflection); +#if HAS_IBL + kSpec = mix( kSpec, iridescenceFresnel, iridescenceFactor); +#endif + vec3 FssEssRadiance = kSpec*vScaleBias.x + vScaleBias.y; + colorSpec += specWeight * specLight * FssEssRadiance; + + // Reference: getIBLRadianceLambertian + vec3 irradiance = getDiffuseLightPBR(n); + vec3 FssEssLambert = specWeight * kSpec * vScaleBias.x + vScaleBias.y; // NOTE: Very similar to FssEssRadiance but with extra specWeight term + float Ems = (1.0 - vScaleBias.x + vScaleBias.y); + vec3 avg = specWeight * (reflect0 + (1.0 - reflect0) / 21.0); + vec3 AvgEms = avg * Ems; + vec3 FmsEms = AvgEms * FssEssLambert / (1.0 - AvgEms); + vec3 kDiffuse = colorDiffuse * (1.0 - FssEssLambert + FmsEms); + colorDiffuse += (FmsEms + kDiffuse) * irradiance; + + color.rgb = colorDiffuse + colorEmissive + colorSpec; + + #if DEBUG_PBR_BRDF_UV + color.rgb = vec3(brdfPoint,0.0); + #endif + #if DEBUG_PBR_BRDF_SCALE_BIAS + color.rgb = vec3(vScaleBias,0.0); + #endif + #if DEBUG_PBR_FRESNEL + color.rgb = fresnelR; + #endif + #if DEBUG_PBR_RAW_DIFF + color.rgb = diffuse.rgb; + #endif + #if DEBUG_PBR_RAW_SPEC + color.rgb = spec.rgb; + #endif + #if DEBUG_PBR_REFLECTANCE + color.rgb = vec3(reflectance); + #endif + #if DEBUG_PBR_IRRADIANCE + color.rgb = irradiance; + #endif + #if DEBUG_PBR_DIFFUSE + color.rgb = colorDiffuse; + #endif + #if DEBUG_PBR_EMISSIVE + color.rgb = colorEmissive; + #endif + #if DEBUG_PBR_METAL + color.rgb = vec3(metal); + #endif + #if DEBUG_PBR_ROUGH_PERCEPTUAL + color.rgb = vec3(perceptualRough); + #endif + #if DEBUG_PBR_ROUGH_ALPHA + color.rgb = vec3(alphaRough); + #endif + #if DEBUG_PBR_SPEC + color.rgb = colorSpec; + #endif + #if DEBUG_PBR_SPEC_REFLECTION + color.rgb = specLight; + #endif + #if DEBUG_PBR_ORM + color.rgb = packedORM; + #endif + #if DEBUG_PBR_NORMAL + color.rgb = norm.xyz; + #endif + #if DEBUG_PBR_VIEW + color.rgb = view_dir; + #endif + #if DEBUG_PBR_DOT_NV + color.rgb = vec3(dotNV); + #endif + #if DEBUG_PBR_DOT_TV + color.rgb = vec3(dotTV); + #endif + #if DEBUG_PBR_DOT_BV + color.rgb = vec3(dotBV); + #endif + } +else +{ amblit = max(ambenv, amblit); color.rgb = amblit*ambocc; @@ -170,7 +359,7 @@ void main() applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity); } - if (norm.w < 0.5) + if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { color = mix(atmosFragLighting(color, additive, atten), fullbrightAtmosTransportFrag(color, additive, atten), diffuse.a); color = mix(scaleSoftClipFrag(color), fullbrightScaleSoftClip(color), diffuse.a); @@ -181,7 +370,7 @@ void main() color = fogged.rgb; bloom = fogged.a; #endif - +} // convert to linear as fullscreen lights need to sum in linear colorspace // and will be gamma (re)corrected downstream... //color = vec3(ambocc); diff --git a/indra/newview/licenses-mac.txt b/indra/newview/licenses-mac.txt index fba6a55da3..29b5a919bd 100644 --- a/indra/newview/licenses-mac.txt +++ b/indra/newview/licenses-mac.txt @@ -719,3 +719,55 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +============ +tinygltf +============ +MIT License + +Copyright (c) 2017 Syoyo Fujita, Aurélien Chatelain and many contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +============== +Vulkan GLTF +============== +MIT License + +Copyright (c) 2018 Sascha Willems + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/indra/newview/licenses-win32.txt b/indra/newview/licenses-win32.txt index 837d92139d..eddc9a4475 100644 --- a/indra/newview/licenses-win32.txt +++ b/indra/newview/licenses-win32.txt @@ -796,3 +796,52 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +============ +tinygltf +============ +MIT License + +Copyright (c) 2017 Syoyo Fujita, Aurélien Chatelain and many contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +============== +Vulkan GLTF +============== +MIT License + +Copyright (c) 2018 Sascha Willems + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index b73ae94bbb..f7fc2d2061 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -48,6 +48,7 @@ public: enum { // Correspond to LLPipeline render type + // NOTE: Keep in sync with gPoolNames POOL_SIMPLE = 1, POOL_GROUND, POOL_FULLBRIGHT, @@ -130,6 +131,7 @@ class LLRenderPass : public LLDrawPool public: // list of possible LLRenderPass types to assign a render batch to // NOTE: "rigged" variant MUST be non-rigged variant + 1 + // see LLVolumeGeometryManager::registerFace() enum { PASS_SIMPLE = NUM_POOL_TYPES, @@ -191,6 +193,8 @@ public: PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, PASS_ALPHA_INVISIBLE, PASS_ALPHA_INVISIBLE_RIGGED, + PASS_PBR_OPAQUE, + PASS_PBR_OPAQUE_RIGGED, NUM_RENDER_TYPES, }; diff --git a/indra/newview/lldrawpoolpbropaque.cpp b/indra/newview/lldrawpoolpbropaque.cpp index 2478aa0cff..0c257a33a5 100644 --- a/indra/newview/lldrawpoolpbropaque.cpp +++ b/indra/newview/lldrawpoolpbropaque.cpp @@ -73,6 +73,12 @@ void LLDrawPoolPBROpaque::renderDeferred(S32 pass) return; } + const U32 type = LLPipeline::RENDER_TYPE_PASS_PBR_OPAQUE; + if (!gPipeline.hasRenderType(type)) + { + return; + } + gGL.flush(); LLGLDisable blend(GL_BLEND); @@ -86,7 +92,55 @@ void LLDrawPoolPBROpaque::renderDeferred(S32 pass) // TODO: handle under water? // if (LLPipeline::sUnderWaterRender) - // PASS_SIMPLE or PASS_MATERIAL - //pushBatches(LLRenderPass::PASS_SIMPLE, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); -} + LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); + LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); + for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) + { + LLDrawInfo& params = **i; + + //gGL.getTexUnit(0)->activate(); + + if (params.mTexture.notNull()) + { + gGL.getTexUnit(0)->bindFast(params.mTexture); // diffuse + } + else + { + gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::sWhiteImagep); + } + + if (params.mNormalMap) + { + gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::BUMP_MAP, params.mNormalMap); + } + else + { + // TODO: bind default normal map (???? WTF is it ???) + } + + if (params.mSpecularMap) + { + gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::SPECULAR_MAP, params.mSpecularMap); // Packed Occlusion Roughness Metal + } + else + { + gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep); + } + + if (params.mEmissiveMap) + { + gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::EMISSIVE_MAP, params.mEmissiveMap); // Packed Occlusion Roughness Metal + } + else + { + gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::EMISSIVE_MAP, LLViewerFetchedTexture::sWhiteImagep); + } + + gDeferredPBROpaqueProgram.uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, params.mGLTFMaterial->mRoughnessFactor); + gDeferredPBROpaqueProgram.uniform1f(LLShaderMgr::METALLIC_FACTOR, params.mGLTFMaterial->mMetallicFactor); + gDeferredPBROpaqueProgram.uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, params.mGLTFMaterial->mEmissiveColor.mV); + + LLRenderPass::pushBatch(params, getVertexDataMask(), FALSE, FALSE); + } +} diff --git a/indra/newview/lldrawpoolpbropaque.h b/indra/newview/lldrawpoolpbropaque.h index ada806a3bf..478d4e1bd4 100644 --- a/indra/newview/lldrawpoolpbropaque.h +++ b/indra/newview/lldrawpoolpbropaque.h @@ -34,11 +34,15 @@ class LLDrawPoolPBROpaque : public LLRenderPass public: enum { - VERTEX_DATA_MASK = 0 - | LLVertexBuffer::MAP_VERTEX - | LLVertexBuffer::MAP_NORMAL - | LLVertexBuffer::MAP_TEXCOORD0 - | LLVertexBuffer::MAP_COLOR + // See: DEFERRED_VB_MASK + VERTEX_DATA_MASK = 0 + | LLVertexBuffer::MAP_VERTEX + | LLVertexBuffer::MAP_NORMAL + | LLVertexBuffer::MAP_TEXCOORD0 // Diffuse + | LLVertexBuffer::MAP_TEXCOORD1 // Normal + | LLVertexBuffer::MAP_TEXCOORD2 // Spec <-- ORM Occlusion Roughness Metal + | LLVertexBuffer::MAP_TANGENT + | LLVertexBuffer::MAP_COLOR }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 08f45b63ef..82b1a7f754 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1476,6 +1476,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLColor4U color = (tep ? tep->getColor() : LLColor4()); // + if (tep->getGLTFMaterial()) + { + color = tep->getGLTFMaterial()->mAlbedoColor; + } + if (rebuild_color) { //decide if shiny goes in alpha channel of color if (tep && @@ -1893,10 +1898,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, // LLMaterial* mat = tep->getMaterialParams().get(); LLMaterial* mat = tep ? tep->getMaterialParams().get() : 0; // + LLGLTFMaterial* gltf_mat = tep->getGLTFMaterial(); bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); - if (mat && !do_bump) + if ((mat || gltf_mat) && !do_bump) { do_bump = mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1) || mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2); @@ -2129,10 +2135,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, mVertexBuffer->flush(); } - if (!mat && do_bump) + if ((!mat && !gltf_mat) && do_bump) { mVertexBuffer->getTexCoord1Strider(tex_coords1, mGeomIndex, mGeomCount, map_range); + mVObjp->getVolume()->genTangents(f); + for (S32 i = 0; i < num_vertices; i++) { LLVector4a tangent = vf.mTangents[i]; diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 9f308c7f6e..27a07e4e84 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -65,7 +65,8 @@ LLFilePicker LLFilePicker::sInstance; #define XML_FILTER L"XML files (*.xml)\0*.xml\0" #define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0" #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0" -#define MODEL_FILTER L"Model files (*.dae; *.gltf; *.glb)\0*.dae;*.gltf;*.glb\0" +#define MODEL_FILTER L"Model files (*.dae)\0*.dae\0" +#define MATERIAL_FILTER L"GLTF Files (*.gltf; *.glb)\0*.gltf;*.glb\0" #define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0" #define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0" // Import filter @@ -235,6 +236,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter) mOFN.lpstrFilter = MODEL_FILTER \ L"\0"; break; + case FFLOAD_MATERIAL: + mOFN.lpstrFilter = MATERIAL_FILTER \ + L"\0"; + break; case FFLOAD_SCRIPT: mOFN.lpstrFilter = SCRIPT_FILTER \ L"\0"; diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index 3844f5054f..d15e8a0445 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -92,9 +92,9 @@ public: FFLOAD_COLLADA = 10, FFLOAD_SCRIPT = 11, FFLOAD_DICTIONARY = 12, - FFLOAD_DIRECTORY = 13, //To call from lldirpicker. - FFLOAD_EXE = 14, // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin - + FFLOAD_DIRECTORY = 13, // To call from lldirpicker. + FFLOAD_EXE = 14, // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin + FFLOAD_MATERIAL = 15, // Firestorm additions FFLOAD_IMPORT = 50 }; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index ef9ac5bbb6..6802bf4ec8 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4420,6 +4420,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items disabled_items.push_back(std::string("New Note")); disabled_items.push_back(std::string("New Settings")); disabled_items.push_back(std::string("New Gesture")); + disabled_items.push_back(std::string("New Material")); disabled_items.push_back(std::string("New Clothes")); disabled_items.push_back(std::string("New Body Parts")); disabled_items.push_back(std::string("upload_def")); @@ -4447,6 +4448,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items disabled_items.push_back(std::string("New Script")); disabled_items.push_back(std::string("New Note")); disabled_items.push_back(std::string("New Gesture")); + disabled_items.push_back(std::string("New Material")); disabled_items.push_back(std::string("New Clothes")); disabled_items.push_back(std::string("New Body Parts")); disabled_items.push_back(std::string("upload_def")); @@ -4518,6 +4520,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items items.push_back(std::string("New Script")); items.push_back(std::string("New Note")); items.push_back(std::string("New Gesture")); + items.push_back(std::string("New Material")); items.push_back(std::string("New Clothes")); items.push_back(std::string("New Body Parts")); items.push_back(std::string("New Settings")); diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index edbb61f178..68a333313f 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -1389,6 +1389,18 @@ const std::string& LLInventoryFilter::getFilterText() filtered_by_all_types = FALSE; } + if (isFilterObjectTypesWith(LLInventoryType::IT_MATERIAL)) + { + filtered_types += LLTrans::getString("Materials"); + filtered_by_type = TRUE; + num_filter_types++; + } + else + { + not_filtered_types += LLTrans::getString("Materials"); + filtered_by_all_types = FALSE; + } + if (isFilterObjectTypesWith(LLInventoryType::IT_NOTECARD)) { filtered_types += LLTrans::getString("Notecards"); diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp index d7389597af..76d7162640 100644 --- a/indra/newview/llinventoryicon.cpp +++ b/indra/newview/llinventoryicon.cpp @@ -99,6 +99,8 @@ LLIconDictionary::LLIconDictionary() addEntry(LLInventoryType::ICONNAME_SETTINGS_DAY, new IconEntry("Inv_SettingsDay")); addEntry(LLInventoryType::ICONNAME_SETTINGS, new IconEntry("Inv_Settings")); + addEntry(LLInventoryType::ICONNAME_MATERIAL, new IconEntry("Inv_Material")); + addEntry(LLInventoryType::ICONNAME_INVALID, new IconEntry("Inv_Invalid")); addEntry(LLInventoryType::ICONNAME_UNKNOWN, new IconEntry("Inv_Unknown")); @@ -178,9 +180,12 @@ const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type, case LLAssetType::AT_MESH: idx = LLInventoryType::ICONNAME_MESH; break; - case LLAssetType::AT_SETTINGS: - idx = assignSettingsIcon(misc_flag); - break; + case LLAssetType::AT_SETTINGS: + idx = assignSettingsIcon(misc_flag); + break; + case LLAssetType::AT_MATERIAL: + idx = LLInventoryType::ICONNAME_MATERIAL; + break; case LLAssetType::AT_UNKNOWN: idx = LLInventoryType::ICONNAME_UNKNOWN; break; diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp new file mode 100644 index 0000000000..e3206947d5 --- /dev/null +++ b/indra/newview/llmaterialeditor.cpp @@ -0,0 +1,810 @@ +/** + * @file llmaterialeditor.cpp + * @brief Implementation of the notecard editor + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llmaterialeditor.h" + +#include "llappviewer.h" +#include "llcombobox.h" +#include "llnotificationsutil.h" +#include "lltexturectrl.h" +#include "lltrans.h" +#include "llviewermenufile.h" +#include "llviewertexture.h" +#include "llselectmgr.h" +#include "llvovolume.h" + +#include "tinygltf/tiny_gltf.h" + +///---------------------------------------------------------------------------- +/// Class LLPreviewNotecard +///---------------------------------------------------------------------------- + +// Default constructor +LLMaterialEditor::LLMaterialEditor(const LLSD& key) + : LLFloater(key) + , mHasUnsavedChanges(false) +{ +} + +BOOL LLMaterialEditor::postBuild() +{ + mAlbedoTextureCtrl = getChild("albedo_texture"); + mMetallicTextureCtrl = getChild("metallic_roughness_texture"); + mEmissiveTextureCtrl = getChild("emissive_texture"); + mNormalTextureCtrl = getChild("normal_texture"); + + mAlbedoTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitAlbedoTexture, this, _1, _2)); + mMetallicTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitMetallicTexture, this, _1, _2)); + mEmissiveTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitEmissiveTexture, this, _1, _2)); + mNormalTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitNormalTexture, this, _1, _2)); + + childSetAction("save", boost::bind(&LLMaterialEditor::onClickSave, this)); + childSetAction("save_as", boost::bind(&LLMaterialEditor::onClickSaveAs, this)); + childSetAction("cancel", boost::bind(&LLMaterialEditor::onClickCancel, this)); + + boost::function changes_callback = [this](LLUICtrl * ctrl, void*) { setHasUnsavedChanges(true); }; + + childSetCommitCallback("double sided", changes_callback, NULL); + + // Albedo + childSetCommitCallback("albedo color", changes_callback, NULL); + childSetCommitCallback("transparency", changes_callback, NULL); + childSetCommitCallback("alpha mode", changes_callback, NULL); + childSetCommitCallback("alpha cutoff", changes_callback, NULL); + + // Metallic-Roughness + childSetCommitCallback("metalness factor", changes_callback, NULL); + childSetCommitCallback("roughness factor", changes_callback, NULL); + + // Metallic-Roughness + childSetCommitCallback("metalness factor", changes_callback, NULL); + childSetCommitCallback("roughness factor", changes_callback, NULL); + + // Emissive + childSetCommitCallback("emissive color", changes_callback, NULL); + + childSetVisible("unsaved_changes", mHasUnsavedChanges); + + return LLFloater::postBuild(); +} + +void LLMaterialEditor::onClickCloseBtn(bool app_quitting) +{ + if (app_quitting) + { + closeFloater(app_quitting); + } + else + { + onClickCancel(); + } +} + +LLUUID LLMaterialEditor::getAlbedoId() +{ + return mAlbedoTextureCtrl->getValue().asUUID(); +} + +void LLMaterialEditor::setAlbedoId(const LLUUID& id) +{ + mAlbedoTextureCtrl->setValue(id); + mAlbedoTextureCtrl->setDefaultImageAssetID(id); + + if (id.notNull()) + { + // todo: this does not account for posibility of texture + // being from inventory, need to check that + childSetValue("albedo_upload_fee", getString("upload_fee_string")); + // Only set if we will need to upload this texture + mAlbedoTextureUploadId = id; + } +} + +LLColor4 LLMaterialEditor::getAlbedoColor() +{ + LLColor4 ret = LLColor4(childGetValue("albedo color")); + ret.mV[3] = getTransparency(); + return ret; +} + +void LLMaterialEditor::setAlbedoColor(const LLColor4& color) +{ + childSetValue("albedo color", color.getValue()); + childSetValue("transparency", color.mV[3]); +} + +F32 LLMaterialEditor::getTransparency() +{ + return childGetValue("transparency").asReal(); +} + +std::string LLMaterialEditor::getAlphaMode() +{ + return childGetValue("alpha mode").asString(); +} + +void LLMaterialEditor::setAlphaMode(const std::string& alpha_mode) +{ + childSetValue("alpha mode", alpha_mode); +} + +F32 LLMaterialEditor::getAlphaCutoff() +{ + return childGetValue("alpha cutoff").asReal(); +} + +void LLMaterialEditor::setAlphaCutoff(F32 alpha_cutoff) +{ + childSetValue("alpha cutoff", alpha_cutoff); +} + +void LLMaterialEditor::setMaterialName(const std::string &name) +{ + setTitle(name); + mMaterialName = name; +} + +LLUUID LLMaterialEditor::getMetallicRoughnessId() +{ + return mMetallicTextureCtrl->getValue().asUUID(); +} + +void LLMaterialEditor::setMetallicRoughnessId(const LLUUID& id) +{ + mMetallicTextureCtrl->setValue(id); + mMetallicTextureCtrl->setDefaultImageAssetID(id); + + if (id.notNull()) + { + // todo: this does not account for posibility of texture + // being from inventory, need to check that + childSetValue("metallic_upload_fee", getString("upload_fee_string")); + mMetallicTextureUploadId = id; + } +} + +F32 LLMaterialEditor::getMetalnessFactor() +{ + return childGetValue("metalness factor").asReal(); +} + +void LLMaterialEditor::setMetalnessFactor(F32 factor) +{ + childSetValue("metalness factor", factor); +} + +F32 LLMaterialEditor::getRoughnessFactor() +{ + return childGetValue("roughness factor").asReal(); +} + +void LLMaterialEditor::setRoughnessFactor(F32 factor) +{ + childSetValue("roughness factor", factor); +} + +LLUUID LLMaterialEditor::getEmissiveId() +{ + return mEmissiveTextureCtrl->getValue().asUUID(); +} + +void LLMaterialEditor::setEmissiveId(const LLUUID& id) +{ + mEmissiveTextureCtrl->setValue(id); + mEmissiveTextureCtrl->setDefaultImageAssetID(id); + + if (id.notNull()) + { + // todo: this does not account for posibility of texture + // being from inventory, need to check that + childSetValue("emissive_upload_fee", getString("upload_fee_string")); + mEmissiveTextureUploadId = id; + } +} + +LLColor4 LLMaterialEditor::getEmissiveColor() +{ + return LLColor4(childGetValue("emissive color")); +} + +void LLMaterialEditor::setEmissiveColor(const LLColor4& color) +{ + childSetValue("emissive color", color.getValue()); +} + +LLUUID LLMaterialEditor::getNormalId() +{ + return mNormalTextureCtrl->getValue().asUUID(); +} + +void LLMaterialEditor::setNormalId(const LLUUID& id) +{ + mNormalTextureCtrl->setValue(id); + mNormalTextureCtrl->setDefaultImageAssetID(id); + + if (id.notNull()) + { + // todo: this does not account for posibility of texture + // being from inventory, need to check that + childSetValue("normal_upload_fee", getString("upload_fee_string")); + mNormalTextureUploadId = id; + } +} + +bool LLMaterialEditor::getDoubleSided() +{ + return childGetValue("double sided").asBoolean(); +} + +void LLMaterialEditor::setDoubleSided(bool double_sided) +{ + childSetValue("double sided", double_sided); +} + +void LLMaterialEditor::setHasUnsavedChanges(bool value) +{ + if (value != mHasUnsavedChanges) + { + mHasUnsavedChanges = value; + childSetVisible("unsaved_changes", value); + } +} + +void LLMaterialEditor::onCommitAlbedoTexture(LLUICtrl * ctrl, const LLSD & data) +{ + // might be better to use arrays, to have a single callback + // and not to repeat the same thing for each tecture control + LLUUID new_val = mAlbedoTextureCtrl->getValue().asUUID(); + if (new_val == mAlbedoTextureUploadId && mAlbedoTextureUploadId.notNull()) + { + childSetValue("albedo_upload_fee", getString("upload_fee_string")); + } + else + { + childSetValue("albedo_upload_fee", getString("no_upload_fee_string")); + } + setHasUnsavedChanges(true); +} + +void LLMaterialEditor::onCommitMetallicTexture(LLUICtrl * ctrl, const LLSD & data) +{ + LLUUID new_val = mMetallicTextureCtrl->getValue().asUUID(); + if (new_val == mMetallicTextureUploadId && mMetallicTextureUploadId.notNull()) + { + childSetValue("metallic_upload_fee", getString("upload_fee_string")); + } + else + { + childSetValue("metallic_upload_fee", getString("no_upload_fee_string")); + } + setHasUnsavedChanges(true); +} + +void LLMaterialEditor::onCommitEmissiveTexture(LLUICtrl * ctrl, const LLSD & data) +{ + LLUUID new_val = mEmissiveTextureCtrl->getValue().asUUID(); + if (new_val == mEmissiveTextureUploadId && mEmissiveTextureUploadId.notNull()) + { + childSetValue("emissive_upload_fee", getString("upload_fee_string")); + } + else + { + childSetValue("emissive_upload_fee", getString("no_upload_fee_string")); + } + setHasUnsavedChanges(true); +} + +void LLMaterialEditor::onCommitNormalTexture(LLUICtrl * ctrl, const LLSD & data) +{ + LLUUID new_val = mNormalTextureCtrl->getValue().asUUID(); + if (new_val == mNormalTextureUploadId && mNormalTextureUploadId.notNull()) + { + childSetValue("normal_upload_fee", getString("upload_fee_string")); + } + else + { + childSetValue("normal_upload_fee", getString("no_upload_fee_string")); + } + setHasUnsavedChanges(true); +} + + +static void write_color(const LLColor4& color, std::vector& c) +{ + for (int i = 0; i < c.size(); ++i) // NOTE -- use c.size because some gltf colors are 3-component + { + c[i] = color.mV[i]; + } +} + +static U32 write_texture(const LLUUID& id, tinygltf::Model& model) +{ + tinygltf::Image image; + image.uri = id.asString(); + model.images.push_back(image); + U32 image_idx = model.images.size() - 1; + + tinygltf::Texture texture; + texture.source = image_idx; + model.textures.push_back(texture); + U32 texture_idx = model.textures.size() - 1; + + return texture_idx; +} + +void LLMaterialEditor::onClickSave() +{ + applyToSelection(); + + tinygltf::Model model; + model.materials.resize(1); + tinygltf::PbrMetallicRoughness& pbrMaterial = model.materials[0].pbrMetallicRoughness; + + // write albedo + LLColor4 albedo_color = getAlbedoColor(); + albedo_color.mV[3] = getTransparency(); + write_color(albedo_color, pbrMaterial.baseColorFactor); + + model.materials[0].alphaCutoff = getAlphaCutoff(); + model.materials[0].alphaMode = getAlphaMode(); + + LLUUID albedo_id = getAlbedoId(); + + if (albedo_id.notNull()) + { + U32 texture_idx = write_texture(albedo_id, model); + + pbrMaterial.baseColorTexture.index = texture_idx; + } + + // write metallic/roughness + F32 metalness = getMetalnessFactor(); + F32 roughness = getRoughnessFactor(); + + pbrMaterial.metallicFactor = metalness; + pbrMaterial.roughnessFactor = roughness; + + LLUUID mr_id = getMetallicRoughnessId(); + if (mr_id.notNull()) + { + U32 texture_idx = write_texture(mr_id, model); + pbrMaterial.metallicRoughnessTexture.index = texture_idx; + } + + //write emissive + LLColor4 emissive_color = getEmissiveColor(); + model.materials[0].emissiveFactor.resize(3); + write_color(emissive_color, model.materials[0].emissiveFactor); + + LLUUID emissive_id = getEmissiveId(); + if (emissive_id.notNull()) + { + U32 idx = write_texture(emissive_id, model); + model.materials[0].emissiveTexture.index = idx; + } + + //write normal + LLUUID normal_id = getNormalId(); + if (normal_id.notNull()) + { + U32 idx = write_texture(normal_id, model); + model.materials[0].normalTexture.index = idx; + } + + //write doublesided + model.materials[0].doubleSided = getDoubleSided(); + + std::ostringstream str; + + tinygltf::TinyGLTF gltf; + model.asset.version = "2.0"; + gltf.WriteGltfSceneToStream(&model, str, true, false); + + std::string dump = str.str(); + + LL_INFOS() << mMaterialName << ": " << dump << LL_ENDL; +} + +void LLMaterialEditor::onClickSaveAs() +{ + LLSD args; + args["DESC"] = mMaterialName; + + LLNotificationsUtil::add("SaveMaterialAs", args, LLSD(), boost::bind(&LLMaterialEditor::onSaveAsMsgCallback, this, _1, _2)); +} + +void LLMaterialEditor::onSaveAsMsgCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) + { + std::string new_name = response["message"].asString(); + LLStringUtil::trim(new_name); + if (!new_name.empty()) + { + setMaterialName(new_name); + onClickSave(); + } + else + { + LLNotificationsUtil::add("InvalidMaterialName"); + } + } +} + +void LLMaterialEditor::onClickCancel() +{ + if (mHasUnsavedChanges) + { + LLNotificationsUtil::add("UsavedMaterialChanges", LLSD(), LLSD(), boost::bind(&LLMaterialEditor::onCancelMsgCallback, this, _1, _2)); + } + else + { + closeFloater(); + } +} + +void LLMaterialEditor::onCancelMsgCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) + { + closeFloater(); + } +} + +class LLMaterialFilePicker : public LLFilePickerThread +{ +public: + LLMaterialFilePicker(LLMaterialEditor* me); + virtual void notify(const std::vector& filenames); + void loadMaterial(const std::string& filename); + static void textureLoadedCallback(BOOL success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata); +private: + LLMaterialEditor* mME; +}; + +LLMaterialFilePicker::LLMaterialFilePicker(LLMaterialEditor* me) + : LLFilePickerThread(LLFilePicker::FFLOAD_MATERIAL) +{ + mME = me; +} + +void LLMaterialFilePicker::notify(const std::vector& filenames) +{ + if (LLAppViewer::instance()->quitRequested()) + { + return; + } + + + if (filenames.size() > 0) + { + loadMaterial(filenames[0]); + } +} + +const tinygltf::Image* get_image_from_texture_index(const tinygltf::Model& model, S32 texture_index) +{ + if (texture_index >= 0) + { + S32 source_idx = model.textures[texture_index].source; + if (source_idx >= 0) + { + return &(model.images[source_idx]); + } + } + + return nullptr; +} + +static LLImageRaw* get_texture(const std::string& folder, const tinygltf::Model& model, S32 texture_index) +{ + const tinygltf::Image* image = get_image_from_texture_index(model, texture_index); + + LLImageRaw* rawImage = nullptr; + + if (image != nullptr && + image->bits == 8 && + !image->image.empty() && + image->component <= 4) + { + rawImage = new LLImageRaw(&image->image[0], image->width, image->height, image->component); + rawImage->verticalFlip(); + } + + return rawImage; +} + +static void strip_alpha_channel(LLPointer& img) +{ + if (img->getComponents() == 4) + { + LLImageRaw* tmp = new LLImageRaw(img->getWidth(), img->getHeight(), 3); + tmp->copyUnscaled4onto3(img); + img = tmp; + } +} + +// copy red channel from src_img to dst_img +// PRECONDITIONS: +// dst_img must be 3 component +// src_img and dst_image must have the same dimensions +static void copy_red_channel(LLPointer& src_img, LLPointer& dst_img) +{ + llassert(src_img->getWidth() == dst_img->getWidth() && src_img->getHeight() == dst_img->getHeight()); + llassert(dst_img->getComponents() == 3); + + U32 pixel_count = dst_img->getWidth() * dst_img->getHeight(); + U8* src = src_img->getData(); + U8* dst = dst_img->getData(); + S8 src_components = src_img->getComponents(); + + for (U32 i = 0; i < pixel_count; ++i) + { + dst[i * 3] = src[i * src_components]; + } +} + +static void pack_textures(tinygltf::Model& model, tinygltf::Material& material, + LLPointer& albedo_img, + LLPointer& normal_img, + LLPointer& mr_img, + LLPointer& emissive_img, + LLPointer& occlusion_img, + LLPointer& albedo_tex, + LLPointer& normal_tex, + LLPointer& mr_tex, + LLPointer& emissive_tex) +{ + // TODO: downscale if needed + if (albedo_img) + { + albedo_tex = LLViewerTextureManager::getFetchedTexture(albedo_img, FTType::FTT_LOCAL_FILE, true); + } + + if (normal_img) + { + strip_alpha_channel(normal_img); + normal_tex = LLViewerTextureManager::getFetchedTexture(normal_img, FTType::FTT_LOCAL_FILE, true); + } + + if (mr_img) + { + strip_alpha_channel(mr_img); + + if (occlusion_img && material.pbrMetallicRoughness.metallicRoughnessTexture.index != material.occlusionTexture.index) + { + // occlusion is a distinct texture from pbrMetallicRoughness + // pack into mr red channel + int occlusion_idx = material.occlusionTexture.index; + int mr_idx = material.pbrMetallicRoughness.metallicRoughnessTexture.index; + if (occlusion_idx != mr_idx) + { + //scale occlusion image to match resolution of mr image + occlusion_img->scale(mr_img->getWidth(), mr_img->getHeight()); + + copy_red_channel(occlusion_img, mr_img); + } + } + } + else if (occlusion_img) + { + //no mr but occlusion exists, make a white mr_img and copy occlusion red channel over + mr_img = new LLImageRaw(occlusion_img->getWidth(), occlusion_img->getHeight(), 3); + mr_img->clear(255, 255, 255); + copy_red_channel(occlusion_img, mr_img); + + } + + if (mr_img) + { + mr_tex = LLViewerTextureManager::getFetchedTexture(mr_img, FTType::FTT_LOCAL_FILE, true); + } + + if (emissive_img) + { + strip_alpha_channel(emissive_img); + emissive_tex = LLViewerTextureManager::getFetchedTexture(emissive_img, FTType::FTT_LOCAL_FILE, true); + } +} + +static LLColor4 get_color(const std::vector& in) +{ + LLColor4 out; + for (S32 i = 0; i < llmin((S32) in.size(), 4); ++i) + { + out.mV[i] = in[i]; + } + + return out; +} + +void LLMaterialFilePicker::textureLoadedCallback(BOOL success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata) +{ +} + + +void LLMaterialFilePicker::loadMaterial(const std::string& filename) +{ + tinygltf::TinyGLTF loader; + std::string error_msg; + std::string warn_msg; + + bool loaded = false; + tinygltf::Model model_in; + + std::string filename_lc = filename; + LLStringUtil::toLower(filename_lc); + + // Load a tinygltf model fom a file. Assumes that the input filename has already been + // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish. + if (std::string::npos == filename_lc.rfind(".gltf")) + { // file is binary + loaded = loader.LoadBinaryFromFile(&model_in, &error_msg, &warn_msg, filename); + } + else + { // file is ascii + loaded = loader.LoadASCIIFromFile(&model_in, &error_msg, &warn_msg, filename); + } + + if (!loaded) + { + LLNotificationsUtil::add("CannotUploadMaterial"); + return; + } + + if (model_in.materials.empty()) + { + // materials are missing + LLNotificationsUtil::add("CannotUploadMaterial"); + return; + } + + std::string folder = gDirUtilp->getDirName(filename); + + + tinygltf::Material material_in = model_in.materials[0]; + + tinygltf::Model model_out; + model_out.asset.version = "2.0"; + model_out.materials.resize(1); + + // get albedo texture + LLPointer albedo_img = get_texture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index); + // get normal map + LLPointer normal_img = get_texture(folder, model_in, material_in.normalTexture.index); + // get metallic-roughness texture + LLPointer mr_img = get_texture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index); + // get emissive texture + LLPointer emissive_img = get_texture(folder, model_in, material_in.emissiveTexture.index); + // get occlusion map if needed + LLPointer occlusion_img; + if (material_in.occlusionTexture.index != material_in.pbrMetallicRoughness.metallicRoughnessTexture.index) + { + occlusion_img = get_texture(folder, model_in, material_in.occlusionTexture.index); + } + + LLPointer albedo_tex; + LLPointer normal_tex; + LLPointer mr_tex; + LLPointer emissive_tex; + + pack_textures(model_in, material_in, albedo_img, normal_img, mr_img, emissive_img, occlusion_img, + albedo_tex, normal_tex, mr_tex, emissive_tex); + + LLUUID albedo_id; + if (albedo_tex != nullptr) + { + albedo_tex->forceToSaveRawImage(0, F32_MAX); + albedo_id = albedo_tex->getID(); + } + + LLUUID normal_id; + if (normal_tex != nullptr) + { + normal_tex->forceToSaveRawImage(0, F32_MAX); + normal_id = normal_tex->getID(); + } + + LLUUID mr_id; + if (mr_tex != nullptr) + { + mr_tex->forceToSaveRawImage(0, F32_MAX); + mr_id = mr_tex->getID(); + } + + LLUUID emissive_id; + if (emissive_tex != nullptr) + { + emissive_tex->forceToSaveRawImage(0, F32_MAX); + emissive_id = emissive_tex->getID(); + } + + mME->setAlbedoId(albedo_id); + mME->setMetallicRoughnessId(mr_id); + mME->setEmissiveId(emissive_id); + mME->setNormalId(normal_id); + + mME->setAlphaMode(material_in.alphaMode); + mME->setAlphaCutoff(material_in.alphaCutoff); + + mME->setAlbedoColor(get_color(material_in.pbrMetallicRoughness.baseColorFactor)); + mME->setEmissiveColor(get_color(material_in.emissiveFactor)); + + mME->setMetalnessFactor(material_in.pbrMetallicRoughness.metallicFactor); + mME->setRoughnessFactor(material_in.pbrMetallicRoughness.roughnessFactor); + + mME->setDoubleSided(material_in.doubleSided); + + std::string new_material = LLTrans::getString("New Material"); + mME->setMaterialName(new_material); + + mME->setHasUnsavedChanges(true); + mME->openFloater(); + + mME->applyToSelection(); +} + +void LLMaterialEditor::importMaterial() +{ + (new LLMaterialFilePicker(this))->getFile(); +} + +void LLMaterialEditor::applyToSelection() +{ + LLViewerObject* objectp = LLSelectMgr::instance().getSelection()->getFirstObject(); + if (objectp && objectp->getVolume()) + { + LLGLTFMaterial* mat = new LLGLTFMaterial(); + mat->mAlbedoColor = getAlbedoColor(); + mat->mAlbedoColor.mV[3] = getTransparency(); + mat->mAlbedoId = getAlbedoId(); + + mat->mNormalId = getNormalId(); + + mat->mMetallicRoughnessId = getMetallicRoughnessId(); + mat->mMetallicFactor = getMetalnessFactor(); + mat->mRoughnessFactor = getRoughnessFactor(); + + mat->mEmissiveColor = getEmissiveColor(); + mat->mEmissiveId = getEmissiveId(); + + mat->mDoubleSided = getDoubleSided(); + mat->setAlphaMode(getAlphaMode()); + + LLVOVolume* vobjp = (LLVOVolume*)objectp; + for (int i = 0; i < vobjp->getNumTEs(); ++i) + { + vobjp->getTE(i)->setGLTFMaterial(mat); + vobjp->updateTEMaterialTextures(i); + } + + vobjp->markForUpdate(TRUE); + } +} diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h new file mode 100644 index 0000000000..7f9c6c0b63 --- /dev/null +++ b/indra/newview/llmaterialeditor.h @@ -0,0 +1,115 @@ +/** + * @file llmaterialeditor.h + * @brief LLMaterialEditor class header file + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#pragma once + +#include "llfloater.h" + +class LLTextureCtrl; + +class LLMaterialEditor : public LLFloater +{ +public: + LLMaterialEditor(const LLSD& key); + + // open a file dialog and select a gltf/glb file for import + void importMaterial(); + + // for live preview, apply current material to currently selected object + void applyToSelection(); + + void onClickSave(); + void onClickSaveAs(); + void onSaveAsMsgCallback(const LLSD& notification, const LLSD& response); + void onClickCancel(); + void onCancelMsgCallback(const LLSD& notification, const LLSD& response); + + // llpanel + BOOL postBuild() override; + void onClickCloseBtn(bool app_quitting = false) override; + + LLUUID getAlbedoId(); + void setAlbedoId(const LLUUID& id); + + LLColor4 getAlbedoColor(); + + // sets both albedo color and transparency + void setAlbedoColor(const LLColor4& color); + + F32 getTransparency(); + + std::string getAlphaMode(); + void setAlphaMode(const std::string& alpha_mode); + + F32 getAlphaCutoff(); + void setAlphaCutoff(F32 alpha_cutoff); + + void setMaterialName(const std::string &name); + + LLUUID getMetallicRoughnessId(); + void setMetallicRoughnessId(const LLUUID& id); + + F32 getMetalnessFactor(); + void setMetalnessFactor(F32 factor); + + F32 getRoughnessFactor(); + void setRoughnessFactor(F32 factor); + + LLUUID getEmissiveId(); + void setEmissiveId(const LLUUID& id); + + LLColor4 getEmissiveColor(); + void setEmissiveColor(const LLColor4& color); + + LLUUID getNormalId(); + void setNormalId(const LLUUID& id); + + bool getDoubleSided(); + void setDoubleSided(bool double_sided); + + void setHasUnsavedChanges(bool value); + + void onCommitAlbedoTexture(LLUICtrl* ctrl, const LLSD& data); + void onCommitMetallicTexture(LLUICtrl* ctrl, const LLSD& data); + void onCommitEmissiveTexture(LLUICtrl* ctrl, const LLSD& data); + void onCommitNormalTexture(LLUICtrl* ctrl, const LLSD& data); + +private: + LLTextureCtrl* mAlbedoTextureCtrl; + LLTextureCtrl* mMetallicTextureCtrl; + LLTextureCtrl* mEmissiveTextureCtrl; + LLTextureCtrl* mNormalTextureCtrl; + + // 'Default' texture, unless it's null or from inventory is the one with the fee + LLUUID mAlbedoTextureUploadId; + LLUUID mMetallicTextureUploadId; + LLUUID mEmissiveTextureUploadId; + LLUUID mNormalTextureUploadId; + + bool mHasUnsavedChanges; + std::string mMaterialName; +}; + diff --git a/indra/newview/llpaneleditsky.cpp b/indra/newview/llpaneleditsky.cpp index a169712bd8..d17845ebc5 100644 --- a/indra/newview/llpaneleditsky.cpp +++ b/indra/newview/llpaneleditsky.cpp @@ -108,6 +108,8 @@ namespace const std::string FIELD_SKY_DENSITY_DROPLET_RADIUS("droplet_radius"); const std::string FIELD_SKY_DENSITY_ICE_LEVEL("ice_level"); + const std::string FIELD_REFLECTION_PROBE_AMBIANCE("probe_ambiance"); + const F32 SLIDER_SCALE_SUN_AMBIENT(3.0f); const F32 SLIDER_SCALE_BLUE_HORIZON_DENSITY(2.0f); const F32 SLIDER_SCALE_GLOW_R(20.0f); @@ -150,6 +152,7 @@ BOOL LLPanelSettingsSkyAtmosTab::postBuild() getChild(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoistureLevelChanged(); }); getChild(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onDropletRadiusChanged(); }); getChild(FIELD_SKY_DENSITY_ICE_LEVEL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onIceLevelChanged(); }); + getChild(FIELD_REFLECTION_PROBE_AMBIANCE)->setCommitCallback([this](LLUICtrl*, const LLSD&) { onReflectionProbeAmbianceChanged(); }); refresh(); return TRUE; @@ -172,6 +175,7 @@ void LLPanelSettingsSkyAtmosTab::setEnabled(BOOL enabled) getChild(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setEnabled(enabled); getChild(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setEnabled(enabled); getChild(FIELD_SKY_DENSITY_ICE_LEVEL)->setEnabled(enabled); + getChild(FIELD_REFLECTION_PROBE_AMBIANCE)->setEnabled(enabled); } } @@ -203,10 +207,12 @@ void LLPanelSettingsSkyAtmosTab::refresh() F32 moisture_level = mSkySettings->getSkyMoistureLevel(); F32 droplet_radius = mSkySettings->getSkyDropletRadius(); F32 ice_level = mSkySettings->getSkyIceLevel(); + F32 rp_ambiance = mSkySettings->getReflectionProbeAmbiance(); getChild(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setValue(moisture_level); getChild(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setValue(droplet_radius); getChild(FIELD_SKY_DENSITY_ICE_LEVEL)->setValue(ice_level); + getChild(FIELD_REFLECTION_PROBE_AMBIANCE)->setValue(rp_ambiance); } //------------------------------------------------------------------------- @@ -311,6 +317,15 @@ void LLPanelSettingsSkyAtmosTab::onIceLevelChanged() setIsDirty(); } +void LLPanelSettingsSkyAtmosTab::onReflectionProbeAmbianceChanged() +{ + if (!mSkySettings) return; + F32 ambiance = getChild(FIELD_REFLECTION_PROBE_AMBIANCE)->getValue().asReal(); + mSkySettings->setReflectionProbeAmbiance(ambiance); + mSkySettings->update(); + setIsDirty(); +} + //========================================================================== LLPanelSettingsSkyCloudTab::LLPanelSettingsSkyCloudTab() : LLPanelSettingsSky() diff --git a/indra/newview/llpaneleditsky.h b/indra/newview/llpaneleditsky.h index cb63d40b0c..cd89e02eea 100644 --- a/indra/newview/llpaneleditsky.h +++ b/indra/newview/llpaneleditsky.h @@ -79,6 +79,7 @@ private: void onMoistureLevelChanged(); void onDropletRadiusChanged(); void onIceLevelChanged(); + void onReflectionProbeAmbianceChanged(); }; diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index b46d79ac43..3167e48015 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -1315,6 +1315,7 @@ void LLFloaterInventoryFinder::updateElementsFromFilter() getChild("check_clothing")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE)); getChild("check_gesture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE)); getChild("check_landmark")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK)); + getChild("check_material")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_MATERIAL)); getChild("check_notecard")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD)); getChild("check_object")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT)); getChild("check_script")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LSL)); @@ -1377,6 +1378,12 @@ void LLFloaterInventoryFinder::draw() filtered_by_all_types = FALSE; } + if (!getChild("check_material")->getValue()) + { + filter &= ~(0x1 << LLInventoryType::IT_MATERIAL); + filtered_by_all_types = FALSE; + } + if (!getChild("check_notecard")->getValue()) { filter &= ~(0x1 << LLInventoryType::IT_NOTECARD); @@ -1555,6 +1562,7 @@ void LLFloaterInventoryFinder::selectAllTypes(void* user_data) self->getChild("check_clothing")->setValue(TRUE); self->getChild("check_gesture")->setValue(TRUE); self->getChild("check_landmark")->setValue(TRUE); + self->getChild("check_material")->setValue(TRUE); self->getChild("check_notecard")->setValue(TRUE); self->getChild("check_object")->setValue(TRUE); self->getChild("check_script")->setValue(TRUE); @@ -1575,6 +1583,7 @@ void LLFloaterInventoryFinder::selectNoTypes(void* user_data) self->getChild("check_clothing")->setValue(FALSE); self->getChild("check_gesture")->setValue(FALSE); self->getChild("check_landmark")->setValue(FALSE); + self->getChild("check_material")->setValue(FALSE); self->getChild("check_notecard")->setValue(FALSE); self->getChild("check_object")->setValue(FALSE); self->getChild("check_script")->setValue(FALSE); diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index 500485fc70..2a7ab84501 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -74,10 +74,11 @@ void LLReflectionMap::autoAdjustOrigin() d.setAdd(bounds[0], bounds[1]); d.sub(mOrigin); mRadius = d.getLength3().getF32(); + mPriority = 1; } else if (mGroup->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME) { - mPriority = 8; + mPriority = 1; // cast a ray towards 8 corners of bounding box // nudge origin towards center of empty space @@ -155,7 +156,7 @@ void LLReflectionMap::autoAdjustOrigin() else { // user placed probe - mPriority = 64; + mPriority = 2; // use center of octree node volume for nodes that are just branches without data mOrigin = node->getCenter(); @@ -196,15 +197,13 @@ extern LLControlGroup gSavedSettings; F32 LLReflectionMap::getAmbiance() { - static LLCachedControl minimum_ambiance(gSavedSettings, "RenderReflectionProbeAmbiance", 0.f); - F32 ret = 0.f; if (mViewerObject && mViewerObject->getVolume()) { ret = ((LLVOVolume*)mViewerObject)->getReflectionProbeAmbiance(); } - return llmax(ret, minimum_ambiance()); + return ret; } F32 LLReflectionMap::getNearClip() diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 3bae000ff8..9e288e47fe 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -33,15 +33,11 @@ #include "pipeline.h" #include "llviewershadermgr.h" #include "llviewercontrol.h" +#include "llenvironment.h" extern BOOL gCubeSnapshot; extern BOOL gTeleportDisplay; -//#pragma optimize("", off) - -// experimental pipeline render target override, if this works, do something less hacky -LLPipeline::RenderTargetPack gProbeRT; - LLReflectionMapManager::LLReflectionMapManager() { for (int i = 0; i < LL_REFLECTION_PROBE_COUNT; ++i) @@ -84,7 +80,11 @@ void LLReflectionMapManager::update() if (mTexture.isNull()) { mTexture = new LLCubeMapArray(); - mTexture->allocate(LL_REFLECTION_PROBE_RESOLUTION, 3, LL_REFLECTION_PROBE_COUNT); + // store LL_REFLECTION_PROBE_COUNT+2 cube maps, final two cube maps are used for render target and radiance map generation source) + mTexture->allocate(LL_REFLECTION_PROBE_RESOLUTION, 3, LL_REFLECTION_PROBE_COUNT+2); + + mIrradianceMaps = new LLCubeMapArray(); + mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, LL_REFLECTION_PROBE_COUNT); } if (!mRenderTarget.isComplete()) @@ -94,15 +94,6 @@ void LLReflectionMapManager::update() const bool use_stencil_buffer = true; U32 targetRes = LL_REFLECTION_PROBE_RESOLUTION * 2; // super sample mRenderTarget.allocate(targetRes, targetRes, color_fmt, use_depth_buffer, use_stencil_buffer, LLTexUnit::TT_RECT_TEXTURE); - - // hack to allocate render targets using gPipeline code - gCubeSnapshot = TRUE; - auto* old_rt = gPipeline.mRT; - gPipeline.mRT = &gProbeRT; - gPipeline.allocateScreenBuffer(targetRes, targetRes); - gPipeline.allocateShadowBuffer(targetRes, targetRes); - gPipeline.mRT = old_rt; - gCubeSnapshot = FALSE; } if (mMipChain.empty()) @@ -118,12 +109,6 @@ void LLReflectionMapManager::update() } } - // =============== TODO -- move to an init function ================= - - // naively drop probes every 16m as we move the camera around for now - // later, use LLSpatialPartition to manage probes - const F32 PROBE_SPACING = 16.f; - const U32 MAX_PROBES = 8; LLVector4a camera_pos; camera_pos.load3(LLViewerCamera::instance().getOrigin().mV); @@ -131,7 +116,7 @@ void LLReflectionMapManager::update() // process kill list for (auto& probe : mKillList) { - auto& iter = std::find(mProbes.begin(), mProbes.end(), probe); + auto const & iter = std::find(mProbes.begin(), mProbes.end(), probe); if (iter != mProbes.end()) { deleteProbe(iter - mProbes.begin()); @@ -152,7 +137,6 @@ void LLReflectionMapManager::update() { return; } - const F32 UPDATE_INTERVAL = 5.f; //update no more than once every 5 seconds bool did_update = false; @@ -375,7 +359,7 @@ void LLReflectionMapManager::deleteProbe(U32 i) // remove from any Neighbors lists for (auto& other : probe->mNeighbors) { - auto& iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe); + auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe); llassert(iter != other->mNeighbors.end()); other->mNeighbors.erase(iter); } @@ -403,13 +387,19 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) { mRenderTarget.bindTarget(); // hacky hot-swap of camera specific render targets - auto* old_rt = gPipeline.mRT; - gPipeline.mRT = &gProbeRT; + gPipeline.mRT = &gPipeline.mAuxillaryRT; probe->update(mRenderTarget.getWidth(), face); - gPipeline.mRT = old_rt; + gPipeline.mRT = &gPipeline.mMainRT; mRenderTarget.flush(); - // generate mipmaps + S32 targetIdx = LL_REFLECTION_PROBE_COUNT; + + if (probe != mUpdatingProbe) + { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel + targetIdx += 1; + } + + // downsample to placeholder map { LLGLDepthTest depth(GL_FALSE, GL_FALSE); LLGLDisable cull(GL_CULL_FACE); @@ -428,7 +418,8 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) S32 mips = log2((F32)LL_REFLECTION_PROBE_RESOLUTION) + 0.5f; - for (int i = 0; i < mMipChain.size(); ++i) + //for (int i = 0; i < mMipChain.size(); ++i) + for (int i = 0; i < 1; ++i) { LL_PROFILE_GPU_ZONE("probe mip"); mMipChain[i].bindTarget(); @@ -483,6 +474,8 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) if (mip >= 0) { mTexture->bind(0); + //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, targetIdx * 6 + face, 0, 0, res, res); glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); mTexture->unbind(); } @@ -495,6 +488,120 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gReflectionMipProgram.unbind(); } + + if (face == 5) + { + //generate radiance map + gRadianceGenProgram.bind(); + S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + mTexture->bind(channel); + static LLStaticHashedString sSourceIdx("sourceIdx"); + gRadianceGenProgram.uniform1i(sSourceIdx, targetIdx); + + static LLStaticHashedString sMipLevel("mipLevel"); + + for (int i = 1; i < mMipChain.size(); ++i) + { + for (int cf = 0; cf < 6; ++cf) + { // for each cube face + LLCoordFrame frame; + frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); + + F32 mat[16]; + frame.getOpenGLRotation(mat); + gGL.loadMatrix(mat); + + mMipChain[i].bindTarget(); + static LLStaticHashedString sRoughness("roughness"); + + gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); + gRadianceGenProgram.uniform1f(sMipLevel, llmax((F32)(i - 1), 0.f)); + if (i > 0) + { + gRadianceGenProgram.uniform1i(sSourceIdx, probe->mCubeIndex); + } + // Remove QUADS rendering mode + //gGL.begin(gGL.QUADS); + //gGL.vertex3f(-1, -1, -1); + //gGL.vertex3f(1, -1, -1); + //gGL.vertex3f(1, 1, -1); + //gGL.vertex3f(-1, 1, -1); + //gGL.end(); + gGL.begin(gGL.TRIANGLES); + gGL.vertex3f(-1, -1, -1); + gGL.vertex3f(1, -1, -1); + gGL.vertex3f(1, 1, -1); + gGL.vertex3f(-1, -1, -1); + gGL.vertex3f(1, 1, -1); + gGL.vertex3f(-1, 1, -1); + gGL.end(); + // + gGL.flush(); + + S32 res = mMipChain[i].getWidth(); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); + mMipChain[i].flush(); + } + } + gRadianceGenProgram.unbind(); + + //generate irradiance map + gIrradianceGenProgram.bind(); + channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + mTexture->bind(channel); + + gIrradianceGenProgram.uniform1i(sSourceIdx, probe->mCubeIndex); + + int start_mip = 0; + // find the mip target to start with based on irradiance map resolution + for (start_mip = 0; start_mip < mMipChain.size(); ++start_mip) + { + if (mMipChain[start_mip].getWidth() == LL_IRRADIANCE_MAP_RESOLUTION) + { + break; + } + } + + for (int i = start_mip; i < mMipChain.size(); ++i) + { + for (int cf = 0; cf < 6; ++cf) + { // for each cube face + LLCoordFrame frame; + frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); + + F32 mat[16]; + frame.getOpenGLRotation(mat); + gGL.loadMatrix(mat); + + mMipChain[i].bindTarget(); + + // Remove QUADS rendering mode + //gGL.begin(gGL.QUADS); + //gGL.vertex3f(-1, -1, -1); + //gGL.vertex3f(1, -1, -1); + //gGL.vertex3f(1, 1, -1); + //gGL.vertex3f(-1, 1, -1); + //gGL.end(); + gGL.begin(gGL.TRIANGLES); + gGL.vertex3f(-1, -1, -1); + gGL.vertex3f(1, -1, -1); + gGL.vertex3f(1, 1, -1); + gGL.vertex3f(-1, -1, -1); + gGL.vertex3f(1, 1, -1); + gGL.vertex3f(-1, 1, -1); + gGL.end(); + // + gGL.flush(); + + S32 res = mMipChain[i].getWidth(); + mIrradianceMaps->bind(channel); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); + mTexture->bind(channel); + mMipChain[i].flush(); + } + } + gIrradianceGenProgram.unbind(); + } } void LLReflectionMapManager::rebuild() @@ -523,7 +630,7 @@ void LLReflectionMapManager::updateNeighbors(LLReflectionMap* probe) for (auto& other : probe->mNeighbors) { - auto& iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe); + auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe); llassert(iter != other->mNeighbors.end()); // <--- bug davep if this ever happens, something broke badly other->mNeighbors.erase(iter); } @@ -577,6 +684,11 @@ void LLReflectionMapManager::updateUniforms() S32 count = 0; U32 nc = 0; // neighbor "cursor" - index into refNeighbor to start writing the next probe's list of neighbors + LLEnvironment& environment = LLEnvironment::instance(); + LLSettingsSky::ptr_t psky = environment.getCurrentSky(); + + F32 minimum_ambiance = psky->getReflectionProbeAmbiance(); + for (auto* refmap : mReflectionMaps) { if (refmap == nullptr) @@ -609,7 +721,7 @@ void LLReflectionMapManager::updateUniforms() rpd.refIndex[count][3] = -rpd.refIndex[count][3]; } - rpd.refParams[count].set(refmap->getAmbiance(), 0.f, 0.f, 0.f); + rpd.refParams[count].set(llmax(minimum_ambiance, refmap->getAmbiance()), 0.f, 0.f, 0.f); S32 ni = nc; // neighbor ("index") - index into refNeighbor to write indices for current reflection probe's neighbors { diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 3b5cdc5520..5f0b11ec17 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -29,6 +29,7 @@ #include "llreflectionmap.h" #include "llrendertarget.h" #include "llcubemaparray.h" +#include "llcubemap.h" class LLSpatialGroup; class LLViewerObject; @@ -38,6 +39,7 @@ class LLViewerObject; // reflection probe resolution #define LL_REFLECTION_PROBE_RESOLUTION 256 +#define LL_IRRADIANCE_MAP_RESOLUTION 64 // reflection probe mininum scale #define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f; @@ -111,9 +113,12 @@ private: std::vector mMipChain; - // storage for reflection probes + // storage for reflection probe radiance maps (plus two scratch space cubemaps) LLPointer mTexture; + // storage for reflection probe irradiance maps + LLPointer mIrradianceMaps; + // array indicating if a particular cubemap is free bool mCubeFree[LL_REFLECTION_PROBE_COUNT]; diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 14a9f4aa30..ed823fbba4 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -758,6 +758,7 @@ LLSettingsSky::parammapping_t LLSettingsVOSky::getParameterMap() const param_map[SETTING_SKY_DROPLET_RADIUS] = DefaultParam(LLShaderMgr::DROPLET_RADIUS, sky_defaults[SETTING_SKY_DROPLET_RADIUS]); param_map[SETTING_SKY_ICE_LEVEL] = DefaultParam(LLShaderMgr::ICE_LEVEL, sky_defaults[SETTING_SKY_ICE_LEVEL]); + param_map[SETTING_REFLECTION_PROBE_AMBIANCE] = DefaultParam(LLShaderMgr::REFLECTION_PROBE_AMBIANCE, sky_defaults[SETTING_REFLECTION_PROBE_AMBIANCE]); // AdvancedAtmospherics TODO // Provide mappings for new shader params here } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 9014d44c1d..b305460ae6 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -124,9 +124,14 @@ public: LL_ALIGN_16(LLFace* mFace); //associated face F32 mDistance; U32 mDrawMode; - LLMaterialPtr mMaterial; // If this is null, the following parameters are unused. - LLMaterialID mMaterialID; - U32 mShaderMask; + + // Material points here are likely for debugging only and are immaterial (zing!) + LLMaterialPtr mMaterial; + LLPointer mGLTFMaterial; + + LLUUID mMaterialID; // id of LLGLTFMaterial or LLMaterial applied to this draw info + + U32 mShaderMask; U32 mBlendFuncSrc; U32 mBlendFuncDst; BOOL mHasGlow; @@ -134,6 +139,8 @@ public: const LLMatrix4* mSpecularMapMatrix; LLPointer mNormalMap; const LLMatrix4* mNormalMapMatrix; + LLPointer mEmissiveMap; + LLVector4 mSpecColor; // XYZ = Specular RGB, W = Specular Exponent F32 mEnvIntensity; F32 mAlphaMaskCutoff; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index e9ca039f53..ef1d450159 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -241,10 +241,8 @@ void LLFloaterTexturePicker::setActive( BOOL active ) void LLFloaterTexturePicker::setCanApplyImmediately(BOOL b) { mCanApplyImmediately = b; - if (!mCanApplyImmediately) - { - getChild("apply_immediate_check")->setValue(FALSE); - } + + getChild("apply_immediate_check")->setValue(mCanApplyImmediately); updateFilterPermMask(); } @@ -480,11 +478,7 @@ BOOL LLFloaterTexturePicker::postBuild() getChild("apply_immediate_check")->setValue(gSavedSettings.getBOOL("TextureLivePreview")); childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this); - - if (!mCanApplyImmediately) - { - getChildView("show_folders_check")->setEnabled(FALSE); - } + getChildView("apply_immediate_check")->setEnabled(mCanApplyImmediately); getChild("Pipette")->setCommitCallback( boost::bind(&LLFloaterTexturePicker::onBtnPipette, this)); // UUID picker @@ -553,7 +547,7 @@ void LLFloaterTexturePicker::draw() } getChildView("Default")->setEnabled(mImageAssetID != mDefaultImageAssetID || mTentative); - getChildView("Blank")->setEnabled(mImageAssetID != mBlankImageAssetID || mTentative); + getChildView("Blank")->setEnabled((mImageAssetID != mBlankImageAssetID && mBlankImageAssetID != mDefaultImageAssetID) || mTentative); getChildView("Transparent")->setEnabled(mImageAssetID != mTransparentImageAssetID || mTentative); // FIRE-5082: "Transparent" button in Texture Panel getChildView("None")->setEnabled(mAllowNoTexture && (!mImageAssetID.isNull() || mTentative)); @@ -1311,7 +1305,7 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p) mOnCloseCallback(NULL), mOnSelectCallback(NULL), mBorderColor( p.border_color() ), - mAllowNoTexture( FALSE ), + mAllowNoTexture( p.allow_no_texture ), mAllowLocalTexture( TRUE ), mImmediateFilterPermMask( PERM_NONE ), mNonImmediateFilterPermMask( PERM_NONE ), diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 10e1f0e1d5..4f972989bb 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -93,7 +93,7 @@ public: : image_id("image"), default_image_id("default_image_id"), default_image_name("default_image_name"), - allow_no_texture("allow_no_texture"), + allow_no_texture("allow_no_texture", false), can_apply_immediately("can_apply_immediately"), no_commit_on_selection("no_commit_on_selection", false), label_width("label_width", -1), diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index dcea1176b1..b376a7e2b3 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -155,6 +155,7 @@ #include "llinspectobject.h" #include "llinspectremoteobject.h" #include "llinspecttoast.h" +#include "llmaterialeditor.h" #include "llmoveview.h" // [FS communication UI] //#include "llfloaterimnearbychat.h @@ -416,6 +417,8 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("save_camera_preset", "floater_save_camera_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("script_colors", "floater_script_ed_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("material_editor", "floater_material_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build); LLFloaterReg::add("test_inspectors", "floater_test_inspectors.xml", &LLFloaterReg::build); //LLFloaterReg::add("test_list_view", "floater_test_list_view.xml",&LLFloaterReg::build); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 3cdf8bb86d..00d883e507 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -150,6 +150,7 @@ LLLocalizedInventoryItemsDictionary::LLLocalizedInventoryItemsDictionary() mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable"); mInventoryItemsDict["New Gesture"] = LLTrans::getString("New Gesture"); + mInventoryItemsDict["New Material"] = LLTrans::getString("New Material"); mInventoryItemsDict["New Script"] = LLTrans::getString("New Script"); mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder"); mInventoryItemsDict["New Note"] = LLTrans::getString("New Note"); @@ -2042,6 +2043,7 @@ void remove_folder_contents(const LLUUID& category, bool keep_outfit_links, const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not) const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not) const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not) +const std::string NEW_MATERIAL_NAME = "New Material"; // *TODO:Translate? (probably not) // ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements... void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid) @@ -2097,6 +2099,15 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, LLInventoryType::IT_GESTURE, PERM_ALL); // overridden in create_new_item } + else if ("material" == type_name) + { + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL); + create_new_item(NEW_GESTURE_NAME, + parent_id, + LLAssetType::AT_MATERIAL, + LLInventoryType::IT_MATERIAL, + PERM_ALL); // overridden in create_new_item + } else if (("sky" == type_name) || ("water" == type_name) || ("daycycle" == type_name)) { LLSettingsType::type_e stype(LLSettingsType::ST_NONE); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 14e393ac63..94e0410644 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -37,6 +37,7 @@ #include "llbuycurrencyhtml.h" #include "llfloatermap.h" #include "llfloatermodelpreview.h" +#include "llmaterialeditor.h" #include "llfloatersnapshot.h" #include "llfloateroutfitsnapshot.h" #include "llimage.h" @@ -109,6 +110,20 @@ class LLFileEnableUploadModel : public view_listener_t } }; +class LLFileEnableUploadMaterial : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::findInstance("material_editor"); + if (me && me->isShown()) + { + return false; + } + + return true; + } +}; + class LLMeshEnabled : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -290,6 +305,7 @@ static std::string SLOBJECT_EXTENSIONS = "slobject"; #endif static std::string ALL_FILE_EXTENSIONS = "*.*"; static std::string MODEL_EXTENSIONS = "dae"; +static std::string MATERIAL_EXTENSIONS = "gltf glb"; std::string build_extensions_string(LLFilePicker::ELoadFilter filter) { @@ -306,6 +322,8 @@ std::string build_extensions_string(LLFilePicker::ELoadFilter filter) return SLOBJECT_EXTENSIONS; case LLFilePicker::FFLOAD_MODEL: return MODEL_EXTENSIONS; + case LLFilePicker::FFLOAD_MATERIAL: + return MATERIAL_EXTENSIONS; case LLFilePicker::FFLOAD_XML: return XML_EXTENSIONS; case LLFilePicker::FFLOAD_ALL: @@ -590,7 +608,20 @@ class LLFileUploadModel : public view_listener_t return TRUE; } }; - + +class LLFileUploadMaterial : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor"); + if (me) + { + me->importMaterial(); + } + return TRUE; + } +}; + class LLFileUploadSound : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -1271,6 +1302,7 @@ void init_menu_file() view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound"); view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim"); view_listener_t::addCommit(new LLFileUploadModel(), "File.UploadModel"); + view_listener_t::addCommit(new LLFileUploadMaterial(), "File.UploadMaterial"); view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk"); view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow"); view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows"); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 1088da323f..734f6a4084 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -424,6 +424,11 @@ void LLViewerObject::deleteTEImages() delete[] mTESpecularMaps; mTESpecularMaps = NULL; } + + mGLTFAlbedoMaps.clear(); + mGLTFNormalMaps.clear(); + mGLTFMetallicRoughnessMaps.clear(); + mGLTFEmissiveMaps.clear(); } void LLViewerObject::markDead() @@ -4890,6 +4895,11 @@ void LLViewerObject::setNumTEs(const U8 num_tes) mTEImages = new_images; mTENormalMaps = new_normmaps; mTESpecularMaps = new_specmaps; + + mGLTFAlbedoMaps.resize(num_tes); + mGLTFNormalMaps.resize(num_tes); + mGLTFMetallicRoughnessMaps.resize(num_tes); + mGLTFEmissiveMaps.resize(num_tes); } else { @@ -5028,23 +5038,28 @@ void LLViewerObject::updateAvatarMeshVisibility(const LLUUID& id, const LLUUID& } } -void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry) + +void LLViewerObject::setTE(const U8 te, const LLTextureEntry& texture_entry) { - LLUUID old_image_id; - if (getTE(te)) - { - old_image_id = getTE(te)->getID(); - } - - LLPrimitive::setTE(te, texture_entry); + LLUUID old_image_id; + if (getTE(te)) + { + old_image_id = getTE(te)->getID(); + } - const LLUUID& image_id = getTEref(te).getID(); - LLViewerTexture* bakedTexture = getBakedTextureForMagicId(image_id); - mTEImages[te] = bakedTexture ? bakedTexture : LLViewerTextureManager::getFetchedTexture(image_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLPrimitive::setTE(te, texture_entry); - - updateAvatarMeshVisibility(image_id,old_image_id); - + const LLUUID& image_id = getTEref(te).getID(); + LLViewerTexture* bakedTexture = getBakedTextureForMagicId(image_id); + mTEImages[te] = bakedTexture ? bakedTexture : LLViewerTextureManager::getFetchedTexture(image_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + + updateAvatarMeshVisibility(image_id, old_image_id); + + updateTEMaterialTextures(te); +} + +void LLViewerObject::updateTEMaterialTextures(U8 te) +{ if (getTEref(te).getMaterialParams().notNull()) { const LLUUID& norm_id = getTEref(te).getMaterialParams()->getNormalID(); @@ -5053,6 +5068,20 @@ void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry) const LLUUID& spec_id = getTEref(te).getMaterialParams()->getSpecularID(); mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(spec_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE); } + + auto fetch_texture = [](const LLUUID& id) + { + return LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE); + }; + + LLGLTFMaterial* mat = getTE(te)->getGLTFMaterial(); + if (mat != nullptr) + { + mGLTFAlbedoMaps[te] = fetch_texture(mat->mAlbedoId); + mGLTFNormalMaps[te] = fetch_texture(mat->mNormalId); + mGLTFMetallicRoughnessMaps[te] = fetch_texture(mat->mMetallicRoughnessId); + mGLTFEmissiveMaps[te] = fetch_texture(mat->mEmissiveId); + } } void LLViewerObject::refreshBakeTexture() @@ -5593,7 +5622,6 @@ void LLViewerObject::fitFaceTexture(const U8 face) LL_INFOS() << "fitFaceTexture not implemented" << LL_ENDL; } - LLBBox LLViewerObject::getBoundingBoxAgent() const { LLVector3 position_agent; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 489377a67e..d97f7b5fa0 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -327,6 +327,7 @@ public: /*virtual*/ void setNumTEs(const U8 num_tes); /*virtual*/ void setTE(const U8 te, const LLTextureEntry &texture_entry); + void updateTEMaterialTextures(U8 te); /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid); /*virtual*/ S32 setTENormalMap(const U8 te, const LLUUID &uuid); /*virtual*/ S32 setTESpecularMap(const U8 te, const LLUUID &uuid); @@ -366,6 +367,12 @@ public: LLViewerTexture *getTEImage(const U8 te) const; LLViewerTexture *getTENormalMap(const U8 te) const; LLViewerTexture *getTESpecularMap(const U8 te) const; + + LLViewerTexture* getGLTFAlbedoMap(U8 te) const { return mGLTFAlbedoMaps[te]; } + LLViewerTexture* getGLTFNormalMap(U8 te) const { return mGLTFNormalMaps[te]; } + LLViewerTexture* getGLTFEmissiveMap(U8 te) const { return mGLTFEmissiveMaps[te]; } + LLViewerTexture* getGLTFMetallicRoughnessMap(U8 te) const { return mGLTFMetallicRoughnessMaps[te]; } + bool isImageAlphaBlended(const U8 te) const; @@ -692,6 +699,13 @@ public: LLPointer *mTEImages; LLPointer *mTENormalMaps; LLPointer *mTESpecularMaps; + + std::vector > mGLTFAlbedoMaps; + std::vector > mGLTFNormalMaps; + std::vector > mGLTFMetallicRoughnessMaps; + std::vector > mGLTFEmissiveMaps; + + // true if user can select this object by clicking under any circumstances (even if pick_unselectable is true) // can likely be factored out diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 82815f51f5..b7674bd7fa 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -85,6 +85,8 @@ LLGLSLShader gCustomAlphaProgram; LLGLSLShader gGlowCombineProgram; LLGLSLShader gSplatTextureRectProgram; LLGLSLShader gReflectionMipProgram; +LLGLSLShader gRadianceGenProgram; +LLGLSLShader gIrradianceGenProgram; LLGLSLShader gGlowCombineFXAAProgram; LLGLSLShader gTwoTextureAddProgram; LLGLSLShader gTwoTextureCompareProgram; @@ -266,6 +268,7 @@ LLGLSLShader gRlvSphereProgram; LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2]; LLGLSLShader gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2]; LLGLSLShader gDeferredPBROpaqueProgram; +LLGLSLShader gDeferredSkinnedPBROpaqueProgram; //helper for making a rigged variant of a given shader bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader) @@ -769,6 +772,8 @@ void LLViewerShaderMgr::unloadShaders() gGlowCombineProgram.unload(); gSplatTextureRectProgram.unload(); gReflectionMipProgram.unload(); + gRadianceGenProgram.unload(); + gIrradianceGenProgram.unload(); gGlowCombineFXAAProgram.unload(); gTwoTextureAddProgram.unload(); gTwoTextureCompareProgram.unload(); @@ -1342,6 +1347,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() } gDeferredPBROpaqueProgram.unload(); + gDeferredSkinnedPBROpaqueProgram.unload(); return TRUE; } @@ -1633,22 +1639,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredMaterialWaterProgram[i].createShader(NULL, NULL);//&mWLUniforms); llassert(success); } - - if (success) - { - gDeferredPBROpaqueProgram.mName = "Deferred PBR Opaque Shader"; - gDeferredPBROpaqueProgram.mFeatures.encodesNormal = true; - gDeferredPBROpaqueProgram.mFeatures.hasSrgb = true; - - gDeferredPBROpaqueProgram.mShaderFiles.clear(); - gDeferredPBROpaqueProgram.mShaderFiles.push_back(make_pair("deferred/pbropaqueV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredPBROpaqueProgram.mShaderFiles.push_back(make_pair("deferred/pbropaqueF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredPBROpaqueProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - gDeferredPBROpaqueProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - //gDeferredPBROpaqueProgram.addPermutation("HAS_NORMAL_MAP", "1"); - success = gDeferredPBROpaqueProgram.createShader(NULL, NULL); - llassert(success); - } } gDeferredMaterialProgram[1].mFeatures.hasLighting = true; @@ -1669,6 +1659,28 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredMaterialWaterProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; gDeferredMaterialWaterProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + if (success) + { + gDeferredPBROpaqueProgram.mName = "Deferred PBR Opaque Shader"; + gDeferredPBROpaqueProgram.mFeatures.encodesNormal = true; + gDeferredPBROpaqueProgram.mFeatures.hasSrgb = true; + + gDeferredPBROpaqueProgram.mShaderFiles.clear(); + gDeferredPBROpaqueProgram.mShaderFiles.push_back(make_pair("deferred/pbropaqueV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredPBROpaqueProgram.mShaderFiles.push_back(make_pair("deferred/pbropaqueF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredPBROpaqueProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredPBROpaqueProgram.addPermutation("HAS_NORMAL_MAP", "1"); + gDeferredPBROpaqueProgram.addPermutation("HAS_SPECULAR_MAP", "1"); + gDeferredPBROpaqueProgram.addPermutation("HAS_EMISSIVE_MAP", "1"); + gDeferredPBROpaqueProgram.addPermutation("DIFFUSE_ALPHA_MODE", "0"); + + success = make_rigged_variant(gDeferredPBROpaqueProgram, gDeferredSkinnedPBROpaqueProgram); + if (success) + { + success = gDeferredPBROpaqueProgram.createShader(NULL, NULL); + } + llassert(success); + } if (success) { @@ -3843,6 +3855,26 @@ BOOL LLViewerShaderMgr::loadShadersInterface() } } + if (success) + { + gRadianceGenProgram.mName = "Radiance Gen Shader"; + gRadianceGenProgram.mShaderFiles.clear(); + gRadianceGenProgram.mShaderFiles.push_back(make_pair("interface/radianceGenV.glsl", GL_VERTEX_SHADER_ARB)); + gRadianceGenProgram.mShaderFiles.push_back(make_pair("interface/radianceGenF.glsl", GL_FRAGMENT_SHADER_ARB)); + gRadianceGenProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gRadianceGenProgram.createShader(NULL, NULL); + } + + if (success) + { + gIrradianceGenProgram.mName = "Irradiance Gen Shader"; + gIrradianceGenProgram.mShaderFiles.clear(); + gIrradianceGenProgram.mShaderFiles.push_back(make_pair("interface/irradianceGenV.glsl", GL_VERTEX_SHADER_ARB)); + gIrradianceGenProgram.mShaderFiles.push_back(make_pair("interface/irradianceGenF.glsl", GL_FRAGMENT_SHADER_ARB)); + gIrradianceGenProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gIrradianceGenProgram.createShader(NULL, NULL); + } + if( !success ) { mShaderLevel[SHADER_INTERFACE] = 0; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 937595cec9..533e8ed4fb 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -162,6 +162,8 @@ extern LLGLSLShader gCustomAlphaProgram; extern LLGLSLShader gGlowCombineProgram; extern LLGLSLShader gSplatTextureRectProgram; extern LLGLSLShader gReflectionMipProgram; +extern LLGLSLShader gRadianceGenProgram; +extern LLGLSLShader gIrradianceGenProgram; extern LLGLSLShader gGlowCombineFXAAProgram; extern LLGLSLShader gDebugProgram; extern LLGLSLShader gClipProgram; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 390281eaf4..1aa41f6a9d 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -308,6 +308,13 @@ LLPointer LLViewerTextureManager::getLocalTexture(const U32 wid return tex; } +LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(const LLImageRaw* raw, FTType type, bool usemipmaps) +{ + LLViewerFetchedTexture* ret = new LLViewerFetchedTexture(raw, type, usemipmaps); + gTextureList.addImage(ret, TEX_LIST_STANDARD); + return ret; +} + LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture( const LLUUID &image_id, FTType f_type, diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 6ab56f8555..82a8c6dc5f 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -714,6 +714,8 @@ public: static LLPointer getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) ; static LLPointer getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ; + static LLViewerFetchedTexture* getFetchedTexture(const LLImageRaw* raw, FTType type, bool usemipmaps); + static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id, FTType f_type = FTT_DEFAULT, BOOL usemipmap = TRUE, diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 474539b39f..35c98120f1 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5665,10 +5665,26 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, LLViewerTexture* tex = facep->getTexture(); + U8 index = facep->getTextureIndex(); - LLMaterial* mat = facep->getTextureEntry()->getMaterialParams().get(); - LLMaterialID mat_id = facep->getTextureEntry()->getMaterialID(); + LLMaterial* mat = nullptr; + + LLUUID mat_id; + + LLGLTFMaterial* gltf_mat = facep->getTextureEntry()->getGLTFMaterial(); + if (gltf_mat != nullptr) + { + mat_id = gltf_mat->getHash(); // TODO: cache this hash + } + else + { + mat = facep->getTextureEntry()->getMaterialParams().get(); + if (mat) + { + mat_id = facep->getTextureEntry()->getMaterialID().asUUID(); + } + } bool batchable = false; @@ -5690,7 +5706,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, if (index < FACE_DO_NOT_BATCH_TEXTURES && idx >= 0) { - if (mat || draw_vec[idx]->mMaterial) + if (mat || gltf_mat || draw_vec[idx]->mMaterial) { //can't batch textures when materials are present (yet) batchable = false; } @@ -5722,7 +5738,6 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && #endif - //draw_vec[idx]->mMaterial == mat && draw_vec[idx]->mMaterialID == mat_id && draw_vec[idx]->mFullbright == fullbright && draw_vec[idx]->mBump == bump && @@ -5779,11 +5794,22 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_info->mEnvIntensity = spec; draw_info->mSpecularMap = NULL; draw_info->mMaterial = mat; + draw_info->mGLTFMaterial = gltf_mat; draw_info->mShaderMask = shader_mask; draw_info->mAvatar = facep->mAvatar; draw_info->mSkinInfo = facep->mSkinInfo; - if (mat) + if (gltf_mat) + { + LLViewerObject* vobj = facep->getViewerObject(); + U8 te = facep->getTEOffset(); + + draw_info->mTexture = vobj->getGLTFAlbedoMap(te); + draw_info->mNormalMap = vobj->getGLTFNormalMap(te); + draw_info->mSpecularMap = vobj->getGLTFMetallicRoughnessMap(te); + draw_info->mEmissiveMap = vobj->getGLTFEmissiveMap(te); + } + else if (mat) { draw_info->mMaterialID = mat_id; @@ -6170,6 +6196,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) continue; } +#if 0 #if LL_RELEASE_WITH_DEBUG_INFO const LLUUID pbr_id( "49c88210-7238-2a6b-70ac-92d4f35963cf" ); const LLUUID obj_id( vobj->getID() ); @@ -6177,6 +6204,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) #else bool is_pbr = false; #endif +#else + bool is_pbr = facep->getTextureEntry()->getGLTFMaterial() != nullptr; +#endif //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render // batch, it will recover its vertex buffer reference from the spatial group @@ -6319,31 +6349,43 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (gPipeline.canUseWindLightShadersOnObjects() && LLPipeline::sRenderBump) { - // We just skip all of this is there is no te entry. This might get some funny results (which would be a face without te anyway). - // if (LLPipeline::sRenderDeferred && te->getMaterialParams().notNull() && !te->getMaterialID().isNull()) - if (LLPipeline::sRenderDeferred && te && te->getMaterialParams().notNull() && !te->getMaterialID().isNull()) - // + // Skip if no te entry + if (!te) + continue; + + LLGLTFMaterial* gltf_mat = te->getGLTFMaterial(); + + if (LLPipeline::sRenderDeferred && + (gltf_mat != nullptr || (te->getMaterialParams().notNull() && !te->getMaterialID().isNull()))) { - LLMaterial* mat = te->getMaterialParams().get(); - if (mat->getNormalID().notNull()) - { - if (mat->getSpecularID().notNull()) - { //has normal and specular maps (needs texcoord1, texcoord2, and tangent) - add_face(sNormSpecFaces, normspec_count, facep); - } - else - { //has normal map (needs texcoord1 and tangent) - add_face(sNormFaces, norm_count, facep); - } - } - else if (mat->getSpecularID().notNull()) - { //has specular map but no normal map, needs texcoord2 - add_face(sSpecFaces, spec_count, facep); - } - else - { //has neither specular map nor normal map, only needs texcoord0 - add_face(sSimpleFaces, simple_count, facep); - } + if (gltf_mat != nullptr) + { + // all gltf materials have all vertex attributes for now + add_face(sNormSpecFaces, normspec_count, facep); + } + else + { + LLMaterial* mat = te->getMaterialParams().get(); + if (mat->getNormalID().notNull()) + { + if (mat->getSpecularID().notNull()) + { //has normal and specular maps (needs texcoord1, texcoord2, and tangent) + add_face(sNormSpecFaces, normspec_count, facep); + } + else + { //has normal map (needs texcoord1 and tangent) + add_face(sNormFaces, norm_count, facep); + } + } + else if (mat->getSpecularID().notNull()) + { //has specular map but no normal map, needs texcoord2 + add_face(sSpecFaces, spec_count, facep); + } + else + { //has neither specular map nor normal map, only needs texcoord0 + add_face(sSimpleFaces, simple_count, facep); + } + } } else if (te->getBumpmap()) { //needs normal + tangent @@ -7058,15 +7100,24 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE; - LLMaterial* mat = te->getMaterialParams().get(); + LLGLTFMaterial* gltf_mat = te->getGLTFMaterial(); - bool can_be_shiny = true; - if (mat) - { - U8 mode = mat->getDiffuseAlphaMode(); - can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || - mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; - } + LLMaterial* mat = nullptr; + bool can_be_shiny = false; + + // ignore traditional material if GLTF material is present + if (gltf_mat == nullptr) + { + mat = te->getMaterialParams().get(); + + can_be_shiny = true; + if (mat) + { + U8 mode = mat->getDiffuseAlphaMode(); + can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || + mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; + } + } F32 te_alpha = te->getColor().mV[3]; bool use_legacy_bump = te->getBumpmap() && (te->getBumpmap() < 18) && (!mat || mat->getNormalID().isNull()); @@ -7075,10 +7126,15 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace is_alpha = (is_alpha || transparent) ? TRUE : FALSE; - if (mat && LLPipeline::sRenderDeferred && !hud_group) + if ((gltf_mat || mat) && LLPipeline::sRenderDeferred && !hud_group) { bool material_pass = false; + if (gltf_mat) + { // all other parameters ignored if gltf material is present + registerFace(group, facep, LLRenderPass::PASS_PBR_OPAQUE); + } + else // do NOT use 'fullbright' for this logic or you risk sending // things without normals down the materials pipeline and will // render poorly if not crash NORSPEC-240,314 diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 210fe25efb..6a381b7efe 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -116,39 +116,39 @@ public: }; public: - LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); - /*virtual*/ void markDead(); // Override (and call through to parent) to clean up media references + LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); + void markDead() override; // Override (and call through to parent) to clean up media references - /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); + LLDrawable* createDrawable(LLPipeline *pipeline) override; void deleteFaces(); void animateTextures(); BOOL isVisible() const ; - /*virtual*/ BOOL isActive() const; - /*virtual*/ BOOL isAttachment() const; - /*virtual*/ BOOL isRootEdit() const; // overridden for sake of attachments treating themselves as a root object - /*virtual*/ BOOL isHUDAttachment() const; + BOOL isActive() const override; + BOOL isAttachment() const override; + BOOL isRootEdit() const override; // overridden for sake of attachments treating themselves as a root object + BOOL isHUDAttachment() const override; void generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point); - /*virtual*/ BOOL setParent(LLViewerObject* parent); - S32 getLOD() const { return mLOD; } + /*virtual*/ BOOL setParent(LLViewerObject* parent) override; + S32 getLOD() const override { return mLOD; } void setNoLOD() { mLOD = NO_LOD; mLODChanged = TRUE; } bool isNoLOD() const { return NO_LOD == mLOD; } - const LLVector3 getPivotPositionAgent() const; + const LLVector3 getPivotPositionAgent() const override; const LLMatrix4& getRelativeXform() const { return mRelativeXform; } const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; } - /*virtual*/ const LLMatrix4 getRenderMatrix() const; + /*virtual*/ const LLMatrix4 getRenderMatrix() const override; typedef std::map texture_cost_t; U32 getRenderCost(texture_cost_t &textures) const; - /*virtual*/ F32 getEstTrianglesMax() const; - /*virtual*/ F32 getEstTrianglesStreamingCost() const; - /* virtual*/ F32 getStreamingCost() const; - /*virtual*/ bool getCostData(LLMeshCostData& costs) const; + /*virtual*/ F32 getEstTrianglesMax() const override; + /*virtual*/ F32 getEstTrianglesStreamingCost() const override; + /* virtual*/ F32 getStreamingCost() const override; + /*virtual*/ bool getCostData(LLMeshCostData& costs) const override; - /*virtual*/ U32 getTriangleCount(S32* vcount = NULL) const; - /*virtual*/ U32 getHighLODTriangleCount(); + /*virtual*/ U32 getTriangleCount(S32* vcount = NULL) const override; + /*virtual*/ U32 getHighLODTriangleCount() override; // Mesh Info in object panel /*virtual*/ U32 getLODTriangleCount(S32 lod); // @@ -162,7 +162,7 @@ public: LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point LLVector4a* normal = NULL, // return the surface normal at the intersection point LLVector4a* tangent = NULL // return the surface tangent at the intersection point - ); + ) override; LLVector3 agentPositionToVolume(const LLVector3& pos) const; LLVector3 agentDirectionToVolume(const LLVector3& dir) const; @@ -172,17 +172,17 @@ public: BOOL getVolumeChanged() const { return mVolumeChanged; } - /*virtual*/ F32 getRadius() const { return mVObjRadius; }; - const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const; + F32 getVObjRadius() const override { return mVObjRadius; }; + const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const override; - void markForUpdate(BOOL priority); + void markForUpdate(BOOL priority) override; void markForUnload() { LLViewerObject::markForUnload(TRUE); mVolumeChanged = TRUE; } void faceMappingChanged() { mFaceMappingChanged=TRUE; }; - /*virtual*/ void onShift(const LLVector4a &shift_vector); // Called when the drawable shifts + /*virtual*/ void onShift(const LLVector4a &shift_vector) override; // Called when the drawable shifts - /*virtual*/ void parameterChanged(U16 param_type, bool local_origin); - /*virtual*/ void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin); + /*virtual*/ void parameterChanged(U16 param_type, bool local_origin) override; + /*virtual*/ void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin) override; // update mReflectionProbe based on isReflectionProbe() void updateReflectionProbePtr(); @@ -190,40 +190,40 @@ public: /*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, const EObjectUpdateType update_type, - LLDataPacker *dp); + LLDataPacker *dp) override; - /*virtual*/ void setSelected(BOOL sel); - /*virtual*/ BOOL setDrawableParent(LLDrawable* parentp); + /*virtual*/ void setSelected(BOOL sel) override; + /*virtual*/ BOOL setDrawableParent(LLDrawable* parentp) override; - /*virtual*/ void setScale(const LLVector3 &scale, BOOL damped); + /*virtual*/ void setScale(const LLVector3 &scale, BOOL damped) override; - /*virtual*/ void changeTEImage(S32 index, LLViewerTexture* new_image) ; - /*virtual*/ void setNumTEs(const U8 num_tes); - /*virtual*/ void setTEImage(const U8 te, LLViewerTexture *imagep); - /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid); - /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color); - /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color); - /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump); - /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny); - /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright); - /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump); - /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags); - /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); - /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); + /*virtual*/ void changeTEImage(S32 index, LLViewerTexture* new_image) override; + /*virtual*/ void setNumTEs(const U8 num_tes) override; + /*virtual*/ void setTEImage(const U8 te, LLViewerTexture *imagep) override; + /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid) override; + /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color) override; + /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color) override; + /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump) override; + /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny) override; + /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright) override; + /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump) override; + /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags) override; + /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow) override; + /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) override; static void setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID& pMaterialID, const LLMaterialPtr pMaterialParams, U32 te); - /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams); - /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t); - /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s); - /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t); - /*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen); - /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media); - /*virtual*/ BOOL setMaterial(const U8 material); + /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) override; + /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t) override; + /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s) override; + /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t) override; + /*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen) override; + /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media) override; + /*virtual*/ BOOL setMaterial(const U8 material) override; void setTexture(const S32 face); S32 getIndexInTex(U32 ch) const {return mIndexInTex[ch];} - /*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false); + /*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false) override; void updateSculptTexture(); void setIndexInTex(U32 ch, S32 index) { mIndexInTex[ch] = index ;} void sculpt(); @@ -232,21 +232,21 @@ public: void* user_data, S32 status, LLExtStat ext_status); void updateRelativeXform(bool force_identity = false); - /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); - /*virtual*/ void updateFaceSize(S32 idx); - /*virtual*/ BOOL updateLOD(); - void updateRadius(); - /*virtual*/ void updateTextures(); + /*virtual*/ BOOL updateGeometry(LLDrawable *drawable) override; + /*virtual*/ void updateFaceSize(S32 idx) override; + /*virtual*/ BOOL updateLOD() override; + void updateRadius() override; + /*virtual*/ void updateTextures() override; void updateTextureVirtualSize(bool forced = false); void updateFaceFlags(); void regenFaces(); BOOL genBBoxes(BOOL force_global); void preRebuild(); - virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max); - virtual F32 getBinRadius(); + virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max) override; + virtual F32 getBinRadius() override; - virtual U32 getPartitionType() const; + virtual U32 getPartitionType() const override; // For Lights void setIsLight(BOOL is_light); @@ -305,11 +305,11 @@ public: // Flexible Objects U32 getVolumeInterfaceID() const; - virtual BOOL isFlexible() const; - virtual BOOL isSculpted() const; - virtual BOOL isMesh() const; - virtual BOOL isRiggedMesh() const; - virtual BOOL hasLightTexture() const; + virtual BOOL isFlexible() const override; + virtual BOOL isSculpted() const override; + virtual BOOL isMesh() const override; + virtual BOOL isRiggedMesh() const override; + virtual BOOL hasLightTexture() const override; BOOL isVolumeGlobal() const; @@ -326,12 +326,12 @@ public: void onSetExtendedMeshFlags(U32 flags); void setExtendedMeshFlags(U32 flags); bool canBeAnimatedObject() const; - bool isAnimatedObject() const; - virtual void onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent); - virtual void afterReparent(); + bool isAnimatedObject() const override; + virtual void onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent) override; + virtual void afterReparent() override; //virtual - void updateRiggingInfo(); + void updateRiggingInfo() override; S32 mLastRiggingInfoLOD; // Functions that deal with media, or media navigation diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 7d65a22c13..8bba4fc2c4 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -299,29 +299,33 @@ static LLStaticHashedString sKern("kern"); static LLStaticHashedString sKernScale("kern_scale"); //---------------------------------------- -std::string gPoolNames[] = +#if 0 +std::string gPoolNames[LLDrawPool::NUM_POOL_TYPES] = { // Correspond to LLDrawpool enum render type - "NONE", - "POOL_SIMPLE", - "POOL_GROUND", - "POOL_FULLBRIGHT", - "POOL_BUMP", - "POOL_MATERIALS", - "POOL_TERRAIN", - "POOL_SKY", - "POOL_WL_SKY", - "POOL_TREE", - "POOL_ALPHA_MASK", - "POOL_FULLBRIGHT_ALPHA_MASK", - "POOL_GRASS", - "POOL_INVISIBLE", - "POOL_AVATAR", - "POOL_VOIDWATER", - "POOL_WATER", - "POOL_GLOW", - "POOL_ALPHA" + "NONE" + , "POOL_SIMPLE" + , "POOL_GROUND" + , "POOL_FULLBRIGHT" + , "POOL_BUMP" + , "POOL_MATERIALS" + , "POOL_TERRAIN" + , "POOL_SKY" + , "POOL_WL_SKY" + , "POOL_TREE" + , "POOL_ALPHA_MASK" + , "POOL_FULLBRIGHT_ALPHA_MASK" + , "POOL_GRASS" + , "POOL_INVISIBLE" + , "POOL_AVATAR" + , "POOL_CONTROL_AV" // Animesh + , "POOL_VOIDWATER" + , "POOL_WATER" + , "POOL_GLOW" + , "POOL_ALPHA" + , "POOL_PBR_OPAQUE" }; +#endif void drawBox(const LLVector4a& c, const LLVector4a& r); void drawBoxOutline(const LLVector3& pos, const LLVector3& size); @@ -396,8 +400,12 @@ void validate_framebuffer_object(); // for_impostor -- whether or not these render targets are for an impostor (if true, avoids implicit sRGB conversions) bool addDeferredAttachments(LLRenderTarget& target, bool for_impostor = false) { - return target.addColorAttachment(for_impostor ? GL_RGBA : GL_SRGB8_ALPHA8) && //specular - target.addColorAttachment(GL_RGB10_A2); //normal+z + bool pbr = gSavedSettings.getBOOL("RenderPBR"); + bool valid = true + && target.addColorAttachment(for_impostor ? GL_RGBA : GL_SRGB8_ALPHA8) // frag-data[1] specular or PBR packed OcclusionRoughnessMetal + && target.addColorAttachment(GL_RGB10_A2) // frag_data[2] normal+z+fogmask, See: class1\deferred\materialF.glsl & softenlight + && (pbr ? target.addColorAttachment(GL_RGBA) : true); // frag_data[3] emissive + return valid; } LLPipeline::LLPipeline() : @@ -464,7 +472,7 @@ void LLPipeline::init() { refreshCachedSettings(); - mRT = new RenderTargetPack(); + mRT = &mMainRT; gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity"); gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize"); @@ -763,9 +771,6 @@ void LLPipeline::cleanup() mDeferredVB = NULL; mCubeVB = NULL; - - delete mRT; - mRT = nullptr; } //============================================================================ @@ -925,6 +930,16 @@ 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) + { // hacky -- allocate auxillary buffer + gCubeSnapshot = TRUE; + mRT = &mAuxillaryRT; + U32 res = LL_REFLECTION_PROBE_RESOLUTION * 2; + allocateScreenBuffer(res, res, 0); + mRT = &mMainRT; + gCubeSnapshot = FALSE; + } + // remember these dimensions mRT->width = resX; mRT->height = resY; @@ -1791,6 +1806,7 @@ U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* ima } LLMaterial* mat = te->getMaterialParams().get(); + LLGLTFMaterial* gltf_mat = te->getGLTFMaterial(); bool color_alpha = te->getColor().mV[3] < 0.999f; bool alpha = color_alpha; @@ -1824,6 +1840,10 @@ U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* ima { return LLDrawPool::POOL_BUMP; } + else if (gltf_mat && !alpha) + { + return LLDrawPool::POOL_PBR_OPAQUE; + } else if (mat && !alpha) { return LLDrawPool::POOL_MATERIALS; @@ -8930,6 +8950,12 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target) soften_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); soften_shader.uniform4fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV); + if(LLPipeline::sRenderPBR) + { + LLVector3 cameraAtAxis = LLViewerCamera::getInstance()->getAtAxis(); + soften_shader.uniform3fv(LLShaderMgr::DEFERRED_VIEW_DIR, 1, cameraAtAxis.mV); + } + { LLGLDepthTest depth(GL_FALSE); LLGLDisable blend(GL_BLEND); @@ -9543,10 +9569,22 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) void LLPipeline::bindReflectionProbes(LLGLSLShader& shader) { S32 channel = shader.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + bool bound = false; if (channel > -1 && mReflectionMapManager.mTexture.notNull()) { - // see comments in class2/deferred/softenLightF.glsl for what these uniforms mean mReflectionMapManager.mTexture->bind(channel); + bound = true; + } + + channel = shader.enableTexture(LLShaderMgr::IRRADIANCE_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + if (channel > -1 && mReflectionMapManager.mIrradianceMaps.notNull()) + { + mReflectionMapManager.mIrradianceMaps->bind(channel); + bound = true; + } + + if (bound) + { mReflectionMapManager.setUniforms(); F32* m = gGLModelView; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 7f37bc7cdc..209f2be9b2 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -538,6 +538,8 @@ public: RENDER_TYPE_PASS_NORMSPEC_MASK_RIGGED = LLRenderPass::PASS_NORMSPEC_MASK_RIGGED, RENDER_TYPE_PASS_NORMSPEC_EMISSIVE = LLRenderPass::PASS_NORMSPEC_EMISSIVE, RENDER_TYPE_PASS_NORMSPEC_EMISSIVE_RIGGED = LLRenderPass::PASS_NORMSPEC_EMISSIVE_RIGGED, + RENDER_TYPE_PASS_PBR_OPAQUE = LLRenderPass::PASS_PBR_OPAQUE, + RENDER_TYPE_PASS_PBR_OPAQUE_RIGGED = LLRenderPass::PASS_PBR_OPAQUE_RIGGED, // Following are object types (only used in drawable mRenderType) RENDER_TYPE_HUD = LLRenderPass::NUM_RENDER_TYPES, RENDER_TYPE_VOLUME, @@ -687,6 +689,13 @@ public: LLRenderTarget shadowOcclusion[4]; }; + // main full resoltuion render target + RenderTargetPack mMainRT; + + // auxillary 512x512 render target pack + RenderTargetPack mAuxillaryRT; + + // currently used render target pack RenderTargetPack* mRT; LLRenderTarget mSpotShadow[2]; diff --git a/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml b/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml index 7f7234bc43..965c08f4c0 100644 --- a/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml @@ -157,6 +157,13 @@ function="Inventory.DoCreate" parameter="gesture" /> + + + diff --git a/indra/newview/skins/default/textures/icons/Inv_Material.png b/indra/newview/skins/default/textures/icons/Inv_Material.png new file mode 100644 index 0000000000..f5918ceaed Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Inv_Material.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 704b60dc7e..d19929bfd4 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -329,6 +329,7 @@ with the same filename but different name + diff --git a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml index 9d9f02ed17..b6bf61cd02 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml @@ -3,7 +3,7 @@ + +