diff --git a/autobuild.xml b/autobuild.xml
index 27e01f6e70..9011fd1400 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1386,9 +1386,9 @@
archive
name
darwin64
@@ -3454,11 +3454,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
name
windows64
diff --git a/indra/cmake/Tracy.cmake b/indra/cmake/Tracy.cmake
index 458be78e9b..dba57eb920 100644
--- a/indra/cmake/Tracy.cmake
+++ b/indra/cmake/Tracy.cmake
@@ -10,17 +10,18 @@ if (USE_TRACY)
add_definitions(-DLL_PROFILER_CONFIGURATION=3)
use_prebuilt_binary(tracy)
- # if (WINDOWS)
- # MESSAGE(STATUS "Including Tracy for Windows: '${TRACY_INCLUDE_DIR}'")
- # endif (WINDOWS)
+ if (WINDOWS)
+ MESSAGE(STATUS "Including Tracy for Windows: '${TRACY_INCLUDE_DIR}'")
+ set(TRACY_LIBRARY "TracyClient")
+ endif (WINDOWS)
- # if (DARWIN)
- # MESSAGE(STATUS "Including Tracy for Darwin: '${TRACY_INCLUDE_DIR}'")
- # endif (DARWIN)
+ if (DARWIN)
+ MESSAGE(STATUS "Including Tracy for Darwin: '${TRACY_INCLUDE_DIR}'")
+ endif (DARWIN)
- # if (LINUX)
- # MESSAGE(STATUS "Including Tracy for Linux: '${TRACY_INCLUDE_DIR}'")
- # endif (LINUX)
+ if (LINUX)
+ MESSAGE(STATUS "Including Tracy for Linux: '${TRACY_INCLUDE_DIR}'")
+ endif (LINUX)
else (USE_TRACY)
# Tracy.cmake should not set LLCOMMON_INCLUDE_DIRS, let LLCommon.cmake do that
set(TRACY_INCLUDE_DIR "")
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index e6cc06e8d0..0bb1f1a0fd 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -96,6 +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_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/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 652c548d59..e8df8574f7 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -127,8 +127,9 @@ public:
AT_RESERVED_6 = 55,
AT_SETTINGS = 56, // Collection of settings
-
- AT_COUNT = 57,
+ AT_MATERIAL = 57, // Render Material
+
+ AT_COUNT = 58,
// +*********************************************************+
// | TO ADD AN ELEMENT TO THIS ENUM: |
diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp
index c54029e8b4..58af32f1af 100644
--- a/indra/llcommon/llframetimer.cpp
+++ b/indra/llcommon/llframetimer.cpp
@@ -30,9 +30,9 @@
#include "llframetimer.h"
// We don't bother building a stand alone lib; we just need to include the one source file for Tracy support
-#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
- #include "TracyClient.cpp"
-#endif // LL_PROFILER_CONFIGURATION
+//#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
+// #include "TracyClient.cpp"
+//#endif // LL_PROFILER_CONFIGURATION
// Static members
//LLTimer LLFrameTimer::sInternalTimer;
diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h
index f756f33ea8..01ad61228d 100644
--- a/indra/llcommon/llprofiler.h
+++ b/indra/llcommon/llprofiler.h
@@ -88,8 +88,8 @@ extern thread_local bool gProfilerEnabled;
// Fixed mutual exclusion issues with RAM and GPU. NOTE: This might still break on Apple in which case we'll need to restrict that platform
//// GPU Mutually exclusive with detailed memory tracing
// #define LL_PROFILER_ENABLE_TRACY_OPENGL 0
- #define LL_PROFILER_ENABLE_TRACY_MEMORY 1
- #define LL_PROFILER_ENABLE_TRACY_OPENGL 1
+ #define LL_PROFILER_ENABLE_TRACY_MEMORY 1
+ #define LL_PROFILER_ENABLE_TRACY_OPENGL 1
#endif
#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY
@@ -117,8 +117,6 @@ extern thread_local bool gProfilerEnabled;
#define LL_PROFILE_ZONE_ERR(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000 ) // RGB yellow
#define LL_PROFILE_ZONE_INFO(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF ) // RGB cyan
#define LL_PROFILE_ZONE_WARN(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 ) // RGB red
- #define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size)
- #define LL_PROFILE_FREE(ptr) TracyFree(ptr)
// Additional FS Tracy macros
#define LL_PROFILE_ZONE_COLOR(color) ZoneNamedC( ___tracy_scoped_zone, color, gProfilerEnabled ) // Additional Tracy macro
@@ -144,8 +142,6 @@ extern thread_local bool gProfilerEnabled;
#define LL_PROFILE_ZONE_ERR(name) (void)(name); // Not supported
#define LL_PROFILE_ZONE_INFO(name) (void)(name); // Not supported
#define LL_PROFILE_ZONE_WARN(name) (void)(name); // Not supported
- #define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size);
- #define LL_PROFILE_FREE(ptr) (void)(ptr);
// Additional FS Tracy macros
#define LL_PROFILE_ZONE_COLOR(color)
#define LL_PROFILE_PLOT( name, value )
@@ -178,8 +174,6 @@ extern thread_local bool gProfilerEnabled;
#define LL_PROFILE_ZONE_ERR(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000 ) // RGB yellow
#define LL_PROFILE_ZONE_INFO(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF ) // RGB cyan
#define LL_PROFILE_ZONE_WARN(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 ) // RGB red
- #define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size)
- #define LL_PROFILE_FREE(ptr) TracyFree(ptr)
// Additional FS Tracy macros
#define LL_PROFILE_ZONE_COLOR(color) ZoneNamedC( ___tracy_scoped_zone, color, gProfilerEnabled )
#define LL_PROFILE_PLOT( name, value ) TracyPlot( name, value)
@@ -213,6 +207,31 @@ extern thread_local bool gProfilerEnabled;
//
#endif // LL_PROFILER
+#if LL_PROFILER_ENABLE_TRACY_OPENGL
+#define LL_PROFILE_GPU_ZONE(name) TracyGpuZone(name)
+#define LL_PROFILE_GPU_ZONEC(name,color) TracyGpuZoneC(name,color)
+#define LL_PROFILER_GPU_COLLECT TracyGpuCollect
+#define LL_PROFILER_GPU_CONTEXT TracyGpuContext
+
+// disable memory tracking (incompatible with GPU tracing
+#define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size);
+#define LL_PROFILE_FREE(ptr) (void)(ptr);
+#else
+#define LL_PROFILE_GPU_ZONE(name) (void)name;
+#define LL_PROFILE_GPU_ZONEC(name,color) (void)name;(void)color;
+#define LL_PROFILER_GPU_COLLECT
+#define LL_PROFILER_GPU_CONTEXT
+
+#if LL_PROFILER_CONFIG > 1
+#define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size)
+#define LL_PROFILE_FREE(ptr) TracyFree(ptr)
+#else
+#define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size);
+#define LL_PROFILE_FREE(ptr) (void)(ptr);
+#endif
+
+#endif
+
#include "llprofilercategories.h"
#endif // LL_PROFILER_H
diff --git a/indra/llinventory/llfoldertype.h b/indra/llinventory/llfoldertype.h
index c3edac9dbf..7239989e77 100644
--- a/indra/llinventory/llfoldertype.h
+++ b/indra/llinventory/llfoldertype.h
@@ -93,10 +93,12 @@ public:
FT_SETTINGS = 56,
+ FT_MATERIAL = 57,
+
// Folder types for our own virtual system folders
- FT_FIRESTORM = 57,
- FT_PHOENIX = 58,
- FT_RLV = 59,
+ FT_FIRESTORM = 58,
+ FT_PHOENIX = 59,
+ FT_RLV = 60,
// Folder types for our own virtual system folders
FT_MY_SUITCASE = 100, // OpenSim HG-support
@@ -104,6 +106,8 @@ public:
FT_COUNT,
FT_NONE = -1
+
+ // When adding, see note at bottom of LLAssetType::Etype
};
static EType lookup(const std::string& type_name);
diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp
index 45eaf9e998..a40bf67abb 100644
--- a/indra/llinventory/llinventorytype.cpp
+++ b/indra/llinventory/llinventorytype.cpp
@@ -154,7 +154,8 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
LLInventoryType::IT_NONE, // 53 AT_RESERVED_4
LLInventoryType::IT_NONE, // 54 AT_RESERVED_5
- LLInventoryType::IT_SETTINGS, // 55 AT_SETTINGS
+ LLInventoryType::IT_SETTINGS, // 55 AT_SETTINGS <- why doesnt this match the value in llassettype.h? -brad
+ LLInventoryType::IT_MATERIAL, // 57 AT_MATERIAL
};
// static
diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h
index b6e7fb047f..a5543814d8 100644
--- a/indra/llinventory/llinventorytype.h
+++ b/indra/llinventory/llinventorytype.h
@@ -65,7 +65,8 @@ public:
IT_WIDGET = 23,
IT_PERSON = 24,
IT_SETTINGS = 25,
- IT_COUNT = 26,
+ IT_MATERIAL = 26,
+ IT_COUNT = 27,
IT_UNKNOWN = 255,
IT_NONE = -1
@@ -118,6 +119,8 @@ public:
ICONNAME_SETTINGS_WATER,
ICONNAME_SETTINGS_DAY,
+ ICONNAME_MATERIAL,
+
ICONNAME_INVALID,
ICONNAME_UNKNOWN,
ICONNAME_COUNT,
diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt
index fa1e01d22c..792892f024 100644
--- a/indra/llprimitive/CMakeLists.txt
+++ b/indra/llprimitive/CMakeLists.txt
@@ -96,6 +96,7 @@ if (LL_TESTS)
INCLUDE(LLAddBuildTest)
SET(llprimitive_TEST_SOURCE_FILES
llmediaentry.cpp
+ llprimitive.cpp
)
LL_ADD_PROJECT_UNIT_TESTS(llprimitive "${llprimitive_TEST_SOURCE_FILES}")
endif (LL_TESTS)
diff --git a/indra/llprimitive/llmaterial.cpp b/indra/llprimitive/llmaterial.cpp
index a219ac1450..f546ac1645 100644
--- a/indra/llprimitive/llmaterial.cpp
+++ b/indra/llprimitive/llmaterial.cpp
@@ -331,6 +331,17 @@ void LLMaterial::setAlphaMaskCutoff(U8 cutoff)
mAlphaMaskCutoff = cutoff;
}
+LLUUID LLMaterial::getMaterialID() const
+{
+ // TODO - not null
+ return LLUUID::null;
+}
+
+void LLMaterial::setMaterialID(const LLUUID &material_id)
+{
+ // TODO - set
+}
+
LLSD LLMaterial::asLLSD() const
{
LLSD material_data;
diff --git a/indra/llprimitive/llmaterial.h b/indra/llprimitive/llmaterial.h
index d58b7ee812..2f8aafc2cf 100644
--- a/indra/llprimitive/llmaterial.h
+++ b/indra/llprimitive/llmaterial.h
@@ -27,8 +27,6 @@
#ifndef LL_LLMATERIAL_H
#define LL_LLMATERIAL_H
-#include
-
#include "llmaterialid.h"
#include "llsd.h"
#include "v4coloru.h"
@@ -54,8 +52,6 @@ public:
ALPHA_SHADER_COUNT = 4
} eShaderCount;
-
-
static const U8 DEFAULT_SPECULAR_LIGHT_EXPONENT = ((U8)(0.2f * 255));
static const LLColor4U DEFAULT_SPECULAR_LIGHT_COLOR;
static const U8 DEFAULT_ENV_INTENSITY = 0;
@@ -119,6 +115,8 @@ public:
void setDiffuseAlphaMode(U8 alpha_mode);
U8 getAlphaMaskCutoff() const;
void setAlphaMaskCutoff(U8 cutoff);
+ LLUUID getMaterialID() const;
+ void setMaterialID(LLUUID const & material_id);
bool isNull() const;
static const LLMaterial null;
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index cf47fdfdd4..ee4e925495 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -39,6 +39,7 @@
#include "llsdutil_math.h"
#include "llprimtexturelist.h"
#include "llmaterialid.h"
+#include "llsdutil.h"
/**
* exported constants
@@ -1704,6 +1705,8 @@ BOOL LLNetworkData::isValid(U16 param_type, U32 size)
return (size == 28);
case PARAMS_EXTENDED_MESH:
return (size == 4);
+ case PARAMS_RENDER_MATERIAL:
+ return (size == 16);
}
return FALSE;
@@ -2195,3 +2198,69 @@ bool LLExtendedMeshParams::fromLLSD(LLSD& sd)
return false;
}
+
+//============================================================================
+
+LLRenderMaterialParams::LLRenderMaterialParams()
+{
+ mType = PARAMS_RENDER_MATERIAL;
+}
+
+BOOL LLRenderMaterialParams::pack(LLDataPacker &dp) const
+{
+ return dp.packUUID(mMaterial, "material");
+
+// return TRUE;
+}
+
+BOOL LLRenderMaterialParams::unpack(LLDataPacker &dp)
+{
+ return dp.unpackUUID(mMaterial, "material");
+
+// return TRUE;
+}
+
+bool LLRenderMaterialParams::operator==(const LLNetworkData& data) const
+{
+ if (data.mType != PARAMS_RENDER_MATERIAL)
+ {
+ return false;
+ }
+
+ const LLRenderMaterialParams ¶m = static_cast(data);
+
+ return param.mMaterial == mMaterial;
+}
+
+void LLRenderMaterialParams::copy(const LLNetworkData& data)
+{
+ llassert_always(data.mType == PARAMS_RENDER_MATERIAL);
+ const LLRenderMaterialParams ¶m = static_cast(data);
+ mMaterial = param.mMaterial;
+}
+
+LLSD LLRenderMaterialParams::asLLSD() const
+{
+ return llsd::map("material", mMaterial);
+}
+
+bool LLRenderMaterialParams::fromLLSD(LLSD& sd)
+{
+ if (sd.has("material"))
+ {
+ setMaterial(sd["material"]);
+ return true;
+ }
+
+ return false;
+}
+
+void LLRenderMaterialParams::setMaterial(const LLUUID & id)
+{
+ mMaterial = id;
+}
+
+LLUUID LLRenderMaterialParams::getMaterial() const
+{
+ return mMaterial;
+}
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index 826d113ed7..211975c1dd 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -115,6 +115,7 @@ public:
PARAMS_RESERVED = 0x50, // Used on server-side
PARAMS_MESH = 0x60,
PARAMS_EXTENDED_MESH = 0x70,
+ PARAMS_RENDER_MATERIAL = 0x80,
};
public:
@@ -328,6 +329,25 @@ public:
};
+class LLRenderMaterialParams : public LLNetworkData
+{
+private:
+ LLUUID mMaterial;
+
+public:
+ LLRenderMaterialParams();
+ BOOL pack(LLDataPacker &dp) const override;
+ BOOL unpack(LLDataPacker &dp) override;
+ bool operator==(const LLNetworkData& data) const override;
+ void copy(const LLNetworkData& data) override;
+ LLSD asLLSD() const;
+ operator LLSD() const { return asLLSD(); }
+ bool fromLLSD(LLSD& sd);
+
+ void setMaterial(const LLUUID & id);
+ LLUUID getMaterial() const;
+};
+
// This code is not naming-standards compliant. Leaving it like this for
// now to make the connection to code in
// BOOL packTEMessage(LLDataPacker &dp) const;
diff --git a/indra/llprimitive/tests/llmessagesystem_stub.cpp b/indra/llprimitive/tests/llmessagesystem_stub.cpp
index 04e70945c4..9006833054 100644
--- a/indra/llprimitive/tests/llmessagesystem_stub.cpp
+++ b/indra/llprimitive/tests/llmessagesystem_stub.cpp
@@ -25,7 +25,7 @@
#include "linden_common.h"
-char * _PREHASH_TextureEntry;
+const char * const _PREHASH_TextureEntry = "TextureEntry";
S32 LLMessageSystem::getSizeFast(char const*, char const*) const
{
diff --git a/indra/llprimitive/tests/llprimitive_test.cpp b/indra/llprimitive/tests/llprimitive_test.cpp
index 0d60c7cd15..0ff0795fdc 100644
--- a/indra/llprimitive/tests/llprimitive_test.cpp
+++ b/indra/llprimitive/tests/llprimitive_test.cpp
@@ -71,6 +71,46 @@ private:
S32 mCurrDetailTest;
};
+LLMaterialID::LLMaterialID() {}
+LLMaterialID::LLMaterialID(LLMaterialID const &m) = default;
+LLMaterialID::~LLMaterialID() {}
+void LLMaterialID::set(void const*) { }
+U8 const * LLMaterialID::get() const { return mID; }
+
+LLPrimTextureList::LLPrimTextureList() { }
+LLPrimTextureList::~LLPrimTextureList() { }
+S32 LLPrimTextureList::setBumpMap(const U8 index, const U8 bump) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setOffsetS(const U8 index, const F32 s) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setOffsetT(const U8 index, const F32 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry &te) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setRotation(const U8 index, const F32 r) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setBumpShiny(const U8 index, const U8 bump_shiny) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setFullbright(const U8 index, const U8 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setMaterialID(const U8 index, const LLMaterialID& pMaterialID) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setMediaFlags(const U8 index, const U8 media_flags) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setMediaTexGen(const U8 index, const U8 media) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setBumpShinyFullbright(const U8 index, const U8 bump) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setID(const U8 index, const LLUUID& id) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setGlow(const U8 index, const F32 glow) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setAlpha(const U8 index, const F32 alpha) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setColor(const U8 index, const LLColor3& color) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setColor(const U8 index, const LLColor4& color) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setScale(const U8 index, const F32 s, const F32 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setScaleS(const U8 index, const F32 s) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setScaleT(const U8 index, const F32 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setShiny(const U8 index, const U8 shiny) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setOffset(const U8 index, const F32 s, const F32 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setTexGen(const U8 index, const U8 texgen) { return TEM_CHANGE_NONE; }
+
+LLMaterialPtr LLPrimTextureList::getMaterialParams(const U8 index) { return LLMaterialPtr(); }
+void LLPrimTextureList::copy(LLPrimTextureList const & ptl) { mEntryList = ptl.mEntryList; } // do we need to call getTexture()->newCopy()?
+void LLPrimTextureList::take(LLPrimTextureList &other_list) { }
+void LLPrimTextureList::setSize(S32 new_size) { mEntryList.resize(new_size); }
+void LLPrimTextureList::setAllIDs(const LLUUID &id) { }
+LLTextureEntry * LLPrimTextureList::getTexture(const U8 index) const { return nullptr; }
+S32 LLPrimTextureList::size() const { return mEntryList.size(); }
+
class PRIMITIVE_TEST_SETUP
{
public:
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index d414ec78c5..474efd912c 100644
--- a/indra/llrender/CMakeLists.txt
+++ b/indra/llrender/CMakeLists.txt
@@ -31,6 +31,7 @@ include_directories(SYSTEM
set(llrender_SOURCE_FILES
llatmosphere.cpp
llcubemap.cpp
+ llcubemaparray.cpp
llfontbitmapcache.cpp
llfontfreetype.cpp
llfontgl.cpp
@@ -58,6 +59,7 @@ set(llrender_HEADER_FILES
llatmosphere.h
llcubemap.h
+ llcubemaparray.h
llfontgl.h
llfontfreetype.h
llfontbitmapcache.h
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
index 834084674e..473447ad72 100644
--- a/indra/llrender/llcubemap.cpp
+++ b/indra/llrender/llcubemap.cpp
@@ -40,8 +40,9 @@
#include "llglheaders.h"
-const F32 epsilon = 1e-7f;
-const U16 RESOLUTION = 64;
+namespace {
+ const U16 RESOLUTION = 64;
+}
bool LLCubeMap::sUseCubeMaps = true;
@@ -166,6 +167,73 @@ void LLCubeMap::init(const std::vector >& rawimages)
}
}
+void LLCubeMap::initReflectionMap(U32 resolution, U32 components)
+{
+ U32 texname = 0;
+
+ LLImageGL::generateTextures(1, &texname);
+
+ mImages[0] = new LLImageGL(resolution, resolution, components, TRUE);
+ mImages[0]->setTexName(texname);
+ mImages[0]->setTarget(mTargets[0], LLTexUnit::TT_CUBE_MAP);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
+ mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
+}
+
+void LLCubeMap::initEnvironmentMap(const std::vector >& rawimages)
+{
+ llassert(rawimages.size() == 6);
+
+ U32 texname = 0;
+
+ LLImageGL::generateTextures(1, &texname);
+
+ U32 resolution = rawimages[0]->getWidth();
+ U32 components = rawimages[0]->getComponents();
+
+ for (int i = 0; i < 6; i++)
+ {
+ llassert(rawimages[i]->getWidth() == resolution);
+ llassert(rawimages[i]->getHeight() == resolution);
+ llassert(rawimages[i]->getComponents() == components);
+
+ mImages[i] = new LLImageGL(resolution, resolution, components, TRUE);
+ mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP);
+ mRawImages[i] = rawimages[i];
+ mImages[i]->createGLTexture(0, mRawImages[i], texname);
+
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
+ mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+
+ mImages[i]->setSubImage(mRawImages[i], 0, 0, resolution, resolution);
+ }
+ enableTexture(0);
+ bind();
+ mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+ glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+ glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
+ gGL.getTexUnit(0)->disable();
+ disable();
+}
+
+void LLCubeMap::generateMipMaps()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+
+ mImages[0]->setUseMipMaps(TRUE);
+ mImages[0]->setHasMipMaps(TRUE);
+ enableTexture(0);
+ bind();
+ mImages[0]->setFilteringOption(LLTexUnit::TFO_BILINEAR);
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("cmgmm - glGenerateMipmap");
+ glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
+ }
+ gGL.getTexUnit(0)->disable();
+ disable();
+}
+
GLuint LLCubeMap::getGLName()
{
return mImages[0]->getTexName();
@@ -256,191 +324,6 @@ void LLCubeMap::restoreMatrix()
}*/
}
-void LLCubeMap::setReflection (void)
-{
- gGL.getTexUnit(mTextureStage)->bindManual(LLTexUnit::TT_CUBE_MAP, getGLName());
- mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
- mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
-}
-
-LLVector3 LLCubeMap::map(U8 side, U16 v_val, U16 h_val) const
-{
- LLVector3 dir;
-
- const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
- const S8 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1
- const U8 i_coef = (curr_coef + 1) % 3;
- const U8 j_coef = (i_coef + 1) % 3;
-
- dir.mV[curr_coef] = side_dir;
-
- switch (side)
- {
- case 0: // negative X
- dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- break;
- case 1: // positive X
- dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
- break;
- case 2: // negative Y
- dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- break;
- case 3: // positive Y
- dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- break;
- case 4: // negative Z
- dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- break;
- case 5: // positive Z
- dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
- break;
- default:
- dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- }
-
- dir.normVec();
- return dir;
-}
-
-
-BOOL LLCubeMap::project(F32& v_val, F32& h_val, BOOL& outside,
- U8 side, const LLVector3& dir) const
-{
- const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
- const S8 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1
- const U8 i_coef = (curr_coef + 1) % 3;
- const U8 j_coef = (i_coef + 1) % 3;
-
- outside = TRUE;
- if (side_dir * dir.mV[curr_coef] < 0)
- return FALSE;
-
- LLVector3 ray;
-
- F32 norm_val = fabs(dir.mV[curr_coef]);
-
- if (norm_val < epsilon)
- norm_val = 1e-5f;
-
- ray.mV[curr_coef] = side_dir;
- ray.mV[i_coef] = dir.mV[i_coef] / norm_val;
- ray.mV[j_coef] = dir.mV[j_coef] / norm_val;
-
-
- const F32 i_val = (ray.mV[i_coef] + 1) * 0.5f * RESOLUTION;
- const F32 j_val = (ray.mV[j_coef] + 1) * 0.5f * RESOLUTION;
-
- switch (side)
- {
- case 0: // negative X
- v_val = RESOLUTION - i_val;
- h_val = j_val;
- break;
- case 1: // positive X
- v_val = RESOLUTION - i_val;
- h_val = RESOLUTION - j_val;
- break;
- case 2: // negative Y
- v_val = RESOLUTION - i_val;
- h_val = j_val;
- break;
- case 3: // positive Y
- v_val = i_val;
- h_val = j_val;
- break;
- case 4: // negative Z
- v_val = RESOLUTION - j_val;
- h_val = RESOLUTION - i_val;
- break;
- case 5: // positive Z
- v_val = RESOLUTION - j_val;
- h_val = i_val;
- break;
- default:
- v_val = i_val;
- h_val = j_val;
- }
-
- outside = ((v_val < 0) || (v_val > RESOLUTION) ||
- (h_val < 0) || (h_val > RESOLUTION));
-
- return TRUE;
-}
-
-BOOL LLCubeMap::project(F32& v_min, F32& v_max, F32& h_min, F32& h_max,
- U8 side, LLVector3 dir[4]) const
-{
- v_min = h_min = RESOLUTION;
- v_max = h_max = 0;
-
- BOOL fully_outside = TRUE;
- for (U8 vtx = 0; vtx < 4; ++vtx)
- {
- F32 v_val, h_val;
- BOOL outside;
- BOOL consider = project(v_val, h_val, outside, side, dir[vtx]);
- if (!outside)
- fully_outside = FALSE;
- if (consider)
- {
- if (v_val < v_min) v_min = v_val;
- if (v_val > v_max) v_max = v_val;
- if (h_val < h_min) h_min = h_val;
- if (h_val > h_max) h_max = h_val;
- }
- }
-
- v_min = llmax(0.0f, v_min);
- v_max = llmin(RESOLUTION - epsilon, v_max);
- h_min = llmax(0.0f, h_min);
- h_max = llmin(RESOLUTION - epsilon, h_max);
-
- return !fully_outside;
-}
-
-
-void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col)
-{
- LL_PROFILE_ZONE_SCOPED;
- F32 v_min, v_max, h_min, h_max;
- LLVector3 center = dir[0] + dir[1] + dir[2] + dir[3];
- center.normVec();
-
- for (U8 side = 0; side < 6; ++side)
- {
- if (!project(v_min, v_max, h_min, h_max, side, dir))
- continue;
-
- U8 *td = mRawImages[side]->getData();
-
- U16 v_minu = (U16) v_min;
- U16 v_maxu = (U16) (ceil(v_max) + 0.5);
- U16 h_minu = (U16) h_min;
- U16 h_maxu = (U16) (ceil(h_max) + 0.5);
-
- for (U16 v = v_minu; v < v_maxu; ++v)
- for (U16 h = h_minu; h < h_maxu; ++h)
- //for (U16 v = 0; v < RESOLUTION; ++v)
- // for (U16 h = 0; h < RESOLUTION; ++h)
- {
- const LLVector3 ray = map(side, v, h);
- if (ray * center > 0.999)
- {
- const U32 offset = (RESOLUTION * v + h) * 4;
- for (U8 cc = 0; cc < 3; ++cc)
- td[offset + cc] = U8((td[offset + cc] + col.mV[cc]) * 0.5);
- }
- }
- mImages[side]->setSubImage(mRawImages[side], 0, 0, RESOLUTION, RESOLUTION);
- }
-}
void LLCubeMap::destroyGL()
{
diff --git a/indra/llrender/llcubemap.h b/indra/llrender/llcubemap.h
index a01636d8d4..b9e081cea3 100644
--- a/indra/llrender/llcubemap.h
+++ b/indra/llrender/llcubemap.h
@@ -40,6 +40,17 @@ class LLCubeMap : public LLRefCount
public:
LLCubeMap(bool init_as_srgb);
void init(const std::vector >& rawimages);
+
+ // initialize as an undefined cubemap at the given resolution
+ // used for render-to-cubemap operations
+ // avoids usage of LLImageRaw
+ void initReflectionMap(U32 resolution, U32 components = 3);
+
+ // init from environment map images
+ // Similar to init, but takes ownership of rawimages and makes this cubemap
+ // respect the resolution of rawimages
+ // Raw images must point to array of six square images that are all the same resolution
+ void initEnvironmentMap(const std::vector >& rawimages);
void initGL();
void initRawData(const std::vector >& rawimages);
void initGLData();
@@ -54,18 +65,15 @@ public:
void disableTexture(void);
void setMatrix(S32 stage);
void restoreMatrix();
- void setReflection (void);
- void finishPaint();
+ U32 getResolution() { return mImages[0].notNull() ? mImages[0]->getWidth(0) : 0; }
+
+ // generate mip maps for this Cube Map using GL
+ // NOTE: Cube Map MUST already be resident in VRAM
+ void generateMipMaps();
GLuint getGLName();
- LLVector3 map(U8 side, U16 v_val, U16 h_val) const;
- BOOL project(F32& v_val, F32& h_val, BOOL& outside,
- U8 side, const LLVector3& dir) const;
- BOOL project(F32& v_min, F32& v_max, F32& h_min, F32& h_max,
- U8 side, LLVector3 dir[4]) const;
- void paintIn(LLVector3 dir[4], const LLColor4U& col);
void destroyGL();
public:
diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp
new file mode 100644
index 0000000000..e4081c1154
--- /dev/null
+++ b/indra/llrender/llcubemaparray.cpp
@@ -0,0 +1,113 @@
+/**
+ * @file llcubemaparray.cpp
+ * @brief LLCubeMap class implementation
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llworkerthread.h"
+
+#include "llcubemaparray.h"
+
+#include "v4coloru.h"
+#include "v3math.h"
+#include "v3dmath.h"
+#include "m3math.h"
+#include "m4math.h"
+
+#include "llrender.h"
+#include "llglslshader.h"
+
+#include "llglheaders.h"
+
+//#pragma optimize("", off)
+
+// MUST match order of OpenGL face-layers
+GLenum LLCubeMapArray::sTargets[6] =
+{
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
+};
+
+LLCubeMapArray::LLCubeMapArray()
+ : mTextureStage(0)
+{
+
+}
+
+LLCubeMapArray::~LLCubeMapArray()
+{
+}
+
+void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count)
+{
+ U32 texname = 0;
+
+ LLImageGL::generateTextures(1, &texname);
+
+ mImage = new LLImageGL(resolution, resolution, components, TRUE);
+ mImage->setTexName(texname);
+ mImage->setTarget(sTargets[0], LLTexUnit::TT_CUBE_MAP_ARRAY);
+
+ mImage->setUseMipMaps(TRUE);
+ mImage->setHasMipMaps(TRUE);
+
+ bind(0);
+
+ glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY_ARB, 0, GL_RGB, resolution, resolution, count*6, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+
+ mImage->setAddressMode(LLTexUnit::TAM_CLAMP);
+
+ mImage->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+
+ glGenerateMipmap(GL_TEXTURE_CUBE_MAP_ARRAY_ARB);
+
+ unbind();
+}
+
+void LLCubeMapArray::bind(S32 stage)
+{
+ mTextureStage = stage;
+ gGL.getTexUnit(stage)->bindManual(LLTexUnit::TT_CUBE_MAP_ARRAY, getGLName(), TRUE);
+}
+
+void LLCubeMapArray::unbind()
+{
+ gGL.getTexUnit(mTextureStage)->unbind(LLTexUnit::TT_CUBE_MAP_ARRAY);
+ mTextureStage = -1;
+}
+
+GLuint LLCubeMapArray::getGLName()
+{
+ return mImage->getTexName();
+}
+
+void LLCubeMapArray::destroyGL()
+{
+ mImage = NULL;
+}
diff --git a/indra/llrender/llcubemaparray.h b/indra/llrender/llcubemaparray.h
new file mode 100644
index 0000000000..52e21f1dda
--- /dev/null
+++ b/indra/llrender/llcubemaparray.h
@@ -0,0 +1,60 @@
+/**
+ * @file llcubemaparray.h
+ * @brief LLCubeMap class 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 "llgl.h"
+
+#include
+
+class LLVector3;
+
+// Environment map hack!
+class LLCubeMapArray : public LLRefCount
+{
+public:
+ LLCubeMapArray();
+
+ static GLenum sTargets[6];
+
+ // allocate a cube map array
+ // res - resolution of each cube face
+ // components - number of components per pixel
+ // count - number of cube maps in the array
+ void allocate(U32 res, U32 components, U32 count);
+ void bind(S32 stage);
+ void unbind();
+
+ GLuint getGLName();
+
+ void destroyGL();
+
+protected:
+ friend class LLTexUnit;
+ ~LLCubeMapArray();
+ LLPointer mImage;
+ S32 mTextureStage;
+};
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 5b7a7cdc16..c3d86af649 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -89,9 +89,10 @@ void APIENTRY gl_debug_callback(GLenum source,
if (gGLDebugLoggingEnabled)
{
- if (severity != GL_DEBUG_SEVERITY_HIGH_ARB &&
- severity != GL_DEBUG_SEVERITY_MEDIUM_ARB &&
- severity != GL_DEBUG_SEVERITY_LOW_ARB)
+ if (severity != GL_DEBUG_SEVERITY_HIGH_ARB // &&
+ //severity != GL_DEBUG_SEVERITY_MEDIUM_ARB &&
+ //severity != GL_DEBUG_SEVERITY_LOW_ARB
+ )
{ //suppress out-of-spec messages sent by nvidia driver (mostly vertexbuffer hints)
return;
}
@@ -316,6 +317,15 @@ PFNGLGETUNIFORMIVARBPROC glGetUniformivARB = NULL;
PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB = NULL;
PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = NULL;
+// GL_ARB_uniform_buffer_object
+PFNGLGETUNIFORMINDICESPROC glGetUniformIndices = NULL;
+PFNGLGETACTIVEUNIFORMSIVPROC glGetActiveUniformsiv = NULL;
+PFNGLGETACTIVEUNIFORMNAMEPROC glGetActiveUniformName = NULL;
+PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKIVPROC glGetActiveUniformBlockiv = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glGetActiveUniformBlockName = NULL;
+PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding = NULL;
+
#if LL_WINDOWS
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
#endif
@@ -436,6 +446,7 @@ LLGLManager::LLGLManager() :
mHasTextureRectangle(FALSE),
mHasTextureMultisample(FALSE),
mHasTransformFeedback(FALSE),
+ mHasUniformBufferObject(FALSE),
mMaxSampleMaskWords(0),
mMaxColorTextureSamples(0),
mMaxDepthTextureSamples(0),
@@ -1062,6 +1073,7 @@ void LLGLManager::initExtensions()
mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts);
mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts);
mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE;
+ mHasUniformBufferObject = ExtensionExists("GL_ARB_uniform_buffer_object", gGLHExts.mSysExts);
#if !LL_DARWIN
mHasPointParameters = ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
#endif
@@ -1294,6 +1306,10 @@ void LLGLManager::initExtensions()
mGLMaxVertexRange = 0;
mGLMaxIndexRange = 0;
}
+
+ // same with glTexImage3D et al
+ glTexImage3D = (PFNGLTEXIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexImage3D");
+ glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyTexSubImage3D");
#endif // !LL_LINUX || LL_LINUX_NV_GL_HEADERS
#if LL_LINUX_NV_GL_HEADERS
// nvidia headers are critically different from mesa-esque
@@ -1327,6 +1343,17 @@ void LLGLManager::initExtensions()
glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfvARB");
}
+ if (mHasUniformBufferObject)
+ {
+ glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformIndices");
+ glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformIndices");
+ glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformName");
+ glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformBlockIndex");
+ glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformBlockiv");
+ glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformBlockName");
+ glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformBlockBinding");
+ }
+
// Assume shader capabilities
glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteObjectARB");
glGetHandleARB = (PFNGLGETHANDLEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetHandleARB");
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index e97f8fe32a..7ecc998428 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -114,6 +114,7 @@ public:
BOOL mHasTextureRectangle;
BOOL mHasTextureMultisample;
BOOL mHasTransformFeedback;
+ BOOL mHasUniformBufferObject;
S32 mMaxSampleMaskWords;
S32 mMaxColorTextureSamples;
S32 mMaxDepthTextureSamples;
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index d68032362e..4cdf1593a7 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -564,6 +564,15 @@ extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB;
extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
extern PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB;
+// GL_ARB_uniform_buffer_object
+extern PFNGLGETUNIFORMINDICESPROC glGetUniformIndices;
+extern PFNGLGETACTIVEUNIFORMSIVPROC glGetActiveUniformsiv;
+extern PFNGLGETACTIVEUNIFORMNAMEPROC glGetActiveUniformName;
+extern PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex;
+extern PFNGLGETACTIVEUNIFORMBLOCKIVPROC glGetActiveUniformBlockiv;
+extern PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glGetActiveUniformBlockName;
+extern PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding;
+
#elif LL_DARWIN
//----------------------------------------------------------------------------
// LL_DARWIN
@@ -827,14 +836,7 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
#define glGetQueryiv glGetQueryivARB
#define glGetQueryObjectiv glGetQueryObjectivARB
#include
-
- #define LL_PROFILER_GPU_ZONEC(name,color) TracyGpuZoneC(name,color);
- #define LL_PROFILER_GPU_COLLECT TracyGpuCollect
- #define LL_PROFILER_GPU_CONTEXT TracyGpuContext
-#else
- #define LL_PROFILER_GPU_ZONEC(name,color) (void)name;(void)color;
- #define LL_PROFILER_GPU_COLLECT
- #define LL_PROFILER_GPU_CONTEXT
#endif
+
#endif // LL_LLGLHEADERS_H
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 5226c110dc..35424d716e 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -746,7 +746,7 @@ void LLGLSLShader::mapUniform(GLint index, const vector *
{
//found it
mUniform[i] = location;
- mTexture[i] = mapUniformTextureChannel(location, type);
+ mTexture[i] = mapUniformTextureChannel(location, type, size);
return;
}
}
@@ -760,7 +760,7 @@ void LLGLSLShader::mapUniform(GLint index, const vector *
{
//found it
mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location;
- mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type);
+ mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type, size);
return;
}
}
@@ -783,16 +783,38 @@ void LLGLSLShader::removePermutation(std::string name)
mDefines[name].erase();
}
-GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
+GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint size)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
if ((type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB) ||
- type == GL_SAMPLER_2D_MULTISAMPLE)
+ type == GL_SAMPLER_2D_MULTISAMPLE ||
+ type == GL_SAMPLER_CUBE_MAP_ARRAY_ARB)
{ //this here is a texture
- glUniform1iARB(location, mActiveTextureChannels);
- LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
- return mActiveTextureChannels++;
+ GLint ret = mActiveTextureChannels;
+ if (size == 1)
+ {
+ glUniform1iARB(location, mActiveTextureChannels);
+ LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
+ mActiveTextureChannels++;
+ }
+ else
+ {
+ //is array of textures, make sequential after this texture
+ GLint channel[32]; // <=== only support up to 32 texture channels
+ llassert(size <= 32);
+ size = llmin(size, 32);
+ for (int i = 0; i < size; ++i)
+ {
+ channel[i] = mActiveTextureChannels++;
+ }
+ glUniform1ivARB(location, size, channel);
+ LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " <<
+ (mActiveTextureChannels-size) << " through " << (mActiveTextureChannels-1) << LL_ENDL;
+ }
+
+ llassert(mActiveTextureChannels <= 32); // too many textures (probably)
+ return ret;
}
return -1;
}
@@ -840,6 +862,9 @@ BOOL LLGLSLShader::mapUniforms(const vector * uniforms)
As example where this situation appear see: "Deferred Material Shader 28/29/30/31"
And tickets: MAINT-4165, MAINT-4839, MAINT-3568, MAINT-6437
+
+ --- davep TODO -- pretty sure the entire block here is superstitious and that the uniform index has nothing to do with the texture channel
+ texture channel should follow the uniform VALUE
*/
@@ -848,6 +873,7 @@ BOOL LLGLSLShader::mapUniforms(const vector * uniforms)
S32 bumpMap = glGetUniformLocationARB(mProgramObject, "bumpMap");
S32 altDiffuseMap = glGetUniformLocationARB(mProgramObject, "altDiffuseMap");
S32 environmentMap = glGetUniformLocationARB(mProgramObject, "environmentMap");
+ S32 reflectionMap = glGetUniformLocationARB(mProgramObject, "reflectionMap");
std::set skip_index;
@@ -890,6 +916,12 @@ BOOL LLGLSLShader::mapUniforms(const vector * uniforms)
continue;
}
+ if (-1 == reflectionMap && std::string(name) == "reflectionMap")
+ {
+ reflectionMap = i;
+ continue;
+ }
+
if (-1 == altDiffuseMap && std::string(name) == "altDiffuseMap")
{
altDiffuseMap = i;
@@ -900,8 +932,9 @@ BOOL LLGLSLShader::mapUniforms(const vector * uniforms)
bool specularDiff = specularMap < diffuseMap && -1 != specularMap;
bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap;
bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap;
+ bool refLessDiff = reflectionMap < diffuseMap && -1 != reflectionMap;
- if (specularDiff || bumpLessDiff || envLessDiff)
+ if (specularDiff || bumpLessDiff || envLessDiff || refLessDiff)
{
mapUniform(diffuseMap, uniforms);
skip_index.insert(diffuseMap);
@@ -920,6 +953,11 @@ BOOL LLGLSLShader::mapUniforms(const vector * uniforms)
mapUniform(environmentMap, uniforms);
skip_index.insert(environmentMap);
}
+
+ if (-1 != reflectionMap) {
+ mapUniform(reflectionMap, uniforms);
+ skip_index.insert(reflectionMap);
+ }
}
}
@@ -1260,6 +1298,30 @@ void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v)
}
}
+void LLGLSLShader::uniform4iv(U32 index, U32 count, const GLint* v)
+{
+ if (mProgramObject)
+ {
+ if (mUniform.size() <= index)
+ {
+ LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ const auto& iter = mValue.find(mUniform[index]);
+ LLVector4 vec(v[0], v[1], v[2], v[3]);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
+ {
+ glUniform1ivARB(mUniform[index], count, v);
+ mValue[mUniform[index]] = vec;
+ }
+ }
+ }
+}
+
+
void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v)
{
if (mProgramObject)
@@ -1497,6 +1559,40 @@ void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v)
}
}
+void LLGLSLShader::uniform1iv(const LLStaticHashedString& uniform, U32 count, const GLint* v)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ LLVector4 vec(v[0], 0, 0, 0);
+ const auto& iter = mValue.find(location);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ glUniform1ivARB(location, count, v);
+ mValue[location] = vec;
+ }
+ }
+}
+
+void LLGLSLShader::uniform4iv(const LLStaticHashedString& uniform, U32 count, const GLint* v)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ LLVector4 vec(v[0], v[1], v[2], v[3]);
+ const auto& iter = mValue.find(location);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ glUniform4ivARB(location, count, v);
+ mValue[location] = vec;
+ }
+ }
+}
+
void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j)
{
GLint location = getUniformLocation(uniform);
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 85e83dbcb9..6b4778c270 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -58,6 +58,7 @@ public:
S32 mIndexedTextureChannels;
bool disableTextureIndex;
bool hasAlphaMask;
+ bool hasReflectionProbes = false;
bool attachNothing;
// char numLights;
@@ -178,6 +179,7 @@ public:
void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z);
void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void uniform1iv(U32 index, U32 count, const GLint* i);
+ void uniform4iv(U32 index, U32 count, const GLint* i);
void uniform1fv(U32 index, U32 count, const GLfloat* v);
void uniform2fv(U32 index, U32 count, const GLfloat* v);
void uniform3fv(U32 index, U32 count, const GLfloat* v);
@@ -188,6 +190,8 @@ public:
void uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
void uniform1i(const LLStaticHashedString& uniform, GLint i);
+ void uniform1iv(const LLStaticHashedString& uniform, U32 count, const GLint* v);
+ void uniform4iv(const LLStaticHashedString& uniform, U32 count, const GLint* v);
void uniform1f(const LLStaticHashedString& uniform, GLfloat v);
void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y);
void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z);
@@ -207,7 +211,7 @@ public:
GLint getUniformLocation(U32 index);
GLint getAttribLocation(U32 attrib);
- GLint mapUniformTextureChannel(GLint location, GLenum type);
+ GLint mapUniformTextureChannel(GLint location, GLenum type, GLint size);
void clearPermutations();
void addPermutation(std::string name, std::string value);
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 128cf22cd6..862e1a7d40 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -820,6 +820,7 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32
if (LLRender::sGLCoreProfile)
{
+ LL_PROFILE_GPU_ZONE("generate mip map");
glGenerateMipmap(mTarget);
}
stop_glerror();
@@ -1527,6 +1528,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
// Call with void data, vmem is allocated but unitialized
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ LL_PROFILE_GPU_ZONE("createGLTexture");
checkActiveThread();
bool main_thread = on_main_thread();
@@ -1696,26 +1698,38 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("cglt - sync");
if (gGLManager.mHasSync)
{
- // post a sync to the main thread (will execute before tex name swap lambda below)
- // glFlush calls here are partly superstitious and partly backed by observation
- // on AMD hardware
- glFlush();
- auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
- glFlush();
- LL::WorkQueue::postMaybe(
- mMainQueue,
- [=]()
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("cglt - wait sync");
+ if (gGLManager.mIsNVIDIA)
+ {
+ // wait for texture upload to finish before notifying main thread
+ // upload is complete
+ auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ glFlush();
+ glClientWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
+ glDeleteSync(sync);
+ }
+ else
+ {
+ // post a sync to the main thread (will execute before tex name swap lambda below)
+ // glFlush calls here are partly superstitious and partly backed by observation
+ // on AMD hardware
+ glFlush();
+ auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ glFlush();
+ LL::WorkQueue::postMaybe(
+ mMainQueue,
+ [=]()
{
- LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("glWaitSync");
- glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
- }
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("glDeleteSync");
- glDeleteSync(sync);
- }
- });
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("cglt - wait sync");
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("glWaitSync");
+ glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
+ }
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("glDeleteSync");
+ glDeleteSync(sync);
+ }
+ });
+ }
}
else
{
@@ -1732,8 +1746,11 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
syncTexName(new_tex_name);
unref();
});
+
+ LL_PROFILER_GPU_COLLECT;
}
+
void LLImageGL::syncTexName(LLGLuint texname)
{
if (texname != 0)
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index eca4366f18..e5653aeb47 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -164,7 +164,7 @@ public:
BOOL getUseMipMaps() const { return mUseMipMaps; }
void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; }
-
+ void setHasMipMaps(BOOL hasmips) { mHasMipMaps = hasmips; }
void updatePickMask(S32 width, S32 height, const U8* data_in);
// [RLVa:KB] - Checked: RLVa-2.2 (@setoverlay)
BOOL getMask(const LLVector2 &tc) const;
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index d1df9f6b6c..e698ade519 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -74,6 +74,7 @@ static const GLenum sGLTextureType[] =
GL_TEXTURE_RECTANGLE,
//
GL_TEXTURE_CUBE_MAP_ARB,
+ GL_TEXTURE_CUBE_MAP_ARRAY_ARB,
GL_TEXTURE_2D_MULTISAMPLE,
GL_TEXTURE_3D
};
@@ -896,6 +897,9 @@ void LLRender::init()
glCullFace(GL_BACK);
+ // necessary for reflection maps
+ glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+
if (sGLCoreProfile && !LLVertexBuffer::sUseVAO)
{ //bind a dummy vertex array object so we're core profile compliant
#ifdef GL_ARB_vertex_array_object
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index ff2b0b0195..a1ff52c365 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -62,7 +62,7 @@ class LLTexture ;
#define LL_MATRIX_STACK_DEPTH 32
-class LLTexUnit
+class LLTexUnit
{
friend class LLRender;
public:
@@ -73,6 +73,7 @@ public:
TT_TEXTURE = 0, // Standard 2D Texture
TT_RECT_TEXTURE, // Non power of 2 texture
TT_CUBE_MAP, // 6-sided cube map texture
+ TT_CUBE_MAP_ARRAY, // Array of cube maps
TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample
TT_TEXTURE_3D, // standard 3D Texture
TT_NONE, // No texture type is currently enabled
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 7acb8aeeec..f95027d4f6 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -119,6 +119,7 @@ void LLRenderTarget::resize(U32 resx, U32 resy)
bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
resx = llmin(resx, (U32) gGLManager.mGLMaxTextureSize);
resy = llmin(resy, (U32) gGLManager.mGLMaxTextureSize);
@@ -219,6 +220,7 @@ void LLRenderTarget::releaseColorAttachment()
bool LLRenderTarget::addColorAttachment(U32 color_fmt)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
if (color_fmt == 0)
{
return true;
@@ -315,6 +317,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
bool LLRenderTarget::allocateDepth()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
if (mStencil)
{
//use render buffers where stencil buffers are in play
@@ -395,6 +398,7 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
void LLRenderTarget::release()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
if (mDepth)
{
if (mStencil)
@@ -484,13 +488,11 @@ void LLRenderTarget::bindTarget()
GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3};
- LL_PROFILER_GPU_ZONEC( "gl.DrawBuffersARB", 0x4000FF )
glDrawBuffersARB(mTex.size(), drawbuffers);
}
if (mTex.empty())
{ //no color buffer to draw to
- LL_PROFILER_GPU_ZONEC( "gl.DrawBuffer", 0x0000FF )
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
}
@@ -511,6 +513,7 @@ void LLRenderTarget::bindTarget()
void LLRenderTarget::clear(U32 mask_in)
{
+ LL_PROFILE_GPU_ZONE("clear");
U32 mask = GL_COLOR_BUFFER_BIT;
if (mUseDepth)
{
@@ -675,6 +678,7 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0
}
{
+ LL_PROFILE_GPU_ZONE("copyContentsToFramebuffer");
GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE;
LLGLDepthTest depth(write_depth, write_depth);
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index c8cea38461..15705d0ac3 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -218,6 +218,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
+ if (features->hasReflectionProbes)
+ {
+ if (!shader->attachFragmentObject("deferred/reflectionProbeF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
if (features->hasAmbientOcclusion)
{
if (!shader->attachFragmentObject("deferred/aoUtil.glsl"))
@@ -718,8 +726,15 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
{
if (major_version >= 4)
{
- //set version to 400
- shader_code_text[shader_code_count++] = strdup("#version 400\n");
+ //set version to 400 or 420
+ if (minor_version >= 20)
+ {
+ shader_code_text[shader_code_count++] = strdup("#version 420\n");
+ }
+ else
+ {
+ shader_code_text[shader_code_count++] = strdup("#version 400\n");
+ }
}
else if (major_version == 3)
{
@@ -1161,6 +1176,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("bumpMap");
mReservedUniforms.push_back("bumpMap2");
mReservedUniforms.push_back("environmentMap");
+ mReservedUniforms.push_back("reflectionProbes");
mReservedUniforms.push_back("cloud_noise_texture");
mReservedUniforms.push_back("cloud_noise_texture_next");
mReservedUniforms.push_back("fullbright");
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index a1f8e43b1b..24c29e31b4 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -80,6 +80,7 @@ public:
BUMP_MAP, // "bumpMap"
BUMP_MAP2, // "bumpMap2"
ENVIRONMENT_MAP, // "environmentMap"
+ REFLECTION_PROBES, // "reflectionProbes"
CLOUD_NOISE_MAP, // "cloud_noise_texture"
CLOUD_NOISE_MAP_NEXT, // "cloud_noise_texture_next"
FULLBRIGHT, // "fullbright"
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 227c05e668..955bab8643 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -639,7 +639,6 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
stop_glerror();
LLGLSLShader::startProfile();
- LL_PROFILER_GPU_ZONEC( "gl.DrawRangeElements", 0xFFFF00 )
glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
idx);
LLGLSLShader::stopProfile(count, mode);
@@ -657,7 +656,6 @@ void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32
U16* idx = ((U16*)getIndicesPointer()) + indices_offset;
- LL_PROFILER_GPU_ZONEC("gl.DrawRangeElements", 0xFFFF00)
glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
idx);
}
@@ -703,8 +701,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
stop_glerror();
LLGLSLShader::startProfile();
- LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0xA0FFA0 )
- glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT,
+ glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT,
((U16*) getIndicesPointer()) + indices_offset);
LLGLSLShader::stopProfile(count, mode);
stop_glerror();
@@ -751,7 +748,6 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
LLGLSLShader::startProfile();
{
- LL_PROFILER_GPU_ZONEC("gl.DrawArrays", 0xFF4040)
glDrawArrays(sGLMode[mode], first, count);
}
LLGLSLShader::stopProfile(count, mode);
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 4d1fd936d8..8db3fb41c2 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -83,7 +83,8 @@ enum EDragAndDropType
DAD_WIDGET = 16,
DAD_PERSON = 17,
DAD_SETTINGS = 18,
- DAD_COUNT = 19, // number of types in this enum
+ DAD_MATERIAL = 19,
+ DAD_COUNT = 20, // number of types in this enum
};
// Reasons for drags to be denied.
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index f1f5e087b2..2b9626ed4d 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -1659,6 +1659,8 @@ const S32 max_format = (S32)num_formats - 1;
swapBuffers();
}
+ LL_PROFILER_GPU_CONTEXT;
+
return TRUE;
}
@@ -1812,6 +1814,7 @@ void* LLWindowWin32::createSharedContext()
void LLWindowWin32::makeContextCurrent(void* contextPtr)
{
wglMakeCurrent(mhDC, (HGLRC) contextPtr);
+ LL_PROFILER_GPU_CONTEXT;
}
void LLWindowWin32::destroySharedContext(void* contextPtr)
@@ -3651,10 +3654,13 @@ void LLWindowWin32::swapBuffers()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;
ASSERT_MAIN_THREAD();
- glFlush(); //superstitious flush for maybe frame stall removal?
+ {
+ LL_PROFILE_GPU_ZONE("flush");
+ glFlush(); //superstitious flush for maybe frame stall removal?
+ }
SwapBuffers(mhDC);
- LL_PROFILER_GPU_COLLECT
+ LL_PROFILER_GPU_COLLECT;
}
//
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index f9a3c934dd..3f88f1dc53 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -296,6 +296,7 @@ set(viewer_SOURCE_FILES
lldrawpoolbump.cpp
lldrawpoolground.cpp
lldrawpoolmaterials.cpp
+ lldrawpoolpbropaque.cpp
lldrawpoolsimple.cpp
lldrawpoolsky.cpp
lldrawpoolterrain.cpp
@@ -660,6 +661,8 @@ set(viewer_SOURCE_FILES
llproductinforequest.cpp
llprogressview.cpp
llrecentpeople.cpp
+ llreflectionmap.cpp
+ llreflectionmapmanager.cpp
llregioninfomodel.cpp
llregionposition.cpp
llremoteparcelrequest.cpp
@@ -1072,6 +1075,7 @@ set(viewer_HEADER_FILES
lldrawpoolavatar.h
lldrawpoolbump.h
lldrawpoolmaterials.h
+ lldrawpoolpbropaque.h
lldrawpoolground.h
lldrawpoolsimple.h
lldrawpoolsky.h
@@ -1425,6 +1429,8 @@ set(viewer_HEADER_FILES
llproductinforequest.h
llprogressview.h
llrecentpeople.h
+ llreflectionmap.h
+ llreflectionmapmanager.h
llregioninfomodel.h
llregionposition.h
llremoteparcelrequest.h
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 826f5ce030..09a7391e4e 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-6.6.0
+6.6.1
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index a61a3db40b..efa0008e4e 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -13288,7 +13288,41 @@ Change of this parameter will affect the layout of buttons in notification toast
2
- RenderReflectionRes
+ RenderReflectionProbeDrawDistance
+
+ RenderReflectionProbeAmbiance
+
+ RenderReflectionProbeTextureHackID
+
+
+ RenderReflectionRes
uniform sampler2DRect normalMap;
-// Colour space and shader fixes for BUG-228586 (Rye)
-// uniform samplerCube environmentMap;
-//
-
uniform sampler2D noiseMap;
uniform sampler2D projectionMap;
uniform sampler2D lightFunc;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
new file mode 100644
index 0000000000..cb9cc4958a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
@@ -0,0 +1,109 @@
+/**
+ * @file pbropaqueF.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]*/
+
+#define DEBUG_BASIC 1
+#define DEBUG_COLOR 0
+#define DEBUG_NORMAL 0
+#define DEBUG_POSITION 0
+#define DEBUG_REFLECT_VEC 0
+#define DEBUG_REFLECT_COLOR 0
+
+#ifdef HAS_SPECULAR_MAP
+uniform sampler2D specularMap;
+#endif
+uniform samplerCube environmentMap;
+uniform mat3 env_mat;
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#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_SPECULAR_MAP
+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;
+
+//#ifdef HAS_SPECULAR_MAP
+//#else
+ vec4 norm = vec4(0,0,0,1.0);
+ vec3 tnorm = vary_normal;
+//#endif
+ norm.xyz = normalize(tnorm.xyz);
+
+ vec3 spec;
+ spec.rgb = vec3(vertex_color.a);
+
+ 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
+#endif
+#if DEBUG_COLOR
+ col.rgb = vertex_color.rgb;
+#endif
+#if DEBUG_NORMAL
+ 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);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl
new file mode 100644
index 0000000000..72bae808e0
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl
@@ -0,0 +1,54 @@
+/**
+ * @file pbropaqueV.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$
+ */
+
+uniform mat3 normal_matrix;
+uniform mat4 texture_matrix0;
+uniform mat4 modelview_matrix;
+uniform mat4 modelview_projection_matrix;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec4 diffuse_color;
+ATTRIBUTE vec3 normal;
+ATTRIBUTE vec2 texcoord0;
+
+VARYING vec3 vary_position;
+VARYING vec3 vary_normal;
+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;
+
+ passTextureIndex();
+ vary_normal = normalize(normal_matrix * normal);
+
+ vertex_color = diffuse_color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
index a8fa7b7115..478c29678d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -37,7 +37,6 @@ uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
// Colour space and shader fixes for BUG-228586 (Rye)
//uniform sampler2DRect normalMap;
-//uniform samplerCube environmentMap;
//
uniform sampler2D noiseMap;
uniform sampler2D lightFunc;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl
new file mode 100644
index 0000000000..8f3e38b08b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl
@@ -0,0 +1,44 @@
+/**
+ * @file class1/deferred/reflectionProbeF.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$
+ */
+
+// fallback stub -- will be used if actual reflection probe shader failed to load (output pink so it's obvious)
+void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
+ vec3 pos, vec3 norm, float glossiness, float envIntensity)
+{
+ ambenv = vec3(1,0,1);
+ glossenv = vec3(1,0,1);
+ legacyenv = vec3(1,0,1);
+}
+
+void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm)
+{
+ color = vec3(1,0,1);
+}
+
+void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity)
+{
+ color = vec3(1,0,1);
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl b/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl
new file mode 100644
index 0000000000..ea687aab4f
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl
@@ -0,0 +1,75 @@
+/**
+ * @file reflectionmipF.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$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2DRect screenMap;
+
+VARYING vec2 vary_texcoord0;
+
+void main()
+{
+ float w[9];
+
+ float c = 1.0/16.0; //corner weight
+ float e = 1.0/8.0; //edge weight
+ float m = 1.0/4.0; //middle weight
+
+ //float wsum = c*4+e*4+m;
+
+ w[0] = c; w[1] = e; w[2] = c;
+ w[3] = e; w[4] = m; w[5] = e;
+ w[6] = c; w[7] = e; w[8] = c;
+
+ vec2 tc[9];
+
+ float ed = 1;
+ float cd = 1;
+
+
+ tc[0] = vec2(-cd, cd); tc[1] = vec2(0, ed); tc[2] = vec2(cd, cd);
+ tc[3] = vec2(-ed, 0); tc[4] = vec2(0, 0); tc[5] = vec2(ed, 0);
+ tc[6] = vec2(-cd, -cd); tc[7] = vec2(0, -ed); tc[8] = vec2(cd, -1);
+
+ vec3 color = vec3(0,0,0);
+
+ for (int i = 0; i < 9; ++i)
+ {
+ color += texture2DRect(screenMap, vary_texcoord0.xy+tc[i]).rgb * w[i];
+ //color += texture2DRect(screenMap, vary_texcoord0.xy+tc[i]*2.0).rgb * w[i]*0.5;
+ }
+
+ //color /= wsum;
+
+ frag_color = vec4(color, 1.0);
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl
new file mode 100644
index 0000000000..8c1323ba1a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl
@@ -0,0 +1,476 @@
+/**
+ * @file class2/deferred/reflectionProbeF.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$
+ */
+
+#extension GL_ARB_shader_texture_lod : enable
+
+#define FLT_MAX 3.402823466e+38
+
+#define REFMAP_COUNT 256
+#define REF_SAMPLE_COUNT 64 //maximum number of samples to consider
+
+uniform samplerCubeArray reflectionProbes;
+
+layout (std140, binding = 1) uniform ReflectionProbes
+{
+ // list of OBBs for user override probes
+ // box is a set of 3 planes outward facing planes and the depth of the box along that plane
+ // for each box refBox[i]...
+ /// box[0..2] - plane 0 .. 2 in [A,B,C,D] notation
+ // box[3][0..2] - plane thickness
+ mat4 refBox[REFMAP_COUNT];
+ // list of bounding spheres for reflection probes sorted by distance to camera (closest first)
+ vec4 refSphere[REFMAP_COUNT];
+ // index of cube map in reflectionProbes for a corresponding reflection probe
+ // e.g. cube map channel of refSphere[2] is stored in refIndex[2]
+ // refIndex.x - cubemap channel in reflectionProbes
+ // refIndex.y - index in refNeighbor of neighbor list (index is ivec4 index, not int index)
+ // refIndex.z - number of neighbors
+ // refIndex.w - priority, if negative, this probe has a box influence
+ ivec4 refIndex[REFMAP_COUNT];
+
+ // neighbor list data (refSphere indices, not cubemap array layer)
+ ivec4 refNeighbor[1024];
+
+ // number of reflection probes present in refSphere
+ int refmapCount;
+
+ // intensity of ambient light from reflection probes
+ float reflectionAmbiance;
+};
+
+// Inputs
+uniform mat3 env_mat;
+
+// list of probeIndexes shader will actually use after "getRefIndex" is called
+// (stores refIndex/refSphere indices, NOT rerflectionProbes layer)
+int probeIndex[REF_SAMPLE_COUNT];
+
+// number of probes stored in probeIndex
+int probeInfluences = 0;
+
+bool isAbove(vec3 pos, vec4 plane)
+{
+ return (dot(plane.xyz, pos) + plane.w) > 0;
+}
+
+// return true if probe at index i influences position pos
+bool shouldSampleProbe(int i, vec3 pos)
+{
+ if (refIndex[i].w < 0)
+ {
+ vec4 v = refBox[i] * vec4(pos, 1.0);
+ if (abs(v.x) > 1 ||
+ abs(v.y) > 1 ||
+ abs(v.z) > 1)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ vec3 delta = pos.xyz - refSphere[i].xyz;
+ float d = dot(delta, delta);
+ float r2 = refSphere[i].w;
+ r2 *= r2;
+
+ if (d > r2)
+ { //outside bounding sphere
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// call before sampleRef
+// populate "probeIndex" with N probe indices that influence pos where N is REF_SAMPLE_COUNT
+// overall algorithm --
+void preProbeSample(vec3 pos)
+{
+ // TODO: make some sort of structure that reduces the number of distance checks
+
+ for (int i = 0; i < refmapCount; ++i)
+ {
+ // found an influencing probe
+ if (shouldSampleProbe(i, pos))
+ {
+ probeIndex[probeInfluences] = i;
+ ++probeInfluences;
+
+ int neighborIdx = refIndex[i].y;
+ if (neighborIdx != -1)
+ {
+ int neighborCount = min(refIndex[i].z, REF_SAMPLE_COUNT-1);
+
+ int count = 0;
+ while (count < neighborCount)
+ {
+ // check up to REF_SAMPLE_COUNT-1 neighbors (neighborIdx is ivec4 index)
+
+ int idx = refNeighbor[neighborIdx].x;
+ if (shouldSampleProbe(idx, pos))
+ {
+ probeIndex[probeInfluences++] = idx;
+ if (probeInfluences == REF_SAMPLE_COUNT)
+ {
+ return;
+ }
+ }
+ count++;
+ if (count == neighborCount)
+ {
+ return;
+ }
+
+ idx = refNeighbor[neighborIdx].y;
+ if (shouldSampleProbe(idx, pos))
+ {
+ probeIndex[probeInfluences++] = idx;
+ if (probeInfluences == REF_SAMPLE_COUNT)
+ {
+ return;
+ }
+ }
+ count++;
+ if (count == neighborCount)
+ {
+ return;
+ }
+
+ idx = refNeighbor[neighborIdx].z;
+ if (shouldSampleProbe(idx, pos))
+ {
+ probeIndex[probeInfluences++] = idx;
+ if (probeInfluences == REF_SAMPLE_COUNT)
+ {
+ return;
+ }
+ }
+ count++;
+ if (count == neighborCount)
+ {
+ return;
+ }
+
+ idx = refNeighbor[neighborIdx].w;
+ if (shouldSampleProbe(idx, pos))
+ {
+ probeIndex[probeInfluences++] = idx;
+ if (probeInfluences == REF_SAMPLE_COUNT)
+ {
+ return;
+ }
+ }
+ count++;
+ if (count == neighborCount)
+ {
+ return;
+ }
+
+ ++neighborIdx;
+ }
+
+ return;
+ }
+ }
+ }
+}
+
+// from https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection
+
+// original reference implementation:
+/*
+bool intersect(const Ray &ray) const
+{
+ float t0, t1; // solutions for t if the ray intersects
+#if 0
+ // geometric solution
+ Vec3f L = center - orig;
+ float tca = L.dotProduct(dir);
+ // if (tca < 0) return false;
+ float d2 = L.dotProduct(L) - tca * tca;
+ if (d2 > radius2) return false;
+ float thc = sqrt(radius2 - d2);
+ t0 = tca - thc;
+ t1 = tca + thc;
+#else
+ // analytic solution
+ Vec3f L = orig - center;
+ float a = dir.dotProduct(dir);
+ float b = 2 * dir.dotProduct(L);
+ float c = L.dotProduct(L) - radius2;
+ if (!solveQuadratic(a, b, c, t0, t1)) return false;
+#endif
+ if (t0 > t1) std::swap(t0, t1);
+
+ if (t0 < 0) {
+ t0 = t1; // if t0 is negative, let's use t1 instead
+ if (t0 < 0) return false; // both t0 and t1 are negative
+ }
+
+ t = t0;
+
+ return true;
+} */
+
+// adapted -- assume that origin is inside sphere, return distance from origin to edge of sphere
+vec3 sphereIntersect(vec3 origin, vec3 dir, vec3 center, float radius2)
+{
+ float t0, t1; // solutions for t if the ray intersects
+
+ vec3 L = center - origin;
+ float tca = dot(L,dir);
+
+ float d2 = dot(L,L) - tca * tca;
+
+ float thc = sqrt(radius2 - d2);
+ t0 = tca - thc;
+ t1 = tca + thc;
+
+ vec3 v = origin + dir * t1;
+ return v;
+}
+
+// from https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
+/*
+vec3 DirectionWS = normalize(PositionWS - CameraWS);
+vec3 ReflDirectionWS = reflect(DirectionWS, NormalWS);
+
+// Intersection with OBB convertto unit box space
+// Transform in local unit parallax cube space (scaled and rotated)
+vec3 RayLS = MulMatrix( float(3x3)WorldToLocal, ReflDirectionWS);
+vec3 PositionLS = MulMatrix( WorldToLocal, PositionWS);
+
+vec3 Unitary = vec3(1.0f, 1.0f, 1.0f);
+vec3 FirstPlaneIntersect = (Unitary - PositionLS) / RayLS;
+vec3 SecondPlaneIntersect = (-Unitary - PositionLS) / RayLS;
+vec3 FurthestPlane = max(FirstPlaneIntersect, SecondPlaneIntersect);
+float Distance = min(FurthestPlane.x, min(FurthestPlane.y, FurthestPlane.z));
+
+// Use Distance in WS directly to recover intersection
+vec3 IntersectPositionWS = PositionWS + ReflDirectionWS * Distance;
+vec3 ReflDirectionWS = IntersectPositionWS - CubemapPositionWS;
+
+return texCUBE(envMap, ReflDirectionWS);
+*/
+
+// get point of intersection with given probe's box influence volume
+// origin - ray origin in clip space
+// dir - ray direction in clip space
+// i - probe index in refBox/refSphere
+vec3 boxIntersect(vec3 origin, vec3 dir, int i)
+{
+ // Intersection with OBB convertto unit box space
+ // Transform in local unit parallax cube space (scaled and rotated)
+ mat4 clipToLocal = refBox[i];
+
+ vec3 RayLS = mat3(clipToLocal) * dir;
+ vec3 PositionLS = (clipToLocal * vec4(origin, 1.0)).xyz;
+
+ vec3 Unitary = vec3(1.0f, 1.0f, 1.0f);
+ vec3 FirstPlaneIntersect = (Unitary - PositionLS) / RayLS;
+ vec3 SecondPlaneIntersect = (-Unitary - PositionLS) / RayLS;
+ vec3 FurthestPlane = max(FirstPlaneIntersect, SecondPlaneIntersect);
+ float Distance = min(FurthestPlane.x, min(FurthestPlane.y, FurthestPlane.z));
+
+ // Use Distance in CS directly to recover intersection
+ vec3 IntersectPositionCS = origin + dir * Distance;
+
+ return IntersectPositionCS;
+}
+
+
+
+// Tap a sphere based reflection probe
+// pos - position of pixel
+// dir - pixel normal
+// lod - which mip to bias towards (lower is higher res, sharper reflections)
+// 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 tapRefMap(vec3 pos, vec3 dir, float lod, 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;
+ {
+ 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;
+ }
+}
+
+vec3 sampleProbes(vec3 pos, vec3 dir, float lod)
+{
+ float wsum = 0.0;
+ vec3 col = vec3(0,0,0);
+ float vd2 = dot(pos,pos); // view distance squared
+
+ for (int idx = 0; idx < probeInfluences; ++idx)
+ {
+ int i = probeIndex[idx];
+ 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 = tapRefMap(pos, dir, lod, 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 = tapRefMap(pos, dir, lod, 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;
+}
+
+vec3 sampleProbeAmbient(vec3 pos, vec3 dir, float lod)
+{
+ vec3 col = sampleProbes(pos, dir, lod);
+
+ //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;
+
+ return col*reflectionAmbiance;
+
+}
+
+// brighten a color so that at least one component is 1
+vec3 brighten(vec3 c)
+{
+ float m = max(max(c.r, c.g), c.b);
+
+ if (m == 0)
+ {
+ return vec3(1,1,1);
+ }
+
+ return c * 1.0/m;
+}
+
+
+void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
+ vec3 pos, vec3 norm, float glossiness, float envIntensity)
+{
+ // TODO - don't hard code lods
+ float reflection_lods = 8;
+ preProbeSample(pos);
+
+ vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
+
+ ambenv = sampleProbeAmbient(pos, norm, reflection_lods-1);
+
+ if (glossiness > 0.0)
+ {
+ float lod = (1.0-glossiness)*reflection_lods;
+ glossenv = sampleProbes(pos, normalize(refnormpersp), lod);
+ }
+
+ if (envIntensity > 0.0)
+ {
+ legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0);
+ }
+}
+
+void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm)
+{
+ glossenv *= 0.35; // fudge darker
+ float fresnel = 1.0+dot(normalize(pos.xyz), norm.xyz);
+ float minf = spec.a * 0.1;
+ fresnel = fresnel * (1.0-minf) + minf;
+ glossenv *= spec.rgb*min(fresnel, 1.0);
+ color.rgb += glossenv;
+}
+
+ void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity)
+ {
+ vec3 reflected_color = legacyenv; //*0.5; //fudge darker
+ vec3 lookAt = normalize(pos);
+ float fresnel = 1.0+dot(lookAt, norm.xyz);
+ fresnel *= fresnel;
+ 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/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index 7700d16007..d88400dddb 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -26,7 +26,10 @@
#extension GL_ARB_texture_rectangle : enable
#extension GL_ARB_shader_texture_lod : enable
-/*[EXTRA_CODE_HERE]*/
+#define FLT_MAX 3.402823466e+38
+
+#define REFMAP_COUNT 256
+#define REF_SAMPLE_COUNT 64 //maximum number of samples to consider
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
@@ -39,7 +42,6 @@ uniform sampler2DRect specularRect;
uniform sampler2DRect normalMap;
uniform sampler2DRect lightMap;
uniform sampler2DRect depthMap;
-uniform samplerCube environmentMap;
uniform sampler2D lightFunc;
uniform float blur_size;
@@ -66,6 +68,12 @@ vec3 scaleSoftClipFrag(vec3 l);
vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
vec3 fullbrightScaleSoftClip(vec3 light);
+// reflection probe interface
+void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyEnv,
+ vec3 pos, vec3 norm, float glossiness, float envIntensity);
+void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm);
+void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity);
+
vec3 linear_to_srgb(vec3 c);
vec3 srgb_to_linear(vec3 c);
@@ -103,40 +111,53 @@ void main()
vec3 amblit;
vec3 additive;
vec3 atten;
+
calcAtmosphericVars(pos.xyz, light_dir, ambocc, sunlit, amblit, additive, atten, true);
- color.rgb = amblit;
+ //vec3 amb_vec = env_mat * norm.xyz;
- float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
- ambient *= 0.5;
- ambient *= ambient;
- ambient = (1.0 - ambient);
- color.rgb *= ambient;
+ vec3 ambenv;
+ vec3 glossenv;
+ vec3 legacyenv;
+ sampleReflectionProbes(ambenv, glossenv, legacyenv, pos.xyz, norm.xyz, spec.a, envIntensity);
+
+ amblit = max(ambenv, amblit);
+ color.rgb = amblit*ambocc;
+
+ //float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
+ //ambient *= 0.5;
+ //ambient *= ambient;
+ //ambient = (1.0 - ambient);
+ //color.rgb *= ambient;
vec3 sun_contrib = min(da, scol) * sunlit;
color.rgb += sun_contrib;
+ color.rgb = min(color.rgb, vec3(1,1,1));
color.rgb *= diffuse.rgb;
- vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+ vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
if (spec.a > 0.0) // specular reflection
{
- float sa = dot(refnormpersp, light_dir.xyz);
+ float sa = dot(normalize(refnormpersp), light_dir.xyz);
vec3 dumbshiny = sunlit * scol * (texture2D(lightFunc, vec2(sa, spec.a)).r);
// add the two types of shiny together
vec3 spec_contrib = dumbshiny * spec.rgb;
bloom = dot(spec_contrib, spec_contrib) / 6;
color.rgb += spec_contrib;
+
+ // add reflection map - EXPERIMENTAL WORK IN PROGRESS
+ applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz);
}
color.rgb = mix(color.rgb, diffuse.rgb, diffuse.a);
if (envIntensity > 0.0)
{ // add environmentmap
- vec3 env_vec = env_mat * refnormpersp;
- vec3 reflected_color = textureCube(environmentMap, env_vec).rgb;
- color = mix(color.rgb, reflected_color, envIntensity);
+ //fudge darker
+ legacyenv *= 0.5*diffuse.a+0.5;;
+ applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity);
}
if (norm.w < 0.5)
@@ -153,6 +174,9 @@ void main()
// convert to linear as fullscreen lights need to sum in linear colorspace
// and will be gamma (re)corrected downstream...
+ //color = vec3(ambocc);
+ //color = ambenv;
+ //color.b = diffuse.a;
frag_color.rgb = srgb_to_linear(color.rgb);
- frag_color.a = bloom;
+ frag_color.a = bloom;
}
diff --git a/indra/newview/exopostprocess.cpp b/indra/newview/exopostprocess.cpp
index acef0015f6..dcc6760952 100644
--- a/indra/newview/exopostprocess.cpp
+++ b/indra/newview/exopostprocess.cpp
@@ -55,9 +55,11 @@ void exoPostProcess::ExodusRenderPostSettingsUpdate()
}
void exoPostProcess::ExodusRenderPostUpdate()
{
+ if (!gPipeline.mRT)
+ return;
+
etc1.setVec(0.f, 0.f);
- etc2.setVec((F32) gPipeline.mScreen.getWidth(),
- (F32) gPipeline.mScreen.getHeight());
+ etc2.setVec((F32) gPipeline.mRT->screen.getWidth(), (F32) gPipeline.mRT->screen.getHeight());
initVB();
}
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index 69ca8901d8..26df54eda2 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -1252,12 +1252,18 @@ void LLAgentCamera::updateLookAt(const S32 mouse_x, const S32 mouse_y)
static LLTrace::BlockTimerStatHandle FTM_UPDATE_CAMERA("Camera");
+extern BOOL gCubeSnapshot;
+
//-----------------------------------------------------------------------------
// updateCamera()
//-----------------------------------------------------------------------------
void LLAgentCamera::updateCamera()
{
LL_RECORD_BLOCK_TIME(FTM_UPDATE_CAMERA);
+ if (gCubeSnapshot)
+ {
+ return;
+ }
// - changed camera_skyward to the new global "mCameraUpVector"
mCameraUpVector = LLVector3::z_axis;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 751305118d..76274b7bec 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1783,23 +1783,23 @@ bool LLAppViewer::doFrame()
// Render scene.
// *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
- if (!LLApp::isExiting() && !gHeadlessClient && gViewerWindow)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df Display" )
- pingMainloopTimeout("Main:Display");
- gGLActive = TRUE;
+ if (!LLApp::isExiting() && !gHeadlessClient && gViewerWindow)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Display");
+ pingMainloopTimeout("Main:Display");
+ gGLActive = TRUE;
- display();
+ display();
- {
- FSPerfStats::RecordSceneTime T(FSPerfStats::StatType_t::RENDER_IDLE);
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Snapshot")
- pingMainloopTimeout("Main:Snapshot");
- LLFloaterSnapshot::update(); // take snapshots
- LLFloaterOutfitSnapshot::update();
- gGLActive = FALSE;
- }
- }
+ {
+ FSPerfStats::RecordSceneTime T(FSPerfStats::StatType_t::RENDER_IDLE);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Snapshot")
+ pingMainloopTimeout("Main:Snapshot");
+ LLFloaterSnapshot::update(); // take snapshots
+ LLFloaterOutfitSnapshot::update();
+ gGLActive = FALSE;
+ }
+ }
}
{
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index d5c00ae9ca..930b2fe30f 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -37,6 +37,7 @@
#include "lldrawpoolbump.h"
#include "lldrawpoolmaterials.h"
#include "lldrawpoolground.h"
+#include "lldrawpoolpbropaque.h"
#include "lldrawpoolsimple.h"
#include "lldrawpoolsky.h"
#include "lldrawpooltree.h"
@@ -118,6 +119,9 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0)
case POOL_WL_SKY:
poolp = new LLDrawPoolWLSky();
break;
+ case POOL_PBR_OPAQUE:
+ poolp = new LLDrawPoolPBROpaque();
+ break;
default:
LL_ERRS() << "Unknown draw pool type!" << LL_ENDL;
return NULL;
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index fd1b022e5b..b73ae94bbb 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -67,6 +67,7 @@ public:
POOL_WATER,
POOL_GLOW,
POOL_ALPHA,
+ POOL_PBR_OPAQUE,
NUM_POOL_TYPES,
// * invisiprims work by rendering to the depth buffer but not the color buffer, occluding anything rendered after them
// - and the LLDrawPool types enum controls what order things are rendered in
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 959b7ad6dc..ec1d349027 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -130,6 +130,8 @@ static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma, bool d
}
}
+extern BOOL gCubeSnapshot;
+
void LLDrawPoolAlpha::renderPostDeferred(S32 pass)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
@@ -156,13 +158,13 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass)
forwardRender();
// final pass, render to depth for depth of field effects
- if (!LLPipeline::sImpostorRender && gSavedSettings.getBOOL("RenderDepthOfField"))
+ if (!LLPipeline::sImpostorRender && gSavedSettings.getBOOL("RenderDepthOfField") && !gCubeSnapshot)
{
//update depth buffer sampler
- gPipeline.mScreen.flush();
- gPipeline.mDeferredDepth.copyContents(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(),
- 0, 0, gPipeline.mDeferredDepth.getWidth(), gPipeline.mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
- gPipeline.mDeferredDepth.bindTarget();
+ gPipeline.mRT->screen.flush();
+ gPipeline.mRT->deferredDepth.copyContents(gPipeline.mRT->deferredScreen, 0, 0, gPipeline.mRT->deferredScreen.getWidth(), gPipeline.mRT->deferredScreen.getHeight(),
+ 0, 0, gPipeline.mRT->deferredDepth.getWidth(), gPipeline.mRT->deferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ gPipeline.mRT->deferredDepth.bindTarget();
simple_shader = fullbright_shader = &gObjectFullbrightAlphaMaskProgram;
simple_shader->bind();
@@ -176,8 +178,8 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass)
renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2,
true); // <--- discard mostly transparent faces
- gPipeline.mDeferredDepth.flush();
- gPipeline.mScreen.bindTarget();
+ gPipeline.mRT->deferredDepth.flush();
+ gPipeline.mRT->screen.bindTarget();
gGL.setColorMask(true, false);
}
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 8db16ef5d0..af666e77ee 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -468,6 +468,11 @@ void LLDrawPoolBump::beginFullbrightShiny()
LLVector4 vec4(vec, gShinyOrigin.mV[3]);
shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
+ if (shader->mFeatures.hasReflectionProbes)
+ {
+ gPipeline.bindReflectionProbes(*shader);
+ }
+
cube_map->setMatrix(1);
// Make sure that texture coord generation happens for tex unit 1, as that's the one we use for
// the cube map in the one pass shiny shaders
@@ -530,6 +535,10 @@ void LLDrawPoolBump::endFullbrightShiny()
{
cube_map->disable();
cube_map->restoreMatrix();
+ if (shader->mFeatures.hasReflectionProbes)
+ {
+ gPipeline.unbindReflectionProbes(*shader);
+ }
shader->unbind();
}
@@ -771,6 +780,7 @@ void LLDrawPoolBump::renderDeferred(S32 pass)
void LLDrawPoolBump::renderPostDeferred(S32 pass)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL
for (int i = 0; i < 2; ++i)
{ // two passes -- static and rigged
mRigged = (i == 1);
diff --git a/indra/newview/lldrawpoolpbropaque.cpp b/indra/newview/lldrawpoolpbropaque.cpp
new file mode 100644
index 0000000000..2478aa0cff
--- /dev/null
+++ b/indra/newview/lldrawpoolpbropaque.cpp
@@ -0,0 +1,92 @@
+/**
+ * @file lldrawpoolpbropaque.cpp
+ * @brief LLDrawPoolPBROpaque class implementation
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lldrawpool.h"
+#include "lldrawpoolpbropaque.h"
+#include "llviewershadermgr.h"
+#include "pipeline.h"
+
+LLDrawPoolPBROpaque::LLDrawPoolPBROpaque() :
+ LLRenderPass(POOL_PBR_OPAQUE)
+{
+}
+
+void LLDrawPoolPBROpaque::prerender()
+{
+ mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+}
+
+// Forward
+void LLDrawPoolPBROpaque::beginRenderPass(S32 pass)
+{
+}
+
+void LLDrawPoolPBROpaque::endRenderPass( S32 pass )
+{
+}
+
+void LLDrawPoolPBROpaque::render(S32 pass)
+{
+}
+
+// Deferred
+void LLDrawPoolPBROpaque::beginDeferredPass(S32 pass)
+{
+ gDeferredPBROpaqueProgram.bind();
+}
+
+void LLDrawPoolPBROpaque::endDeferredPass(S32 pass)
+{
+ gDeferredPBROpaqueProgram.unbind();
+ LLRenderPass::endRenderPass(pass);
+}
+
+void LLDrawPoolPBROpaque::renderDeferred(S32 pass)
+{
+ if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_MATERIALS))
+ {
+ return;
+ }
+
+ gGL.flush();
+
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable alpha_test(GL_ALPHA_TEST);
+
+ // TODO: handle HUDs?
+ //if (LLPipeline::sRenderingHUDs)
+ // mShader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+ //else
+ // mShader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+
+ // TODO: handle under water?
+ // if (LLPipeline::sUnderWaterRender)
+ // PASS_SIMPLE or PASS_MATERIAL
+ //pushBatches(LLRenderPass::PASS_SIMPLE, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+}
+
diff --git a/indra/newview/lldrawpoolpbropaque.h b/indra/newview/lldrawpoolpbropaque.h
new file mode 100644
index 0000000000..ada806a3bf
--- /dev/null
+++ b/indra/newview/lldrawpoolpbropaque.h
@@ -0,0 +1,61 @@
+/**
+ * @file lldrawpoolpbropaque.h
+ * @brief LLDrawPoolPBrOpaque class 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$
+ */
+
+#ifndef LL_LLDRAWPOOLPBROPAQUE_H
+#define LL_LLDRAWPOOLPBROPAQUE_H
+
+#include "lldrawpool.h"
+
+class LLDrawPoolPBROpaque : public LLRenderPass
+{
+public:
+ enum
+ {
+ VERTEX_DATA_MASK = 0
+ | LLVertexBuffer::MAP_VERTEX
+ | LLVertexBuffer::MAP_NORMAL
+ | LLVertexBuffer::MAP_TEXCOORD0
+ | LLVertexBuffer::MAP_COLOR
+ };
+ virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+
+ LLDrawPoolPBROpaque();
+
+ /*virtual*/ S32 getNumDeferredPasses() { return 1; }
+ /*virtual*/ void beginDeferredPass(S32 pass);
+ /*virtual*/ void endDeferredPass(S32 pass);
+ /*virtual*/ void renderDeferred(S32 pass);
+
+ // Non ALM isn't supported
+ /*virtual*/ void beginRenderPass(S32 pass);
+ /*virtual*/ void endRenderPass(S32 pass);
+ /*virtual*/ S32 getNumPasses() { return 0; }
+ /*virtual*/ void render(S32 pass = 0);
+ /*virtual*/ void prerender();
+
+};
+
+#endif // LL_LLDRAWPOOLPBROPAQUE_H
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 198926511f..08f45b63ef 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -612,7 +612,6 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
// glTexCoordPointer(2, GL_FLOAT, 8, vol_face.mTexCoords);
//}
//gGL.syncMatrices();
- //LL_PROFILER_GPU_ZONEC("gl.DrawElements", 0x00FF00);
//glDrawElements(GL_TRIANGLES, vol_face.mNumIndices, GL_UNSIGNED_SHORT, vol_face.mIndices);
//glDisableClientState(GL_TEXTURE_COORD_ARRAY);
LLVertexBuffer::drawElements(LLRender::TRIANGLES, vol_face.mPositions, vol_face.mTexCoords, vol_face.mNumIndices, vol_face.mIndices);
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 49e036cec6..aff052a47a 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -375,10 +375,10 @@ void LLFloaterModelPreview::initModelPreview()
S32 tex_width = 512;
S32 tex_height = 512;
// Fix up regressions from LL's merge of uploader changes
- // S32 max_width = llmin(PREVIEW_RENDER_SIZE, (S32)gPipeline.mScreenWidth);
- // S32 max_height = llmin(PREVIEW_RENDER_SIZE, (S32)gPipeline.mScreenHeight);
- S32 max_width = llmin(gSavedSettings.getS32("PreviewRenderSize"), (S32)gPipeline.mScreenWidth);
- S32 max_height = llmin(gSavedSettings.getS32("PreviewRenderSize"), (S32)gPipeline.mScreenHeight);
+ // S32 max_width = llmin(PREVIEW_RENDER_SIZE, (S32)gPipeline.mRT->width);
+ // S32 max_height = llmin(PREVIEW_RENDER_SIZE, (S32)gPipeline.mRT->height);
+ S32 max_width = llmin(gSavedSettings.getS32("PreviewRenderSize"), (S32)gPipeline.mRT->width);
+ S32 max_height = llmin(gSavedSettings.getS32("PreviewRenderSize"), (S32)gPipeline.mRT->height);
//
while ((tex_width << 1) <= max_width) // Fix up regressions from LL's merge of uploader changes
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 8c4562dd65..ddc3076073 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -125,6 +125,7 @@ F32 LLPanelFace::getCurrentShinyScaleU() { return mCtrlShinyScaleU->getValue()
F32 LLPanelFace::getCurrentShinyScaleV() { return mCtrlShinyScaleV->getValue().asReal(); }
F32 LLPanelFace::getCurrentShinyOffsetU() { return mCtrlShinyOffsetU->getValue().asReal(); }
F32 LLPanelFace::getCurrentShinyOffsetV() { return mCtrlShinyOffsetV->getValue().asReal(); }
+LLUUID LLPanelFace::getCurrentMaterialID() { return getChild("materialID")->getValue().asUUID(); }
// UI provided diffuse parameters
F32 LLPanelFace::getCurrentTextureRot() { return mCtrlTexRot->getValue().asReal(); }
@@ -164,6 +165,7 @@ BOOL LLPanelFace::postBuild()
childSetCommitCallback("glossiness",&LLPanelFace::onCommitMaterialGloss, this);
childSetCommitCallback("environment",&LLPanelFace::onCommitMaterialEnv, this);
childSetCommitCallback("maskcutoff",&LLPanelFace::onCommitMaterialMaskCutoff, this);
+ childSetCommitCallback("materialID", &LLPanelFace::onCommitMaterialID, this);
//
childSetCommitCallback("checkbox_sync_settings", &LLPanelFace::onClickMapsSync, this);
@@ -256,6 +258,7 @@ BOOL LLPanelFace::postBuild()
childSetAction("button align",&LLPanelFace::onClickAutoFix,this);
childSetAction("button align textures", &LLPanelFace::onAlignTexture, this);
+ childSetAction("button save material", &LLPanelFace::onSaveMaterial, this);
// Moved to the header so other functions can use them too.
//LLTextureCtrl* mTextureCtrl;
@@ -399,6 +402,7 @@ BOOL LLPanelFace::postBuild()
mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this);
}
+
clearCtrls();
return TRUE;
@@ -1543,7 +1547,15 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
LLMaterialPtr material;
LLSelectedTEMaterial::getCurrent(material, identical);
- if (material && editable)
+ // enable this UI box if a single face is selected.
+ BOOL is_single_face = !LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected();
+ childSetEnabled("button save material", static_cast(is_single_face));
+ childSetEnabled("materialID", static_cast(is_single_face)); // doesn't work - why?
+
+ // TODO: 2022-04 conflicts with media button placement. hide the button if applying media
+ // i.e. childSetVisible("button save material", !applying_media);
+
+ if (material && editable)
{
LL_DEBUGS("Materials") << material->asLLSD() << LL_ENDL;
@@ -1651,6 +1663,8 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
calcp->setVar(LLCalc::TEX_ROTATION, getCurrentTextureRot());
calcp->setVar(LLCalc::TEX_TRANSPARENCY, childGetValue("ColorTrans").asReal());
calcp->setVar(LLCalc::TEX_GLOW, childGetValue("glow").asReal());
+
+ getChildView("materialID")->setEnabled(editable);
}
else
{
@@ -2445,6 +2459,17 @@ void LLPanelFace::onCommitMaterialMaskCutoff(LLUICtrl* ctrl, void* userdata)
LLSelectedTEMaterial::setAlphaMaskCutoff(self,self->getCurrentAlphaMaskCutoff());
}
+//static
+void LLPanelFace::onCommitMaterialID(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = static_cast(userdata);
+ LLUUID matID = self->getCurrentMaterialID();
+ LLSelectedTEMaterial::setMaterialID(self, matID);
+
+ // Temporary demo hack - replace the TE entries with those from the Material's LLSD
+ applyMaterialUUID(matID, userdata);
+}
+
// static
void LLPanelFace::onCommitTextureInfo( LLUICtrl* ctrl, void* userdata )
{
@@ -2681,6 +2706,207 @@ void LLPanelFace::onAlignTexture(void* userdata)
self->alignTestureLayer();
}
+#include "llagent.h"
+#include "llfilesystem.h"
+#include "llviewerassetupload.h"
+#include "llviewermenufile.h"
+#include "llsd.h"
+#include "llsdutil.h"
+#include "llsdserialize.h"
+#include "llinventorymodel.h"
+
+void LLPanelFace::onSaveMaterial(void* userdata)
+{
+ // DRTVWR-559, Q&D material picker - save to inventory goes here
+ LL_DEBUGS("Material") << "saving render material to inventory" << LL_ENDL;
+
+ std::string name = "New Material";
+
+ LLSD material_data = llsd::map(
+ "version", "1",
+ "material", LLSD::emptyMap()
+ );
+
+ // gen a new uuid for this asset
+ LLTransactionID tid;
+ tid.generate(); // timestamp-based randomization + uniquification
+ LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+
+ material_data["material"] = renderMaterialToLLSD(new_asset_id, userdata);
+ std::stringstream output;
+ LLSDSerialize::toNotation(material_data, output);
+
+ //S32 expected_upload_cost = 0;// LLAgentBenefitsMgr::current().getTextureUploadCost();
+
+ std::string res_name = name;
+ std::string res_desc = "Saved Material";
+ //LLFolderType::EType folder_type = LLFolderType::FT_MATERIAL;
+ //LLInventoryType::EType inv_type = LLInventoryType::IT_MATERIAL;
+ U32 next_owner_perm = LLPermissions::DEFAULT.getMaskNextOwner();
+
+ LLUUID parent = gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL);
+ const U8 subtype = NO_INV_SUBTYPE; // TODO maybe use AT_SETTINGS and LLSettingsType::ST_MATERIAL ?
+
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(), parent, tid, res_name, res_desc,
+ LLAssetType::AT_MATERIAL, LLInventoryType::IT_MATERIAL, subtype, next_owner_perm,
+ new LLBoostFuncInventoryCallback([output=output.str()](LLUUID const & inv_item_id){
+ // from reference in LLSettingsVOBase::createInventoryItem()/updateInventoryItem()
+ LLResourceUploadInfo::ptr_t uploadInfo =
+ std::make_shared(
+ inv_item_id,
+ LLAssetType::AT_SETTINGS, // TODO switch to AT_MATERIAL
+ output,
+ [](LLUUID item_id, LLUUID new_asset_id, LLUUID new_item_id, LLSD response) {
+ LL_INFOS("Material") << "inventory item uploaded. item: " << item_id << " asset: " << new_asset_id << " new_item_id: " << new_item_id << " response: " << response << LL_ENDL;
+ LLSD params = llsd::map("ASSET_ID", new_asset_id);
+ LLNotificationsUtil::add("MaterialCreated", params);
+ });
+
+ const LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ std::string agent_url(region->getCapability("UpdateSettingsAgentInventory"));
+ if (agent_url.empty())
+ {
+ LL_ERRS() << "missing required agent inventory cap url" << LL_ENDL;
+ }
+ LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
+ }
+ })
+ );
+
+}
+
+// Fill an LLSD with data describing the current face's texture settings
+// TODO 2022-05 FUBAR there are both colliding and different data in LLPanelFace vs the TE. Also, neither one has the diffuse tex settings.
+//
+LLSD LLPanelFace::renderMaterialToLLSD(LLUUID uuid, void* userdata)
+{
+ llassert(userdata != nullptr);
+
+ LLSD sd;
+
+ sd.insert("RenderMaterialUUID", LLSD(uuid));
+
+ // now pull same data from the selected TE (same but different. W T F?)
+ LLMaterialPtr mat = nullptr;
+ bool ident; // ?
+ LLSelectedTEMaterial::getCurrent(mat, ident);
+
+ if (mat)
+ {
+ sd.insert("teMaterialID", LLSD(mat->getMaterialID()));
+
+ sd.insert("teNormalMap", LLSD(mat->getNormalID()));
+ sd.insert("teNormalOffsetX", LLSD(mat->getNormalOffsetX()));
+ sd.insert("teNormalOffsetY", LLSD(mat->getNormalOffsetY()));
+ sd.insert("teNormalRepeatX", LLSD(mat->getNormalRepeatX()));
+ sd.insert("teNormalRepeatY", LLSD(mat->getNormalRepeatY()));
+ sd.insert("teNormalRotation", LLSD(mat->getNormalRotation()));
+
+ sd.insert("teSpecularMap", LLSD(mat->getSpecularID()));
+ LLColor4U color = mat->getSpecularLightColor();
+
+ sd.insert("teSpecularColorR", LLSD(static_cast(color.mV[0])));
+ sd.insert("teSpecularColorG", LLSD(static_cast(color.mV[1])));
+ sd.insert("teSpecularColorB", LLSD(static_cast(color.mV[2])));
+ sd.insert("teSpecularColorA", LLSD(static_cast(color.mV[3])));
+ sd.insert("teSpecularExponent", LLSD(static_cast(mat->getSpecularLightExponent())));
+ sd.insert("teSpecularOffsetX", LLSD(mat->getSpecularOffsetX()));
+ sd.insert("teSpecularOffsetY", LLSD(mat->getSpecularOffsetY()));
+ sd.insert("teSpecularRepeatX", LLSD(mat->getSpecularRepeatX()));
+ sd.insert("teSpecularRepeatY", LLSD(mat->getSpecularRepeatY()));
+ sd.insert("teSpecularRotation", LLSD(mat->getSpecularRotation()));
+
+ sd.insert("teAlphaMode", LLSD(static_cast(mat->getDiffuseAlphaMode())));
+ sd.insert("teAlphaCutoff", LLSD(static_cast(mat->getAlphaMaskCutoff())));
+ sd.insert("teEnvIntensity", LLSD(static_cast(mat->getEnvironmentIntensity())));
+ sd.insert("teShaderMask", LLSD(static_cast(mat->getShaderMask())));
+ }
+ else
+ {
+ // pull data from the LLPanelFace
+ LLPanelFace* instance = static_cast(userdata);
+ sd.insert("pfNormalMap", LLSD(instance->getCurrentNormalMap()));
+ sd.insert("pfSpecularMap", LLSD(instance->getCurrentSpecularMap()));
+ sd.insert("pfShininess", LLSD(static_cast(instance->getCurrentShininess())));
+ sd.insert("pfBumpiness", LLSD(static_cast(instance->getCurrentBumpiness())));
+ sd.insert("pfAlphaMode", LLSD(static_cast(instance->getCurrentDiffuseAlphaMode())));
+ sd.insert("pfAlphaCutoff", LLSD(static_cast(instance->getCurrentAlphaMaskCutoff())));
+ sd.insert("pfEnvIntensity", LLSD(static_cast(instance->getCurrentEnvIntensity())));
+ sd.insert("pfGlossiness", LLSD(static_cast(instance->getCurrentGlossiness())));
+ sd.insert("pfNormalRotation", LLSD(instance->getCurrentBumpyRot()));
+ sd.insert("pfNormalScaleU", LLSD(instance->getCurrentBumpyScaleU()));
+ sd.insert("pfNormalScaleV", LLSD(instance->getCurrentBumpyScaleV()));
+ sd.insert("pfNormalOffsetU", LLSD(instance->getCurrentBumpyOffsetU()));
+ sd.insert("pfNormalOffsetV", LLSD(instance->getCurrentBumpyOffsetV()));
+ sd.insert("pfSpecularRotation", LLSD(instance->getCurrentShinyRot()));
+ sd.insert("pfSpecularScaleU", LLSD(instance->getCurrentShinyScaleU()));
+ sd.insert("pfSpecularScaleV", LLSD(instance->getCurrentShinyScaleV()));
+ sd.insert("pfSpecularOffsetU", LLSD(instance->getCurrentShinyOffsetU()));
+ sd.insert("pfSpecularOffsetV", LLSD(instance->getCurrentShinyOffsetV()));
+ sd.insert("pfMaterialID", LLSD(instance->getCurrentMaterialID()));
+ }
+
+ return sd;
+}
+
+// Take the individual texture settings from the material and apply to current face & TE
+void LLPanelFace::applyMaterialUUID(LLUUID uuid, void* userdata)
+{
+ llassert(userdata != nullptr);
+ //LLPanelFace* instance = static_cast(userdata);
+
+ LLFileSystem material_file(uuid, LLAssetType::AT_MATERIAL, LLFileSystem::READ);
+ S32 bufsize = material_file.getSize();
+ llassert(bufsize > 0);
+ std::vector buffer(bufsize);
+ material_file.read(&buffer[0], bufsize);
+ std::istringstream input(std::string(buffer.begin(), buffer.end())); // TODO - extend LLFileSystem to expose iostream interface
+ LLSD matSD;
+
+ LLSDSerialize::fromNotation(matSD, input, bufsize);
+
+ LL_INFOS() << "dump matSD: " << matSD << LL_ENDL;
+
+ // strip off the versioning wrapper for now
+ matSD = matSD["material"];
+
+ // wrong, oops. llassert(uuid == matSD.get("RenderMaterialUUID").asUUID()); // if not, whoo boy
+
+ LLMaterialPtr mat = nullptr;
+ bool ident; // ?
+ LLSelectedTEMaterial::getCurrent(mat, ident);
+
+ mat->setMaterialID(matSD.get("teMaterialID").asUUID());
+
+ mat->setNormalID(matSD.get("teNormalMap").asUUID());
+ mat->setNormalOffsetX(matSD.get("teNormalOffsetX").asReal());
+ mat->setNormalOffsetY(matSD.get("teNormalOffsetY").asReal());
+ mat->setNormalRepeatX(matSD.get("teNormalRepeatX").asReal());
+ mat->setNormalRepeatY(matSD.get("teNormalRepeatY").asReal());
+ mat->setNormalRotation(matSD.get("teNormalRotation").asReal());
+
+ mat->setSpecularID(matSD.get("teSpecularMap").asUUID());
+ LLColor4U color;
+ color.mV[0] = static_cast(matSD.get("teSecularColorR").asInteger());
+ color.mV[1] = static_cast(matSD.get("teSecularColorG").asInteger());
+ color.mV[2] = static_cast(matSD.get("teSecularColorB").asInteger());
+ color.mV[3] = static_cast(matSD.get("teSecularColorA").asInteger());
+ mat->setSpecularLightColor(color);
+ mat->setSpecularLightExponent(static_cast(matSD.get("teSpecularExponent").asInteger()));
+ mat->setSpecularOffsetX(matSD.get("teSpecularOffsetX").asReal());
+ mat->setSpecularOffsetY(matSD.get("teSpecularOffsetY").asReal());
+ mat->setSpecularRepeatX(matSD.get("teSpecularRepeatX").asReal());
+ mat->setSpecularRepeatY(matSD.get("teSpecularRepeatY").asReal());
+ mat->setSpecularRotation(matSD.get("teSpecularRotation").asReal());
+
+ mat->setDiffuseAlphaMode(static_cast(matSD.get("teAlphaMode").asInteger()));
+ mat->setAlphaMaskCutoff(static_cast(matSD.get("teAlphaCutoff").asInteger()));
+ mat->setEnvironmentIntensity(static_cast(matSD.get("teEnvIntensity").asInteger()));
+ //mat->setShaderMask(static_cast(matSD.get(teShaderMask").asInteger());
+}
+
// TODO: I don't know who put these in or what these are for???
void LLPanelFace::setMediaURL(const std::string& url)
diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h
index 7aae9ff3e1..be19f763de 100644
--- a/indra/newview/llpanelface.h
+++ b/indra/newview/llpanelface.h
@@ -193,6 +193,7 @@ protected:
static void onCommitMaterialGloss( LLUICtrl* ctrl, void* userdata);
static void onCommitMaterialEnv( LLUICtrl* ctrl, void* userdata);
static void onCommitMaterialMaskCutoff( LLUICtrl* ctrl, void* userdata);
+ static void onCommitMaterialID( LLUICtrl* ctrl, void* userdata);
static void onCommitMaterialsMedia( LLUICtrl* ctrl, void* userdata);
static void onCommitMaterialType( LLUICtrl* ctrl, void* userdata);
@@ -207,6 +208,10 @@ protected:
static void onClickAutoFix(void*);
static void onAlignTexture(void*);
+ static void onSaveMaterial(void*);
+ static LLSD renderMaterialToLLSD(LLUUID uuid, void* userdata);
+ static void applyMaterialUUID(LLUUID uuid, void*);
+
static F32 valueGlow(LLViewerObject* object, S32 face);
// Texture params copy/paste
@@ -261,7 +266,8 @@ private:
F32 getCurrentShinyScaleV();
F32 getCurrentShinyOffsetU();
F32 getCurrentShinyOffsetV();
-
+ LLUUID getCurrentMaterialID();
+
// Convenience funcs for diffuse maps
F32 getCurrentTextureRot();
F32 getCurrentTextureScaleU();
@@ -552,6 +558,7 @@ public:
DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setNormalID);
DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setSpecularID);
DEF_EDIT_MAT_STATE(LLColor4U, const LLColor4U&,setSpecularLightColor);
+ DEF_EDIT_MAT_STATE(LLUUID, const LLUUID&, setMaterialID);
};
class LLSelectedTE
diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp
new file mode 100644
index 0000000000..54a627efd4
--- /dev/null
+++ b/indra/newview/llreflectionmap.cpp
@@ -0,0 +1,269 @@
+/**
+ * @file llreflectionmap.cpp
+ * @brief LLReflectionMap class implementation
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llreflectionmap.h"
+#include "pipeline.h"
+#include "llviewerwindow.h"
+#include "llviewerregion.h"
+
+extern F32SecondsImplicit gFrameTimeSeconds;
+
+LLReflectionMap::LLReflectionMap()
+{
+ mLastUpdateTime = gFrameTimeSeconds;
+}
+
+void LLReflectionMap::update(U32 resolution, U32 face)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ mLastUpdateTime = gFrameTimeSeconds;
+ llassert(mCubeArray.notNull());
+ llassert(mCubeIndex != -1);
+ llassert(LLPipeline::sRenderDeferred);
+
+ // make sure we don't walk off the edge of the render target
+ while (resolution > gPipeline.mRT->deferredScreen.getWidth() ||
+ resolution > gPipeline.mRT->deferredScreen.getHeight())
+ {
+ resolution /= 2;
+ }
+ gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face);
+}
+
+bool LLReflectionMap::shouldUpdate()
+{
+ const F32 TIMEOUT_INTERVAL = 30.f; // update no less than this often
+ const F32 RENDER_TIMEOUT = 1.f; // don't update if hasn't been used for rendering for this long
+
+ if (mLastBindTime > gFrameTimeSeconds - RENDER_TIMEOUT)
+ {
+ if (mLastUpdateTime < gFrameTimeSeconds - TIMEOUT_INTERVAL)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void LLReflectionMap::dirty()
+{
+ mDirty = true;
+ mLastUpdateTime = gFrameTimeSeconds;
+}
+
+void LLReflectionMap::autoAdjustOrigin()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+
+ if (mGroup)
+ {
+ const LLVector4a* bounds = mGroup->getBounds();
+ auto* node = mGroup->getOctreeNode();
+
+ if (mGroup->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_TERRAIN)
+ {
+ // for terrain, make probes float a couple meters above the highest point in the surface patch
+ mOrigin = bounds[0];
+ mOrigin.getF32ptr()[2] += bounds[1].getF32ptr()[2] + 3.f;
+
+ // update radius to encompass bounding box
+ LLVector4a d;
+ d.setAdd(bounds[0], bounds[1]);
+ d.sub(mOrigin);
+ mRadius = d.getLength3().getF32();
+ }
+ else if (mGroup->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME)
+ {
+ mPriority = 8;
+ // cast a ray towards 8 corners of bounding box
+ // nudge origin towards center of empty space
+
+ if (node->isLeaf() || node->getChildCount() > 1 || node->getData().size() > 0)
+ { // use center of object bounding box for leaf nodes or nodes with multiple child nodes
+ mOrigin = bounds[0];
+
+ LLVector4a start;
+ LLVector4a end;
+
+ LLVector4a size = bounds[1];
+
+ LLVector4a corners[] =
+ {
+ { 1, 1, 1 },
+ { -1, 1, 1 },
+ { 1, -1, 1 },
+ { -1, -1, 1 },
+ { 1, 1, -1 },
+ { -1, 1, -1 },
+ { 1, -1, -1 },
+ { -1, -1, -1 }
+ };
+
+ for (int i = 0; i < 8; ++i)
+ {
+ corners[i].mul(size);
+ corners[i].add(bounds[0]);
+ }
+
+ LLVector4a extents[2];
+ extents[0].setAdd(bounds[0], bounds[1]);
+ extents[1].setSub(bounds[0], bounds[1]);
+
+ bool hit = false;
+ for (int i = 0; i < 8; ++i)
+ {
+ int face = -1;
+ LLVector4a intersection;
+ LLDrawable* drawable = mGroup->lineSegmentIntersect(bounds[0], corners[i], true, false, &face, &intersection);
+ if (drawable != nullptr)
+ {
+ hit = true;
+ update_min_max(extents[0], extents[1], intersection);
+ }
+ else
+ {
+ update_min_max(extents[0], extents[1], corners[i]);
+ }
+ }
+
+ if (hit)
+ {
+ mOrigin.setAdd(extents[0], extents[1]);
+ mOrigin.mul(0.5f);
+ }
+
+ // make sure radius encompasses all objects
+ LLSimdScalar r2 = 0.0;
+ for (int i = 0; i < 8; ++i)
+ {
+ LLVector4a v;
+ v.setSub(corners[i], mOrigin);
+
+ LLSimdScalar d = v.dot3(v);
+
+ if (d > r2)
+ {
+ r2 = d;
+ }
+ }
+
+ mRadius = llmax(sqrtf(r2.getF32()), 8.f);
+ }
+ else
+ {
+ // user placed probe
+ mPriority = 64;
+
+ // use center of octree node volume for nodes that are just branches without data
+ mOrigin = node->getCenter();
+
+ // update radius to encompass entire octree node volume
+ mRadius = node->getSize().getLength3().getF32();
+
+ //mOrigin = bounds[0];
+ //mRadius = bounds[1].getLength3().getF32();
+
+ }
+ }
+ }
+ else if (mViewerObject)
+ {
+ mPriority = 64;
+ mOrigin.load3(mViewerObject->getPositionAgent().mV);
+ mRadius = mViewerObject->getScale().mV[0]*0.5f;
+ }
+}
+
+bool LLReflectionMap::intersects(LLReflectionMap* other)
+{
+ // TODO: incorporate getBox
+ LLVector4a delta;
+ delta.setSub(other->mOrigin, mOrigin);
+
+ F32 dist = delta.dot3(delta).getF32();
+
+ F32 r2 = mRadius + other->mRadius;
+
+ r2 *= r2;
+
+ return dist < r2;
+}
+
+bool LLReflectionMap::getBox(LLMatrix4& box)
+{
+ if (mViewerObject)
+ {
+ LLVolume* volume = mViewerObject->getVolume();
+ if (volume)
+ {
+ LLVOVolume* vobjp = (LLVOVolume*)mViewerObject;
+
+ U8 profile = volume->getProfileType();
+ U8 path = volume->getPathType();
+
+ if (profile == LL_PCODE_PROFILE_SQUARE &&
+ path == LL_PCODE_PATH_LINE)
+ {
+ // nope
+ /*box = vobjp->getRelativeXform();
+ box *= vobjp->mDrawable->getRenderMatrix();
+ LLMatrix4 modelview(gGLModelView);
+ box *= modelview;
+ box.invert();*/
+
+ // nope
+ /*box = LLMatrix4(gGLModelView);
+ box *= vobjp->mDrawable->getRenderMatrix();
+ box *= vobjp->getRelativeXform();
+ box.invert();*/
+
+ glh::matrix4f mv(gGLModelView);
+ glh::matrix4f scale;
+ LLVector3 s = vobjp->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f));
+ mRadius = s.magVec();
+ scale.set_scale(glh::vec3f(s.mV));
+ if (vobjp->mDrawable != nullptr)
+ {
+ glh::matrix4f rm((F32*)vobjp->mDrawable->getWorldMatrix().mMatrix);
+
+ glh::matrix4f rt((F32*)vobjp->getRelativeXform().mMatrix);
+
+ mv = mv * rm * scale; // *rt;
+ mv = mv.inverse();
+
+ box = LLMatrix4(mv.m);
+
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h
new file mode 100644
index 0000000000..4f0f124118
--- /dev/null
+++ b/indra/newview/llreflectionmap.h
@@ -0,0 +1,101 @@
+/**
+ * @file llreflectionmap.h
+ * @brief LLReflectionMap class declaration
+ *
+ * $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 "llcubemaparray.h"
+#include "llmemory.h"
+
+class LLSpatialGroup;
+class LLViewerObject;
+
+class alignas(16) LLReflectionMap : public LLRefCount
+{
+ LL_ALIGN_NEW
+public:
+ // allocate an environment map of the given resolution
+ LLReflectionMap();
+
+ // update this environment map
+ // resolution - size of cube map to generate
+ void update(U32 resolution, U32 face);
+
+ // return true if this probe should update *now*
+ bool shouldUpdate();
+
+ // Mark this reflection map as needing an update (resets last update time, so spamming this call will cause a cube map to never update)
+ void dirty();
+
+ // for volume partition probes, try to place this probe in the best spot
+ void autoAdjustOrigin();
+
+ // return true if given Reflection Map's influence volume intersect's with this one's
+ bool intersects(LLReflectionMap* other);
+
+ // get the encoded bounding box of this probe's influence volume
+ // will only return a box if this probe has a volume with a square
+ // profile and a linear path
+ // return false if no bounding box (treat as sphere influence volume)
+ bool getBox(LLMatrix4& box);
+
+ // point at which environment map was last generated from (in agent space)
+ LLVector4a mOrigin;
+
+ // distance from viewer camera
+ F32 mDistance;
+
+ // radius of this probe's affected area
+ F32 mRadius = 16.f;
+
+ // last time this probe was updated (or when its update timer got reset)
+ F32 mLastUpdateTime = 0.f;
+
+ // last time this probe was bound for rendering
+ F32 mLastBindTime = 0.f;
+
+ // cube map used to sample this environment map
+ LLPointer mCubeArray;
+ S32 mCubeIndex = -1; // index into cube map array or -1 if not currently stored in cube map array
+
+ // index into array packed by LLReflectionMapManager::getReflectionMaps
+ // WARNING -- only valid immediately after call to getReflectionMaps
+ S32 mProbeIndex = -1;
+
+ // set of any LLReflectionMaps that intersect this map (maintained by LLReflectionMapManager
+ std::vector mNeighbors;
+
+ // spatial group this probe is tracking (if any)
+ LLSpatialGroup* mGroup = nullptr;
+
+ // viewer object this probe is tracking (if any)
+ LLViewerObject* mViewerObject = nullptr;
+
+ // what priority should this probe have (higher is higher priority)
+ U32 mPriority = 1;
+
+ bool mDirty = true;
+};
+
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
new file mode 100644
index 0000000000..0d03e7fe39
--- /dev/null
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -0,0 +1,738 @@
+/**
+ * @file llreflectionmapmanager.cpp
+ * @brief LLReflectionMapManager class implementation
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llreflectionmapmanager.h"
+#include "llviewercamera.h"
+#include "llspatialpartition.h"
+#include "llviewerregion.h"
+#include "pipeline.h"
+#include "llviewershadermgr.h"
+#include "llviewercontrol.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)
+ {
+ mCubeFree[i] = true;
+ }
+}
+
+struct CompareReflectionMapDistance
+{
+
+};
+
+
+struct CompareProbeDistance
+{
+ bool operator()(const LLPointer& lhs, const LLPointer& rhs)
+ {
+ return lhs->mDistance < rhs->mDistance;
+ }
+};
+
+// helper class to seed octree with probes
+void LLReflectionMapManager::update()
+{
+ if (!LLPipeline::sRenderDeferred || gTeleportDisplay)
+ {
+ return;
+ }
+
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(!gCubeSnapshot); // assert a snapshot is not in progress
+ if (LLAppViewer::instance()->logoutRequestSent())
+ {
+ return;
+ }
+
+ // =============== TODO -- move to an init function =================
+
+ if (mTexture.isNull())
+ {
+ mTexture = new LLCubeMapArray();
+ mTexture->allocate(LL_REFLECTION_PROBE_RESOLUTION, 3, LL_REFLECTION_PROBE_COUNT);
+ }
+
+ if (!mRenderTarget.isComplete())
+ {
+ U32 color_fmt = GL_RGBA;
+ const bool use_depth_buffer = true;
+ 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
+ auto* old_rt = gPipeline.mRT;
+ gPipeline.mRT = &gProbeRT;
+ gPipeline.allocateScreenBuffer(targetRes, targetRes);
+ gPipeline.allocateShadowBuffer(targetRes, targetRes);
+ gPipeline.mRT = old_rt;
+ }
+
+ if (mMipChain.empty())
+ {
+ U32 res = LL_REFLECTION_PROBE_RESOLUTION;
+ U32 count = log2((F32)res) + 0.5f;
+
+ mMipChain.resize(count);
+ for (int i = 0; i < count; ++i)
+ {
+ mMipChain[i].allocate(res, res, GL_RGB, false, false, LLTexUnit::TT_RECT_TEXTURE);
+ res /= 2;
+ }
+ }
+
+ // =============== 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);
+
+ // process kill list
+ for (int i = 0; i < mProbes.size(); )
+ {
+ auto& iter = std::find(mKillList.begin(), mKillList.end(), mProbes[i]);
+ if (iter != mKillList.end())
+ {
+ deleteProbe(i);
+ mProbes.erase(mProbes.begin() + i);
+ mKillList.erase(iter);
+ }
+ else
+ {
+ ++i;
+ }
+ }
+
+ mKillList.clear();
+
+ // process create list
+ for (auto& probe : mCreateList)
+ {
+ mProbes.push_back(probe);
+ }
+
+ mCreateList.clear();
+
+ if (mProbes.empty())
+ {
+ return;
+ }
+ const F32 UPDATE_INTERVAL = 5.f; //update no more than once every 5 seconds
+
+ bool did_update = false;
+
+ LLReflectionMap* oldestProbe = nullptr;
+
+ if (mUpdatingProbe != nullptr)
+ {
+ did_update = true;
+ doProbeUpdate();
+ }
+
+ for (int i = 0; i < mProbes.size(); ++i)
+ {
+ LLReflectionMap* probe = mProbes[i];
+ if (probe->getNumRefs() == 1)
+ { // no references held outside manager, delete this probe
+ deleteProbe(i);
+ --i;
+ continue;
+ }
+
+ probe->mProbeIndex = i;
+
+ LLVector4a d;
+
+ if (!did_update &&
+ i < LL_REFLECTION_PROBE_COUNT &&
+ (oldestProbe == nullptr || probe->mLastUpdateTime < oldestProbe->mLastUpdateTime))
+ {
+ oldestProbe = probe;
+ }
+
+ d.setSub(camera_pos, probe->mOrigin);
+ probe->mDistance = d.getLength3().getF32()-probe->mRadius;
+ }
+
+#if 1
+ if (!did_update && oldestProbe != nullptr)
+ {
+ LLReflectionMap* probe = oldestProbe;
+ if (probe->mCubeIndex == -1)
+ {
+ probe->mCubeArray = mTexture;
+ probe->mCubeIndex = allocateCubeIndex();
+ }
+
+ probe->autoAdjustOrigin();
+
+ mUpdatingProbe = probe;
+ doProbeUpdate();
+ probe->mDirty = false;
+ }
+#endif
+
+ // update distance to camera for all probes
+ std::sort(mProbes.begin(), mProbes.end(), CompareProbeDistance());
+}
+
+LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group)
+{
+ LLReflectionMap* probe = new LLReflectionMap();
+ probe->mGroup = group;
+ probe->mOrigin = group->getOctreeNode()->getCenter();
+ probe->mDirty = true;
+
+ if (gCubeSnapshot)
+ { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update
+ mCreateList.push_back(probe);
+ }
+ else
+ {
+ mProbes.push_back(probe);
+ }
+
+ return probe;
+}
+
+void LLReflectionMapManager::getReflectionMaps(std::vector& maps)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+
+ U32 count = 0;
+ U32 lastIdx = 0;
+ for (U32 i = 0; count < maps.size() && i < mProbes.size(); ++i)
+ {
+ mProbes[i]->mLastBindTime = gFrameTimeSeconds; // something wants to use this probe, indicate it's been requested
+ if (mProbes[i]->mCubeIndex != -1)
+ {
+ mProbes[i]->mProbeIndex = count;
+ maps[count++] = mProbes[i];
+ }
+ else
+ {
+ mProbes[i]->mProbeIndex = -1;
+ }
+ lastIdx = i;
+ }
+
+ // set remaining probe indices to -1
+ for (U32 i = lastIdx+1; i < mProbes.size(); ++i)
+ {
+ mProbes[i]->mProbeIndex = -1;
+ }
+
+ // null terminate list
+ if (count < maps.size())
+ {
+ maps[count] = nullptr;
+ }
+}
+
+LLReflectionMap* LLReflectionMapManager::registerSpatialGroup(LLSpatialGroup* group)
+{
+#if 1
+ if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME)
+ {
+ OctreeNode* node = group->getOctreeNode();
+ F32 size = node->getSize().getF32ptr()[0];
+ if (size >= 7.f && size <= 17.f)
+ {
+ return addProbe(group);
+ }
+ }
+
+ if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_TERRAIN)
+ {
+ OctreeNode* node = group->getOctreeNode();
+ F32 size = node->getSize().getF32ptr()[0];
+ if (size >= 15.f && size <= 17.f)
+ {
+ return addProbe(group);
+ }
+ }
+#endif
+ return nullptr;
+}
+
+LLReflectionMap* LLReflectionMapManager::registerViewerObject(LLViewerObject* vobj)
+{
+ llassert(vobj != nullptr);
+
+ LLReflectionMap* probe = new LLReflectionMap();
+ probe->mViewerObject = vobj;
+ probe->mOrigin.load3(vobj->getPositionAgent().mV);
+ probe->mDirty = true;
+
+ if (gCubeSnapshot)
+ { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update
+ mCreateList.push_back(probe);
+ }
+ else
+ {
+ mProbes.push_back(probe);
+ }
+
+ return probe;
+}
+
+
+S32 LLReflectionMapManager::allocateCubeIndex()
+{
+ for (int i = 0; i < LL_REFLECTION_PROBE_COUNT; ++i)
+ {
+ if (mCubeFree[i])
+ {
+ mCubeFree[i] = false;
+ return i;
+ }
+ }
+
+ // no cubemaps free, steal one from the back of the probe list
+ for (int i = mProbes.size() - 1; i >= LL_REFLECTION_PROBE_COUNT; --i)
+ {
+ if (mProbes[i]->mCubeIndex != -1)
+ {
+ S32 ret = mProbes[i]->mCubeIndex;
+ mProbes[i]->mCubeIndex = -1;
+ return ret;
+ }
+ }
+
+ llassert(false); // should never fail to allocate, something is probably wrong with mCubeFree
+ return -1;
+}
+
+void LLReflectionMapManager::deleteProbe(U32 i)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ LLReflectionMap* probe = mProbes[i];
+
+ if (probe->mCubeIndex != -1)
+ { // mark the cube index used by this probe as being free
+ mCubeFree[probe->mCubeIndex] = true;
+ }
+ if (mUpdatingProbe == probe)
+ {
+ mUpdatingProbe = nullptr;
+ mUpdatingFace = 0;
+ }
+
+ // remove from any Neighbors lists
+ for (auto& other : probe->mNeighbors)
+ {
+ auto& iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe);
+ llassert(iter != other->mNeighbors.end());
+ other->mNeighbors.erase(iter);
+ }
+
+ mProbes.erase(mProbes.begin() + i);
+}
+
+
+void LLReflectionMapManager::doProbeUpdate()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(mUpdatingProbe != nullptr);
+
+ mRenderTarget.bindTarget();
+ auto* old_rt = gPipeline.mRT;
+ gPipeline.mRT = &gProbeRT;
+ mUpdatingProbe->update(mRenderTarget.getWidth(), mUpdatingFace);
+ gPipeline.mRT = old_rt;
+ mRenderTarget.flush();
+
+ // generate mipmaps
+ {
+ LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
+
+ gReflectionMipProgram.bind();
+ gGL.matrixMode(gGL.MM_MODELVIEW);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+
+ gGL.matrixMode(gGL.MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+
+ gGL.flush();
+ U32 res = LL_REFLECTION_PROBE_RESOLUTION*2;
+
+ S32 mips = log2((F32) LL_REFLECTION_PROBE_RESOLUTION)+0.5f;
+
+ for (int i = 0; i < mMipChain.size(); ++i)
+ {
+ LL_PROFILE_GPU_ZONE("probe mip");
+ mMipChain[i].bindTarget();
+
+ if (i == 0)
+ {
+ gGL.getTexUnit(0)->bind(&mRenderTarget);
+ }
+ else
+ {
+ gGL.getTexUnit(0)->bind(&(mMipChain[i - 1]));
+ }
+
+ // Remove QUADS rendering mode
+ //gGL.begin(gGL.QUADS);
+ //
+ //gGL.texCoord2f(0, 0);
+ //gGL.vertex2f(-1, -1);
+ //
+ //gGL.texCoord2f(res, 0);
+ //gGL.vertex2f(1, -1);
+
+ //gGL.texCoord2f(res, res);
+ //gGL.vertex2f(1, 1);
+
+ //gGL.texCoord2f(0, res);
+ //gGL.vertex2f(-1, 1);
+ //gGL.end();
+
+ gGL.begin(gGL.TRIANGLES);
+ gGL.texCoord2f(0, 0);
+ gGL.vertex2f(-1, -1);
+ gGL.texCoord2f(res, 0);
+ gGL.vertex2f(1, -1);
+ gGL.texCoord2f(res, res);
+ gGL.vertex2f(1, 1);
+
+ gGL.texCoord2f(0, 0);
+ gGL.vertex2f(-1, -1);
+ gGL.texCoord2f(res, res);
+ gGL.vertex2f(1, 1);
+ gGL.texCoord2f(0, res);
+ gGL.vertex2f(-1, 1);
+ gGL.end();
+ //
+ gGL.flush();
+
+ res /= 2;
+
+ S32 mip = i - (mMipChain.size() - mips);
+
+ if (mip >= 0)
+ {
+ mTexture->bind(0);
+ glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, mUpdatingProbe->mCubeIndex * 6 + mUpdatingFace, 0, 0, res, res);
+ mTexture->unbind();
+ }
+ mMipChain[i].flush();
+ }
+
+ gGL.popMatrix();
+ gGL.matrixMode(gGL.MM_MODELVIEW);
+ gGL.popMatrix();
+
+ gReflectionMipProgram.unbind();
+ }
+
+ if (++mUpdatingFace == 6)
+ {
+ updateNeighbors(mUpdatingProbe);
+ mUpdatingProbe = nullptr;
+ mUpdatingFace = 0;
+ }
+}
+
+void LLReflectionMapManager::rebuild()
+{
+ for (auto& probe : mProbes)
+ {
+ probe->mLastUpdateTime = 0.f;
+ }
+}
+
+void LLReflectionMapManager::shift(const LLVector4a& offset)
+{
+ for (auto& probe : mProbes)
+ {
+ probe->mOrigin.add(offset);
+ }
+}
+
+void LLReflectionMapManager::updateNeighbors(LLReflectionMap* probe)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+
+ //remove from existing neighbors
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - clear");
+
+ for (auto& other : probe->mNeighbors)
+ {
+ auto& 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);
+ }
+
+ probe->mNeighbors.clear();
+ }
+
+ // search for new neighbors
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - search");
+ for (auto& other : mProbes)
+ {
+ if (other != probe)
+ {
+ if (probe->intersects(other))
+ {
+ probe->mNeighbors.push_back(other);
+ other->mNeighbors.push_back(probe);
+ }
+ }
+ }
+ }
+}
+
+void LLReflectionMapManager::updateUniforms()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+
+ // structure for packing uniform buffer object
+ // see class2/deferred/softenLightF.glsl
+ struct ReflectionProbeData
+ {
+ LLMatrix4 refBox[LL_REFLECTION_PROBE_COUNT]; // object bounding box as needed
+ LLVector4 refSphere[LL_REFLECTION_PROBE_COUNT]; //origin and radius of refmaps in clip space
+ GLint refIndex[LL_REFLECTION_PROBE_COUNT][4];
+ GLint refNeighbor[4096];
+ GLint refmapCount;
+ GLfloat reflectionAmbiance;
+ };
+
+ mReflectionMaps.resize(LL_REFLECTION_PROBE_COUNT);
+ getReflectionMaps(mReflectionMaps);
+
+ ReflectionProbeData rpd;
+
+ static LLCachedControl ambiance(gSavedSettings, "RenderReflectionProbeAmbiance", 0.f);
+ rpd.reflectionAmbiance = ambiance;
+
+ // load modelview matrix into matrix 4a
+ LLMatrix4a modelview;
+ modelview.loadu(gGLModelView);
+ LLVector4a oa; // scratch space for transformed origin
+
+ S32 count = 0;
+ U32 nc = 0; // neighbor "cursor" - index into refNeighbor to start writing the next probe's list of neighbors
+
+ for (auto* refmap : mReflectionMaps)
+ {
+ if (refmap == nullptr)
+ {
+ break;
+ }
+
+ llassert(refmap->mProbeIndex == count);
+ llassert(mReflectionMaps[refmap->mProbeIndex] == refmap);
+
+ llassert(refmap->mCubeIndex >= 0); // should always be true, if not, getReflectionMaps is bugged
+
+ {
+ //LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - refSphere");
+
+ modelview.affineTransform(refmap->mOrigin, oa);
+ rpd.refSphere[count].set(oa.getF32ptr());
+ rpd.refSphere[count].mV[3] = refmap->mRadius;
+ }
+
+ rpd.refIndex[count][0] = refmap->mCubeIndex;
+ llassert(nc % 4 == 0);
+ rpd.refIndex[count][1] = nc / 4;
+ rpd.refIndex[count][3] = refmap->mPriority;
+
+ // for objects that are reflection probes, use the volume as the influence volume of the probe
+ // only possibile influence volumes are boxes and spheres, so detect boxes and treat everything else as spheres
+ if (refmap->getBox(rpd.refBox[count]))
+ { // negate priority to indicate this probe has a box influence volume
+ rpd.refIndex[count][3] = -rpd.refIndex[count][3];
+ }
+
+ S32 ni = nc; // neighbor ("index") - index into refNeighbor to write indices for current reflection probe's neighbors
+ {
+ //LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - refNeighbors");
+ //pack neghbor list
+ for (auto& neighbor : refmap->mNeighbors)
+ {
+ if (ni >= 4096)
+ { // out of space
+ break;
+ }
+
+ GLint idx = neighbor->mProbeIndex;
+ if (idx == -1)
+ {
+ continue;
+ }
+
+ // this neighbor may be sampled
+ rpd.refNeighbor[ni++] = idx;
+ }
+ }
+
+ if (nc == ni)
+ {
+ //no neighbors, tag as empty
+ rpd.refIndex[count][1] = -1;
+ }
+ else
+ {
+ rpd.refIndex[count][2] = ni - nc;
+
+ // move the cursor forward
+ nc = ni;
+ if (nc % 4 != 0)
+ { // jump to next power of 4 for compatibility with ivec4
+ nc += 4 - (nc % 4);
+ }
+ }
+
+
+ count++;
+ }
+
+ rpd.refmapCount = count;
+
+ //copy rpd into uniform buffer object
+ if (mUBO == 0)
+ {
+ glGenBuffersARB(1, &mUBO);
+ }
+
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer");
+ glBindBufferARB(GL_UNIFORM_BUFFER, mUBO);
+ glBufferDataARB(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeData), &rpd, GL_STREAM_DRAW);
+ glBindBufferARB(GL_UNIFORM_BUFFER, 0);
+ }
+}
+
+void LLReflectionMapManager::setUniforms()
+{
+ if (mUBO == 0)
+ {
+ updateUniforms();
+ }
+ glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO);
+}
+
+
+void renderReflectionProbe(LLReflectionMap* probe)
+{
+
+ F32* po = probe->mOrigin.getF32ptr();
+
+ //draw orange line from probe to neighbors
+ gGL.flush();
+ gGL.diffuseColor4f(1, 0.5f, 0, 1);
+ gGL.begin(gGL.LINES);
+ for (auto& neighbor : probe->mNeighbors)
+ {
+ gGL.vertex3fv(po);
+ gGL.vertex3fv(neighbor->mOrigin.getF32ptr());
+ }
+ gGL.end();
+ gGL.flush();
+
+#if 0
+ LLSpatialGroup* group = probe->mGroup;
+ if (group)
+ { // draw lines from corners of object aabb to reflection probe
+
+ const LLVector4a* bounds = group->getBounds();
+ LLVector4a o = bounds[0];
+
+ gGL.flush();
+ gGL.diffuseColor4f(0, 0, 1, 1);
+ F32* c = o.getF32ptr();
+
+ const F32* bc = bounds[0].getF32ptr();
+ const F32* bs = bounds[1].getF32ptr();
+
+ // daaw blue lines from corners to center of node
+ gGL.begin(gGL.LINES);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] + bs[0], bc[1] + bs[1], bc[2] + bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] - bs[0], bc[1] + bs[1], bc[2] + bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] + bs[0], bc[1] - bs[1], bc[2] + bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] - bs[0], bc[1] - bs[1], bc[2] + bs[2]);
+
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] + bs[0], bc[1] + bs[1], bc[2] - bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] - bs[0], bc[1] + bs[1], bc[2] - bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] + bs[0], bc[1] - bs[1], bc[2] - bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] - bs[0], bc[1] - bs[1], bc[2] - bs[2]);
+ gGL.end();
+
+ //draw yellow line from center of node to reflection probe origin
+ gGL.flush();
+ gGL.diffuseColor4f(1, 1, 0, 1);
+ gGL.begin(gGL.LINES);
+ gGL.vertex3fv(c);
+ gGL.vertex3fv(po);
+ gGL.end();
+ gGL.flush();
+ }
+#endif
+}
+
+void LLReflectionMapManager::renderDebug()
+{
+ gDebugProgram.bind();
+
+ for (auto& probe : mProbes)
+ {
+ renderReflectionProbe(probe);
+ }
+
+ gDebugProgram.unbind();
+}
diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h
new file mode 100644
index 0000000000..bf963f3486
--- /dev/null
+++ b/indra/newview/llreflectionmapmanager.h
@@ -0,0 +1,138 @@
+/**
+ * @file llreflectionmapmanager.h
+ * @brief LLReflectionMapManager class declaration
+ *
+ * $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 "llreflectionmap.h"
+#include "llrendertarget.h"
+#include "llcubemaparray.h"
+
+class LLSpatialGroup;
+class LLViewerObject;
+
+// number of reflection probes to keep in vram
+#define LL_REFLECTION_PROBE_COUNT 256
+
+// reflection probe resolution
+#define LL_REFLECTION_PROBE_RESOLUTION 256
+
+// reflection probe mininum scale
+#define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f;
+
+class alignas(16) LLReflectionMapManager
+{
+ LL_ALIGN_NEW
+public:
+ // allocate an environment map of the given resolution
+ LLReflectionMapManager();
+
+ // maintain reflection probes
+ void update();
+
+ // add a probe for the given spatial group
+ LLReflectionMap* addProbe(LLSpatialGroup* group);
+
+ // Populate "maps" with the N most relevant Reflection Maps where N is no more than maps.size()
+ // If less than maps.size() ReflectionMaps are available, will assign trailing elements to nullptr.
+ // maps -- presized array of Reflection Map pointers
+ void getReflectionMaps(std::vector& maps);
+
+ // called by LLSpatialGroup constructor
+ // If spatial group should receive a Reflection Probe, will create one for the specified spatial group
+ LLReflectionMap* registerSpatialGroup(LLSpatialGroup* group);
+
+ // presently hacked into LLViewerObject::setTE
+ // Used by LLViewerObjects that are Reflection Probes
+ // Guaranteed to not return null
+ LLReflectionMap* registerViewerObject(LLViewerObject* vobj);
+
+ // force an update of all probes
+ void rebuild();
+
+ // called on region crossing to "shift" probes into new coordinate frame
+ void shift(const LLVector4a& offset);
+
+ // debug display, called from llspatialpartition if reflection
+ // probe debug display is active
+ void renderDebug();
+
+private:
+ friend class LLPipeline;
+
+ // delete the probe with the given index in mProbes
+ void deleteProbe(U32 i);
+
+ // get a free cube index
+ // if no cube indices are free, free one starting from the back of the probe list
+ S32 allocateCubeIndex();
+
+ // update the neighbors of the given probe
+ void updateNeighbors(LLReflectionMap* probe);
+
+ // update UBO used for rendering (call only once per render pipe flush)
+ void updateUniforms();
+
+ // bind UBO used for rendering
+ void setUniforms();
+
+ // render target for cube snapshots
+ // used to generate mipmaps without doing a copy-to-texture
+ LLRenderTarget mRenderTarget;
+
+ std::vector mMipChain;
+
+ // storage for reflection probes
+ LLPointer mTexture;
+
+ // array indicating if a particular cubemap is free
+ bool mCubeFree[LL_REFLECTION_PROBE_COUNT];
+
+ // start tracking the given spatial group
+ void trackGroup(LLSpatialGroup* group);
+
+ // perform an update on the currently updating Probe
+ void doProbeUpdate();
+
+ // list of active reflection maps
+ std::vector > mProbes;
+
+ // list of reflection maps to kill
+ std::vector > mKillList;
+
+ // list of reflection maps to create
+ std::vector > mCreateList;
+
+ // handle to UBO
+ U32 mUBO = 0;
+
+ // list of maps being used for rendering
+ std::vector mReflectionMaps;
+
+ LLReflectionMap* mUpdatingProbe = nullptr;
+ U32 mUpdatingFace = 0;
+
+};
+
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 1b7dd03fbc..3fe0aba757 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -560,9 +560,12 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLO
sg_assert(mOctreeNode->getListenerCount() == 0);
setState(SG_INITIAL_STATE_MASK);
gPipeline.markRebuild(this, TRUE);
+
+ // let the reflection map manager know about this spatial group
+ mReflectionProbe = gPipeline.mReflectionMapManager.registerSpatialGroup(this);
- mRadius = 1;
- mPixelArea = 1024.f;
+ mRadius = 1;
+ mPixelArea = 1024.f;
}
void LLSpatialGroup::updateDistance(LLCamera &camera)
@@ -741,8 +744,17 @@ BOOL LLSpatialGroup::changeLOD()
return FALSE;
}
+void LLSpatialGroup::dirtyReflectionProbe()
+{
+ if (mReflectionProbe != nullptr)
+ {
+ mReflectionProbe->dirty();
+ }
+}
+
void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* entry)
{
+ dirtyReflectionProbe();
addObject((LLDrawable*)entry->getDrawable());
unbound();
setState(OBJECT_DIRTY);
@@ -750,6 +762,7 @@ void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry*
void LLSpatialGroup::handleRemoval(const TreeNode* node, LLViewerOctreeEntry* entry)
{
+ dirtyReflectionProbe();
removeObject((LLDrawable*)entry->getDrawable(), TRUE);
LLViewerOctreeGroup::handleRemoval(node, entry);
}
@@ -786,6 +799,8 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL
+ dirtyReflectionProbe();
+
if (child->getListenerCount() == 0)
{
new LLSpatialGroup(child, getSpatialPartition());
@@ -800,6 +815,11 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c
assert_states_valid(this);
}
+void LLSpatialGroup::handleChildRemoval(const oct_node* parent, const oct_node* child)
+{
+ dirtyReflectionProbe();
+}
+
void LLSpatialGroup::destroyGL(bool keep_occlusion)
{
// Reset VB during TP
@@ -1420,7 +1440,9 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector* result
return 0;
}
-
+
+extern BOOL gCubeSnapshot;
+
S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL;
@@ -1439,7 +1461,7 @@ S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion)
LLOctreeCullShadow culler(&camera);
culler.traverse(mOctree);
}
- else if (mInfiniteFarClip || !LLPipeline::sUseFarClip)
+ else if (mInfiniteFarClip || (!LLPipeline::sUseFarClip && !gCubeSnapshot))
{
LLOctreeCullNoFarClip culler(&camera);
culler.traverse(mOctree);
@@ -1759,7 +1781,7 @@ void renderOctree(LLSpatialGroup* group)
}
}*/
}
-
+
// LLSpatialGroup::OctreeNode* node = group->mOctreeNode;
// gGL.diffuseColor4f(0,1,0,1);
// drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize()));
@@ -2661,14 +2683,12 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
//gGL.diffuseColor4fv(line_color.mV);
//gGL.syncMatrices();
//{
- // LL_PROFILER_GPU_ZONEC("gl.DrawElements", 0x20FF20)
// glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices);
//}
//gGL.diffuseColor4fv(color.mV);
//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//{
- // LL_PROFILER_GPU_ZONEC("gl.DrawElements", 0x40FF40)
// glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices);
//}
gGL.diffuseColor4fv(line_color.mV);
@@ -3216,7 +3236,6 @@ void renderRaycast(LLDrawable* drawablep)
//gGL.diffuseColor4f(0, 1, 1, 0.5f);
//glVertexPointer(3, GL_FLOAT, sizeof(LLVector4a), face.mPositions);
//gGL.syncMatrices();
- //LL_PROFILER_GPU_ZONEC("gl.DrawElements", 0x60FF60);
//glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices);
gGL.diffuseColor4f(0.f, 1.f, 1.f, 0.5f);
LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, NULL, face.mNumIndices, face.mIndices);
@@ -3767,7 +3786,7 @@ void LLSpatialPartition::renderDebug()
//LLPipeline::RENDER_DEBUG_BUILD_QUEUE |
LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA |
LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY |
- LLPipeline::RENDER_DEBUG_TEXEL_DENSITY))
+ LLPipeline::RENDER_DEBUG_TEXEL_DENSITY))
{
return;
}
@@ -3801,7 +3820,6 @@ void LLSpatialPartition::renderDebug()
LLOctreeRenderNonOccluded render_debug(camera);
render_debug.traverse(mOctree);
-
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
{
{
@@ -4148,6 +4166,23 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, co
return drawable;
}
+LLDrawable* LLSpatialGroup::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
+ BOOL pick_transparent,
+ BOOL pick_rigged,
+ S32* face_hit, // return the face hit
+ LLVector4a* intersection, // return the intersection point
+ LLVector2* tex_coord, // return the texture coordinates of the intersection point
+ LLVector4a* normal, // return the surface normal at the intersection point
+ LLVector4a* tangent // return the surface tangent at the intersection point
+)
+
+{
+ LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, face_hit, intersection, tex_coord, normal, tangent);
+ LLDrawable* drawable = intersect.check(getOctreeNode());
+
+ return drawable;
+}
+
LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
LLViewerTexture* texture, LLVertexBuffer* buffer,
bool selected,
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index d0c67fdb0a..20ee42180f 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -56,6 +56,7 @@ class LLSpatialPartition;
class LLSpatialBridge;
class LLSpatialGroup;
class LLViewerRegion;
+class LLReflectionMap;
void pushVerts(LLFace* face, U32 mask);
// Make helper functions externally visible for use from viewerwindow
@@ -324,6 +325,17 @@ public:
void drawObjectBox(LLColor4 col);
+ LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
+ BOOL pick_transparent,
+ BOOL pick_rigged,
+ S32* face_hit, // return the face hit
+ LLVector4a* intersection = NULL, // return the intersection point
+ 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
+ );
+
+
LLSpatialPartition* getSpatialPartition() {return (LLSpatialPartition*)mSpatialPartition;}
//LISTENER FUNCTIONS
@@ -331,6 +343,7 @@ public:
virtual void handleRemoval(const TreeNode* node, LLViewerOctreeEntry* face);
virtual void handleDestruction(const TreeNode* node);
virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
+ virtual void handleChildRemoval(const oct_node* parent, const oct_node* child);
public:
LL_ALIGN_16(LLVector4a mViewAngle);
@@ -338,6 +351,8 @@ public:
F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3()
+ void dirtyReflectionProbe();
+
protected:
virtual ~LLSpatialGroup();
@@ -363,6 +378,10 @@ public:
F32 mPixelArea;
F32 mRadius;
+ // Reflection Probe associated with this node (if any)
+ LLPointer mReflectionProbe = nullptr;
+
+
//used by LLVOAVatar to set render order in alpha draw pool to preserve legacy render order behavior
LLVOAvatar* mAvatarp = nullptr;
U32 mRenderOrder = 0;
diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp
index 4804ef6ddc..481086f760 100644
--- a/indra/newview/llviewerassettype.cpp
+++ b/indra/newview/llviewerassettype.cpp
@@ -88,6 +88,7 @@ LLViewerAssetDictionary::LLViewerAssetDictionary()
addEntry(LLViewerAssetType::AT_NONE, new ViewerAssetEntry(DAD_NONE));
addEntry(LLViewerAssetType::AT_SETTINGS, new ViewerAssetEntry(DAD_SETTINGS));
+ addEntry(LLViewerAssetType::AT_MATERIAL, new ViewerAssetEntry(DAD_MATERIAL));
};
EDragAndDropType LLViewerAssetType::lookupDragAndDropType(EType asset_type)
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 0b2b13536b..8e2ebcf80f 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -110,6 +110,7 @@ BOOL gResizeScreenTexture = FALSE;
BOOL gResizeShadowTexture = FALSE;
BOOL gWindowResized = FALSE;
BOOL gSnapshot = FALSE;
+BOOL gCubeSnapshot = FALSE;
BOOL gShaderProfileFrame = FALSE;
// This is how long the sim will try to teleport you before giving up.
@@ -206,7 +207,12 @@ void display_update_camera()
// Cut draw distance in half when customizing avatar,
// but on the viewer only.
F32 final_far = gAgentCamera.mDrawDistance;
- if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode())
+ if (gCubeSnapshot)
+ {
+ final_far = gSavedSettings.getF32("RenderReflectionProbeDrawDistance");
+ }
+ else if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode())
+
{
final_far *= 0.5f;
}
@@ -220,8 +226,11 @@ void display_update_camera()
LLViewerCamera::getInstance()->setFar(final_far);
gViewerWindow->setup3DRender();
- // Update land visibility too
- LLWorld::getInstance()->setLandFarClip(final_far);
+ if (!gCubeSnapshot)
+ {
+ // Update land visibility too
+ LLWorld::getInstance()->setLandFarClip(final_far);
+ }
}
// Write some stats to LL_INFOS()
@@ -1028,19 +1037,19 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (LLPipeline::sRenderDeferred)
{
- gPipeline.mDeferredScreen.bindTarget();
+ gPipeline.mRT->deferredScreen.bindTarget();
glClearColor(1, 0, 1, 1);
- gPipeline.mDeferredScreen.clear();
+ gPipeline.mRT->deferredScreen.clear();
}
else
{
- gPipeline.mScreen.bindTarget();
+ gPipeline.mRT->screen.bindTarget();
if (LLPipeline::sUnderWaterRender && !gPipeline.canUseWindLightShaders())
{
const LLColor4 &col = LLEnvironment::instance().getCurrentWater()->getWaterFogColor();
glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
}
- gPipeline.mScreen.clear();
+ gPipeline.mRT->screen.clear();
}
gGL.setColorMask(true, false);
@@ -1114,7 +1123,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush");
- LLRenderTarget &rt = (gPipeline.sRenderDeferred ? gPipeline.mDeferredScreen : gPipeline.mScreen);
+ LLRenderTarget &rt = (gPipeline.sRenderDeferred ? gPipeline.mRT->deferredScreen : gPipeline.mRT->screen);
rt.flush();
if (rt.sUseFBO)
@@ -1126,7 +1135,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (LLPipeline::sRenderDeferred)
{
- gPipeline.renderDeferredLighting(&gPipeline.mScreen);
+ gPipeline.renderDeferredLighting(&gPipeline.mRT->screen);
}
LLPipeline::sUnderWaterRender = FALSE;
@@ -1174,6 +1183,114 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
}
}
+// WIP simplified copy of display() that does minimal work
+void display_cube_face()
+{
+ LL_RECORD_BLOCK_TIME(FTM_RENDER);
+ LL_PROFILE_GPU_ZONE("display cube face");
+
+ llassert(!gSnapshot);
+ llassert(!gTeleportDisplay);
+ llassert(LLPipeline::sRenderDeferred);
+ llassert(LLStartUp::getStartupState() >= STATE_PRECACHE);
+ llassert(!LLAppViewer::instance()->logoutRequestSent());
+ llassert(!gRestoreGL);
+ llassert(!gUseWireframe);
+
+ bool rebuild = false;
+
+ LLGLSDefault gls_default;
+ LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL);
+
+ LLVertexBuffer::unbind();
+
+ gPipeline.disableLights();
+
+ gPipeline.mBackfaceCull = TRUE;
+
+ LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE);
+ gViewerWindow->setup3DViewport();
+
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ { //don't draw hud objects in this frame
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ }
+
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES))
+ { //don't draw hud particles in this frame
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
+ }
+
+ display_update_camera();
+
+ LLSpatialGroup::sNoDelete = TRUE;
+
+ S32 occlusion = LLPipeline::sUseOcclusion;
+ LLPipeline::sUseOcclusion = 0; // occlusion data is from main camera point of view, don't read or write it during cube snapshots
+ //gDepthDirty = TRUE; //let "real" render pipe know it can't trust the depth buffer for occlusion data
+
+ static LLCullResult result;
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater();
+ gPipeline.updateCull(*LLViewerCamera::getInstance(), result);
+
+ gGL.setColorMask(true, true);
+ glClearColor(0, 0, 0, 0);
+ gPipeline.generateSunShadow(*LLViewerCamera::getInstance());
+
+ glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ {
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ gPipeline.stateSort(*LLViewerCamera::getInstance(), result);
+
+ if (rebuild)
+ {
+ //////////////////////////////////////
+ //
+ // rebuildPools
+ //
+ //
+ gPipeline.rebuildPools();
+ stop_glerror();
+ }
+ }
+
+ LLPipeline::sUseOcclusion = occlusion;
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart");
+
+ LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE;
+
+ gGL.setColorMask(true, true);
+
+ gPipeline.mRT->deferredScreen.bindTarget();
+ glClearColor(1, 0, 1, 1);
+ gPipeline.mRT->deferredScreen.clear();
+
+ gGL.setColorMask(true, false);
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+
+ gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance());
+
+ gGL.setColorMask(true, true);
+
+ gPipeline.mRT->deferredScreen.flush();
+
+ gPipeline.renderDeferredLighting(&gPipeline.mRT->screen);
+
+ LLPipeline::sUnderWaterRender = FALSE;
+
+ // Finalize scene
+ gPipeline.renderFinalize();
+
+ LLSpatialGroup::sNoDelete = FALSE;
+ gPipeline.clearReferences();
+
+ gPipeline.rebuildGroups();
+}
+
void render_hud_attachments()
{
FSPerfStats::RecordSceneTime T ( FSPerfStats::StatType_t::RENDER_HUDS); // render time capture - Primary contributor to HUDs (though these end up in render batches)
@@ -1386,7 +1503,7 @@ void render_ui(F32 zoom_factor, int subfield)
{
FSPerfStats::RecordSceneTime T ( FSPerfStats::StatType_t::RENDER_UI ); // render time capture - Primary UI stat can have HUD time overlap (TODO)
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
-
+ LL_PROFILE_GPU_ZONE("ui");
LLGLState::checkStates();
glh::matrix4f saved_view = get_current_modelview();
@@ -1476,7 +1593,7 @@ void swap()
{
FSPerfStats::RecordSceneTime T ( FSPerfStats::StatType_t::RENDER_SWAP ); // render time capture - Swap buffer time - can signify excessive data transfer to/from GPU
LL_RECORD_BLOCK_TIME(FTM_SWAP);
-
+ LL_PROFILE_GPU_ZONE("swap");
if (gDisplaySwapBuffers)
{
gViewerWindow->getWindow()->swapBuffers();
@@ -1653,7 +1770,7 @@ void render_ui_2d()
LLView::sIsRectDirty = false;
LLRect t_rect;
- gPipeline.mUIScreen.bindTarget();
+ gPipeline.mRT->uiScreen.bindTarget();
gGL.setColorMask(true, true);
{
static const S32 pad = 8;
@@ -1690,7 +1807,7 @@ void render_ui_2d()
gViewerWindow->draw();
}
- gPipeline.mUIScreen.flush();
+ gPipeline.mRT->uiScreen.flush();
gGL.setColorMask(true, false);
LLView::sDirtyRect = t_rect;
@@ -1700,7 +1817,7 @@ void render_ui_2d()
LLGLDisable blend(GL_BLEND);
S32 width = gViewerWindow->getWindowWidthScaled();
S32 height = gViewerWindow->getWindowHeightScaled();
- gGL.getTexUnit(0)->bind(&gPipeline.mUIScreen);
+ gGL.getTexUnit(0)->bind(&gPipeline.mRT->uiScreen);
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.color4f(1,1,1,1);
gGL.texCoord2f(0, 0); gGL.vertex2i(0, 0);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 817c13d956..732d9d5a9e 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -1249,6 +1249,10 @@ U64 info_display_from_string(std::string info_display)
{
return LLPipeline::RENDER_DEBUG_IMPOSTORS;
}
+ else if ("reflection probes" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_REFLECTION_PROBES;
+ }
else if ("texture size" == info_display)
{
return LLPipeline::RENDER_DEBUG_TEXTURE_SIZE;
@@ -10634,6 +10638,12 @@ void handle_cache_clear_immediately()
LLNotificationsUtil::add("ConfirmClearCache", LLSD(), LLSD(), callback_clear_cache_immediately);
}
+void handle_rebuild_reflection_probes()
+{
+ gPipeline.mReflectionMapManager.rebuild();
+}
+
+
void handle_web_content_test(const LLSD& param)
{
std::string url = param.asString();
@@ -12122,6 +12132,8 @@ void initialize_menus()
view_listener_t::addMenu(new LLDevelopTextureFetchDebugger(), "Develop.SetTexFetchDebugger");
//Develop (clear cache immediately)
commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) );
+ //Develop (override environment map)
+ commit.add("Develop.RebuildReflectionProbes", boost::bind(&handle_rebuild_reflection_probes));
#ifdef TRACY_ENABLE
// Add telemetry controls to the viewer Develop menu (Toggle profiling)
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 4d65345c62..5bd0f28302 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -361,6 +361,13 @@ LLViewerObject::~LLViewerObject()
{
deleteTEImages();
+ // unhook from reflection probe manager
+ if (mReflectionProbe.notNull())
+ {
+ mReflectionProbe->mViewerObject = nullptr;
+ mReflectionProbe = nullptr;
+ }
+
if(mInventory)
{
mInventory->clear(); // will deref and delete entries
@@ -6193,6 +6200,11 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para
{
new_block = new LLExtendedMeshParams();
break;
+ }
+ case LLNetworkData::PARAMS_RENDER_MATERIAL:
+ {
+ new_block = new LLRenderMaterialParams();
+ break;
}
default:
{
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index c5d181d2c9..6f70982425 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -43,6 +43,7 @@
#include "llvertexbuffer.h"
#include "llbbox.h"
#include "llrigginginfo.h"
+#include "llreflectionmap.h"
#include "fsregioncross.h" // Improved region crossing support
@@ -865,7 +866,7 @@ protected:
F32 mLinksetCost;
F32 mPhysicsCost;
F32 mLinksetPhysicsCost;
-
+
bool mCostStale;
mutable bool mPhysicsShapeUnknown;
@@ -927,8 +928,12 @@ private:
RegionCrossExtrapolate mExtrap; // improved extrapolator
- // export
public:
+ // reflection probe state
+ bool mIsReflectionProbe = false; // if true, this object should register itself with LLReflectionProbeManager
+ LLPointer mReflectionProbe = nullptr; // reflection probe coupled to this viewer object. If not null, should be deregistered when this object is destroyed
+
+ // export
LLViewerPartSourceScript* getPartSourceScript() { return mPartSourcep.get(); }
bool getPhysicsShapeUnknown () { return mPhysicsShapeUnknown; }
//
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 271cc1ff84..0240a3e0d7 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -82,6 +82,7 @@ LLGLSLShader gOcclusionCubeProgram;
LLGLSLShader gCustomAlphaProgram;
LLGLSLShader gGlowCombineProgram;
LLGLSLShader gSplatTextureRectProgram;
+LLGLSLShader gReflectionMipProgram;
LLGLSLShader gGlowCombineFXAAProgram;
LLGLSLShader gTwoTextureAddProgram;
LLGLSLShader gTwoTextureCompareProgram;
@@ -262,6 +263,7 @@ LLGLSLShader gRlvSphereProgram;
// Deferred materials shaders
LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2];
LLGLSLShader gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2];
+LLGLSLShader gDeferredPBROpaqueProgram;
//helper for making a rigged variant of a given shader
bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader)
@@ -648,7 +650,6 @@ void LLViewerShaderMgr::setShaders()
}
if (loaded)
-
{
loaded = loadTransformShaders();
if (loaded)
@@ -759,6 +760,7 @@ void LLViewerShaderMgr::unloadShaders()
gCustomAlphaProgram.unload();
gGlowCombineProgram.unload();
gSplatTextureRectProgram.unload();
+ gReflectionMipProgram.unload();
gGlowCombineFXAAProgram.unload();
gTwoTextureAddProgram.unload();
gTwoTextureCompareProgram.unload();
@@ -983,6 +985,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/deferredUtil.glsl", 1) );
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/shadowUtil.glsl", 1) );
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/aoUtil.glsl", 1) );
+ index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/reflectionProbeF.glsl", llmax(mShaderLevel[SHADER_DEFERRED], 1)) );
index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) );
index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightAlphaMaskNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) );
index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) );
@@ -1328,6 +1331,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredMaterialProgram[i].unload();
gDeferredMaterialWaterProgram[i].unload();
}
+
+ gDeferredPBROpaqueProgram.unload();
+
return TRUE;
}
@@ -1519,6 +1525,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredMaterialProgram[i].mFeatures.hasGamma = true;
gDeferredMaterialProgram[i].mFeatures.hasShadows = use_sun_shadow;
+ if (mShaderLevel[SHADER_DEFERRED] > 1)
+ {
+ gDeferredMaterialProgram[i].mFeatures.hasReflectionProbes = true;
+ gDeferredMaterialProgram[i].addPermutation("HAS_REFLECTION_PROBES", "1");
+ }
+
if (has_skin)
{
gDeferredMaterialProgram[i].addPermutation("HAS_SKIN", "1");
@@ -1612,6 +1624,22 @@ 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;
@@ -2202,6 +2230,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ if (gDeferredFullbrightShinyProgram.mShaderLevel >= 2) // TODO : make this a 3 when reflection probes are restricted to class 3
+ {
+ gDeferredFullbrightShinyProgram.addPermutation("HAS_REFLECTION_PROBES", "1");
+ gDeferredFullbrightShinyProgram.mFeatures.hasReflectionProbes = true;
+ }
success = make_rigged_variant(gDeferredFullbrightShinyProgram, gDeferredSkinnedFullbrightShinyProgram);
success = success && gDeferredFullbrightShinyProgram.createShader(NULL, NULL);
llassert(success);
@@ -2274,6 +2307,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSoftenProgram.mFeatures.hasGamma = true;
gDeferredSoftenProgram.mFeatures.isDeferred = true;
gDeferredSoftenProgram.mFeatures.hasShadows = use_sun_shadow;
+ gDeferredSoftenProgram.mFeatures.hasReflectionProbes = true;
gDeferredSoftenProgram.clearPermutations();
gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB));
@@ -2324,6 +2358,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSoftenWaterProgram.mFeatures.hasGamma = true;
gDeferredSoftenWaterProgram.mFeatures.isDeferred = true;
gDeferredSoftenWaterProgram.mFeatures.hasShadows = use_sun_shadow;
+ gDeferredSoftenWaterProgram.mFeatures.hasReflectionProbes = true;
if (ambient_kill)
{
@@ -3596,7 +3631,6 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
}
}
-
if (success)
{
gTwoTextureAddProgram.mName = "Two Texture Add Shader";
@@ -3772,6 +3806,22 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
success = gAlphaMaskProgram.createShader(NULL, NULL);
}
+ if (success)
+ {
+ gReflectionMipProgram.mName = "Reflection Mip Shader";
+ gReflectionMipProgram.mShaderFiles.clear();
+ gReflectionMipProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectV.glsl", GL_VERTEX_SHADER_ARB));
+ gReflectionMipProgram.mShaderFiles.push_back(make_pair("interface/reflectionmipF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gReflectionMipProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
+ success = gReflectionMipProgram.createShader(NULL, NULL);
+ if (success)
+ {
+ gReflectionMipProgram.bind();
+ gReflectionMipProgram.uniform1i(sScreenMap, 0);
+ gReflectionMipProgram.unbind();
+ }
+ }
+
if( !success )
{
mShaderLevel[SHADER_INTERFACE] = 0;
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 11c2fc8574..937595cec9 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -161,6 +161,7 @@ extern LLGLSLShader gOcclusionCubeProgram;
extern LLGLSLShader gCustomAlphaProgram;
extern LLGLSLShader gGlowCombineProgram;
extern LLGLSLShader gSplatTextureRectProgram;
+extern LLGLSLShader gReflectionMipProgram;
extern LLGLSLShader gGlowCombineFXAAProgram;
extern LLGLSLShader gDebugProgram;
extern LLGLSLShader gClipProgram;
@@ -317,4 +318,6 @@ extern LLGLSLShader gRlvSphereProgram;
// Deferred materials shaders
extern LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2];
extern LLGLSLShader gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2];
+
+extern LLGLSLShader gDeferredPBROpaqueProgram;
#endif
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 729306ef87..8744b42fa2 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -258,6 +258,7 @@ extern BOOL gDebugClicks;
extern BOOL gDisplaySwapBuffers;
extern BOOL gDepthDirty;
extern BOOL gResizeScreenTexture;
+extern BOOL gCubeSnapshot;
LLViewerWindow *gViewerWindow = NULL;
@@ -6085,8 +6086,8 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
//
if (scratch_space.allocate(image_width, image_height, color_fmt, true, true))
{
- original_width = gPipeline.mDeferredScreen.getWidth();
- original_height = gPipeline.mDeferredScreen.getHeight();
+ original_width = gPipeline.mRT->deferredScreen.getWidth();
+ original_height = gPipeline.mRT->deferredScreen.getHeight();
if (gPipeline.allocateScreenBuffer(image_width, image_height))
{
@@ -6372,6 +6373,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, const int num_render_passes)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
gDisplaySwapBuffers = FALSE;
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -6386,8 +6388,8 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_
LLPipeline::sShowHUDAttachments = FALSE;
LLRect window_rect = getWorldViewRectRaw();
- S32 original_width = LLPipeline::sRenderDeferred ? gPipeline.mDeferredScreen.getWidth() : gViewerWindow->getWorldViewWidthRaw();
- S32 original_height = LLPipeline::sRenderDeferred ? gPipeline.mDeferredScreen.getHeight() : gViewerWindow->getWorldViewHeightRaw();
+ S32 original_width = LLPipeline::sRenderDeferred ? gPipeline.mRT->deferredScreen.getWidth() : gViewerWindow->getWorldViewWidthRaw();
+ S32 original_height = LLPipeline::sRenderDeferred ? gPipeline.mRT->deferredScreen.getHeight() : gViewerWindow->getWorldViewHeightRaw();
LLRenderTarget scratch_space;
U32 color_fmt = GL_RGBA;
@@ -6468,6 +6470,125 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_
return true;
}
+void display_cube_face();
+
+BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face)
+{
+ // NOTE: implementation derived from LLFloater360Capture::capture360Images() and simpleSnapshot
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
+ LL_PROFILE_GPU_ZONE("cubeSnapshot");
+ llassert(LLPipeline::sRenderDeferred);
+ llassert(!gCubeSnapshot); //assert a snapshot isn't already in progress
+
+ U32 res = LLRenderTarget::sCurResX;
+
+ llassert(res <= gPipeline.mRT->deferredScreen.getWidth());
+ llassert(res <= gPipeline.mRT->deferredScreen.getHeight());
+
+ // save current view/camera settings so we can restore them afterwards
+ S32 old_occlusion = LLPipeline::sUseOcclusion;
+
+ // set new parameters specific to the 360 requirements
+ LLPipeline::sUseOcclusion = 0;
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+
+ LLViewerCamera saved_camera = LLViewerCamera::instance();
+ glh::matrix4f saved_proj = get_current_projection();
+ glh::matrix4f saved_mod = get_current_modelview();
+
+ // camera constants for the square, cube map capture image
+ camera->setAspect(1.0); // must set aspect ratio first to avoid undesirable clamping of vertical FoV
+ camera->setView(F_PI_BY_TWO);
+ camera->yaw(0.0);
+ camera->setOrigin(origin);
+
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE;
+ if (prev_draw_ui != false)
+ {
+ LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+ BOOL prev_draw_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
+ if (prev_draw_particles)
+ {
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
+ }
+ LLPipeline::sShowHUDAttachments = FALSE;
+ LLRect window_rect = getWorldViewRectRaw();
+
+ mWorldViewRectRaw.set(0, res, res, 0);
+
+ // these are the 6 directions we will point the camera, see LLCubeMapArray::sTargets
+ LLVector3 look_dirs[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 look_upvecs[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)
+ };
+
+ // for each of six sides of cubemap
+ //for (int i = 0; i < 6; ++i)
+ int i = face;
+ {
+ // set up camera to look in each direction
+ camera->lookDir(look_dirs[i], look_upvecs[i]);
+
+ // turning this flag off here prohibits the screen swap
+ // to present the new page to the viewer - this stops
+ // the black flash in between captures when the number
+ // of render passes is more than 1. We need to also
+ // set it here because code in LLViewerDisplay resets
+ // it to TRUE each time.
+ gDisplaySwapBuffers = FALSE;
+
+ // actually render the scene
+ gCubeSnapshot = TRUE;
+ display_cube_face();
+ gCubeSnapshot = FALSE;
+ }
+
+ gDisplaySwapBuffers = TRUE;
+
+ if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ {
+ if (prev_draw_ui != false)
+ {
+ LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+ }
+
+ if (prev_draw_particles)
+ {
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
+ }
+
+ LLPipeline::sShowHUDAttachments = TRUE;
+
+ gPipeline.resetDrawOrders();
+ mWorldViewRectRaw = window_rect;
+
+ // restore original view/camera/avatar settings settings
+ *camera = saved_camera;
+ set_current_modelview(saved_mod);
+ set_current_projection(saved_proj);
+ LLPipeline::sUseOcclusion = old_occlusion;
+
+ // ====================================================
+ return true;
+}
+
void LLViewerWindow::destroyWindow()
{
if (mWindow)
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 98b3433d00..de18f8709c 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -69,6 +69,8 @@ class LLWindowListener;
class LLViewerWindowListener;
class LLVOPartGroup;
class LLPopupView;
+class LLCubeMap;
+class LLCubeMapArray;
#define PICK_HALF_WIDTH 5
#define PICK_DIAMETER (2 * PICK_HALF_WIDTH + 1)
@@ -361,6 +363,18 @@ public:
BOOL simpleSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, const int num_render_passes);
+
+
+ // take a cubemap snapshot
+ // origin - vantage point to take the snapshot from
+ // cubearray - cubemap array for storing the results
+ // index - cube index in the array to use (cube index, not face-layer)
+ BOOL cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 index, S32 face);
+
+
+ // special implementation of simpleSnapshot for reflection maps
+ BOOL reflectionSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, const int num_render_passes);
+
BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type);
BOOL isSnapshotLocSet() const;
void resetSnapshotLoc() const;
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 63ab827303..3d093da64a 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -112,6 +112,7 @@ LLPointer LLVOVolume::sObjectMediaClient = NULL;
LLPointer LLVOVolume::sObjectMediaNavigateClient = NULL;
extern BOOL gGLDebugLoggingEnabled;
+extern BOOL gCubeSnapshot;
// NaCl - Graphics crasher protection
static bool enableVolumeSAPProtection()
@@ -838,7 +839,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
// Update the pixel area of all faces
- if (mDrawable.isNull())
+ if (mDrawable.isNull() || gCubeSnapshot)
{
return;
}
@@ -2348,7 +2349,7 @@ void LLVOVolume::setNumTEs(const U8 num_tes)
return ;
}
-//virtual
+//virtual
void LLVOVolume::changeTEImage(S32 index, LLViewerTexture* imagep)
{
BOOL changed = (mTEImages[index] != imagep);
@@ -3580,6 +3581,11 @@ F32 LLVOVolume::getSpotLightPriority() const
void LLVOVolume::updateSpotLightPriority()
{
+ if (gCubeSnapshot)
+ {
+ return;
+ }
+
F32 r = getLightRadius();
LLVector3 pos = mDrawable->getPositionAgent();
@@ -5761,6 +5767,8 @@ static inline void add_face(T*** list, U32* count, T* face)
void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
+ llassert(!gCubeSnapshot);
+
if (group->changeLOD())
{
group->mLastUpdateDistance = group->mDistance;
@@ -5984,6 +5992,32 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
continue;
}
+#if LL_RELEASE_WITH_DEBUG_INFO
+ const LLUUID pbr_id( "49c88210-7238-2a6b-70ac-92d4f35963cf" );
+ const LLUUID obj_id( vobj->getID() );
+ bool is_pbr = (obj_id == pbr_id);
+#else
+ bool is_pbr = false;
+#endif
+
+ // HACK - make this object a Reflection Probe if a certain UUID is detected
+ static LLCachedControl reflection_probe_id(gSavedSettings, "RenderReflectionProbeTextureHackID", "");
+ if (facep->getTextureEntry()->getID() == LLUUID(reflection_probe_id))
+ {
+ if (!vobj->mIsReflectionProbe)
+ {
+ vobj->mIsReflectionProbe = true;
+ vobj->mReflectionProbe = gPipeline.mReflectionMapManager.registerViewerObject(vobj);
+ }
+ }
+ else
+ {
+ // not a refleciton probe any more
+ vobj->mIsReflectionProbe = false;
+ vobj->mReflectionProbe = nullptr;
+ }
+ // END HACK
+
//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
facep->setVertexBuffer(NULL);
@@ -6052,6 +6086,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA);
U32 type = gPipeline.getPoolTypeFromTE(te, tex);
+
+ if (is_pbr)
+ {
+ type = LLDrawPool::POOL_PBR_OPAQUE;
+ }
+ else
if (type != LLDrawPool::POOL_ALPHA && force_simple)
{
type = LLDrawPool::POOL_SIMPLE;
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 8f9b8d9d6d..bc3d485737 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -1262,7 +1262,7 @@ void LLWorld::updateNetStats()
void LLWorld::printPacketsLost()
{
- LL_INFOS() << "Simulators:" << LL_ENDL;
+ LL_INFOS() << "Simulators:" << LL_ENDL;
LL_INFOS() << "----------" << LL_ENDL;
LLCircuitData *cdp = NULL;
@@ -1297,6 +1297,7 @@ F32 LLWorld::getLandFarClip() const
void LLWorld::setLandFarClip(const F32 far_clip)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT;
// Aurora Sim
//static S32 const rwidth = (S32)REGION_WIDTH_U32;
static S32 const rwidth = (S32)getRegionWidthInMeters();
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index c0833944c9..159e634df1 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -245,6 +245,7 @@ extern S32 gBoxFrame;
//extern BOOL gHideSelectedObjects;
extern BOOL gDisplaySwapBuffers;
extern BOOL gDebugGL;
+extern BOOL gCubeSnapshot;
bool gAvatarBacklight = false;
@@ -433,9 +434,7 @@ LLPipeline::LLPipeline() :
mWLSkyPool(NULL),
mLightMask(0),
mLightMovingMask(0),
- mLightingDetail(0),
- mScreenWidth(0),
- mScreenHeight(0)
+ mLightingDetail(0)
{
mNoiseMap = 0;
mTrueNoiseMap = 0;
@@ -464,6 +463,8 @@ void LLPipeline::init()
{
refreshCachedSettings();
+ mRT = new RenderTargetPack();
+
gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize");
sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
@@ -502,6 +503,7 @@ void LLPipeline::init()
getPool(LLDrawPool::POOL_BUMP);
getPool(LLDrawPool::POOL_MATERIALS);
getPool(LLDrawPool::POOL_GLOW);
+ getPool(LLDrawPool::POOL_PBR_OPAQUE);
resetFrameStats();
@@ -759,6 +761,9 @@ void LLPipeline::cleanup()
mDeferredVB = NULL;
mCubeVB = NULL;
+
+ delete mRT;
+ mRT = nullptr;
}
//============================================================================
@@ -800,10 +805,7 @@ void LLPipeline::requestResizeShadowTexture()
void LLPipeline::resizeShadowTexture()
{
releaseShadowTargets();
- // FIRE-30538 don;t pass zero screen size to shadow buff allocator
- // allocateShadowBuffer(mScreenWidth, mScreenHeight);
- allocateShadowBuffer( mScreen.getWidth(), mScreen.getHeight() );
- //
+ allocateShadowBuffer(mRT->width, mRT->height);
gResizeShadowTexture = FALSE;
}
@@ -829,9 +831,9 @@ void LLPipeline::resizeScreenTexture()
}
// [/SL:KB]
-// if (gResizeScreenTexture || (resX != mScreen.getWidth()) || (resY != mScreen.getHeight()))
+// if (gResizeScreenTexture || (resX != mRT->screen.getWidth()) || (resY != mRT->screen.getHeight()))
// [SL:KB] - Patch: Settings-RenderResolutionMultiplier | Checked: Catznip-5.4
- if (gResizeScreenTexture || (scaledResX != mScreen.getWidth()) || (scaledResY != mScreen.getHeight()))
+ if (gResizeScreenTexture || (scaledResX != mRT->screen.getWidth()) || (scaledResY != mRT->screen.getHeight()))
// [/SL:KB]
{
releaseScreenBuffers();
@@ -855,43 +857,16 @@ void LLPipeline::allocatePhysicsBuffer()
bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
{
- refreshCachedSettings();
-
- bool save_settings = sRenderDeferred;
- if (save_settings)
- {
- // Set this flag in case we crash while resizing window or allocating space for deferred rendering targets
- gSavedSettings.setBOOL("RenderInitError", TRUE);
- gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
- }
-
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
eFBOStatus ret = doAllocateScreenBuffer(resX, resY);
- if (save_settings)
- {
- // don't disable shaders on next session
- gSavedSettings.setBOOL("RenderInitError", FALSE);
- gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
- }
-
- if (ret == FBO_FAILURE)
- { //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled
- //NOTE: if the session closes successfully after this call, deferred rendering will be
- // disabled on future sessions
- if (LLPipeline::sRenderDeferred)
- {
- LL_WARNS() << "Couldn't allocate screen buffer - Deferred rendering disabled" << LL_ENDL; // FS:Ansariel> FIRE-20305: Debug output
- gSavedSettings.setBOOL("RenderDeferred", FALSE);
- LLPipeline::refreshCachedSettings();
- }
- }
-
return ret == FBO_SUCCESS_FULLRES;
}
LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
// try to allocate screen buffers at requested resolution and samples
// - on failure, shrink number of samples and try again
// - if not multisampled, shrink resolution and try again (favor X resolution over Y)
@@ -945,11 +920,10 @@ LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY)
bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
{
- refreshCachedSettings();
-
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
// remember these dimensions
- mScreenWidth = resX;
- mScreenHeight = resY;
+ mRT->width = resX;
+ mRT->height = resY;
U32 res_mod = RenderResolutionDivisor;
@@ -980,7 +954,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
if (RenderUIBuffer)
{
- if (!mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE))
+ if (!mRT->uiScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE))
{
return false;
}
@@ -994,10 +968,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
const U32 occlusion_divisor = 3;
//allocate deferred rendering color buffers
- if (!mDeferredScreen.allocate(resX, resY, GL_SRGB8_ALPHA8, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (!mOcclusionDepth.allocate(resX/occlusion_divisor, resY/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (!addDeferredAttachments(mDeferredScreen)) return false;
+ if (!mRT->deferredScreen.allocate(resX, resY, GL_SRGB8_ALPHA8, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+ if (!mRT->deferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+ if (!mRT->occlusionDepth.allocate(resX/occlusion_divisor, resY/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+ if (!addDeferredAttachments(mRT->deferredScreen)) return false;
GLuint screenFormat = GL_RGBA16;
if (gGLManager.mIsAMD)
@@ -1010,26 +984,26 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
screenFormat = GL_RGBA16F_ARB;
}
- if (!mScreen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+ if (!mRT->screen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
if (samples > 0)
{
- if (!mFXAABuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;
+ if (!mRT->fxaaBuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;
}
else
{
- mFXAABuffer.release();
+ mRT->fxaaBuffer.release();
}
// if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0)
// [RLVa:KB] - @setsphere
if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0 || RlvActions::hasPostProcess())
// [/RLVa:KB]
- { //only need mDeferredLight for shadows OR ssao OR dof OR fxaa
- if (!mDeferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
+ { //only need mRT->deferredLight for shadows OR ssao OR dof OR fxaa
+ if (!mRT->deferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
}
else
{
- mDeferredLight.release();
+ mRT->deferredLight.release();
}
allocateShadowBuffer(resX, resY);
@@ -1042,36 +1016,36 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
}
else
{
- mDeferredLight.release();
+ mRT->deferredLight.release();
releaseShadowTargets();
- mFXAABuffer.release();
- mScreen.release();
- mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
+ mRT->fxaaBuffer.release();
+ mRT->screen.release();
+ mRT->deferredScreen.release(); //make sure to release any render targets that share a depth buffer with mRT->deferredScreen first
// [RLVa:KB] - @setsphere
if (!LLRenderTarget::sUseFBO || !LLPipeline::sUseDepthTexture)
{
- mDeferredDepth.release();
- mOcclusionDepth.release();
+ mRT->deferredDepth.release();
+ mRT->occlusionDepth.release();
}
else
{
const U32 occlusion_divisor = 3;
- if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (!mOcclusionDepth.allocate(resX / occlusion_divisor, resY / occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (RlvActions::isRlvEnabled() && !mDeferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
+ if (!mRT->deferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+ if (!mRT->occlusionDepth.allocate(resX / occlusion_divisor, resY / occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+ if (RlvActions::isRlvEnabled() && !!mRT->deferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
}
// [/RLVa:KB]
-// mDeferredDepth.release();
-// mOcclusionDepth.release();
+// mRT->deferredDepth.release();
+// mRT->occlusionDepth.release();
- if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
+ if (!mRT->screen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
}
if (LLPipeline::sRenderDeferred)
{ //share depth buffer between deferred targets
- mDeferredScreen.shareDepthBuffer(mScreen);
+ mRT->deferredScreen.shareDepthBuffer(mRT->screen);
}
gGL.getTexUnit(0)->disable();
@@ -1086,8 +1060,7 @@ inline U32 BlurHappySize(U32 x, F32 scale) { return U32( x * scale + 16.0f) & ~0
bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY)
{
- refreshCachedSettings();
-
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
if (LLPipeline::sRenderDeferred)
{
S32 shadow_detail = RenderShadowDetail;
@@ -1102,12 +1075,12 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY)
{ //allocate 4 sun shadow maps
for (U32 i = 0; i < 4; i++)
{
- if (!mShadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
+ if (!mRT->shadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
{
return false;
}
- if (!mShadowOcclusion[i].allocate(sun_shadow_map_width/occlusion_divisor, sun_shadow_map_height/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
+ if (!mRT->shadowOcclusion[i].allocate(sun_shadow_map_width/occlusion_divisor, sun_shadow_map_height/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
{
return false;
}
@@ -1130,11 +1103,11 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY)
U32 spot_shadow_map_height = height;
for (U32 i = 4; i < 6; i++)
{
- if (!mShadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, TRUE, FALSE))
+ if (!mRT->shadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, TRUE, FALSE))
{
return false;
}
- if (!mShadowOcclusion[i].allocate(spot_shadow_map_width/occlusion_divisor, height/occlusion_divisor, 0, TRUE, FALSE))
+ if (!mRT->shadowOcclusion[i].allocate(spot_shadow_map_width/occlusion_divisor, height/occlusion_divisor, 0, TRUE, FALSE))
{
return false;
}
@@ -1188,6 +1161,7 @@ void LLPipeline::updateRenderDeferred()
// static
void LLPipeline::refreshCachedSettings()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred");
LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred");
LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip");
@@ -1351,21 +1325,21 @@ void LLPipeline::releaseShadowBuffers()
void LLPipeline::releaseScreenBuffers()
{
- mUIScreen.release();
- mScreen.release();
- mFXAABuffer.release();
+ mRT->uiScreen.release();
+ mRT->screen.release();
+ mRT->fxaaBuffer.release();
mPhysicsDisplay.release();
- mDeferredScreen.release();
- mDeferredDepth.release();
- mDeferredLight.release();
- mOcclusionDepth.release();
+ mRT->deferredScreen.release();
+ mRT->deferredDepth.release();
+ mRT->deferredLight.release();
+ mRT->occlusionDepth.release();
}
void LLPipeline::releaseShadowTarget(U32 index)
{
- mShadow[index].release();
- mShadowOcclusion[index].release();
+ mRT->shadow[index].release();
+ mRT->shadowOcclusion[index].release();
}
void LLPipeline::releaseShadowTargets()
@@ -1411,8 +1385,8 @@ void LLPipeline::createGLBuffers()
}
allocateScreenBuffer(resX, resY);
- mScreenWidth = 0;
- mScreenHeight = 0;
+ mRT->width = 0;
+ mRT->height = 0;
if (sRenderDeferred)
{
@@ -1752,6 +1726,10 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
poolp = mWLSkyPool;
break;
+ case LLDrawPool::POOL_PBR_OPAQUE:
+ poolp = mPBROpaquePool;
+ break;
+
default:
llassert(0);
LL_ERRS() << "Invalid Pool Type in LLPipeline::findPool() type=" << type << LL_ENDL;
@@ -2192,6 +2170,7 @@ void LLPipeline::updateMove()
//static
F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera)
{
+ llassert(!gCubeSnapshot); // shouldn't be doing ANY of this during cube snap shots
LLVector3 lookAt = center - camera.getOrigin();
F32 dist = lookAt.length();
@@ -2520,11 +2499,11 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* pla
{
if (LLPipeline::sRenderDeferred && can_use_occlusion)
{
- mOcclusionDepth.bindTarget();
+ mRT->occlusionDepth.bindTarget();
}
else
{
- mScreen.bindTarget();
+ mRT->screen.bindTarget();
}
}
@@ -2646,11 +2625,11 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* pla
{
if (LLPipeline::sRenderDeferred && can_use_occlusion)
{
- mOcclusionDepth.flush();
+ mRT->occlusionDepth.flush();
}
else
{
- mScreen.flush();
+ mRT->screen.flush();
}
}
}
@@ -2664,7 +2643,7 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
group->setVisible();
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{
group->updateDistance(camera);
}
@@ -2770,6 +2749,8 @@ void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& d
void LLPipeline::doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(!gCubeSnapshot);
downsampleDepthBuffer(source, dest, scratch_space);
dest.bindTarget();
doOcclusion(camera);
@@ -3012,7 +2993,7 @@ void LLPipeline::rebuildPriorityGroups()
void LLPipeline::rebuildGroups()
{
- if (mGroupQ2.empty())
+ if (mGroupQ2.empty() || gCubeSnapshot)
{
return;
}
@@ -3063,6 +3044,10 @@ void LLPipeline::updateGeom(F32 max_dtime)
LLPointer drawablep;
LL_RECORD_BLOCK_TIME(FTM_GEO_UPDATE);
+ if (gCubeSnapshot)
+ {
+ return;
+ }
assertInitialized();
@@ -3302,6 +3287,8 @@ void LLPipeline::shiftObjects(const LLVector3 &offset)
}
}
+ mReflectionMapManager.shift(offseta);
+
LLHUDText::shiftAll(offset);
LLHUDNameTag::shiftAll(offset);
@@ -3496,7 +3483,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
}
}
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("WorldCamera");
LLSpatialGroup* last_group = NULL;
@@ -3580,7 +3567,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
stateSort(drawablep, camera);
}
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{ //avoid redundant stateSort calls
group->mLastUpdateDistance = group->mDistance;
}
@@ -3656,7 +3643,7 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
}
}
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{
//if (drawablep->isVisible()) isVisible() check here is redundant, if it wasn't visible, it wouldn't be here
{
@@ -3935,23 +3922,26 @@ void LLPipeline::postSort(LLCamera& camera)
sVolumeSAFrame = 0.f; //ZK LBG
LL_PUSH_CALLSTACKS();
- //rebuild drawable geometry
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("PostSort: rebuildGeom");
- for (LLCullResult::sg_iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i)
- {
- LLSpatialGroup* group = *i;
- if (!sUseOcclusion ||
- !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
- {
- group->rebuildGeom();
- }
- }
- LL_PUSH_CALLSTACKS();
- //rebuild groups
- sCull->assertDrawMapsEmpty();
- rebuildPriorityGroups();
+ if (!gCubeSnapshot)
+ {
+ //rebuild drawable geometry
+ for (LLCullResult::sg_iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i)
+ {
+ LLSpatialGroup* group = *i;
+ if (!sUseOcclusion ||
+ !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+ {
+ group->rebuildGeom();
+ }
+ }
+ LL_PUSH_CALLSTACKS();
+ //rebuild groups
+ sCull->assertDrawMapsEmpty();
+
+ rebuildPriorityGroups();
+ }
+
LL_PUSH_CALLSTACKS();
@@ -3969,7 +3959,7 @@ void LLPipeline::postSort(LLCamera& camera)
continue;
}
- if (group->hasState(LLSpatialGroup::NEW_DRAWINFO) && group->hasState(LLSpatialGroup::GEOM_DIRTY))
+ if (group->hasState(LLSpatialGroup::NEW_DRAWINFO) && group->hasState(LLSpatialGroup::GEOM_DIRTY) && !gCubeSnapshot)
{ //no way this group is going to be drawable without a rebuild
group->rebuildGeom();
}
@@ -3987,7 +3977,7 @@ void LLPipeline::postSort(LLCamera& camera)
LLDrawInfo* info = *k;
sCull->pushDrawInfo(j->first, info);
- if (!sShadowRender && !sReflectionRender)
+ if (!sShadowRender && !sReflectionRender && !gCubeSnapshot)
{
touchTextures(info);
addTrianglesDrawn(info->mCount, info->mDrawMode);
@@ -4003,7 +3993,7 @@ void LLPipeline::postSort(LLCamera& camera)
if (alpha != group->mDrawMap.end())
{ //store alpha groups for sorting
LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge();
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{
if (bridge)
{
@@ -4067,7 +4057,6 @@ void LLPipeline::postSort(LLCamera& camera)
(*iter)->rebuildMesh();
}
}
- }
/*if (use_transform_feedback)
{
@@ -4471,7 +4460,7 @@ U32 LLPipeline::sCurRenderPoolType = 0 ;
void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY);
-
+ LL_PROFILE_GPU_ZONE("renderGeom");
assertInitialized();
F32 saved_modelview[16];
@@ -4593,7 +4582,7 @@ void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate)
}
else
{
- doOcclusion(camera, mScreen, mOcclusionDepth, &mDeferredDepth);
+ doOcclusion(camera, mRT->screen, mRT->occlusionDepth, &mRT->deferredDepth);
}
// [/RLVa:KB]
// doOcclusion(camera);
@@ -4656,7 +4645,7 @@ void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate)
gGL.loadMatrix(gGLModelView);
if (occlude)
- {
+ { // catch uncommon condition where pools at drawpool grass and later are disabled
occlude = false;
gGLLastMatrix = NULL;
gGL.loadMatrix(gGLModelView);
@@ -4731,14 +4720,10 @@ void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate)
void LLPipeline::renderGeomDeferred(LLCamera& camera)
{
LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred");
-
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY);
+ LL_PROFILE_GPU_ZONE("renderGeomDeferred");
+
{
- // SL-15709 -- NOTE: Tracy only allows one ZoneScoped per function.
- // Solutions are:
- // 1. Use a new scope
- // 2. Use named zones
- // 3. Use transient zones
LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred pools"); //LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLS);
LLGLEnable cull(GL_CULL_FACE);
@@ -4759,6 +4744,12 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
LLGLState::checkStates();
LLGLState::checkTextureChannels();
+ if (LLViewerShaderMgr::instance()->mShaderLevel[LLViewerShaderMgr::SHADER_DEFERRED] > 1)
+ {
+ //update reflection probe uniform
+ mReflectionMapManager.updateUniforms();
+ }
+
U32 cur_type = 0;
gGL.setColorMask(true, true);
@@ -4830,6 +4821,8 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_POST_DEFERRED_POOLS);
+ LL_PROFILE_GPU_ZONE("renderGeomPostDeferred");
+
U32 cur_type = 0;
LLGLEnable cull(GL_CULL_FACE);
@@ -4852,11 +4845,12 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)
if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
{
+ llassert(!gCubeSnapshot); // never do occlusion culling on cube snapshots
occlude = false;
gGLLastMatrix = NULL;
gGL.loadMatrix(gGLModelView);
LLGLSLShader::bindNoShader();
- doOcclusion(camera, mScreen, mOcclusionDepth, &mDeferredDepth);
+ doOcclusion(camera, mRT->screen, mRT->occlusionDepth, &mRT->deferredDepth);
gGL.setColorMask(true, false);
}
@@ -4925,6 +4919,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)
void LLPipeline::renderGeomShadow(LLCamera& camera)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ LL_PROFILE_GPU_ZONE("renderGeomShadow");
U32 cur_type = 0;
LLGLEnable cull(GL_CULL_FACE);
@@ -5380,7 +5375,6 @@ void LLPipeline::renderDebug()
glPointSize(1.f);
}
-
// Debug stuff.
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
@@ -5434,6 +5428,12 @@ void LLPipeline::renderDebug()
visible_selected_groups.clear();
+ //draw reflection probes and links between them
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_REFLECTION_PROBES) && !hud_only)
+ {
+ mReflectionMapManager.renderDebug();
+ }
+
gUIProgram.bind();
if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST) && !hud_only)
@@ -5922,6 +5922,18 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
}
break;
+ case LLDrawPool::POOL_PBR_OPAQUE:
+ if( mPBROpaquePool )
+ {
+ llassert(0);
+ LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate PBR Opaque Pool" << LL_ENDL;
+ }
+ else
+ {
+ mPBROpaquePool = new_poolp;
+ }
+ break;
+
default:
llassert(0);
LL_WARNS() << "Invalid Pool Type in LLPipeline::addPool()" << LL_ENDL;
@@ -6038,6 +6050,11 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
mGroundPool = NULL;
break;
+ case LLDrawPool::POOL_PBR_OPAQUE:
+ llassert( poolp == mPBROpaquePool );
+ mPBROpaquePool = NULL;
+ break;
+
default:
llassert(0);
LL_WARNS() << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << LL_ENDL;
@@ -6154,6 +6171,7 @@ void LLPipeline::setupAvatarLights(bool for_edit)
static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
F32 inten = light->getLightIntensity();
if (inten < .001f)
{
@@ -6177,9 +6195,10 @@ static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_
void LLPipeline::calcNearbyLights(LLCamera& camera)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
assertInitialized();
- if (LLPipeline::sReflectionRender)
+ if (LLPipeline::sReflectionRender || gCubeSnapshot)
{
return;
}
@@ -6362,6 +6381,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
void LLPipeline::setupHWLights(LLDrawPool* pool)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
assertInitialized();
LLEnvironment& environment = LLEnvironment::instance();
@@ -7701,9 +7721,11 @@ void LLPipeline::renderFinalize()
}
LLVector2 tc1(0, 0);
- LLVector2 tc2((F32) mScreen.getWidth() * 2, (F32) mScreen.getHeight() * 2);
+ LLVector2 tc2((F32) mRT->screen.getWidth() * 2, (F32) mRT->screen.getHeight() * 2);
LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM);
+ LL_PROFILE_GPU_ZONE("renderFinalize");
+
gGL.color4f(1, 1, 1, 1);
LLGLDepthTest depth(GL_FALSE);
LLGLDisable blend(GL_BLEND);
@@ -7722,10 +7744,11 @@ void LLPipeline::renderFinalize()
gGL.setColorMask(true, true);
glClearColor(0, 0, 0, 0);
- exoPostProcess::instance().ExodusRenderPostStack(&mScreen, &mScreen); // Import Vignette from Exodus
+ exoPostProcess::instance().ExodusRenderPostStack(&mRT->screen, &mRT->screen); // Import Vignette from Exodus
if (sRenderGlow)
{
+ LL_PROFILE_GPU_ZONE("glow");
mGlow[2].bindTarget();
mGlow[2].clear();
@@ -7750,7 +7773,7 @@ void LLPipeline::renderFinalize()
gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
- mScreen.bindTexture(0, 0, LLTexUnit::TFO_POINT);
+ mRT->screen.bindTexture(0, 0, LLTexUnit::TFO_POINT);
gGL.color4f(1, 1, 1, 1);
gPipeline.enableLightsFullbright();
@@ -7769,7 +7792,7 @@ void LLPipeline::renderFinalize()
drawAuxiliaryVB(tc1, tc2);
//
- gGL.getTexUnit(0)->unbind(mScreen.getUsage());
+ gGL.getTexUnit(0)->unbind(mRT->screen.getUsage());
mGlow[2].flush();
@@ -7850,38 +7873,39 @@ void LLPipeline::renderFinalize()
gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- tc2.setVec((F32) mScreen.getWidth(), (F32) mScreen.getHeight());
+ tc2.setVec((F32) mRT->screen.getWidth(), (F32) mRT->screen.getHeight());
gGL.flush();
LLVertexBuffer::unbind();
// [RLVa:KB] - @setsphere
- LLRenderTarget* pRenderBuffer = (RlvActions::hasBehaviour(RLV_BHVR_SETSPHERE)) ? &mDeferredLight : nullptr;
+ LLRenderTarget* pRenderBuffer = (RlvActions::hasBehaviour(RLV_BHVR_SETSPHERE)) ? &mRT->deferredLight : nullptr;
// [/RLVa:KB]
if (LLPipeline::sRenderDeferred)
{
-
// FIRE-16251: Depth of Field does not work underwater
//bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() &&
bool dof_enabled = (FSRenderDepthOfFieldUnderwater || !LLViewerCamera::getInstance()->cameraUnderWater()) &&
// FIRE-16251
(RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) &&
- RenderDepthOfField;
+ RenderDepthOfField &&
+ !gCubeSnapshot;
- bool multisample = RenderFSAASamples > 1 && mFXAABuffer.isComplete();
+ bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete();
exoPostProcess::instance().multisample = multisample; // Import Vignette from Exodus
// [RLVa:KB] - @setsphere
- if (multisample && !pRenderBuffer)
- {
- pRenderBuffer = &mDeferredLight;
- }
+ if (multisample && !pRenderBuffer)
+ {
+ pRenderBuffer = &mRT->deferredLight;
+ }
// [/RLVa:KB]
gViewerWindow->setup3DViewport();
if (dof_enabled)
{
+ LL_PROFILE_GPU_ZONE("dof");
LLGLSLShader *shader = &gDeferredPostProgram;
LLGLDisable blend(GL_BLEND);
@@ -7978,7 +8002,7 @@ void LLPipeline::renderFinalize()
const F32 default_fov = CameraFieldOfView * F_PI / 180.f;
- // F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight();
+ // F32 aspect_ratio = (F32) mRT->screen.getWidth()/(F32)mRT->screen.getHeight();
F32 dv = 2.f * default_focal_length * tanf(default_fov / 2.f);
@@ -7998,15 +8022,15 @@ void LLPipeline::renderFinalize()
F32 magnification = focal_length / (subject_distance - focal_length);
{ // build diffuse+bloom+CoF
- mDeferredLight.bindTarget();
+ mRT->deferredLight.bindTarget();
shader = &gDeferredCoFProgram;
bindDeferredShader(*shader);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage());
if (channel > -1)
{
- mScreen.bindTexture(0, channel);
+ mRT->screen.bindTexture(0, channel);
}
shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f);
@@ -8032,23 +8056,23 @@ void LLPipeline::renderFinalize()
//
unbindDeferredShader(*shader);
- mDeferredLight.flush();
+ mRT->deferredLight.flush();
}
- U32 dof_width = (U32)(mScreen.getWidth() * CameraDoFResScale);
- U32 dof_height = (U32)(mScreen.getHeight() * CameraDoFResScale);
+ U32 dof_width = (U32)(mRT->screen.getWidth() * CameraDoFResScale);
+ U32 dof_height = (U32)(mRT->screen.getHeight() * CameraDoFResScale);
{ // perform DoF sampling at half-res (preserve alpha channel)
- mScreen.bindTarget();
+ mRT->screen.bindTarget();
glViewport(0, 0, dof_width, dof_height);
gGL.setColorMask(true, false);
shader = &gDeferredPostProgram;
bindDeferredShader(*shader);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->deferredLight.getUsage());
if (channel > -1)
{
- mDeferredLight.bindTexture(0, channel);
+ mRT->deferredLight.bindTexture(0, channel);
}
shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
@@ -8070,21 +8094,21 @@ void LLPipeline::renderFinalize()
//
unbindDeferredShader(*shader);
- mScreen.flush();
+ mRT->screen.flush();
gGL.setColorMask(true, true);
}
{ // combine result based on alpha
// if (multisample)
// {
-// mDeferredLight.bindTarget();
-// glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
+// mRT->deferredLight.bindTarget();
+// glViewport(0, 0, mRT->deferredScreen.getWidth(), mRT->deferredScreen.getHeight());
// }
// [RLVa:KB] - @setsphere
if (pRenderBuffer)
{
- pRenderBuffer->bindTarget();
- glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
+ pRenderBuffer->bindTarget();
+ glViewport(0, 0, mRT->deferredScreen.getWidth(), mRT->deferredScreen.getHeight());
}
// [/RLVa:KB]
else
@@ -8099,10 +8123,10 @@ void LLPipeline::renderFinalize()
shader = &gDeferredDoFCombineProgram;
bindDeferredShader(*shader);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage());
if (channel > -1)
{
- mScreen.bindTexture(0, channel);
+ mRT->screen.bindTexture(0, channel);
}
shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
@@ -8135,30 +8159,31 @@ void LLPipeline::renderFinalize()
// [/RLVa:KB]
// if (multisample)
// {
-// mDeferredLight.flush();
+// mRT->deferredLight.flush();
// }
}
}
else
{
+ LL_PROFILE_GPU_ZONE("no dof");
// if (multisample)
// {
-// mDeferredLight.bindTarget();
+// mRT->deferredLight.bindTarget();
// }
// [RLVa:KB] - @setsphere
if (pRenderBuffer)
{
- pRenderBuffer->bindTarget();
+ pRenderBuffer->bindTarget();
}
// [/RLVa:KB]
LLGLSLShader *shader = &gDeferredPostNoDoFProgram;
bindDeferredShader(*shader);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage());
if (channel > -1)
{
- mScreen.bindTexture(0, channel);
+ mRT->screen.bindTexture(0, channel);
}
// FIRE-16829: Visual Artifacts with ALM enabled on AMD graphics
@@ -8181,31 +8206,32 @@ void LLPipeline::renderFinalize()
// [RLVa:KB] - @setsphere
if (pRenderBuffer)
{
- pRenderBuffer->flush();
+ pRenderBuffer->flush();
}
// [/RLVa:KB]
// if (multisample)
// {
-// mDeferredLight.flush();
+// mRT->deferredLight.flush();
// }
}
// [RLVa:KB] - @setsphere
- if (RlvActions::hasBehaviour(RLV_BHVR_SETSPHERE))
- {
- LLShaderEffectParams params(pRenderBuffer, &mScreen, !multisample);
- LLVfxManager::instance().runEffect(EVisualEffect::RlvSphere, ¶ms);
- pRenderBuffer = params.m_pDstBuffer;
- }
+ if (RlvActions::hasBehaviour(RLV_BHVR_SETSPHERE))
+ {
+ LLShaderEffectParams params(pRenderBuffer, &mRT->screen, !multisample);
+ LLVfxManager::instance().runEffect(EVisualEffect::RlvSphere, ¶ms);
+ pRenderBuffer = params.m_pDstBuffer;
+ }
// [/RLVa:KB]
if (multisample)
{
+ LL_PROFILE_GPU_ZONE("aa");
// bake out texture2D with RGBL for FXAA shader
- mFXAABuffer.bindTarget();
+ mRT->fxaaBuffer.bindTarget();
- S32 width = mScreen.getWidth();
- S32 height = mScreen.getHeight();
+ S32 width = mRT->screen.getWidth();
+ S32 height = mRT->screen.getHeight();
glViewport(0, 0, width, height);
LLGLSLShader *shader = &gGlowCombineFXAAProgram;
@@ -8213,16 +8239,16 @@ void LLPipeline::renderFinalize()
shader->bind();
shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height);
-// S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+// S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->deferredLight.getUsage());
// if (channel > -1)
// {
-// mDeferredLight.bindTexture(0, channel);
+// mRT->deferredLight.bindTexture(0, channel);
// }
// [RLVa:KB] - @setsphere
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, pRenderBuffer->getUsage());
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, pRenderBuffer->getUsage());
if (channel > -1)
{
- pRenderBuffer->bindTexture(0, channel);
+ pRenderBuffer->bindTexture(0, channel);
}
// [RLVa:KB]
@@ -8240,18 +8266,18 @@ void LLPipeline::renderFinalize()
// [RLVa:KB] - @setsphere
shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, pRenderBuffer->getUsage());
// [/RLVa:KB]
-// shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+// shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->deferredLight.getUsage());
shader->unbind();
- mFXAABuffer.flush();
+ mRT->fxaaBuffer.flush();
shader = &gFXAAProgram;
shader->bind();
- channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAABuffer.getUsage());
+ channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mRT->fxaaBuffer.getUsage());
if (channel > -1)
{
- mFXAABuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
+ mRT->fxaaBuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
}
gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
@@ -8260,8 +8286,8 @@ void LLPipeline::renderFinalize()
gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- F32 scale_x = (F32) width / mFXAABuffer.getWidth();
- F32 scale_y = (F32) height / mFXAABuffer.getHeight();
+ F32 scale_x = (F32) width / mRT->fxaaBuffer.getWidth();
+ F32 scale_y = (F32) height / mRT->fxaaBuffer.getHeight();
shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f / width * scale_x, 1.f / height * scale_y);
shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f / width * scale_x, -0.5f / height * scale_y,
@@ -8285,12 +8311,12 @@ void LLPipeline::renderFinalize()
else // not deferred
{
// [RLVa:KB] - @setsphere
- if (RlvActions::hasBehaviour(RLV_BHVR_SETSPHERE))
- {
- LLShaderEffectParams params(&mScreen, &mDeferredLight, false);
- LLVfxManager::instance().runEffect(EVisualEffect::RlvSphere, ¶ms);
- pRenderBuffer = params.m_pDstBuffer;
- }
+ if (RlvActions::hasBehaviour(RLV_BHVR_SETSPHERE))
+ {
+ LLShaderEffectParams params(&mRT->screen, &mRT->deferredLight, false);
+ LLVfxManager::instance().runEffect(EVisualEffect::RlvSphere, ¶ms);
+ pRenderBuffer = params.m_pDstBuffer;
+ }
// [/RLVa:KB]
U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
@@ -8325,9 +8351,9 @@ void LLPipeline::renderFinalize()
gGL.getTexUnit(0)->bind(&mGlow[1]);
// [RLVa:KB] - @setsphere
- gGL.getTexUnit(1)->bind( pRenderBuffer ? pRenderBuffer : &mScreen );
+ gGL.getTexUnit(1)->bind( pRenderBuffer ? pRenderBuffer : &mRT->screen );
// [/RLVa:KB]
-// gGL.getTexUnit(1)->bind(&mScreen);
+// gGL.getTexUnit(1)->bind(&mRT->screen);
LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
@@ -8373,10 +8399,10 @@ void LLPipeline::renderFinalize()
gSplatTextureRectProgram.unbind();
}
- if (LLRenderTarget::sUseFBO)
- { // copy depth buffer from mScreen to framebuffer
- LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), 0, 0,
- mScreen.getWidth(), mScreen.getHeight(),
+ if (LLRenderTarget::sUseFBO && !gCubeSnapshot)
+ { // copy depth buffer from mRT->screen to framebuffer
+ LLRenderTarget::copyContentsToFramebuffer(mRT->screen, 0, 0, mRT->screen.getWidth(), mRT->screen.getHeight(), 0, 0,
+ mRT->screen.getWidth(), mRT->screen.getHeight(),
GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
}
@@ -8394,10 +8420,10 @@ void LLPipeline::renderFinalize()
void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
-
- LLRenderTarget* deferred_target = &mDeferredScreen;
- LLRenderTarget* deferred_depth_target = &mDeferredDepth;
- LLRenderTarget* deferred_light_target = &mDeferredLight;
+ LL_PROFILE_GPU_ZONE("bindDeferredShader");
+ LLRenderTarget* deferred_target = &mRT->deferredScreen;
+ LLRenderTarget* deferred_depth_target = &mRT->deferredDepth;
+ LLRenderTarget* deferred_light_target = &mRT->deferredLight;
shader.bind();
S32 channel = 0;
@@ -8546,16 +8572,19 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
{
cube_map->enable(channel);
cube_map->bind();
- F32* m = gGLModelView;
-
- F32 mat[] = { m[0], m[1], m[2],
- m[4], m[5], m[6],
- m[8], m[9], m[10] };
-
- shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat);
}
+
+ F32* m = gGLModelView;
+
+ F32 mat[] = { m[0], m[1], m[2],
+ m[4], m[5], m[6],
+ m[8], m[9], m[10] };
+
+ shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat);
}
+ bindReflectionProbes(shader);
+
if (gAtmosphere)
{
// bind precomputed textures necessary for calculating sun and sky luminance
@@ -8584,7 +8613,14 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
}
}
- shader.uniform4fv(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1, mSunClipPlanes.mV);
+ /*if (gCubeSnapshot)
+ { // we only really care about the first two values, but the shader needs increasing separation between clip planes
+ shader.uniform4f(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1.f, 64.f, 128.f, 256.f);
+ }
+ else*/
+ {
+ shader.uniform4fv(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1, mSunClipPlanes.mV);
+ }
shader.uniform1f(LLShaderMgr::DEFERRED_SUN_WASH, RenderDeferredSunWash);
shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_NOISE, RenderShadowNoise);
shader.uniform1f(LLShaderMgr::DEFERRED_BLUR_SIZE, RenderShadowBlurSize);
@@ -8619,8 +8655,8 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV);
shader.uniform3fv(LLShaderMgr::DEFERRED_MOON_DIR, 1, mTransformedMoonDir.mV);
- shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mShadow[0].getWidth(), mShadow[0].getHeight());
- shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mShadow[4].getWidth(), mShadow[4].getHeight());
+ shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mRT->shadow[0].getWidth(), mRT->shadow[0].getHeight());
+ shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mRT->shadow[4].getWidth(), mRT->shadow[4].getHeight());
shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff);
shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff);
@@ -8656,14 +8692,15 @@ LLVector4 pow4fsrgb(LLVector4 v, F32 f)
void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ LL_PROFILE_GPU_ZONE("renderDeferredLighting");
if (!sCull)
{
return;
}
- LLRenderTarget *deferred_target = &mDeferredScreen;
- LLRenderTarget *deferred_depth_target = &mDeferredDepth;
- LLRenderTarget *deferred_light_target = &mDeferredLight;
+ LLRenderTarget *deferred_target = &mRT->deferredScreen;
+ LLRenderTarget *deferred_depth_target = &mRT->deferredDepth;
+ LLRenderTarget *deferred_light_target = &mRT->deferredLight;
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("deferred"); //LL_RECORD_BLOCK_TIME(FTM_RENDER_DEFERRED);
@@ -8730,6 +8767,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
if (RenderDeferredSSAO || RenderShadowDetail > 0)
{
+ LL_PROFILE_GPU_ZONE("sun program");
deferred_light_target->bindTarget();
{ // paint shadow/SSAO light map (direct lighting lightmap)
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - sun shadow");
@@ -8777,66 +8815,79 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
}
if (RenderDeferredSSAO)
- { // soften direct lighting lightmap
- LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - soften shadow");
- // blur lightmap
- screen_target->bindTarget();
- glClearColor(1, 1, 1, 1);
- screen_target->clear(GL_COLOR_BUFFER_BIT);
- glClearColor(0, 0, 0, 0);
-
- bindDeferredShader(gDeferredBlurLightProgram);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- LLVector3 go = RenderShadowGaussian;
- const U32 kern_length = 4;
- F32 blur_size = RenderShadowBlurSize;
- F32 dist_factor = RenderShadowBlurDistFactor;
-
- // sample symmetrically with the middle sample falling exactly on 0.0
- F32 x = 0.f;
-
- LLVector3 gauss[32]; // xweight, yweight, offset
-
- for (U32 i = 0; i < kern_length; i++)
- {
- gauss[i].mV[0] = llgaussian(x, go.mV[0]);
- gauss[i].mV[1] = llgaussian(x, go.mV[1]);
- gauss[i].mV[2] = x;
- x += 1.f;
+ {
+ /*if (gCubeSnapshot)
+ { // SSAO and shadows disabled in reflection maps
+ deferred_light_target->bindTarget();
+ glClearColor(1, 1, 1, 1);
+ deferred_light_target->clear();
+ glClearColor(0, 0, 0, 0);
+ deferred_light_target->flush();
}
-
- gDeferredBlurLightProgram.uniform2f(sDelta, 1.f, 0.f);
- gDeferredBlurLightProgram.uniform1f(sDistFactor, dist_factor);
- gDeferredBlurLightProgram.uniform3fv(sKern, kern_length, gauss[0].mV);
- gDeferredBlurLightProgram.uniform1f(sKernScale, blur_size * (kern_length / 2.f - 0.5f));
-
+ else*/
{
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- stop_glerror();
+ // soften direct lighting lightmap
+ LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - soften shadow");
+ LL_PROFILE_GPU_ZONE("soften shadow");
+ // blur lightmap
+ screen_target->bindTarget();
+ glClearColor(1, 1, 1, 1);
+ screen_target->clear(GL_COLOR_BUFFER_BIT);
+ glClearColor(0, 0, 0, 0);
+
+ bindDeferredShader(gDeferredBlurLightProgram);
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ LLVector3 go = RenderShadowGaussian;
+ const U32 kern_length = 4;
+ F32 blur_size = RenderShadowBlurSize;
+ F32 dist_factor = RenderShadowBlurDistFactor;
+
+ // sample symmetrically with the middle sample falling exactly on 0.0
+ F32 x = 0.f;
+
+ LLVector3 gauss[32]; // xweight, yweight, offset
+
+ for (U32 i = 0; i < kern_length; i++)
+ {
+ gauss[i].mV[0] = llgaussian(x, go.mV[0]);
+ gauss[i].mV[1] = llgaussian(x, go.mV[1]);
+ gauss[i].mV[2] = x;
+ x += 1.f;
+ }
+
+ gDeferredBlurLightProgram.uniform2f(sDelta, 1.f, 0.f);
+ gDeferredBlurLightProgram.uniform1f(sDistFactor, dist_factor);
+ gDeferredBlurLightProgram.uniform3fv(sKern, kern_length, gauss[0].mV);
+ gDeferredBlurLightProgram.uniform1f(sKernScale, blur_size * (kern_length / 2.f - 0.5f));
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
+ }
+
+ screen_target->flush();
+ unbindDeferredShader(gDeferredBlurLightProgram);
+
+ bindDeferredShader(gDeferredBlurLightProgram, screen_target);
+
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ deferred_light_target->bindTarget();
+
+ gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, 1.f);
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
+ }
+ deferred_light_target->flush();
+ unbindDeferredShader(gDeferredBlurLightProgram);
}
-
- screen_target->flush();
- unbindDeferredShader(gDeferredBlurLightProgram);
-
- bindDeferredShader(gDeferredBlurLightProgram, screen_target);
-
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- deferred_light_target->bindTarget();
-
- gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, 1.f);
-
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- stop_glerror();
- }
- deferred_light_target->flush();
- unbindDeferredShader(gDeferredBlurLightProgram);
}
stop_glerror();
@@ -8857,6 +8908,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
LLGLSLShader &soften_shader = LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram;
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - atmospherics");
+ LL_PROFILE_GPU_ZONE("atmospherics");
bindDeferredShader(soften_shader);
LLEnvironment &environment = LLEnvironment::instance();
@@ -8903,7 +8955,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
gPipeline.popRenderTypeMask();
}
- bool render_local = RenderLocalLights;
+ bool render_local = RenderLocalLights; // && !gCubeSnapshot;
if (render_local)
{
@@ -8912,9 +8964,12 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
LLDrawable::drawable_list_t spot_lights;
LLDrawable::drawable_list_t fullscreen_spot_lights;
- for (U32 i = 0; i < 2; i++)
+ if (!gCubeSnapshot)
{
- mTargetShadowSpotLight[i] = NULL;
+ for (U32 i = 0; i < 2; i++)
+ {
+ mTargetShadowSpotLight[i] = NULL;
+ }
}
std::list light_colors;
@@ -8923,6 +8978,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - local lights");
+ LL_PROFILE_GPU_ZONE("local lights");
bindDeferredShader(gDeferredLightProgram);
if (mCubeVB.isNull())
@@ -9029,6 +9085,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
if (!spot_lights.empty())
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - projectors");
+ LL_PROFILE_GPU_ZONE("projectors");
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
bindDeferredShader(gDeferredSpotLightProgram);
@@ -9075,7 +9132,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - fullscreen lights");
LLGLDepthTest depth(GL_FALSE);
-
+ LL_PROFILE_GPU_ZONE("fullscreen lights");
// full screen blit
gGL.pushMatrix();
gGL.loadIdentity();
@@ -9171,6 +9228,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
gGL.loadIdentity();
{
+ LL_PROFILE_GPU_ZONE("gamma correct");
LLGLDepthTest depth(GL_FALSE, GL_FALSE);
LLVector2 tc1(0, 0);
@@ -9254,6 +9312,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
popRenderTypeMask();
}
+ if (!gCubeSnapshot)
{
// render highlights, etc.
renderHighlights();
@@ -9365,6 +9424,7 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f);
}
+ if (!gCubeSnapshot)
{
LLDrawable* potential = drawablep;
//determine if this is a good light for casting shadows
@@ -9416,9 +9476,9 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
{
- LLRenderTarget* deferred_target = &mDeferredScreen;
- LLRenderTarget* deferred_depth_target = &mDeferredDepth;
- LLRenderTarget* deferred_light_target = &mDeferredLight;
+ LLRenderTarget* deferred_target = &mRT->deferredScreen;
+ LLRenderTarget* deferred_depth_target = &mRT->deferredDepth;
+ LLRenderTarget* deferred_light_target = &mRT->deferredLight;
stop_glerror();
shader.disableTexture(LLShaderMgr::DEFERRED_NORMAL, deferred_target->getUsage());
@@ -9457,11 +9517,47 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
cube_map->disable();
}
}
+
+ unbindReflectionProbes(shader);
+
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(0)->activate();
shader.unbind();
}
+void LLPipeline::bindReflectionProbes(LLGLSLShader& shader)
+{
+ S32 channel = shader.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
+ if (channel > -1 && mReflectionMapManager.mTexture.notNull())
+ {
+ // see comments in class2/deferred/softenLightF.glsl for what these uniforms mean
+ mReflectionMapManager.mTexture->bind(channel);
+ mReflectionMapManager.setUniforms();
+
+ F32* m = gGLModelView;
+
+ F32 mat[] = { m[0], m[1], m[2],
+ m[4], m[5], m[6],
+ m[8], m[9], m[10] };
+
+ shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat);
+ }
+}
+
+void LLPipeline::unbindReflectionProbes(LLGLSLShader& shader)
+{
+ S32 channel = shader.disableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP);
+ if (channel > -1 && mReflectionMapManager.mTexture.notNull())
+ {
+ mReflectionMapManager.mTexture->unbind();
+ if (channel == 0)
+ {
+ gGL.getTexUnit(channel)->enable(LLTexUnit::TT_TEXTURE);
+ }
+ }
+}
+
+
inline float sgn(float a)
{
if (a > 0.0F) return (1.0F);
@@ -9472,8 +9568,9 @@ inline float sgn(float a)
void LLPipeline::generateWaterReflection(LLCamera& camera_in)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ LL_PROFILE_GPU_ZONE("generateWaterReflection");
- if (!assertInitialized())
+ if (!assertInitialized() || gCubeSnapshot)
{
return;
}
@@ -9918,7 +10015,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
gDeferredShadowCubeProgram.bind();
}
- LLRenderTarget& occlusion_target = mShadowOcclusion[LLViewerCamera::sCurCameraID - 1];
+ LLRenderTarget& occlusion_target = mRT->shadowOcclusion[LLViewerCamera::sCurCameraID - 1];
occlusion_target.bindTarget();
updateCull(shadow_cam, result);
@@ -10062,9 +10159,12 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
gGLLastMatrix = NULL;
gGL.loadMatrix(gGLModelView);
- LLRenderTarget& occlusion_source = mShadow[LLViewerCamera::sCurCameraID - 1];
+ LLRenderTarget& occlusion_source = mRT->shadow[LLViewerCamera::sCurCameraID - 1];
- doOcclusion(shadow_cam, occlusion_source, occlusion_target);
+ if (occlude > 1)
+ {
+ doOcclusion(shadow_cam, occlusion_source, occlusion_target);
+ }
if (use_shader)
{
@@ -10285,7 +10385,8 @@ void LLPipeline::generateHighlight(LLCamera& camera)
{
mHighlightSet.insert(HighlightItem(mHighlightObject));
}
-
+ llassert(!gCubeSnapshot);
+
if (!mHighlightSet.empty())
{
F32 transition = gFrameIntervalSeconds.value()/RenderHighlightFadeTime;
@@ -10335,7 +10436,7 @@ void LLPipeline::generateHighlight(LLCamera& camera)
LLRenderTarget* LLPipeline::getShadowTarget(U32 i)
{
- return &mShadow[i];
+ return &mRT->shadow[i];
}
static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW("Gen Sun Shadow");
@@ -10349,6 +10450,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
}
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_GEN_SUN_SHADOW);
+ LL_PROFILE_GPU_ZONE("generateSunShadow");
bool skip_avatar_update = false;
if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
@@ -10460,6 +10562,12 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
clip = RenderShadowOrthoClipPlanes;
mSunOrthoClipPlanes = LLVector4(clip, clip.mV[2]*clip.mV[2]/clip.mV[1]);
+ //if (gCubeSnapshot)
+ { //always do a single 64m shadow in reflection maps
+ mSunClipPlanes.set(64.f, 128.f, 256.f);
+ mSunOrthoClipPlanes.set(64.f, 128.f, 256.f);
+ }
+
//currently used for amount to extrude frusta corners for constructing shadow frusta
//LLVector3 n = RenderShadowNearDist;
//F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] };
@@ -10576,21 +10684,34 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
// convenience array of 4 near clip plane distances
F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
-
if (mSunDiffuse == LLColor4::black)
- { //sun diffuse is totally black, shadows don't matter
+ { //sun diffuse is totally shadows don't matter
LLGLDepthTest depth(GL_TRUE);
for (S32 j = 0; j < 4; j++)
{
- mShadow[j].bindTarget();
- mShadow[j].clear();
- mShadow[j].flush();
+ mRT->shadow[j].bindTarget();
+ mRT->shadow[j].clear();
+ mRT->shadow[j].flush();
}
}
else
{
- for (S32 j = 0; j < 4; j++)
+ /*if (gCubeSnapshot)
+ {
+ // do one shadow split for cube snapshots, clear the rest
+ mSunClipPlanes.set(64.f, 64.f, 64.f);
+ dist[1] = dist[2] = dist[3] = dist[4] = 64.f;
+ for (S32 j = 1; j < 4; j++)
+ {
+ mRT->shadow[j].bindTarget();
+ mRT->shadow[j].clear();
+ mRT->shadow[j].flush();
+ }
+ }*/
+
+ //for (S32 j = 0; j < (gCubeSnapshot ? 1 : 4); j++)
+ for (S32 j = 0; j < 4; j++)
{
if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
{
@@ -10651,12 +10772,12 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
mShadowCamera[j+4] = shadow_cam;
}
- mShadow[j].bindTarget();
+ mRT->shadow[j].bindTarget();
{
LLGLDepthTest depth(GL_TRUE);
- mShadow[j].clear();
+ mRT->shadow[j].clear();
}
- mShadow[j].flush();
+ mRT->shadow[j].flush();
mShadowError.mV[j] = 0.f;
mShadowFOV.mV[j] = 0.f;
@@ -10943,18 +11064,18 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
stop_glerror();
- mShadow[j].bindTarget();
- mShadow[j].getViewport(gGLViewport);
- mShadow[j].clear();
+ mRT->shadow[j].bindTarget();
+ mRT->shadow[j].getViewport(gGLViewport);
+ mRT->shadow[j].clear();
- U32 target_width = mShadow[j].getWidth();
+ U32 target_width = mRT->shadow[j].getWidth();
{
static LLCullResult result[4];
renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE, FALSE, target_width);
}
- mShadow[j].flush();
+ mRT->shadow[j].flush();
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
@@ -10969,142 +11090,145 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
if (gen_shadow)
{
- LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat();
- F32 fade_amt = gFrameIntervalSeconds.value()
- * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0);
+ if (!gCubeSnapshot) //skip updating spot shadow maps during cubemap updates
+ {
+ LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat();
+ F32 fade_amt = gFrameIntervalSeconds.value()
+ * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0);
- //update shadow targets
- for (U32 i = 0; i < 2; i++)
- { //for each current shadow
- LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW4+i);
+ //update shadow targets
+ for (U32 i = 0; i < 2; i++)
+ { //for each current shadow
+ LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW4+i);
- if (mShadowSpotLight[i].notNull() &&
- (mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
- mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
- { //keep this spotlight
- mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f);
- }
- else
- { //fade out this light
- mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f);
+ if (mShadowSpotLight[i].notNull() &&
+ (mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
+ mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
+ { //keep this spotlight
+ mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f);
+ }
+ else
+ { //fade out this light
+ mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f);
- if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
- { //faded out, grab one of the pending spots (whichever one isn't already taken)
- if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2])
- {
- mShadowSpotLight[i] = mTargetShadowSpotLight[0];
- }
- else
- {
- mShadowSpotLight[i] = mTargetShadowSpotLight[1];
- }
- }
- }
- }
+ if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
+ { //faded out, grab one of the pending spots (whichever one isn't already taken)
+ if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2])
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[0];
+ }
+ else
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[1];
+ }
+ }
+ }
+ }
- for (S32 i = 0; i < 2; i++)
- {
- set_current_modelview(saved_view);
- set_current_projection(saved_proj);
+ for (S32 i = 0; i < 2; i++)
+ {
+ set_current_modelview(saved_view);
+ set_current_projection(saved_proj);
- if (mShadowSpotLight[i].isNull())
- {
- continue;
- }
+ if (mShadowSpotLight[i].isNull())
+ {
+ continue;
+ }
- LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
+ LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
- if (!volume)
- {
- mShadowSpotLight[i] = NULL;
- continue;
- }
+ if (!volume)
+ {
+ mShadowSpotLight[i] = NULL;
+ continue;
+ }
- LLDrawable* drawable = mShadowSpotLight[i];
+ LLDrawable* drawable = mShadowSpotLight[i];
- LLVector3 params = volume->getSpotLightParams();
- F32 fov = params.mV[0];
+ LLVector3 params = volume->getSpotLightParams();
+ F32 fov = params.mV[0];
- //get agent->light space matrix (modelview)
- LLVector3 center = drawable->getPositionAgent();
- LLQuaternion quat = volume->getRenderRotation();
+ //get agent->light space matrix (modelview)
+ LLVector3 center = drawable->getPositionAgent();
+ LLQuaternion quat = volume->getRenderRotation();
- //get near clip plane
- LLVector3 scale = volume->getScale();
- LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
- at_axis *= quat;
+ //get near clip plane
+ LLVector3 scale = volume->getScale();
+ LLVector3 at_axis(0, 0, -scale.mV[2] * 0.5f);
+ at_axis *= quat;
- LLVector3 np = center+at_axis;
- at_axis.normVec();
+ LLVector3 np = center + at_axis;
+ at_axis.normVec();
- //get origin that has given fov for plane np, at_axis, and given scale
- F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
+ //get origin that has given fov for plane np, at_axis, and given scale
+ F32 dist = (scale.mV[1] * 0.5f) / tanf(fov * 0.5f);
- LLVector3 origin = np - at_axis*dist;
+ LLVector3 origin = np - at_axis * dist;
- LLMatrix4 mat(quat, LLVector4(origin, 1.f));
+ LLMatrix4 mat(quat, LLVector4(origin, 1.f));
- view[i+4] = glh::matrix4f((F32*) mat.mMatrix);
+ view[i + 4] = glh::matrix4f((F32*)mat.mMatrix);
- view[i+4] = view[i+4].inverse();
+ view[i + 4] = view[i + 4].inverse();
- //get perspective matrix
- F32 near_clip = dist+0.01f;
- F32 width = scale.mV[VX];
- F32 height = scale.mV[VY];
- F32 far_clip = dist+volume->getLightRadius()*1.5f;
+ //get perspective matrix
+ F32 near_clip = dist + 0.01f;
+ F32 width = scale.mV[VX];
+ F32 height = scale.mV[VY];
+ F32 far_clip = dist + volume->getLightRadius() * 1.5f;
- F32 fovy = fov * RAD_TO_DEG;
- F32 aspect = width/height;
-
- proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip);
+ F32 fovy = fov * RAD_TO_DEG;
+ F32 aspect = width / height;
- //translate and scale to from [-1, 1] to [0, 1]
- glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
- 0.f, 0.5f, 0.f, 0.5f,
- 0.f, 0.f, 0.5f, 0.5f,
- 0.f, 0.f, 0.f, 1.f);
+ proj[i + 4] = gl_perspective(fovy, aspect, near_clip, far_clip);
- set_current_modelview(view[i+4]);
- set_current_projection(proj[i+4]);
+ //translate and scale to from [-1, 1] to [0, 1]
+ glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
- mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view;
-
- for (U32 j = 0; j < 16; j++)
- {
- gGLLastModelView[j] = mShadowModelview[i+4].m[j];
- gGLLastProjection[j] = mShadowProjection[i+4].m[j];
- }
+ set_current_modelview(view[i + 4]);
+ set_current_projection(proj[i + 4]);
- mShadowModelview[i+4] = view[i+4];
- mShadowProjection[i+4] = proj[i+4];
+ mSunShadowMatrix[i + 4] = trans * proj[i + 4] * view[i + 4] * inv_view;
- LLCamera shadow_cam = camera;
- shadow_cam.setFar(far_clip);
- shadow_cam.setOrigin(origin);
+ for (U32 j = 0; j < 16; j++)
+ {
+ gGLLastModelView[j] = mShadowModelview[i + 4].m[j];
+ gGLLastProjection[j] = mShadowProjection[i + 4].m[j];
+ }
- LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+ mShadowModelview[i + 4] = view[i + 4];
+ mShadowProjection[i + 4] = proj[i + 4];
- stop_glerror();
+ LLCamera shadow_cam = camera;
+ shadow_cam.setFar(far_clip);
+ shadow_cam.setOrigin(origin);
- mShadow[i+4].bindTarget();
- mShadow[i+4].getViewport(gGLViewport);
- mShadow[i+4].clear();
+ LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
- U32 target_width = mShadow[i+4].getWidth();
+ stop_glerror();
- static LLCullResult result[2];
+ mRT->shadow[i + 4].bindTarget();
+ mRT->shadow[i + 4].getViewport(gGLViewport);
+ mRT->shadow[i + 4].clear();
- LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0 + i + 4);
+ U32 target_width = mRT->shadow[i + 4].getWidth();
- RenderSpotLight = drawable;
+ static LLCullResult result[2];
- renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE, target_width);
+ LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0 + i + 4);
- RenderSpotLight = nullptr;
+ RenderSpotLight = drawable;
- mShadow[i+4].flush();
- }
+ renderShadow(view[i + 4], proj[i + 4], shadow_cam, result[i], FALSE, FALSE, target_width);
+
+ RenderSpotLight = nullptr;
+
+ mRT->shadow[i + 4].flush();
+ }
+ }
}
else
{ //no spotlight shadows
@@ -11177,6 +11301,7 @@ static LLTrace::BlockTimerStatHandle FTM_GENERATE_IMPOSTOR("Generate Impostor");
void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
{
LL_RECORD_BLOCK_TIME(FTM_GENERATE_IMPOSTOR);
+ LL_PROFILE_GPU_ZONE("generateImpostor");
LLGLState::checkStates();
LLGLState::checkTextureChannels();
@@ -11422,7 +11547,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
if (LLPipeline::sRenderDeferred)
{
GLuint buff = GL_COLOR_ATTACHMENT0;
- LL_PROFILER_GPU_ZONEC( "gl.DrawBuffersARB", 0x8000FF );
glDrawBuffersARB(1, &buff);
}
@@ -11837,6 +11961,12 @@ void LLPipeline::restoreHiddenObject( const LLUUID& id )
}
}
+void LLPipeline::overrideEnvironmentMap()
+{
+ //mReflectionMapManager.mProbes.clear();
+ //mReflectionMapManager.addProbe(LLViewerCamera::instance().getOrigin());
+}
+
// Reset VB during TP
void LLPipeline::initDeferredVB()
{
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 70c4c4884e..eb9557e31f 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -38,6 +38,7 @@
#include "llgl.h"
#include "lldrawable.h"
#include "llrendertarget.h"
+#include "llreflectionmapmanager.h"
#include
@@ -293,6 +294,10 @@ public:
void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep);
void unbindDeferredShader(LLGLSLShader& shader);
+
+ void bindReflectionProbes(LLGLSLShader& shader);
+ void unbindReflectionProbes(LLGLSLShader& shader);
+
void renderDeferredLighting(LLRenderTarget* light_target);
void postDeferredGammaCorrect(LLRenderTarget* screen_target);
@@ -426,6 +431,9 @@ public:
void hideObject( const LLUUID& id );
void restoreHiddenObject( const LLUUID& id );
+ LLReflectionMapManager mReflectionMapManager;
+ void overrideEnvironmentMap();
+
private:
void unloadShaders();
void addToQuickLookup( LLDrawPool* new_poolp );
@@ -585,7 +593,8 @@ public:
RENDER_DEBUG_TEXEL_DENSITY = 0x40000000,
RENDER_DEBUG_TRIANGLE_COUNT = 0x80000000,
RENDER_DEBUG_IMPOSTORS = 0x100000000,
- RENDER_DEBUG_TEXTURE_SIZE = 0x200000000
+ RENDER_DEBUG_REFLECTION_PROBES = 0x200000000,
+ RENDER_DEBUG_TEXTURE_SIZE = 0x400000000
};
public:
@@ -653,20 +662,31 @@ public:
static LLTrace::EventStatHandle sStatBatchSize;
- //screen texture
- U32 mScreenWidth;
- U32 mScreenHeight;
-
- LLRenderTarget mScreen;
- LLRenderTarget mUIScreen;
- LLRenderTarget mDeferredScreen;
- LLRenderTarget mFXAABuffer;
- LLRenderTarget mEdgeMap;
- LLRenderTarget mDeferredDepth;
- LLRenderTarget mOcclusionDepth;
- LLRenderTarget mDeferredLight;
- LLRenderTarget mHighlight;
- LLRenderTarget mPhysicsDisplay;
+ class RenderTargetPack
+ {
+ public:
+ U32 width = 0;
+ U32 height = 0;
+
+ //screen texture
+ LLRenderTarget screen;
+ LLRenderTarget uiScreen;
+ LLRenderTarget deferredScreen;
+ LLRenderTarget fxaaBuffer;
+ LLRenderTarget edgeMap;
+ LLRenderTarget deferredDepth;
+ LLRenderTarget occlusionDepth;
+ LLRenderTarget deferredLight;
+
+ //sun shadow map
+ LLRenderTarget shadow[6];
+ LLRenderTarget shadowOcclusion[6];
+ };
+
+ RenderTargetPack* mRT;
+
+ LLRenderTarget mHighlight;
+ LLRenderTarget mPhysicsDisplay;
LLCullResult mSky;
LLCullResult mReflectedObjects;
@@ -681,9 +701,8 @@ public:
// FIRE-16829: Visual Artifacts with ALM enabled on AMD graphics
LLPointer mAuxiliaryVB;
- //sun shadow map
- LLRenderTarget mShadow[6];
- LLRenderTarget mShadowOcclusion[6];
+ //list of currently bound reflection maps
+ std::vector mReflectionMaps;
std::vector mShadowFrustPoints[4];
LLVector4 mShadowError;
@@ -894,6 +913,7 @@ protected:
LLDrawPool* mBumpPool;
LLDrawPool* mMaterialsPool;
LLDrawPool* mWLSkyPool;
+ LLDrawPool* mPBROpaquePool;
// Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar
public:
diff --git a/indra/newview/rlveffects.cpp b/indra/newview/rlveffects.cpp
index 1767bd6476..a189cd9bb4 100644
--- a/indra/newview/rlveffects.cpp
+++ b/indra/newview/rlveffects.cpp
@@ -299,7 +299,7 @@ ERlvCmdRet RlvSphereEffect::onValueMaxChanged(const LLUUID& idRlvObj, const boos
void RlvSphereEffect::setShaderUniforms(LLGLSLShader* pShader)
{
pShader->uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, get_current_projection().inverse().m);
- pShader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, gPipeline.mScreen.getWidth(), gPipeline.mScreen.getHeight());
+ pShader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, gPipeline.mRT->screen.getWidth(), gPipeline.mRT->screen.getHeight());
pShader->uniform1i(LLShaderMgr::RLV_EFFECT_MODE, llclamp((int)m_eMode, 0, (int)ESphereMode::Count));
// Pass the sphere origin to the shader
@@ -356,10 +356,10 @@ void RlvSphereEffect::renderPass(LLGLSLShader* pShader, const LLShaderEffectPara
gGL.getTexUnit(nDiffuseChannel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
- S32 nDepthChannel = pShader->enableTexture(LLShaderMgr::DEFERRED_DEPTH, gPipeline.mDeferredDepth.getUsage());
+ S32 nDepthChannel = pShader->enableTexture(LLShaderMgr::DEFERRED_DEPTH, gPipeline.mRT->deferredDepth.getUsage());
if (nDepthChannel > -1)
{
- gGL.getTexUnit(nDepthChannel)->bind(&gPipeline.mDeferredDepth, TRUE);
+ gGL.getTexUnit(nDepthChannel)->bind(&gPipeline.mRT->deferredDepth, TRUE);
}
gGL.matrixMode(LLRender::MM_PROJECTION);
@@ -370,7 +370,7 @@ void RlvSphereEffect::renderPass(LLGLSLShader* pShader, const LLShaderEffectPara
gGL.loadMatrix(gGLModelView);
LLVector2 tc1(0, 0);
- LLVector2 tc2((F32)gPipeline.mScreen.getWidth() * 2, (F32)gPipeline.mScreen.getHeight() * 2);
+ LLVector2 tc2((F32)gPipeline.mRT->screen.getWidth() * 2, (F32)gPipeline.mRT->screen.getHeight() * 2);
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
gGL.vertex2f(-1, -1);
@@ -386,7 +386,7 @@ void RlvSphereEffect::renderPass(LLGLSLShader* pShader, const LLShaderEffectPara
gGL.popMatrix();
pShader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, pParams->m_pSrcBuffer->getUsage());
- pShader->disableTexture(LLShaderMgr::DEFERRED_DEPTH, gPipeline.mDeferredDepth.getUsage());
+ pShader->disableTexture(LLShaderMgr::DEFERRED_DEPTH, gPipeline.mRT->deferredDepth.getUsage());
if (pParams->m_pDstBuffer)
{
diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp
index beebf94dc5..9c18600728 100644
--- a/indra/newview/rlvhandler.cpp
+++ b/indra/newview/rlvhandler.cpp
@@ -2167,12 +2167,12 @@ ERlvCmdRet RlvBehaviourHandler::onCommand(const RlvCommand&
gPipeline.resetVertexBuffers();
LLViewerShaderMgr::instance()->setShaders();
}
- else if (!gPipeline.mDeferredLight.isComplete())
+ else if (!gPipeline.mRT->deferredLight.isComplete())
{
// In case of deferred with no shadows, no ambient occlusion, no depth of field, and no antialiasing
gPipeline.releaseGLBuffers();
gPipeline.createGLBuffers();
- RLV_ASSERT(gPipeline.mDeferredLight.isComplete());
+ RLV_ASSERT(gPipeline.mRT->deferredLight.isComplete());
}
}
else
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 70455d3d0c..3cac8b0e0b 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -4171,6 +4171,16 @@
function="Advanced.ToggleInfoDisplay"
parameter="lights" />
+
+
+
+
@@ -4526,6 +4536,13 @@
function="ToggleControl"
parameter="RenderHoverGlowEnable" />
+
+
+
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 383f7dad44..dc052413b8 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -13756,6 +13756,13 @@ Unpacking: [UNPACK_TIME]s [USIZE]KB
+
+Material successfully created. Asset ID: [ASSET_ID]
+
+
-
+
+
+
+