master
Ansariel 2022-05-21 15:04:54 +02:00
commit 3765c775cb
90 changed files with 4409 additions and 864 deletions

View File

@ -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>

View File

@ -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 "")

View File

@ -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));

View File

@ -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: |

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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,

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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 &param = static_cast<const LLRenderMaterialParams&>(data);
return param.mMaterial == mMaterial;
}
void LLRenderMaterialParams::copy(const LLNetworkData& data)
{
llassert_always(data.mType == PARAMS_RENDER_MATERIAL);
const LLRenderMaterialParams &param = 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;
}

View File

@ -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;

View File

@ -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
{

View File

@ -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:

View File

@ -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

View File

@ -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()
{

View File

@ -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:

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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");

View File

@ -114,6 +114,7 @@ public:
BOOL mHasTextureRectangle;
BOOL mHasTextureMultisample;
BOOL mHasTransformFeedback;
BOOL mHasUniformBufferObject;
S32 mMaxSampleMaskWords;
S32 mMaxColorTextureSamples;
S32 mMaxDepthTextureSamples;

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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");

View File

@ -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"

View File

@ -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);

View File

@ -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.

View File

@ -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;
}
//

View File

@ -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

View File

@ -1 +1 @@
6.6.0
6.6.1

View File

@ -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>

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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;
}
}
}
{

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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();
}

View File

@ -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;
};

View File

@ -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,

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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:
{

View File

@ -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>

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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:

View File

@ -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)
{

View File

@ -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

View File

@ -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>

View File

@ -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"

View File

@ -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>