summaryrefslogtreecommitdiff
path: root/indra/newview/llreflectionmapmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llreflectionmapmanager.cpp')
-rw-r--r--indra/newview/llreflectionmapmanager.cpp195
1 files changed, 169 insertions, 26 deletions
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index 669989e6e1..5a8f44f5c2 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -27,6 +27,9 @@
#include "llviewerprecompiledheaders.h"
#include "llreflectionmapmanager.h"
+
+#include <vector>
+
#include "llviewercamera.h"
#include "llspatialpartition.h"
#include "llviewerregion.h"
@@ -35,6 +38,86 @@
#include "llviewercontrol.h"
#include "llenvironment.h"
#include "llstartup.h"
+#include "llviewermenufile.h"
+#include "llnotificationsutil.h"
+
+#if LL_WINDOWS
+#pragma warning (push)
+#pragma warning (disable : 4702) // compiler complains unreachable code
+#endif
+#define TINYEXR_USE_MINIZ 0
+#include "zlib.h"
+#define TINYEXR_IMPLEMENTATION
+#include "tinyexr/tinyexr.h"
+#if LL_WINDOWS
+#pragma warning (pop)
+#endif
+
+LLPointer<LLImageGL> gEXRImage;
+
+void load_exr(const std::string& filename)
+{
+ // reset reflection maps when previewing a new HDRI
+ gPipeline.mReflectionMapManager.reset();
+ gPipeline.mReflectionMapManager.initReflectionMaps();
+
+ float* out; // width * height * RGBA
+ int width;
+ int height;
+ const char* err = NULL; // or nullptr in C++11
+
+ int ret = LoadEXRWithLayer(&out, &width, &height, filename.c_str(), /* layername */ nullptr, &err);
+ if (ret == TINYEXR_SUCCESS)
+ {
+ U32 texName = 0;
+ LLImageGL::generateTextures(1, &texName);
+
+ gEXRImage = new LLImageGL(texName, 4, GL_TEXTURE_2D, GL_RGB16F, GL_RGB16F, GL_FLOAT, LLTexUnit::TAM_CLAMP);
+ gEXRImage->setHasMipMaps(TRUE);
+ gEXRImage->setUseMipMaps(TRUE);
+ gEXRImage->setFilteringOption(LLTexUnit::TFO_TRILINEAR);
+
+ gGL.getTexUnit(0)->bind(gEXRImage);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGBA, GL_FLOAT, out);
+ free(out); // release memory of image data
+
+ glGenerateMipmap(GL_TEXTURE_2D);
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ }
+ else
+ {
+ LLSD notif_args;
+ notif_args["WHAT"] = filename;
+ notif_args["REASON"] = "Unknown";
+ if (err)
+ {
+ notif_args["REASON"] = std::string(err);
+ FreeEXRErrorMessage(err); // release memory of error message.
+ }
+ LLNotificationsUtil::add("CannotLoad", notif_args);
+ }
+}
+
+void hdri_preview()
+{
+ LLFilePickerReplyThread::startPicker(
+ [](const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter load_filter, LLFilePicker::ESaveFilter save_filter)
+ {
+ if (LLAppViewer::instance()->quitRequested())
+ {
+ return;
+ }
+ if (filenames.size() > 0)
+ {
+ load_exr(filenames[0]);
+ }
+ },
+ LLFilePicker::FFLOAD_HDRI,
+ true);
+}
extern BOOL gCubeSnapshot;
extern BOOL gTeleportDisplay;
@@ -130,6 +213,11 @@ void LLReflectionMapManager::update()
return;
}
+ if (mPaused && gFrameTimeSeconds > mResumeTime)
+ {
+ resume();
+ }
+
initReflectionMaps();
if (!mRenderTarget.isComplete())
@@ -143,7 +231,7 @@ void LLReflectionMapManager::update()
{
U32 res = mProbeResolution;
U32 count = log2((F32)res) + 0.5f;
-
+
mMipChain.resize(count);
for (int i = 0; i < count; ++i)
{
@@ -153,7 +241,7 @@ void LLReflectionMapManager::update()
}
llassert(mProbes[0] == mDefaultProbe);
-
+
LLVector4a camera_pos;
camera_pos.load3(LLViewerCamera::instance().getOrigin().mV);
@@ -168,7 +256,7 @@ void LLReflectionMapManager::update()
}
mKillList.clear();
-
+
// process create list
for (auto& probe : mCreateList)
{
@@ -184,12 +272,12 @@ void LLReflectionMapManager::update()
bool did_update = false;
-
+
static LLCachedControl<S32> sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1);
static LLCachedControl<S32> sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3);
bool realtime = sDetail >= (S32)LLReflectionMapManager::DetailLevel::REALTIME;
-
+
LLReflectionMap* closestDynamic = nullptr;
LLReflectionMap* oldestProbe = nullptr;
@@ -251,7 +339,7 @@ void LLReflectionMapManager::update()
--i;
continue;
}
-
+
if (probe != mDefaultProbe &&
(!probe->isRelevant() || mPaused))
{ // skip irrelevant probes (or all non-default probes if paused)
@@ -354,7 +442,7 @@ void LLReflectionMapManager::update()
{
LLReflectionMap* probe = oldestProbe;
llassert(probe->mCubeIndex != -1);
-
+
probe->autoAdjustOrigin();
sUpdateCount++;
@@ -543,7 +631,7 @@ void LLReflectionMapManager::doProbeUpdate()
llassert(mUpdatingProbe != nullptr);
updateProbeFace(mUpdatingProbe, mUpdatingFace);
-
+
bool debug_updates = gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PROBE_UPDATES) && mUpdatingProbe->mViewerObject;
if (++mUpdatingFace == 6)
@@ -596,11 +684,11 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
touch_default_probe(probe);
gPipeline.pushRenderTypeMask();
-
+
//only render sky, water, terrain, and clouds
gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY,
LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::END_RENDER_TYPES);
-
+
probe->update(mRenderTarget.getWidth(), face);
gPipeline.popRenderTypeMask();
@@ -609,7 +697,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
{
probe->update(mRenderTarget.getWidth(), face);
}
-
+
gPipeline.mRT = &gPipeline.mMainRT;
S32 sourceIdx = mReflectionProbeCount;
@@ -686,12 +774,12 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gGL.getTexUnit(diffuseChannel)->bind(&(mMipChain[i - 1]));
}
-
+
gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2));
-
+
gPipeline.mScreenTriangleVB->setBuffer();
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-
+
res /= 2;
S32 mip = i - (mMipChain.size() - mips);
@@ -734,6 +822,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
mTexture->bind(channel);
gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
+ gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, 1.f);
U32 res = mMipChain[0].getWidth();
@@ -780,7 +869,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
-
+
mVertexBuffer->setBuffer();
int start_mip = 0;
// find the mip target to start with based on irradiance map resolution
@@ -827,9 +916,10 @@ void LLReflectionMapManager::reset()
mReset = true;
}
-void LLReflectionMapManager::pause()
+void LLReflectionMapManager::pause(F32 duration)
{
mPaused = true;
+ mResumeTime = gFrameTimeSeconds + duration;
}
void LLReflectionMapManager::resume()
@@ -856,7 +946,7 @@ void LLReflectionMapManager::updateNeighbors(LLReflectionMap* probe)
//remove from existing neighbors
{
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - clear");
-
+
for (auto& other : probe->mNeighbors)
{
auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe);
@@ -902,6 +992,8 @@ void LLReflectionMapManager::updateUniforms()
// the box probe
LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT];
+ LLMatrix4 heroBox;
+
// for sphere probes, origin (xyz) and radius (w) of refmaps in clip space
LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT];
@@ -912,6 +1004,8 @@ void LLReflectionMapManager::updateUniforms()
// w - znear
LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT];
+ LLVector4 heroSphere;
+
// indices used by probe:
// [i][0] - cubemap array index for this probe
// [i][1] - index into "refNeighbor" for probes that intersect this probe
@@ -925,6 +1019,10 @@ void LLReflectionMapManager::updateUniforms()
GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth
// numbrer of active refmaps
GLint refmapCount;
+
+ GLint heroShape;
+ GLint heroMipCount;
+ GLint heroProbeCount;
};
mReflectionMaps.resize(mReflectionProbeCount);
@@ -954,14 +1052,13 @@ void LLReflectionMapManager::updateUniforms()
LLEnvironment& environment = LLEnvironment::instance();
LLSettingsSky::ptr_t psky = environment.getCurrentSky();
- static LLCachedControl<F32> cloud_shadow_scale(gSavedSettings, "RenderCloudShadowAmbianceFactor", 0.125f);
static LLCachedControl<bool> should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true);
- F32 minimum_ambiance = psky->getTotalReflectionProbeAmbiance(cloud_shadow_scale, should_auto_adjust);
+ F32 minimum_ambiance = psky->getReflectionProbeAmbiance(should_auto_adjust);
bool is_ambiance_pass = gCubeSnapshot && !isRadiancePass();
F32 ambscale = is_ambiance_pass ? 0.f : 1.f;
F32 radscale = is_ambiance_pass ? 0.5f : 1.f;
-
+
for (auto* refmap : mReflectionMaps)
{
if (refmap == nullptr)
@@ -1012,7 +1109,6 @@ void LLReflectionMapManager::updateUniforms()
{
refmap->mRadius = refmap->mViewerObject->getScale().mV[0] * 0.5f;
}
-
}
modelview.affineTransform(refmap->mOrigin, oa);
rpd.refSphere[count].set(oa.getF32ptr());
@@ -1093,7 +1189,7 @@ void LLReflectionMapManager::updateUniforms()
{
// fill in gaps in refBucket
S32 probe_idx = mReflectionProbeCount;
-
+
for (int i = 0; i < 256; ++i)
{
if (i < count)
@@ -1115,6 +1211,16 @@ void LLReflectionMapManager::updateUniforms()
rpd.refmapCount = count;
+ gPipeline.mHeroProbeManager.updateUniforms();
+
+ // Get the hero data.
+
+ rpd.heroBox = gPipeline.mHeroProbeManager.mHeroData.heroBox;
+ rpd.heroSphere = gPipeline.mHeroProbeManager.mHeroData.heroSphere;
+ rpd.heroShape = gPipeline.mHeroProbeManager.mHeroData.heroShape;
+ rpd.heroMipCount = gPipeline.mHeroProbeManager.mHeroData.heroMipCount;
+ rpd.heroProbeCount = gPipeline.mHeroProbeManager.mHeroData.heroProbeCount;
+
//copy rpd into uniform buffer object
if (mUBO == 0)
{
@@ -1262,6 +1368,8 @@ void LLReflectionMapManager::initReflectionMaps()
if (mTexture.isNull() || mReflectionProbeCount != count || mReset)
{
+ gEXRImage = nullptr;
+
mReset = false;
mReflectionProbeCount = count;
mProbeResolution = nhpo2(llclamp(gSavedSettings.getU32("RenderReflectionProbeResolution"), (U32)64, (U32)512));
@@ -1319,7 +1427,6 @@ void LLReflectionMapManager::initReflectionMaps()
mDefaultProbe->mComplete = default_complete;
touch_default_probe(mDefaultProbe);
-
}
if (mVertexBuffer.isNull())
@@ -1329,9 +1436,9 @@ void LLReflectionMapManager::initReflectionMaps()
buff->allocateBuffer(4, 0);
LLStrider<LLVector3> v;
-
+
buff->getVertexStrider(v);
-
+
v[0] = LLVector3(-1, -1, -1);
v[1] = LLVector3(1, -1, -1);
v[2] = LLVector3(-1, 1, -1);
@@ -1359,7 +1466,7 @@ void LLReflectionMapManager::cleanup()
mReflectionMaps.clear();
mUpdatingFace = 0;
-
+
mDefaultProbe = nullptr;
mUpdatingProbe = nullptr;
@@ -1383,3 +1490,39 @@ void LLReflectionMapManager::doOcclusion()
}
}
}
+
+void LLReflectionMapManager::forceDefaultProbeAndUpdateUniforms(bool force)
+{
+ static std::vector<bool> mProbeWasOccluded;
+
+ if (force)
+ {
+ llassert(mProbeWasOccluded.empty());
+
+ for (size_t i = 0; i < mProbes.size(); ++i)
+ {
+ auto& probe = mProbes[i];
+ mProbeWasOccluded.push_back(probe->mOccluded);
+ if (probe != nullptr && probe != mDefaultProbe)
+ {
+ probe->mOccluded = true;
+ }
+ }
+
+ updateUniforms();
+ }
+ else
+ {
+ llassert(mProbes.size() == mProbeWasOccluded.size());
+
+ const size_t n = llmin(mProbes.size(), mProbeWasOccluded.size());
+ for (size_t i = 0; i < n; ++i)
+ {
+ auto& probe = mProbes[i];
+ llassert(probe->mOccluded == (probe != mDefaultProbe));
+ probe->mOccluded = mProbeWasOccluded[i];
+ }
+ mProbeWasOccluded.clear();
+ mProbeWasOccluded.shrink_to_fit();
+ }
+}