diff options
Diffstat (limited to 'indra/newview/llreflectionmapmanager.cpp')
-rw-r--r-- | indra/newview/llreflectionmapmanager.cpp | 195 |
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(); + } +} |