Merge branch 'DRTVWR-559' of https://bitbucket.org/lindenlab/viewer
commit
3765c775cb
|
|
@ -1386,9 +1386,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>1bd3214ac23474ea4c869e386970a1be</string>
|
||||
<string>c5e9a59c7cf03c88a5cb4ab0a9c21091</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54835/510029/glext-68-darwin64-538965.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/99835/880141/glext-68-darwin64-571812.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -3454,11 +3454,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>b649ee6591e67d2341e886b3fc3484a7</string>
|
||||
<string>dff3dd1db6a4cb0b73f60a5db3ee0de2</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/86974/801642/tracy-v0.7.8.563351-windows64-563351.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/100101/882119/tracy-v0.8.1.571983-windows64-571983.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
|
|
|
|||
|
|
@ -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 "")
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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: |
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -88,8 +88,8 @@ extern thread_local bool gProfilerEnabled;
|
|||
// <FS:Beq> 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)
|
||||
|
||||
// <FS:Beq> Additional FS Tracy macros
|
||||
#define LL_PROFILE_ZONE_COLOR(color) ZoneNamedC( ___tracy_scoped_zone, color, gProfilerEnabled ) // <FS:Beq/> 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);
|
||||
// <FS:Beq> 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)
|
||||
// <FS:Beq> 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;
|
|||
// </FS:Ansariel>
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -93,10 +93,12 @@ public:
|
|||
|
||||
FT_SETTINGS = 56,
|
||||
|
||||
FT_MATERIAL = 57,
|
||||
|
||||
// <FS:Ansariel> 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,
|
||||
// </FS:Ansariel> Folder types for our own virtual system folders
|
||||
|
||||
FT_MY_SUITCASE = 100, // <FS:Ansariel> 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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@
|
|||
#ifndef LL_LLMATERIAL_H
|
||||
#define LL_LLMATERIAL_H
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#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;
|
||||
|
|
|
|||
|
|
@ -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<const LLRenderMaterialParams&>(data);
|
||||
|
||||
return param.mMaterial == mMaterial;
|
||||
}
|
||||
|
||||
void LLRenderMaterialParams::copy(const LLNetworkData& data)
|
||||
{
|
||||
llassert_always(data.mType == PARAMS_RENDER_MATERIAL);
|
||||
const LLRenderMaterialParams ¶m = static_cast<const LLRenderMaterialParams&>(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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<LLPointer<LLImageRaw> >& 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<LLPointer<LLImageRaw> >& 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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,6 +40,17 @@ class LLCubeMap : public LLRefCount
|
|||
public:
|
||||
LLCubeMap(bool init_as_srgb);
|
||||
void init(const std::vector<LLPointer<LLImageRaw> >& 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<LLPointer<LLImageRaw> >& rawimages);
|
||||
void initGL();
|
||||
void initRawData(const std::vector<LLPointer<LLImageRaw> >& 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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 <vector>
|
||||
|
||||
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<LLImageGL> mImage;
|
||||
S32 mTextureStage;
|
||||
};
|
||||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ public:
|
|||
BOOL mHasTextureRectangle;
|
||||
BOOL mHasTextureMultisample;
|
||||
BOOL mHasTransformFeedback;
|
||||
BOOL mHasUniformBufferObject;
|
||||
S32 mMaxSampleMaskWords;
|
||||
S32 mMaxColorTextureSamples;
|
||||
S32 mMaxDepthTextureSamples;
|
||||
|
|
|
|||
|
|
@ -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 <tracy/TracyOpenGL.hpp>
|
||||
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -746,7 +746,7 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
|
|||
{
|
||||
//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<LLStaticHashedString> *
|
|||
{
|
||||
//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<LLStaticHashedString> * 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<LLStaticHashedString> * uniforms)
|
|||
S32 bumpMap = glGetUniformLocationARB(mProgramObject, "bumpMap");
|
||||
S32 altDiffuseMap = glGetUniformLocationARB(mProgramObject, "altDiffuseMap");
|
||||
S32 environmentMap = glGetUniformLocationARB(mProgramObject, "environmentMap");
|
||||
S32 reflectionMap = glGetUniformLocationARB(mProgramObject, "reflectionMap");
|
||||
|
||||
std::set<S32> skip_index;
|
||||
|
||||
|
|
@ -890,6 +916,12 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * 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<LLStaticHashedString> * 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<LLStaticHashedString> * 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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ static const GLenum sGLTextureType[] =
|
|||
GL_TEXTURE_RECTANGLE,
|
||||
// </FS:Ansariel>
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
6.6.0
|
||||
6.6.1
|
||||
|
|
|
|||
|
|
@ -13288,7 +13288,41 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<integer>2</integer>
|
||||
</map>
|
||||
|
||||
<key>RenderReflectionRes</key>
|
||||
<key>RenderReflectionProbeDrawDistance</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Camera far clip to use when updating reflection probes.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>64</real>
|
||||
</map>
|
||||
<key>RenderReflectionProbeAmbiance</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Amount reflection probes contribute to ambient light.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0</real>
|
||||
</map>
|
||||
<key>RenderReflectionProbeTextureHackID</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>HACK -- Any object with a diffuse texture with this ID will be treated as a user override reflection probe. (default is "Violet Info Hub" photo from Library)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>6b186931-05da-eafa-a3ed-a012a33bbfb6</string>
|
||||
</map>
|
||||
|
||||
<key>RenderReflectionRes</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Reflection map resolution.</string>
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@ uniform sampler2DRect depthMap;
|
|||
|
||||
uniform float ssao_radius;
|
||||
uniform float ssao_max_radius;
|
||||
uniform float ssao_factor;
|
||||
uniform float ssao_factor_inv;
|
||||
|
||||
uniform mat4 inv_proj;
|
||||
uniform vec2 screen_res;
|
||||
|
|
@ -83,14 +81,14 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen)
|
|||
{
|
||||
float ret = 1.0;
|
||||
vec3 pos_world = pos.xyz;
|
||||
vec2 noise_reflect = texture2D(noiseMap, pos_screen.xy/128.0).xy;
|
||||
|
||||
|
||||
float angle_hidden = 0.0;
|
||||
float points = 0;
|
||||
|
||||
float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
|
||||
|
||||
// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
|
||||
float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
|
||||
vec2 noise_reflect = texture2D(noiseMap, pos_screen.xy/128.0).xy;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
|
||||
|
|
@ -105,14 +103,14 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen)
|
|||
//(k should vary inversely with # of samples, but this is taken care of later)
|
||||
|
||||
float funky_val = (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) ? 1.0 : 0.0;
|
||||
angle_hidden = angle_hidden + funky_val * min(1.0/dist2, ssao_factor_inv);
|
||||
angle_hidden = angle_hidden + funky_val * min(1.0/dist2, 1.0);
|
||||
|
||||
// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
|
||||
float diffz_val = (diff.z > -1.0) ? 1.0 : 0.0;
|
||||
points = points + diffz_val;
|
||||
}
|
||||
|
||||
angle_hidden = min(ssao_factor*angle_hidden/points, 1.0);
|
||||
|
||||
angle_hidden = min(angle_hidden/points, 1.0);
|
||||
|
||||
float points_val = (points > 0.0) ? 1.0 : 0.0;
|
||||
ret = (1.0 - (points_val * angle_hidden));
|
||||
|
|
|
|||
|
|
@ -69,36 +69,47 @@ void main()
|
|||
tc_mod *= 2.0;
|
||||
tc += ( (tc_mod - 0.5) * kern[1].z * dlt * 0.5 );
|
||||
|
||||
for (int i = 1; i < 4; i++)
|
||||
// TODO: move this to kern instead of building kernel per pixel
|
||||
vec3 k[7];
|
||||
k[0] = kern[0];
|
||||
k[2] = kern[1];
|
||||
k[4] = kern[2];
|
||||
k[6] = kern[3];
|
||||
|
||||
k[1] = (k[0]+k[2])*0.5f;
|
||||
k[3] = (k[2]+k[4])*0.5f;
|
||||
k[5] = (k[4]+k[6])*0.5f;
|
||||
|
||||
for (int i = 1; i < 7; i++)
|
||||
{
|
||||
vec2 samptc = tc + kern[i].z*dlt;
|
||||
vec2 samptc = tc + k[i].z*dlt*2.0;
|
||||
vec3 samppos = getPosition(samptc).xyz;
|
||||
|
||||
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
|
||||
|
||||
if (d*d <= pointplanedist_tolerance_pow2)
|
||||
{
|
||||
col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
|
||||
defined_weight += kern[i].xy;
|
||||
col += texture2DRect(lightMap, samptc)*k[i].xyxx;
|
||||
defined_weight += k[i].xy;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < 4; i++)
|
||||
for (int i = 1; i < 7; i++)
|
||||
{
|
||||
vec2 samptc = tc - kern[i].z*dlt;
|
||||
vec2 samptc = tc - k[i].z*dlt*2.0;
|
||||
vec3 samppos = getPosition(samptc).xyz;
|
||||
|
||||
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
|
||||
|
||||
if (d*d <= pointplanedist_tolerance_pow2)
|
||||
{
|
||||
col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
|
||||
defined_weight += kern[i].xy;
|
||||
col += texture2DRect(lightMap, samptc)*k[i].xyxx;
|
||||
defined_weight += k[i].xy;
|
||||
}
|
||||
}
|
||||
|
||||
col /= defined_weight.xyxx;
|
||||
col.y *= col.y;
|
||||
//col.y *= max(col.y, 0.75);
|
||||
|
||||
frag_color = col;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,10 +35,11 @@ out vec4 frag_color;
|
|||
uniform sampler2D diffuseMap;
|
||||
#endif
|
||||
|
||||
|
||||
VARYING vec4 vertex_color;
|
||||
VARYING vec2 vary_texcoord0;
|
||||
VARYING vec3 vary_texcoord1;
|
||||
VARYING vec4 vary_position;
|
||||
VARYING vec3 vary_position;
|
||||
|
||||
uniform samplerCube environmentMap;
|
||||
|
||||
|
|
@ -54,6 +55,14 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou
|
|||
vec3 linear_to_srgb(vec3 c);
|
||||
vec3 srgb_to_linear(vec3 c);
|
||||
|
||||
#ifdef HAS_REFLECTION_PROBES
|
||||
// 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);
|
||||
#endif
|
||||
|
||||
// See:
|
||||
// class1\deferred\fullbrightShinyF.glsl
|
||||
// class1\lighting\lightFullbrightShinyF.glsl
|
||||
|
|
@ -70,21 +79,29 @@ void main()
|
|||
// SL-9632 HUDs are affected by Atmosphere
|
||||
if (no_atmo == 0)
|
||||
{
|
||||
vec3 sunlit;
|
||||
vec3 amblit;
|
||||
vec3 additive;
|
||||
vec3 atten;
|
||||
vec3 pos = vary_position.xyz/vary_position.w;
|
||||
vec3 sunlit;
|
||||
vec3 amblit;
|
||||
vec3 additive;
|
||||
vec3 atten;
|
||||
vec3 pos = vary_position;
|
||||
calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false);
|
||||
|
||||
calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false);
|
||||
|
||||
vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
|
||||
float env_intensity = vertex_color.a;
|
||||
|
||||
//color.rgb = srgb_to_linear(color.rgb);
|
||||
color.rgb = mix(color.rgb, envColor.rgb, env_intensity);
|
||||
color.rgb = fullbrightAtmosTransportFrag(color.rgb, additive, atten);
|
||||
color.rgb = fullbrightScaleSoftClip(color.rgb);
|
||||
float env_intensity = vertex_color.a;
|
||||
#ifndef HAS_REFLECTION_PROBES
|
||||
vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
|
||||
color.rgb = mix(color.rgb, envColor.rgb, env_intensity);
|
||||
#else
|
||||
vec3 ambenv;
|
||||
vec3 glossenv;
|
||||
vec3 legacyenv;
|
||||
vec3 norm = normalize(vary_texcoord1.xyz);
|
||||
vec4 spec = vec4(0,0,0,0);
|
||||
sampleReflectionProbes(ambenv, glossenv, legacyenv, pos.xyz, norm.xyz, spec.a, env_intensity);
|
||||
legacyenv *= 1.5; // fudge brighter
|
||||
applyLegacyEnv(color.rgb, legacyenv, spec, pos, norm, env_intensity);
|
||||
#endif
|
||||
color.rgb = fullbrightAtmosTransportFrag(color.rgb, additive, atten);
|
||||
color.rgb = fullbrightScaleSoftClip(color.rgb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -98,7 +115,6 @@ void main()
|
|||
*/
|
||||
|
||||
color.a = 1.0;
|
||||
|
||||
//color.rgb = linear_to_srgb(color.rgb);
|
||||
|
||||
frag_color = color;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ ATTRIBUTE vec2 texcoord0;
|
|||
VARYING vec4 vertex_color;
|
||||
VARYING vec2 vary_texcoord0;
|
||||
VARYING vec3 vary_texcoord1;
|
||||
VARYING vec4 vary_position;
|
||||
VARYING vec3 vary_position;
|
||||
|
||||
#ifdef HAS_SKIN
|
||||
mat4 getObjectSkinnedTransform();
|
||||
|
|
@ -62,17 +62,23 @@ void main()
|
|||
mat4 mat = getObjectSkinnedTransform();
|
||||
mat = modelview_matrix * mat;
|
||||
vec4 pos = mat * vert;
|
||||
vary_position = gl_Position = projection_matrix * pos;
|
||||
gl_Position = projection_matrix * pos;
|
||||
vec3 norm = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz);
|
||||
#else
|
||||
vec4 pos = (modelview_matrix * vert);
|
||||
vary_position = gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
|
||||
gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
|
||||
vec3 norm = normalize(normal_matrix * normal);
|
||||
#endif
|
||||
vec3 ref = reflect(pos.xyz, -norm);
|
||||
|
||||
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
|
||||
vary_position = pos.xyz;
|
||||
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
|
||||
|
||||
#ifndef HAS_REFLECTION_PROBES
|
||||
vec3 ref = reflect(pos.xyz, -norm);
|
||||
vary_texcoord1 = (texture_matrix1 * vec4(ref,1.0)).xyz;
|
||||
#else
|
||||
vary_texcoord1 = norm;
|
||||
#endif
|
||||
|
||||
calcAtmospherics(pos.xyz);
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,13 @@ out vec4 frag_color;
|
|||
float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_REFLECTION_PROBES
|
||||
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);
|
||||
#endif
|
||||
|
||||
uniform samplerCube environmentMap;
|
||||
uniform sampler2D lightFunc;
|
||||
|
||||
|
|
@ -322,6 +329,16 @@ void main()
|
|||
// lighting from the sun stays sharp
|
||||
float da = clamp(dot(normalize(norm.xyz), light_dir.xyz), 0.0, 1.0);
|
||||
da = pow(da, 1.0 / 1.3);
|
||||
vec3 sun_contrib = min(da, shadow) * sunlit;
|
||||
|
||||
#ifdef HAS_REFLECTION_PROBES
|
||||
vec3 ambenv;
|
||||
vec3 glossenv;
|
||||
vec3 legacyenv;
|
||||
sampleReflectionProbes(ambenv, glossenv, legacyenv, pos.xyz, norm.xyz, spec.a, envIntensity);
|
||||
amblit = max(ambenv, amblit);
|
||||
color.rgb = amblit;
|
||||
#else
|
||||
|
||||
color = amblit;
|
||||
|
||||
|
|
@ -333,9 +350,8 @@ void main()
|
|||
ambient *= ambient;
|
||||
ambient = (1.0 - ambient);
|
||||
|
||||
vec3 sun_contrib = min(da, shadow) * sunlit;
|
||||
|
||||
color *= ambient;
|
||||
#endif
|
||||
|
||||
color += sun_contrib;
|
||||
|
||||
|
|
@ -345,35 +361,6 @@ void main()
|
|||
|
||||
if (spec.a > 0.0) // specular reflection
|
||||
{
|
||||
/* // Reverting this specular calculation to previous 'dumbshiny' version - DJH 6/17/2020
|
||||
// Preserving the refactored version as a comment for potential reconsideration,
|
||||
// overriding the general rule to avoid pollutiong the source with commented code.
|
||||
//
|
||||
// If you're reading this in 2021+, feel free to obliterate.
|
||||
|
||||
vec3 npos = -normalize(pos.xyz);
|
||||
|
||||
//vec3 ref = dot(pos+lv, norm);
|
||||
vec3 h = normalize(light_dir.xyz + npos);
|
||||
float nh = dot(norm.xyz, h);
|
||||
float nv = dot(norm.xyz, npos);
|
||||
float vh = dot(npos, h);
|
||||
float sa = nh;
|
||||
float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5;
|
||||
|
||||
float gtdenom = 2 * nh;
|
||||
float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
|
||||
|
||||
if (nh > 0.0)
|
||||
{
|
||||
float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt / (nh*da);
|
||||
vec3 sp = sun_contrib*scol / 6.0f;
|
||||
sp = clamp(sp, vec3(0), vec3(1));
|
||||
bloom = dot(sp, sp) / 4.0;
|
||||
color += sp * spec.rgb;
|
||||
}
|
||||
*/
|
||||
|
||||
float sa = dot(refnormpersp, sun_dir.xyz);
|
||||
vec3 dumbshiny = sunlit * shadow * (texture2D(lightFunc, vec2(sa, spec.a)).r);
|
||||
|
||||
|
|
@ -385,10 +372,24 @@ void main()
|
|||
glare = max(glare, spec_contrib.b);
|
||||
|
||||
color += spec_contrib;
|
||||
|
||||
#ifdef HAS_REFLECTION_PROBES
|
||||
applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
color = mix(color.rgb, diffcol.rgb, diffuse.a);
|
||||
|
||||
#ifdef HAS_REFLECTION_PROBES
|
||||
if (envIntensity > 0.0)
|
||||
{ // add environmentmap
|
||||
//fudge darker
|
||||
legacyenv *= 0.5*diffuse.a+0.5;
|
||||
|
||||
applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity);
|
||||
}
|
||||
#else
|
||||
if (envIntensity > 0.0)
|
||||
{
|
||||
//add environmentmap
|
||||
|
|
@ -403,6 +404,7 @@ void main()
|
|||
cur_glare *= envIntensity*4.0;
|
||||
glare += cur_glare;
|
||||
}
|
||||
#endif
|
||||
|
||||
color = atmosFragLighting(color, additive, atten);
|
||||
color = scaleSoftClipFrag(color);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ out vec4 frag_color;
|
|||
// uniform sampler2DRect depthMap; // <FS:Beq/> Colour space and shader fixes for BUG-228586 (Rye)
|
||||
uniform sampler2DRect diffuseRect;
|
||||
uniform sampler2DRect specularRect;
|
||||
// uniform samplerCube environmentMap;// <FS:Beq/> Colour space and shader fixes for BUG-228586 (Rye)
|
||||
uniform sampler2D noiseMap;
|
||||
uniform sampler2D lightFunc;
|
||||
|
||||
|
|
|
|||
|
|
@ -44,10 +44,6 @@ uniform sampler2DRect specularRect;
|
|||
// uniform sampler2DRect depthMap;
|
||||
// </FS:Beq>
|
||||
uniform sampler2DRect normalMap;
|
||||
// <FS:Beq> Colour space and shader fixes for BUG-228586 (Rye)
|
||||
// uniform samplerCube environmentMap;
|
||||
// </FS:Beq>
|
||||
|
||||
uniform sampler2D noiseMap;
|
||||
uniform sampler2D projectionMap;
|
||||
uniform sampler2D lightFunc;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -37,7 +37,6 @@ uniform sampler2DRect diffuseRect;
|
|||
uniform sampler2DRect specularRect;
|
||||
// <FS:Beq> Colour space and shader fixes for BUG-228586 (Rye)
|
||||
//uniform sampler2DRect normalMap;
|
||||
//uniform samplerCube environmentMap;
|
||||
// </FS:Beq>
|
||||
uniform sampler2D noiseMap;
|
||||
uniform sampler2D lightFunc;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -375,10 +375,10 @@ void LLFloaterModelPreview::initModelPreview()
|
|||
S32 tex_width = 512;
|
||||
S32 tex_height = 512;
|
||||
// <FS:Beq> 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);
|
||||
// </FS:Beq>
|
||||
|
||||
while ((tex_width << 1) <= max_width) // <FS:Beq/> Fix up regressions from LL's merge of uploader changes
|
||||
|
|
|
|||
|
|
@ -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<LLUICtrl>("materialID")->getValue().asUUID(); }
|
||||
|
||||
// <FS:CR> 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);
|
||||
|
||||
// <FS:CR>
|
||||
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);
|
||||
|
||||
// <FS:CR> 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<bool>(is_single_face));
|
||||
childSetEnabled("materialID", static_cast<bool>(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<LLPanelFace*>(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<LLBufferedAssetUploadInfo>(
|
||||
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<S32>(color.mV[0])));
|
||||
sd.insert("teSpecularColorG", LLSD(static_cast<S32>(color.mV[1])));
|
||||
sd.insert("teSpecularColorB", LLSD(static_cast<S32>(color.mV[2])));
|
||||
sd.insert("teSpecularColorA", LLSD(static_cast<S32>(color.mV[3])));
|
||||
sd.insert("teSpecularExponent", LLSD(static_cast<S32>(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<S32>(mat->getDiffuseAlphaMode())));
|
||||
sd.insert("teAlphaCutoff", LLSD(static_cast<S32>(mat->getAlphaMaskCutoff())));
|
||||
sd.insert("teEnvIntensity", LLSD(static_cast<S32>(mat->getEnvironmentIntensity())));
|
||||
sd.insert("teShaderMask", LLSD(static_cast<S32>(mat->getShaderMask())));
|
||||
}
|
||||
else
|
||||
{
|
||||
// pull data from the LLPanelFace
|
||||
LLPanelFace* instance = static_cast<LLPanelFace*>(userdata);
|
||||
sd.insert("pfNormalMap", LLSD(instance->getCurrentNormalMap()));
|
||||
sd.insert("pfSpecularMap", LLSD(instance->getCurrentSpecularMap()));
|
||||
sd.insert("pfShininess", LLSD(static_cast<S32>(instance->getCurrentShininess())));
|
||||
sd.insert("pfBumpiness", LLSD(static_cast<S32>(instance->getCurrentBumpiness())));
|
||||
sd.insert("pfAlphaMode", LLSD(static_cast<S32>(instance->getCurrentDiffuseAlphaMode())));
|
||||
sd.insert("pfAlphaCutoff", LLSD(static_cast<S32>(instance->getCurrentAlphaMaskCutoff())));
|
||||
sd.insert("pfEnvIntensity", LLSD(static_cast<S32>(instance->getCurrentEnvIntensity())));
|
||||
sd.insert("pfGlossiness", LLSD(static_cast<S32>(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<LLPanelFace*>(userdata);
|
||||
|
||||
LLFileSystem material_file(uuid, LLAssetType::AT_MATERIAL, LLFileSystem::READ);
|
||||
S32 bufsize = material_file.getSize();
|
||||
llassert(bufsize > 0);
|
||||
std::vector<U8> 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<U8>(matSD.get("teSecularColorR").asInteger());
|
||||
color.mV[1] = static_cast<U8>(matSD.get("teSecularColorG").asInteger());
|
||||
color.mV[2] = static_cast<U8>(matSD.get("teSecularColorB").asInteger());
|
||||
color.mV[3] = static_cast<U8>(matSD.get("teSecularColorA").asInteger());
|
||||
mat->setSpecularLightColor(color);
|
||||
mat->setSpecularLightExponent(static_cast<U8>(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<U8>(matSD.get("teAlphaMode").asInteger()));
|
||||
mat->setAlphaMaskCutoff(static_cast<U8>(matSD.get("teAlphaCutoff").asInteger()));
|
||||
mat->setEnvironmentIntensity(static_cast<U8>(matSD.get("teEnvIntensity").asInteger()));
|
||||
//mat->setShaderMask(static_cast<U32>(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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
// <FS> Texture params copy/paste
|
||||
|
|
@ -261,7 +266,8 @@ private:
|
|||
F32 getCurrentShinyScaleV();
|
||||
F32 getCurrentShinyOffsetU();
|
||||
F32 getCurrentShinyOffsetV();
|
||||
|
||||
LLUUID getCurrentMaterialID();
|
||||
|
||||
// <FS:CR> 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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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<LLCubeMapArray> 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<LLReflectionMap*> 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;
|
||||
};
|
||||
|
||||
|
|
@ -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<LLReflectionMap>& lhs, const LLPointer<LLReflectionMap>& 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<LLReflectionMap*>& 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]));
|
||||
}
|
||||
|
||||
// <FS:Ansariel> 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();
|
||||
// </FS:Ansariel>
|
||||
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<F32> 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();
|
||||
}
|
||||
|
|
@ -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<LLReflectionMap*>& 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<LLRenderTarget> mMipChain;
|
||||
|
||||
// storage for reflection probes
|
||||
LLPointer<LLCubeMapArray> 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<LLPointer<LLReflectionMap> > mProbes;
|
||||
|
||||
// list of reflection maps to kill
|
||||
std::vector<LLPointer<LLReflectionMap> > mKillList;
|
||||
|
||||
// list of reflection maps to create
|
||||
std::vector<LLPointer<LLReflectionMap> > mCreateList;
|
||||
|
||||
// handle to UBO
|
||||
U32 mUBO = 0;
|
||||
|
||||
// list of maps being used for rendering
|
||||
std::vector<LLReflectionMap*> mReflectionMaps;
|
||||
|
||||
LLReflectionMap* mUpdatingProbe = nullptr;
|
||||
U32 mUpdatingFace = 0;
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -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)
|
||||
{
|
||||
// <FS:Ansariel> Reset VB during TP
|
||||
|
|
@ -1420,7 +1440,9 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* 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,
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ class LLSpatialPartition;
|
|||
class LLSpatialBridge;
|
||||
class LLSpatialGroup;
|
||||
class LLViewerRegion;
|
||||
class LLReflectionMap;
|
||||
|
||||
void pushVerts(LLFace* face, U32 mask);
|
||||
//<FS:BEQ> 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<LLReflectionMap> 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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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); // <FS:Beq/> 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 ); // <FS:Beq/> 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 ); // <FS:Beq/> 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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
// <FS:Beq/> Add telemetry controls to the viewer Develop menu (Toggle profiling)
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
{
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include "llvertexbuffer.h"
|
||||
#include "llbbox.h"
|
||||
#include "llrigginginfo.h"
|
||||
#include "llreflectionmap.h"
|
||||
|
||||
#include "fsregioncross.h" // <FS:JN> 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; // <FS:JN> improved extrapolator
|
||||
|
||||
// <FS:Techwolf Lupindo> export
|
||||
public:
|
||||
// reflection probe state
|
||||
bool mIsReflectionProbe = false; // if true, this object should register itself with LLReflectionProbeManager
|
||||
LLPointer<LLReflectionMap> mReflectionProbe = nullptr; // reflection probe coupled to this viewer object. If not null, should be deregistered when this object is destroyed
|
||||
|
||||
// <FS:Techwolf Lupindo> export
|
||||
LLViewerPartSourceScript* getPartSourceScript() { return mPartSourcep.get(); }
|
||||
bool getPhysicsShapeUnknown () { return mPhysicsShapeUnknown; }
|
||||
// </FS:Techwolf Lupindo>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|||
// </FS:Ansariel>
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ LLPointer<LLObjectMediaDataClient> LLVOVolume::sObjectMediaClient = NULL;
|
|||
LLPointer<LLObjectMediaNavigateClient> 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<std::string> 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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
// <FS:CR> Aurora Sim
|
||||
//static S32 const rwidth = (S32)REGION_WIDTH_U32;
|
||||
static S32 const rwidth = (S32)getRegionWidthInMeters();
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -38,6 +38,7 @@
|
|||
#include "llgl.h"
|
||||
#include "lldrawable.h"
|
||||
#include "llrendertarget.h"
|
||||
#include "llreflectionmapmanager.h"
|
||||
|
||||
#include <stack>
|
||||
|
||||
|
|
@ -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<S64> 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:
|
|||
// <FS:Ansariel> FIRE-16829: Visual Artifacts with ALM enabled on AMD graphics
|
||||
LLPointer<LLVertexBuffer> mAuxiliaryVB;
|
||||
|
||||
//sun shadow map
|
||||
LLRenderTarget mShadow[6];
|
||||
LLRenderTarget mShadowOcclusion[6];
|
||||
//list of currently bound reflection maps
|
||||
std::vector<LLReflectionMap*> mReflectionMaps;
|
||||
|
||||
std::vector<LLVector3> 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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2167,12 +2167,12 @@ ERlvCmdRet RlvBehaviourHandler<RLV_BHVR_SETSPHERE>::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
|
||||
|
|
|
|||
|
|
@ -4171,6 +4171,16 @@
|
|||
function="Advanced.ToggleInfoDisplay"
|
||||
parameter="lights" />
|
||||
</menu_item_check>
|
||||
<menu_item_check
|
||||
label="Reflection Probes"
|
||||
name="Reflection Probes">
|
||||
<menu_item_check.on_check
|
||||
function="Advanced.CheckInfoDisplay"
|
||||
parameter="reflection probes" />
|
||||
<menu_item_check.on_click
|
||||
function="Advanced.ToggleInfoDisplay"
|
||||
parameter="reflection probes" />
|
||||
</menu_item_check>
|
||||
<menu_item_check
|
||||
label="Particles"
|
||||
name="Particles">
|
||||
|
|
@ -4526,6 +4536,13 @@
|
|||
function="ToggleControl"
|
||||
parameter="RenderHoverGlowEnable" />
|
||||
</menu_item_check>
|
||||
<menu_item_call
|
||||
enabled="true"
|
||||
label="Rebuild Reflection Probes"
|
||||
name="Rebuild Reflection Probes">
|
||||
<menu_item_call.on_click
|
||||
function="Develop.RebuildReflectionProbes" />
|
||||
</menu_item_call>
|
||||
<menu_item_separator />
|
||||
</menu>
|
||||
|
||||
|
|
|
|||
|
|
@ -13756,6 +13756,13 @@ Unpacking: [UNPACK_TIME]s [USIZE]KB
|
|||
</form>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="notifytip.tga"
|
||||
name="MaterialCreated"
|
||||
type="notifytip">
|
||||
Material successfully created. Asset ID: [ASSET_ID]
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="notify.tga"
|
||||
name="NoValidEnvSettingFound"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<panel
|
||||
border="false"
|
||||
follows="all"
|
||||
height="420"
|
||||
height="500"
|
||||
label="Texture"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
|
|
@ -862,4 +862,29 @@
|
|||
height="4"
|
||||
start_url="about:blank"
|
||||
decouple_texture_size="true" />
|
||||
</panel>
|
||||
<button
|
||||
left="90"
|
||||
top="222"
|
||||
height="20"
|
||||
label="Save as Material"
|
||||
label_selected="Save current face as a Material"
|
||||
layout="topleft"
|
||||
name="button save material"
|
||||
top_delta="0"
|
||||
tool_tip="Save material to inventory"
|
||||
width="110" />
|
||||
|
||||
<line_editor
|
||||
enabled="true"
|
||||
follows="top|left"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
left="7"
|
||||
label="Material UUID"
|
||||
name="materialID"
|
||||
select_on_focus="true"
|
||||
top="380"
|
||||
width="200"
|
||||
tool_tip="UUID for a material asset"
|
||||
/>
|
||||
</panel>
|
||||
|
|
|
|||
Loading…
Reference in New Issue