From 423820475c7201c39d03c0622dedbf4b1e8b1879 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 7 Aug 2023 00:17:04 -0700 Subject: Revert LLReflectionMapManager DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 1333 ++++++++++++++++++++++++++++++++++ 1 file changed, 1333 insertions(+) create mode 100644 indra/newview/llheroprobemanager.cpp (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp new file mode 100644 index 0000000000..54a61d000e --- /dev/null +++ b/indra/newview/llheroprobemanager.cpp @@ -0,0 +1,1333 @@ +/** + * @file LLHeroProbeManager.cpp + * @brief LLHeroProbeManager 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 "llheroprobemanager.h" +#include "llreflectionmapmanager.h" +#include "llviewercamera.h" +#include "llspatialpartition.h" +#include "llviewerregion.h" +#include "pipeline.h" +#include "llviewershadermgr.h" +#include "llviewercontrol.h" +#include "llenvironment.h" +#include "llstartup.h" + +extern BOOL gCubeSnapshot; +extern BOOL gTeleportDisplay; + +// get the next highest power of two of v (or v if v is already a power of two) +//defined in llvertexbuffer.cpp +extern U32 nhpo2(U32 v); + +static void touch_default_probe(LLReflectionMap* probe) +{ + if (LLViewerCamera::getInstance()) + { + LLVector3 origin = LLViewerCamera::getInstance()->getOrigin(); + origin.mV[2] += 64.f; + + probe->mOrigin.load3(origin.mV); + } +} + +LLHeroProbeManager::LLHeroProbeManager() +{ + initCubeFree(); +} + +void LLHeroProbeManager::initCubeFree() +{ + // start at 1 because index 0 is reserved for mDefaultProbe + for (int i = 1; i < LL_MAX_REFLECTION_PROBE_COUNT; ++i) + { + mCubeFree.push_back(i); + } +} + +struct CompareProbeDistance +{ + LLReflectionMap* mDefaultProbe; + + bool operator()(const LLPointer& lhs, const LLPointer& rhs) + { + return lhs->mDistance < rhs->mDistance; + } +}; + +static F32 update_score(LLReflectionMap* p) +{ + return gFrameTimeSeconds - p->mLastUpdateTime - p->mDistance*0.1f; +} + +// return true if a is higher priority for an update than b +static bool check_priority(LLReflectionMap* a, LLReflectionMap* b) +{ + if (a->mCubeIndex == -1) + { // not a candidate for updating + return false; + } + else if (b->mCubeIndex == -1) + { // certainly higher priority than b + return true; + } + else if (!a->mComplete && !b->mComplete) + { //neither probe is complete, use distance + return a->mDistance < b->mDistance; + } + else if (a->mComplete && b->mComplete) + { //both probes are complete, use update_score metric + return update_score(a) > update_score(b); + } + + // one of these probes is not complete, if b is complete, a is higher priority + return b->mComplete; +} + +// helper class to seed octree with probes +void LLHeroProbeManager::update() +{ + if (!LLPipeline::sReflectionProbesEnabled || gTeleportDisplay || LLStartUp::getStartupState() < STATE_PRECACHE) + { + return; + } + + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + llassert(!gCubeSnapshot); // assert a snapshot is not in progress + if (LLAppViewer::instance()->logoutRequestSent()) + { + return; + } + + initReflectionMaps(); + + if (!mRenderTarget.isComplete()) + { + U32 color_fmt = GL_RGB16F; + U32 targetRes = mProbeResolution * 4; // super sample + mRenderTarget.allocate(targetRes, targetRes, color_fmt, true); + } + + if (!mHeroRenderTarget.isComplete()) + { + U32 color_fmt = GL_RGB16F; + U32 targetRes = mHeroProbeResolution * 2; + mHeroRenderTarget.allocate(targetRes, targetRes, color_fmt, true); + } + + if (mMipChain.empty()) + { + U32 res = mHeroProbeResolution; + U32 count = log2((F32)res) + 0.5f; + + mMipChain.resize(count); + for (int i = 0; i < count; ++i) + { + mMipChain[i].allocate(res, res, GL_RGB16F); + res /= 2; + } + } + + llassert(mProbes[0] == mDefaultProbe); + + LLVector4a camera_pos; + camera_pos.load3(LLViewerCamera::instance().getOrigin().mV); + + // process kill list + for (auto& probe : mKillList) + { + auto const & iter = std::find(mProbes.begin(), mProbes.end(), probe); + if (iter != mProbes.end()) + { + deleteProbe(iter - mProbes.begin()); + } + } + + mKillList.clear(); + + // process create list + for (auto& probe : mCreateList) + { + mProbes.push_back(probe); + } + + mCreateList.clear(); + + if (mProbes.empty()) + { + return; + } + + + bool did_update = false; + + static LLCachedControl sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); + static LLCachedControl sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); + + bool realtime = sDetail >= (S32)LLHeroProbeManager::DetailLevel::REALTIME; + + LLReflectionMap* closestDynamic = nullptr; + + LLReflectionMap* oldestProbe = nullptr; + LLReflectionMap* oldestOccluded = nullptr; + + if (mUpdatingProbe != nullptr) + { + did_update = true; + doProbeUpdate(); + } + + // update distance to camera for all probes + std::sort(mProbes.begin()+1, mProbes.end(), CompareProbeDistance()); + llassert(mProbes[0] == mDefaultProbe); + llassert(mProbes[0]->mCubeArray == mTexture); + llassert(mProbes[0]->mCubeIndex == 0); + + // make sure we're assigning cube slots to the closest probes + + // first free any cube indices for distant probes + for (U32 i = mReflectionProbeCount; i < mProbes.size(); ++i) + { + LLReflectionMap* probe = mProbes[i]; + llassert(probe != nullptr); + + if (probe->mCubeIndex != -1 && mUpdatingProbe != probe) + { // free this index + mCubeFree.push_back(probe->mCubeIndex); + + probe->mCubeArray = nullptr; + probe->mCubeIndex = -1; + probe->mComplete = false; + } + } + + // next distribute the free indices + U32 count = llmin(mReflectionProbeCount, (U32)mProbes.size()); + + for (S32 i = 1; i < count && !mCubeFree.empty(); ++i) + { + // find the closest probe that needs a cube index + LLReflectionMap* probe = mProbes[i]; + + if (probe->mCubeIndex == -1) + { + S32 idx = allocateCubeIndex(); + llassert(idx > 0); //if we're still in this loop, mCubeFree should not be empty and allocateCubeIndex should be returning good indices + probe->mCubeArray = mTexture; + probe->mCubeIndex = idx; + } + } + + 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; + } + + if (probe != mDefaultProbe && !probe->isRelevant()) + { + continue; + } + + LLVector4a d; + + if (probe != mDefaultProbe) + { + if (probe->mViewerObject) //make sure probes track the viewer objects they are attached to + { + probe->mOrigin.load3(probe->mViewerObject->getPositionAgent().mV); + } + d.setSub(camera_pos, probe->mOrigin); + probe->mDistance = d.getLength3().getF32() - probe->mRadius; + } + else if (probe->mComplete) + { + // make default probe have a distance of 64m for the purposes of prioritization (if it's already been generated once) + probe->mDistance = 64.f; + } + else + { + probe->mDistance = -4096.f; //boost priority of default probe when it's not complete + } + + if (probe->mComplete) + { + probe->autoAdjustOrigin(); + probe->mFadeIn = llmin((F32) (probe->mFadeIn + gFrameIntervalSeconds), 1.f); + } + if (probe->mOccluded && probe->mComplete) + { + if (oldestOccluded == nullptr) + { + oldestOccluded = probe; + } + else if (probe->mLastUpdateTime < oldestOccluded->mLastUpdateTime) + { + oldestOccluded = probe; + } + } + else + { + if (!did_update && + i < mReflectionProbeCount && + (oldestProbe == nullptr || + check_priority(probe, oldestProbe))) + { + oldestProbe = probe; + } + } + + if (realtime && + closestDynamic == nullptr && + probe->mCubeIndex != -1 && + probe->getIsDynamic()) + { + closestDynamic = probe; + } + } + + if (realtime && closestDynamic != nullptr) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); + // update the closest dynamic probe realtime + // should do a full irradiance pass on "odd" frames and a radiance pass on "even" frames + closestDynamic->autoAdjustOrigin(); + + // store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set + // lighting values etc + bool radiance_pass = isRadiancePass(); + mRadiancePass = mRealtimeRadiancePass; + for (U32 i = 0; i < 6; ++i) + { + updateProbeFace(closestDynamic, i, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); + } + mRealtimeRadiancePass = !mRealtimeRadiancePass; + + // restore "isRadiancePass" + mRadiancePass = radiance_pass; + } + + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); + + mHeroProbe->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); + bool radiance_pass = isRadiancePass(); + mRadiancePass = true; + for (U32 i = 0; i < 6; ++i) + { + updateProbeFace(mHeroProbe, i, mHeroProbeResolution, mHeroArray, mMipChain, mHeroProbeCount); + } + + // restore "isRadiancePass" + mRadiancePass = radiance_pass; + } + + static LLCachedControl sUpdatePeriod(gSavedSettings, "RenderDefaultProbeUpdatePeriod", 2.f); + if ((gFrameTimeSeconds - mDefaultProbe->mLastUpdateTime) < sUpdatePeriod) + { + if (sLevel == 0) + { // when probes are disabled don't update the default probe more often than the prescribed update period + oldestProbe = nullptr; + } + } + else if (sLevel > 0) + { // when probes are enabled don't update the default probe less often than the prescribed update period + oldestProbe = mDefaultProbe; + } + + // switch to updating the next oldest probe + if (!did_update && oldestProbe != nullptr) + { + LLReflectionMap* probe = oldestProbe; + llassert(probe->mCubeIndex != -1); + + probe->autoAdjustOrigin(); + + mUpdatingProbe = probe; + doProbeUpdate(); + } + + if (oldestOccluded) + { + // as far as this occluded probe is concerned, an origin/radius update is as good as a full update + oldestOccluded->autoAdjustOrigin(); + oldestOccluded->mLastUpdateTime = gFrameTimeSeconds; + } +} + +LLReflectionMap* LLHeroProbeManager::addProbe(LLSpatialGroup* group) +{ + LLReflectionMap* probe = new LLReflectionMap(); + probe->mGroup = group; + + if (mDefaultProbe.isNull()) + { //safety check to make sure default probe is always first probe added + mDefaultProbe = new LLReflectionMap(); + mProbes.push_back(mDefaultProbe); + } + + llassert(mProbes[0] == mDefaultProbe); + + if (group) + { + probe->mOrigin = group->getOctreeNode()->getCenter(); + } + + 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; +} + +struct CompareProbeDepth +{ + bool operator()(const LLReflectionMap* lhs, const LLReflectionMap* rhs) + { + return lhs->mMinDepth < rhs->mMinDepth; + } +}; + +void LLHeroProbeManager::getReflectionMaps(std::vector& maps) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + + LLMatrix4a modelview; + modelview.loadu(gGLModelView); + LLVector4a oa; // scratch space for transformed origin + + 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) + { + if (!mProbes[i]->mOccluded && mProbes[i]->mComplete) + { + maps[count++] = mProbes[i]; + modelview.affineTransform(mProbes[i]->mOrigin, oa); + mProbes[i]->mMinDepth = -oa.getF32ptr()[2] - mProbes[i]->mRadius; + mProbes[i]->mMaxDepth = -oa.getF32ptr()[2] + mProbes[i]->mRadius; + } + } + 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; + } + + if (count > 1) + { + std::sort(maps.begin(), maps.begin() + count, CompareProbeDepth()); + } + + for (U32 i = 0; i < count; ++i) + { + maps[i]->mProbeIndex = i; + } + + // null terminate list + if (count < maps.size()) + { + maps[count] = nullptr; + } +} + +LLReflectionMap* LLHeroProbeManager::registerSpatialGroup(LLSpatialGroup* group) +{ + if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME) + { + OctreeNode* node = group->getOctreeNode(); + F32 size = node->getSize().getF32ptr()[0]; + if (size >= 15.f && size <= 17.f) + { + return addProbe(group); + } + } + + return nullptr; +} + +LLReflectionMap* LLHeroProbeManager::registerViewerObject(LLViewerObject* vobj) +{ + llassert(vobj != nullptr); + + LLReflectionMap* probe = new LLReflectionMap(); + probe->mViewerObject = vobj; + probe->mOrigin.load3(vobj->getPositionAgent().mV); + + 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 LLHeroProbeManager::allocateCubeIndex() +{ + if (!mCubeFree.empty()) + { + S32 ret = mCubeFree.front(); + mCubeFree.pop_front(); + return ret; + } + + return -1; +} + +void LLHeroProbeManager::deleteProbe(U32 i) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + LLReflectionMap* probe = mProbes[i]; + + llassert(probe != mDefaultProbe); + + if (probe->mCubeIndex != -1) + { // mark the cube index used by this probe as being free + mCubeFree.push_back(probe->mCubeIndex); + } + if (mUpdatingProbe == probe) + { + mUpdatingProbe = nullptr; + mUpdatingFace = 0; + } + + // remove from any Neighbors lists + for (auto& other : probe->mNeighbors) + { + auto const & 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 LLHeroProbeManager::doProbeUpdate() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + llassert(mUpdatingProbe != nullptr); + + updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); + + if (++mUpdatingFace == 6) + { + updateNeighbors(mUpdatingProbe); + mUpdatingFace = 0; + if (isRadiancePass()) + { + mUpdatingProbe->mComplete = true; + mUpdatingProbe = nullptr; + mRadiancePass = false; + } + else + { + mRadiancePass = true; + } + } +} + +// Do the reflection map update render passes. +// For every 12 calls of this function, one complete reflection probe radiance map and irradiance map is generated +// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate +// a simple mip chain (not convolution filter). +// At the end of these passes, an irradiance map is generated for this probe and placed into the irradiance cube map array at the index for this probe +// The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain. +// At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe. +// In effect this simulates single-bounce lighting. +void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount) +{ + // hacky hot-swap of camera specific render targets + gPipeline.mRT = &gPipeline.mAuxillaryRT; + + LLRenderTarget* target = &mRenderTarget; + + S32 sourceIdx = probeCount; + + if (probeResolution == mHeroProbeResolution) + { + sourceIdx = 0; + target = &mHeroRenderTarget; + } + + mLightScale = 1.f; + static LLCachedControl max_local_light_ambiance(gSavedSettings, "RenderReflectionProbeMaxLocalLightAmbiance", 8.f); + if (!isRadiancePass() && probe->getAmbiance() > max_local_light_ambiance) + { + mLightScale = max_local_light_ambiance / probe->getAmbiance(); + } + + if (probe == mDefaultProbe) + { + 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(target->getWidth(), face); + + gPipeline.popRenderTypeMask(); + } + else + { + probe->update(target->getWidth(), face); + } + + gPipeline.mRT = &gPipeline.mMainRT; + + if (probe != mUpdatingProbe && probe->mType != LLReflectionMap::ProbeType::REFLECTION) + { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel + sourceIdx += 1; + } + + gGL.setColorMask(true, true); + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + LLGLDisable cull(GL_CULL_FACE); + LLGLDisable blend(GL_BLEND); + + // downsample to placeholder map + { + gGL.matrixMode(gGL.MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); + + gGL.matrixMode(gGL.MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + + gGL.flush(); + U32 res = probeResolution * 2; + + static LLStaticHashedString resScale("resScale"); + static LLStaticHashedString direction("direction"); + static LLStaticHashedString znear("znear"); + static LLStaticHashedString zfar("zfar"); + + LLRenderTarget* screen_rt = &gPipeline.mAuxillaryRT.screen; + + // perform a gaussian blur on the super sampled render before downsampling + { + gGaussianProgram.bind(); + gGaussianProgram.uniform1f(resScale, 1.f / (probeResolution * 2)); + S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); + + // horizontal + gGaussianProgram.uniform2f(direction, 1.f, 0.f); + gGL.getTexUnit(diffuseChannel)->bind(screen_rt); + target->bindTarget(); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + target->flush(); + + // vertical + gGaussianProgram.uniform2f(direction, 0.f, 1.f); + gGL.getTexUnit(diffuseChannel)->bind(target); + screen_rt->bindTarget(); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + screen_rt->flush(); + } + + + S32 mips = log2((F32)probeResolution) + 0.5f; + + gReflectionMipProgram.bind(); + S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); + + for (int i = 0; i < mMipChain.size(); ++i) + { + LL_PROFILE_GPU_ZONE("probe mip"); + mMipChain[i].bindTarget(); + if (i == 0) + { + gGL.getTexUnit(diffuseChannel)->bind(screen_rt); + } + else + { + gGL.getTexUnit(diffuseChannel)->bind(&(mMipChain[i - 1])); + } + + + gReflectionMipProgram.uniform1f(resScale, 1.f/(probeResolution*2)); + + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + res /= 2; + + S32 mip = i - (mMipChain.size() - mips); + + if (mip >= 0) + { + LL_PROFILE_GPU_ZONE("probe mip copy"); + cubeArray->bind(0); + + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res); + + cubeArray->unbind(); + } + mMipChain[i].flush(); + } + + gGL.popMatrix(); + gGL.matrixMode(gGL.MM_MODELVIEW); + gGL.popMatrix(); + + gGL.getTexUnit(diffuseChannel)->unbind(LLTexUnit::TT_TEXTURE); + gReflectionMipProgram.unbind(); + } + + if (face == 5) + { + mMipChain[0].bindTarget(); + static LLStaticHashedString sSourceIdx("sourceIdx"); + + if (isRadiancePass()) + { + //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) + gRadianceGenProgram.bind(); + mVertexBuffer->setBuffer(); + + S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + cubeArray->bind(channel); + gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); + gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); + + U32 res = mMipChain[0].getWidth(); + + for (int i = 0; i < mMipChain.size(); ++i) + { + LL_PROFILE_GPU_ZONE("probe radiance gen"); + static LLStaticHashedString sMipLevel("mipLevel"); + static LLStaticHashedString sRoughness("roughness"); + static LLStaticHashedString sWidth("u_width"); + + gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); + gRadianceGenProgram.uniform1f(sMipLevel, i); + gRadianceGenProgram.uniform1i(sWidth, probeResolution); + + for (int cf = 0; cf < 6; ++cf) + { // for each cube face + LLCoordFrame frame; + frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); + + F32 mat[16]; + frame.getOpenGLRotation(mat); + gGL.loadMatrix(mat); + + mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4); + + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); + } + + if (i != mMipChain.size() - 1) + { + res /= 2; + glViewport(0, 0, res, res); + } + } + + gRadianceGenProgram.unbind(); + } + else + { + //generate irradiance map + gIrradianceGenProgram.bind(); + S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + cubeArray->bind(channel); + + 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 + for (start_mip = 0; start_mip < mMipChain.size(); ++start_mip) + { + if (mMipChain[start_mip].getWidth() == LL_IRRADIANCE_MAP_RESOLUTION) + { + break; + } + } + + //for (int i = start_mip; i < mMipChain.size(); ++i) + { + int i = start_mip; + LL_PROFILE_GPU_ZONE("probe irradiance gen"); + glViewport(0, 0, mMipChain[i].getWidth(), mMipChain[i].getHeight()); + for (int cf = 0; cf < 6; ++cf) + { // for each cube face + LLCoordFrame frame; + frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); + + F32 mat[16]; + frame.getOpenGLRotation(mat); + gGL.loadMatrix(mat); + + mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4); + + S32 res = mMipChain[i].getWidth(); + mIrradianceMaps->bind(channel); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); + cubeArray->bind(channel); + } + } + } + + mMipChain[0].flush(); + + gIrradianceGenProgram.unbind(); + } +} + +void LLHeroProbeManager::reset() +{ + mReset = true; +} + +void LLHeroProbeManager::shift(const LLVector4a& offset) +{ + for (auto& probe : mProbes) + { + probe->mOrigin.add(offset); + } +} + +void LLHeroProbeManager::updateNeighbors(LLReflectionMap* probe) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + if (mDefaultProbe == probe) + { + return; + } + + //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); + 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 + if (probe->isRelevant()) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - search"); + for (auto& other : mProbes) + { + if (other != mDefaultProbe && other != probe) + { + if (other->isRelevant() && probe->intersects(other)) + { + probe->mNeighbors.push_back(other); + other->mNeighbors.push_back(probe); + } + } + } + } +} + +void LLHeroProbeManager::updateUniforms() +{ + if (!LLPipeline::sReflectionProbesEnabled) + { + return; + } + + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + + // structure for packing uniform buffer object + // see class3/deferred/reflectionProbeF.glsl + struct ReflectionProbeData + { + // for box probes, matrix that transforms from camera space to a [-1, 1] cube representing the bounding box of + // the box probe + LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT]; + + // for sphere probes, origin (xyz) and radius (w) of refmaps in clip space + LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT]; + + // extra parameters + // x - irradiance scale + // y - radiance scale + // z - fade in + // w - znear + LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT]; + + // indices used by probe: + // [i][0] - cubemap array index for this probe + // [i][1] - index into "refNeighbor" for probes that intersect this probe + // [i][2] - number of probes that intersect this probe, or -1 for no neighbors + // [i][3] - priority (probe type stored in sign bit - positive for spheres, negative for boxes) + GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4]; + + // list of neighbor indices + GLint refNeighbor[4096]; + + GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth + // numbrer of active refmaps + GLint refmapCount; + }; + + mReflectionMaps.resize(mReflectionProbeCount); + getReflectionMaps(mReflectionMaps); + + ReflectionProbeData rpd; + + F32 minDepth[256]; + + for (int i = 0; i < 256; ++i) + { + rpd.refBucket[i][0] = mReflectionProbeCount; + rpd.refBucket[i][1] = mReflectionProbeCount; + rpd.refBucket[i][2] = mReflectionProbeCount; + rpd.refBucket[i][3] = mReflectionProbeCount; + minDepth[i] = FLT_MAX; + } + + // 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 + + LLEnvironment& environment = LLEnvironment::instance(); + LLSettingsSky::ptr_t psky = environment.getCurrentSky(); + + static LLCachedControl cloud_shadow_scale(gSavedSettings, "RenderCloudShadowAmbianceFactor", 0.125f); + static LLCachedControl should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true); + F32 minimum_ambiance = psky->getTotalReflectionProbeAmbiance(cloud_shadow_scale, 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) + { + break; + } + + if (refmap != mDefaultProbe) + { + // bucket search data + // theory of operation: + // 1. Determine minimum and maximum depth of each influence volume and store in mDepth (done in getReflectionMaps) + // 2. Sort by minimum depth + // 3. Prepare a bucket for each 1m of depth out to 256m + // 4. For each bucket, store the index of the nearest probe that might influence pixels in that bucket + // 5. In the shader, lookup the bucket for the pixel depth to get the index of the first probe that could possibly influence + // the current pixel. + int depth_min = llclamp(llfloor(refmap->mMinDepth), 0, 255); + int depth_max = llclamp(llfloor(refmap->mMaxDepth), 0, 255); + for (U32 i = depth_min; i <= depth_max; ++i) + { + if (refmap->mMinDepth < minDepth[i]) + { + minDepth[i] = refmap->mMinDepth; + rpd.refBucket[i][0] = refmap->mProbeIndex; + } + } + } + + llassert(refmap->mProbeIndex == count); + llassert(mReflectionMaps[refmap->mProbeIndex] == refmap); + + llassert(refmap->mCubeIndex >= 0); // should always be true, if not, getReflectionMaps is bugged + + { + if (refmap->mViewerObject) + { // have active manual probes live-track the object they're associated with + refmap->mOrigin.load3(refmap->mViewerObject->getPositionAgent().mV); + refmap->mRadius = refmap->mViewerObject->getScale().mV[0] * 0.5f; + + } + 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]; + } + + rpd.refParams[count].set( + llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, // ambiance scale + radscale, // radiance scale + refmap->mFadeIn, // fade in weight + oa.getF32ptr()[2] - refmap->mRadius); // z near + + 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 + const U32 max_neighbors = 64; + U32 neighbor_count = 0; + + for (auto& neighbor : refmap->mNeighbors) + { + if (ni >= 4096) + { // out of space + break; + } + + GLint idx = neighbor->mProbeIndex; + if (idx == -1 || neighbor->mOccluded || neighbor->mCubeIndex == -1) + { + continue; + } + + // this neighbor may be sampled + rpd.refNeighbor[ni++] = idx; + + neighbor_count++; + if (neighbor_count >= max_neighbors) + { + break; + } + } + } + + 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++; + } + +#if 0 + { + // fill in gaps in refBucket + S32 probe_idx = mReflectionProbeCount; + + for (int i = 0; i < 256; ++i) + { + if (i < count) + { // for debugging, store depth of mReflectionsMaps[i] + rpd.refBucket[i][1] = (S32) (mReflectionMaps[i]->mDepth * 10); + } + + if (rpd.refBucket[i][0] == mReflectionProbeCount) + { + rpd.refBucket[i][0] = probe_idx; + } + else + { + probe_idx = rpd.refBucket[i][0]; + } + } + } +#endif + + rpd.refmapCount = count; + + //copy rpd into uniform buffer object + if (mUBO == 0) + { + glGenBuffers(1, &mUBO); + } + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer"); + glBindBuffer(GL_UNIFORM_BUFFER, mUBO); + glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeData), &rpd, GL_STREAM_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + + struct HeroProbeData + { + LLVector4 heroPosition[1]; + GLint heroProbeCount = 1; + }; + + HeroProbeData hpd; + + modelview.loadu(gGLModelView); + + oa.set(0, 0, 0, 0); + hpd.heroProbeCount = 1; + modelview.affineTransform(mHeroProbe->mOrigin, oa); + hpd.heroPosition[0].set(oa.getF32ptr()); + + //copy rpd into uniform buffer object + if (mUBO == 0) + { + glGenBuffers(1, &mHeroUBO); + } + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer"); + glBindBuffer(GL_UNIFORM_BUFFER, mHeroUBO); + glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + +#if 0 + if (!gCubeSnapshot) + { + for (auto& probe : mProbes) + { + LLViewerObject* vobj = probe->mViewerObject; + if (vobj) + { + F32 time = (F32)gFrameTimeSeconds - probe->mLastUpdateTime; + vobj->setDebugText(llformat("%d/%d/%d/%.1f - %.1f/%.1f", probe->mCubeIndex, probe->mProbeIndex, (U32) probe->mNeighbors.size(), probe->mMinDepth, probe->mMaxDepth, time), time > 1.f ? LLColor4::white : LLColor4::green); + } + } + } +#endif +} + +void LLHeroProbeManager::setUniforms() +{ + if (!LLPipeline::sReflectionProbesEnabled) + { + return; + } + + if (mUBO == 0) + { + updateUniforms(); + } + glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO); +} + +void LLHeroProbeManager::renderDebug() +{ + gDebugProgram.bind(); + + for (auto& probe : mProbes) + { + renderReflectionProbe(probe); + } + + gDebugProgram.unbind(); +} + +void LLHeroProbeManager::initReflectionMaps() +{ + U32 count = LL_MAX_REFLECTION_PROBE_COUNT; + + if (mTexture.isNull() || mReflectionProbeCount != count || mReset || mHeroArray.isNull()) + { + mReset = false; + mReflectionProbeCount = count; + mProbeResolution = nhpo2(llclamp(gSavedSettings.getU32("RenderReflectionProbeResolution"), (U32)64, (U32)512)); + mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1 + + mTexture = new LLCubeMapArray(); + + // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source) + mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2); + + mIrradianceMaps = new LLCubeMapArray(); + mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, FALSE); + + // reset probe state + mUpdatingFace = 0; + mUpdatingProbe = nullptr; + mRadiancePass = false; + mRealtimeRadiancePass = false; + + for (auto& probe : mProbes) + { + probe->mLastUpdateTime = 0.f; + probe->mComplete = false; + probe->mProbeIndex = -1; + probe->mCubeArray = nullptr; + probe->mCubeIndex = -1; + probe->mNeighbors.clear(); + } + + mCubeFree.clear(); + initCubeFree(); + + if (mDefaultProbe.isNull()) + { + llassert(mProbes.empty()); // default probe MUST be the first probe created + mDefaultProbe = new LLReflectionMap(); + mProbes.push_back(mDefaultProbe); + } + + llassert(mProbes[0] == mDefaultProbe); + + mDefaultProbe->mCubeIndex = 0; + mDefaultProbe->mCubeArray = mTexture; + mDefaultProbe->mDistance = 64.f; + mDefaultProbe->mRadius = 4096.f; + mDefaultProbe->mProbeIndex = 0; + touch_default_probe(mDefaultProbe); + + mHeroProbeResolution = 128; + + // Revise when we have both water and mirrors in hero probes. + mHeroProbeCount = 1; + + mHeroArray = new LLCubeMapArray(); + + // We use an extra probe for scratch space on these. + mHeroArray->allocate(mHeroProbeResolution, 3, mHeroProbeCount + 1, true); + + if (mHeroProbe.isNull()) { + mHeroProbe = new LLReflectionMap(); + } + + mHeroProbe->mCubeIndex = 0; + mHeroProbe->mCubeArray = mHeroArray; + mHeroProbe->mDistance = 64.f; + mHeroProbe->mRadius = 4096.f; + mHeroProbe->mProbeIndex = 0; + touch_default_probe(mHeroProbe); + + } + + if (mVertexBuffer.isNull()) + { + U32 mask = LLVertexBuffer::MAP_VERTEX; + LLPointer buff = new LLVertexBuffer(mask); + buff->allocateBuffer(4, 0); + + LLStrider v; + + buff->getVertexStrider(v); + + v[0] = LLVector3(-1, -1, -1); + v[1] = LLVector3(1, -1, -1); + v[2] = LLVector3(-1, 1, -1); + v[3] = LLVector3(1, 1, -1); + + buff->unmapBuffer(); + + mVertexBuffer = buff; + } +} + +void LLHeroProbeManager::cleanup() +{ + mVertexBuffer = nullptr; + mRenderTarget.release(); + mHeroRenderTarget.release(); + + mMipChain.clear(); + + mTexture = nullptr; + mIrradianceMaps = nullptr; + mHeroArray = nullptr; + + mProbes.clear(); + mKillList.clear(); + mCreateList.clear(); + + mReflectionMaps.clear(); + mUpdatingFace = 0; + + mDefaultProbe = nullptr; + mUpdatingProbe = nullptr; + + mHeroProbe = nullptr; + + glDeleteBuffers(1, &mUBO); + mUBO = 0; + + glDeleteBuffers(1, &mHeroUBO); + mHeroUBO = 0; + + // note: also called on teleport (not just shutdown), so make sure we're in a good "starting" state + initCubeFree(); +} + +void LLHeroProbeManager::doOcclusion() +{ + LLVector4a eye; + eye.load3(LLViewerCamera::instance().getOrigin().mV); + + for (auto& probe : mProbes) + { + if (probe != nullptr && probe != mDefaultProbe) + { + probe->doOcclusion(eye); + } + } +} -- cgit v1.2.3 From d5845fe3e7f3a620453f00421608211d6353905f Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 18 Aug 2023 21:47:40 -0700 Subject: Latest updates to the hero probe manager. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 923 ++--------------------------------- 1 file changed, 42 insertions(+), 881 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 54a61d000e..5edf819fff 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -57,55 +57,6 @@ static void touch_default_probe(LLReflectionMap* probe) LLHeroProbeManager::LLHeroProbeManager() { - initCubeFree(); -} - -void LLHeroProbeManager::initCubeFree() -{ - // start at 1 because index 0 is reserved for mDefaultProbe - for (int i = 1; i < LL_MAX_REFLECTION_PROBE_COUNT; ++i) - { - mCubeFree.push_back(i); - } -} - -struct CompareProbeDistance -{ - LLReflectionMap* mDefaultProbe; - - bool operator()(const LLPointer& lhs, const LLPointer& rhs) - { - return lhs->mDistance < rhs->mDistance; - } -}; - -static F32 update_score(LLReflectionMap* p) -{ - return gFrameTimeSeconds - p->mLastUpdateTime - p->mDistance*0.1f; -} - -// return true if a is higher priority for an update than b -static bool check_priority(LLReflectionMap* a, LLReflectionMap* b) -{ - if (a->mCubeIndex == -1) - { // not a candidate for updating - return false; - } - else if (b->mCubeIndex == -1) - { // certainly higher priority than b - return true; - } - else if (!a->mComplete && !b->mComplete) - { //neither probe is complete, use distance - return a->mDistance < b->mDistance; - } - else if (a->mComplete && b->mComplete) - { //both probes are complete, use update_score metric - return update_score(a) > update_score(b); - } - - // one of these probes is not complete, if b is complete, a is higher priority - return b->mComplete; } // helper class to seed octree with probes @@ -131,17 +82,10 @@ void LLHeroProbeManager::update() U32 targetRes = mProbeResolution * 4; // super sample mRenderTarget.allocate(targetRes, targetRes, color_fmt, true); } - - if (!mHeroRenderTarget.isComplete()) - { - U32 color_fmt = GL_RGB16F; - U32 targetRes = mHeroProbeResolution * 2; - mHeroRenderTarget.allocate(targetRes, targetRes, color_fmt, true); - } if (mMipChain.empty()) { - U32 res = mHeroProbeResolution; + U32 res = mProbeResolution; U32 count = log2((F32)res) + 0.5f; mMipChain.resize(count); @@ -156,422 +100,22 @@ void LLHeroProbeManager::update() LLVector4a camera_pos; camera_pos.load3(LLViewerCamera::instance().getOrigin().mV); - - // process kill list - for (auto& probe : mKillList) - { - auto const & iter = std::find(mProbes.begin(), mProbes.end(), probe); - if (iter != mProbes.end()) - { - deleteProbe(iter - mProbes.begin()); - } - } - - mKillList.clear(); - // process create list - for (auto& probe : mCreateList) - { - mProbes.push_back(probe); - } - - mCreateList.clear(); - - if (mProbes.empty()) - { - return; - } - - - bool did_update = false; - - static LLCachedControl sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); - static LLCachedControl sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); - - bool realtime = sDetail >= (S32)LLHeroProbeManager::DetailLevel::REALTIME; - - LLReflectionMap* closestDynamic = nullptr; - - LLReflectionMap* oldestProbe = nullptr; - LLReflectionMap* oldestOccluded = nullptr; - - if (mUpdatingProbe != nullptr) - { - did_update = true; - doProbeUpdate(); - } - - // update distance to camera for all probes - std::sort(mProbes.begin()+1, mProbes.end(), CompareProbeDistance()); - llassert(mProbes[0] == mDefaultProbe); - llassert(mProbes[0]->mCubeArray == mTexture); - llassert(mProbes[0]->mCubeIndex == 0); - - // make sure we're assigning cube slots to the closest probes + static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); + static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); - // first free any cube indices for distant probes - for (U32 i = mReflectionProbeCount; i < mProbes.size(); ++i) - { - LLReflectionMap* probe = mProbes[i]; - llassert(probe != nullptr); - - if (probe->mCubeIndex != -1 && mUpdatingProbe != probe) - { // free this index - mCubeFree.push_back(probe->mCubeIndex); - - probe->mCubeArray = nullptr; - probe->mCubeIndex = -1; - probe->mComplete = false; - } - } - - // next distribute the free indices - U32 count = llmin(mReflectionProbeCount, (U32)mProbes.size()); - - for (S32 i = 1; i < count && !mCubeFree.empty(); ++i) - { - // find the closest probe that needs a cube index - LLReflectionMap* probe = mProbes[i]; - - if (probe->mCubeIndex == -1) - { - S32 idx = allocateCubeIndex(); - llassert(idx > 0); //if we're still in this loop, mCubeFree should not be empty and allocateCubeIndex should be returning good indices - probe->mCubeArray = mTexture; - probe->mCubeIndex = idx; - } - } - - 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; - } - - if (probe != mDefaultProbe && !probe->isRelevant()) - { - continue; - } - - LLVector4a d; - - if (probe != mDefaultProbe) - { - if (probe->mViewerObject) //make sure probes track the viewer objects they are attached to - { - probe->mOrigin.load3(probe->mViewerObject->getPositionAgent().mV); - } - d.setSub(camera_pos, probe->mOrigin); - probe->mDistance = d.getLength3().getF32() - probe->mRadius; - } - else if (probe->mComplete) - { - // make default probe have a distance of 64m for the purposes of prioritization (if it's already been generated once) - probe->mDistance = 64.f; - } - else - { - probe->mDistance = -4096.f; //boost priority of default probe when it's not complete - } - - if (probe->mComplete) - { - probe->autoAdjustOrigin(); - probe->mFadeIn = llmin((F32) (probe->mFadeIn + gFrameIntervalSeconds), 1.f); - } - if (probe->mOccluded && probe->mComplete) - { - if (oldestOccluded == nullptr) - { - oldestOccluded = probe; - } - else if (probe->mLastUpdateTime < oldestOccluded->mLastUpdateTime) - { - oldestOccluded = probe; - } - } - else - { - if (!did_update && - i < mReflectionProbeCount && - (oldestProbe == nullptr || - check_priority(probe, oldestProbe))) - { - oldestProbe = probe; - } - } - - if (realtime && - closestDynamic == nullptr && - probe->mCubeIndex != -1 && - probe->getIsDynamic()) - { - closestDynamic = probe; - } - } - - if (realtime && closestDynamic != nullptr) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); - // update the closest dynamic probe realtime - // should do a full irradiance pass on "odd" frames and a radiance pass on "even" frames - closestDynamic->autoAdjustOrigin(); - - // store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set - // lighting values etc - bool radiance_pass = isRadiancePass(); - mRadiancePass = mRealtimeRadiancePass; - for (U32 i = 0; i < 6; ++i) - { - updateProbeFace(closestDynamic, i, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); - } - mRealtimeRadiancePass = !mRealtimeRadiancePass; - - // restore "isRadiancePass" - mRadiancePass = radiance_pass; - } - - { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); - mHeroProbe->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); - bool radiance_pass = isRadiancePass(); - mRadiancePass = true; - for (U32 i = 0; i < 6; ++i) - { - updateProbeFace(mHeroProbe, i, mHeroProbeResolution, mHeroArray, mMipChain, mHeroProbeCount); - } - - // restore "isRadiancePass" - mRadiancePass = radiance_pass; - } - - static LLCachedControl sUpdatePeriod(gSavedSettings, "RenderDefaultProbeUpdatePeriod", 2.f); - if ((gFrameTimeSeconds - mDefaultProbe->mLastUpdateTime) < sUpdatePeriod) - { - if (sLevel == 0) - { // when probes are disabled don't update the default probe more often than the prescribed update period - oldestProbe = nullptr; - } - } - else if (sLevel > 0) - { // when probes are enabled don't update the default probe less often than the prescribed update period - oldestProbe = mDefaultProbe; - } - - // switch to updating the next oldest probe - if (!did_update && oldestProbe != nullptr) - { - LLReflectionMap* probe = oldestProbe; - llassert(probe->mCubeIndex != -1); - - probe->autoAdjustOrigin(); - - mUpdatingProbe = probe; - doProbeUpdate(); - } - - if (oldestOccluded) - { - // as far as this occluded probe is concerned, an origin/radius update is as good as a full update - oldestOccluded->autoAdjustOrigin(); - oldestOccluded->mLastUpdateTime = gFrameTimeSeconds; - } -} - -LLReflectionMap* LLHeroProbeManager::addProbe(LLSpatialGroup* group) -{ - LLReflectionMap* probe = new LLReflectionMap(); - probe->mGroup = group; - - if (mDefaultProbe.isNull()) - { //safety check to make sure default probe is always first probe added - mDefaultProbe = new LLReflectionMap(); - mProbes.push_back(mDefaultProbe); - } - - llassert(mProbes[0] == mDefaultProbe); - - if (group) - { - probe->mOrigin = group->getOctreeNode()->getCenter(); - } - - 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; -} - -struct CompareProbeDepth -{ - bool operator()(const LLReflectionMap* lhs, const LLReflectionMap* rhs) - { - return lhs->mMinDepth < rhs->mMinDepth; - } -}; - -void LLHeroProbeManager::getReflectionMaps(std::vector& maps) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - - LLMatrix4a modelview; - modelview.loadu(gGLModelView); - LLVector4a oa; // scratch space for transformed origin - - 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) + // Probe 0 is always our mirror probe. Probe N - 1 is our water probe. + mProbes[0]->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); + for (U32 j = 0; j < mProbes.size(); j++) { - if (!mProbes[i]->mOccluded && mProbes[i]->mComplete) + for (U32 i = 0; i < 6; ++i) { - maps[count++] = mProbes[i]; - modelview.affineTransform(mProbes[i]->mOrigin, oa); - mProbes[i]->mMinDepth = -oa.getF32ptr()[2] - mProbes[i]->mRadius; - mProbes[i]->mMaxDepth = -oa.getF32ptr()[2] + mProbes[i]->mRadius; + updateProbeFace(mProbes[j], 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; - } - - if (count > 1) - { - std::sort(maps.begin(), maps.begin() + count, CompareProbeDepth()); - } - - for (U32 i = 0; i < count; ++i) - { - maps[i]->mProbeIndex = i; - } - - // null terminate list - if (count < maps.size()) - { - maps[count] = nullptr; - } -} - -LLReflectionMap* LLHeroProbeManager::registerSpatialGroup(LLSpatialGroup* group) -{ - if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME) - { - OctreeNode* node = group->getOctreeNode(); - F32 size = node->getSize().getF32ptr()[0]; - if (size >= 15.f && size <= 17.f) - { - return addProbe(group); - } - } - - return nullptr; -} - -LLReflectionMap* LLHeroProbeManager::registerViewerObject(LLViewerObject* vobj) -{ - llassert(vobj != nullptr); - - LLReflectionMap* probe = new LLReflectionMap(); - probe->mViewerObject = vobj; - probe->mOrigin.load3(vobj->getPositionAgent().mV); - - 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 LLHeroProbeManager::allocateCubeIndex() -{ - if (!mCubeFree.empty()) - { - S32 ret = mCubeFree.front(); - mCubeFree.pop_front(); - return ret; - } - - return -1; -} - -void LLHeroProbeManager::deleteProbe(U32 i) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - LLReflectionMap* probe = mProbes[i]; - - llassert(probe != mDefaultProbe); - - if (probe->mCubeIndex != -1) - { // mark the cube index used by this probe as being free - mCubeFree.push_back(probe->mCubeIndex); - } - if (mUpdatingProbe == probe) - { - mUpdatingProbe = nullptr; - mUpdatingFace = 0; - } - - // remove from any Neighbors lists - for (auto& other : probe->mNeighbors) - { - auto const & 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 LLHeroProbeManager::doProbeUpdate() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - llassert(mUpdatingProbe != nullptr); - - updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); - - if (++mUpdatingFace == 6) - { - updateNeighbors(mUpdatingProbe); - mUpdatingFace = 0; - if (isRadiancePass()) - { - mUpdatingProbe->mComplete = true; - mUpdatingProbe = nullptr; - mRadiancePass = false; - } - else - { - mRadiancePass = true; - } } } @@ -583,53 +127,36 @@ void LLHeroProbeManager::doProbeUpdate() // The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain. // At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe. // In effect this simulates single-bounce lighting. -void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount) +void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) { // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; - - LLRenderTarget* target = &mRenderTarget; - - S32 sourceIdx = probeCount; - - if (probeResolution == mHeroProbeResolution) - { - sourceIdx = 0; - target = &mHeroRenderTarget; - } mLightScale = 1.f; static LLCachedControl max_local_light_ambiance(gSavedSettings, "RenderReflectionProbeMaxLocalLightAmbiance", 8.f); - if (!isRadiancePass() && probe->getAmbiance() > max_local_light_ambiance) + if (probe->getAmbiance() > max_local_light_ambiance) { mLightScale = max_local_light_ambiance / probe->getAmbiance(); } - if (probe == mDefaultProbe) { - 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); + LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::END_RENDER_TYPES); - probe->update(target->getWidth(), face); + probe->update(mRenderTarget.getWidth(), face); gPipeline.popRenderTypeMask(); } - else - { - probe->update(target->getWidth(), face); - } gPipeline.mRT = &gPipeline.mMainRT; - if (probe != mUpdatingProbe && probe->mType != LLReflectionMap::ProbeType::REFLECTION) - { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel - sourceIdx += 1; - } + S32 sourceIdx = mReflectionProbeCount; + + // Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes. + sourceIdx += 1; gGL.setColorMask(true, true); LLGLDepthTest depth(GL_FALSE, GL_FALSE); @@ -647,7 +174,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p gGL.loadIdentity(); gGL.flush(); - U32 res = probeResolution * 2; + U32 res = mProbeResolution * 2; static LLStaticHashedString resScale("resScale"); static LLStaticHashedString direction("direction"); @@ -659,20 +186,20 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p // perform a gaussian blur on the super sampled render before downsampling { gGaussianProgram.bind(); - gGaussianProgram.uniform1f(resScale, 1.f / (probeResolution * 2)); + gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); // horizontal gGaussianProgram.uniform2f(direction, 1.f, 0.f); gGL.getTexUnit(diffuseChannel)->bind(screen_rt); - target->bindTarget(); + mRenderTarget.bindTarget(); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - target->flush(); + mRenderTarget.flush(); // vertical gGaussianProgram.uniform2f(direction, 0.f, 1.f); - gGL.getTexUnit(diffuseChannel)->bind(target); + gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); screen_rt->bindTarget(); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -680,7 +207,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p } - S32 mips = log2((F32)probeResolution) + 0.5f; + S32 mips = log2((F32)mProbeResolution) + 0.5f; gReflectionMipProgram.bind(); S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); @@ -699,7 +226,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p } - gReflectionMipProgram.uniform1f(resScale, 1.f/(probeResolution*2)); + gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2)); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -711,11 +238,14 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p if (mip >= 0) { LL_PROFILE_GPU_ZONE("probe mip copy"); - cubeArray->bind(0); - + mTexture->bind(0); + //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res); - - cubeArray->unbind(); + //if (i == 0) + //{ + //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); + //} + mTexture->unbind(); } mMipChain[i].flush(); } @@ -733,14 +263,13 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p mMipChain[0].bindTarget(); static LLStaticHashedString sSourceIdx("sourceIdx"); - if (isRadiancePass()) { //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) gRadianceGenProgram.bind(); mVertexBuffer->setBuffer(); S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - cubeArray->bind(channel); + mTexture->bind(channel); gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); @@ -755,7 +284,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); gRadianceGenProgram.uniform1f(sMipLevel, i); - gRadianceGenProgram.uniform1i(sWidth, probeResolution); + gRadianceGenProgram.uniform1i(sWidth, mProbeResolution); for (int cf = 0; cf < 6; ++cf) { // for each cube face @@ -780,50 +309,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p gRadianceGenProgram.unbind(); } - else - { - //generate irradiance map - gIrradianceGenProgram.bind(); - S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - cubeArray->bind(channel); - - 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 - for (start_mip = 0; start_mip < mMipChain.size(); ++start_mip) - { - if (mMipChain[start_mip].getWidth() == LL_IRRADIANCE_MAP_RESOLUTION) - { - break; - } - } - - //for (int i = start_mip; i < mMipChain.size(); ++i) - { - int i = start_mip; - LL_PROFILE_GPU_ZONE("probe irradiance gen"); - glViewport(0, 0, mMipChain[i].getWidth(), mMipChain[i].getHeight()); - for (int cf = 0; cf < 6; ++cf) - { // for each cube face - LLCoordFrame frame; - frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); - - F32 mat[16]; - frame.getOpenGLRotation(mat); - gGL.loadMatrix(mat); - - mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4); - - S32 res = mMipChain[i].getWidth(); - mIrradianceMaps->bind(channel); - glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); - cubeArray->bind(channel); - } - } - } mMipChain[0].flush(); @@ -831,59 +316,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p } } -void LLHeroProbeManager::reset() -{ - mReset = true; -} - -void LLHeroProbeManager::shift(const LLVector4a& offset) -{ - for (auto& probe : mProbes) - { - probe->mOrigin.add(offset); - } -} - -void LLHeroProbeManager::updateNeighbors(LLReflectionMap* probe) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - if (mDefaultProbe == probe) - { - return; - } - - //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); - 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 - if (probe->isRelevant()) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - search"); - for (auto& other : mProbes) - { - if (other != mDefaultProbe && other != probe) - { - if (other->isRelevant() && probe->intersects(other)) - { - probe->mNeighbors.push_back(other); - other->mNeighbors.push_back(probe); - } - } - } - } -} - void LLHeroProbeManager::updateUniforms() { if (!LLPipeline::sReflectionProbesEnabled) @@ -892,229 +324,6 @@ void LLHeroProbeManager::updateUniforms() } LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - - // structure for packing uniform buffer object - // see class3/deferred/reflectionProbeF.glsl - struct ReflectionProbeData - { - // for box probes, matrix that transforms from camera space to a [-1, 1] cube representing the bounding box of - // the box probe - LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT]; - - // for sphere probes, origin (xyz) and radius (w) of refmaps in clip space - LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT]; - - // extra parameters - // x - irradiance scale - // y - radiance scale - // z - fade in - // w - znear - LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT]; - - // indices used by probe: - // [i][0] - cubemap array index for this probe - // [i][1] - index into "refNeighbor" for probes that intersect this probe - // [i][2] - number of probes that intersect this probe, or -1 for no neighbors - // [i][3] - priority (probe type stored in sign bit - positive for spheres, negative for boxes) - GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4]; - - // list of neighbor indices - GLint refNeighbor[4096]; - - GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth - // numbrer of active refmaps - GLint refmapCount; - }; - - mReflectionMaps.resize(mReflectionProbeCount); - getReflectionMaps(mReflectionMaps); - - ReflectionProbeData rpd; - - F32 minDepth[256]; - - for (int i = 0; i < 256; ++i) - { - rpd.refBucket[i][0] = mReflectionProbeCount; - rpd.refBucket[i][1] = mReflectionProbeCount; - rpd.refBucket[i][2] = mReflectionProbeCount; - rpd.refBucket[i][3] = mReflectionProbeCount; - minDepth[i] = FLT_MAX; - } - - // 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 - - LLEnvironment& environment = LLEnvironment::instance(); - LLSettingsSky::ptr_t psky = environment.getCurrentSky(); - - static LLCachedControl cloud_shadow_scale(gSavedSettings, "RenderCloudShadowAmbianceFactor", 0.125f); - static LLCachedControl should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true); - F32 minimum_ambiance = psky->getTotalReflectionProbeAmbiance(cloud_shadow_scale, 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) - { - break; - } - - if (refmap != mDefaultProbe) - { - // bucket search data - // theory of operation: - // 1. Determine minimum and maximum depth of each influence volume and store in mDepth (done in getReflectionMaps) - // 2. Sort by minimum depth - // 3. Prepare a bucket for each 1m of depth out to 256m - // 4. For each bucket, store the index of the nearest probe that might influence pixels in that bucket - // 5. In the shader, lookup the bucket for the pixel depth to get the index of the first probe that could possibly influence - // the current pixel. - int depth_min = llclamp(llfloor(refmap->mMinDepth), 0, 255); - int depth_max = llclamp(llfloor(refmap->mMaxDepth), 0, 255); - for (U32 i = depth_min; i <= depth_max; ++i) - { - if (refmap->mMinDepth < minDepth[i]) - { - minDepth[i] = refmap->mMinDepth; - rpd.refBucket[i][0] = refmap->mProbeIndex; - } - } - } - - llassert(refmap->mProbeIndex == count); - llassert(mReflectionMaps[refmap->mProbeIndex] == refmap); - - llassert(refmap->mCubeIndex >= 0); // should always be true, if not, getReflectionMaps is bugged - - { - if (refmap->mViewerObject) - { // have active manual probes live-track the object they're associated with - refmap->mOrigin.load3(refmap->mViewerObject->getPositionAgent().mV); - refmap->mRadius = refmap->mViewerObject->getScale().mV[0] * 0.5f; - - } - 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]; - } - - rpd.refParams[count].set( - llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, // ambiance scale - radscale, // radiance scale - refmap->mFadeIn, // fade in weight - oa.getF32ptr()[2] - refmap->mRadius); // z near - - 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 - const U32 max_neighbors = 64; - U32 neighbor_count = 0; - - for (auto& neighbor : refmap->mNeighbors) - { - if (ni >= 4096) - { // out of space - break; - } - - GLint idx = neighbor->mProbeIndex; - if (idx == -1 || neighbor->mOccluded || neighbor->mCubeIndex == -1) - { - continue; - } - - // this neighbor may be sampled - rpd.refNeighbor[ni++] = idx; - - neighbor_count++; - if (neighbor_count >= max_neighbors) - { - break; - } - } - } - - 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++; - } - -#if 0 - { - // fill in gaps in refBucket - S32 probe_idx = mReflectionProbeCount; - - for (int i = 0; i < 256; ++i) - { - if (i < count) - { // for debugging, store depth of mReflectionsMaps[i] - rpd.refBucket[i][1] = (S32) (mReflectionMaps[i]->mDepth * 10); - } - - if (rpd.refBucket[i][0] == mReflectionProbeCount) - { - rpd.refBucket[i][0] = probe_idx; - } - else - { - probe_idx = rpd.refBucket[i][0]; - } - } - } -#endif - - rpd.refmapCount = count; - - //copy rpd into uniform buffer object - if (mUBO == 0) - { - glGenBuffers(1, &mUBO); - } - - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer"); - glBindBuffer(GL_UNIFORM_BUFFER, mUBO); - glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeData), &rpd, GL_STREAM_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - } struct HeroProbeData { @@ -1124,22 +333,23 @@ void LLHeroProbeManager::updateUniforms() HeroProbeData hpd; + LLMatrix4a modelview; modelview.loadu(gGLModelView); - + LLVector4a oa; // scratch space for transformed origin oa.set(0, 0, 0, 0); hpd.heroProbeCount = 1; - modelview.affineTransform(mHeroProbe->mOrigin, oa); + modelview.affineTransform(mProbes[0]->mOrigin, oa); hpd.heroPosition[0].set(oa.getF32ptr()); //copy rpd into uniform buffer object if (mUBO == 0) { - glGenBuffers(1, &mHeroUBO); + glGenBuffers(1, &mUBO); } { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer"); - glBindBuffer(GL_UNIFORM_BUFFER, mHeroUBO); + glBindBuffer(GL_UNIFORM_BUFFER, mUBO); glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); } @@ -1190,11 +400,11 @@ void LLHeroProbeManager::initReflectionMaps() { U32 count = LL_MAX_REFLECTION_PROBE_COUNT; - if (mTexture.isNull() || mReflectionProbeCount != count || mReset || mHeroArray.isNull()) + if (mTexture.isNull() || mReflectionProbeCount != count || mReset) { mReset = false; mReflectionProbeCount = count; - mProbeResolution = nhpo2(llclamp(gSavedSettings.getU32("RenderReflectionProbeResolution"), (U32)64, (U32)512)); + mProbeResolution = nhpo2(llclamp(gSavedSettings.getU32("RenderHeroProbeResolution"), (U32)128, (U32)1024)); mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1 mTexture = new LLCubeMapArray(); @@ -1205,25 +415,6 @@ void LLHeroProbeManager::initReflectionMaps() mIrradianceMaps = new LLCubeMapArray(); mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, FALSE); - // reset probe state - mUpdatingFace = 0; - mUpdatingProbe = nullptr; - mRadiancePass = false; - mRealtimeRadiancePass = false; - - for (auto& probe : mProbes) - { - probe->mLastUpdateTime = 0.f; - probe->mComplete = false; - probe->mProbeIndex = -1; - probe->mCubeArray = nullptr; - probe->mCubeIndex = -1; - probe->mNeighbors.clear(); - } - - mCubeFree.clear(); - initCubeFree(); - if (mDefaultProbe.isNull()) { llassert(mProbes.empty()); // default probe MUST be the first probe created @@ -1233,6 +424,8 @@ void LLHeroProbeManager::initReflectionMaps() llassert(mProbes[0] == mDefaultProbe); + // For hero probes, we treat this as the main mirror probe. + mDefaultProbe->mCubeIndex = 0; mDefaultProbe->mCubeArray = mTexture; mDefaultProbe->mDistance = 64.f; @@ -1240,27 +433,7 @@ void LLHeroProbeManager::initReflectionMaps() mDefaultProbe->mProbeIndex = 0; touch_default_probe(mDefaultProbe); - mHeroProbeResolution = 128; - - // Revise when we have both water and mirrors in hero probes. - mHeroProbeCount = 1; - - mHeroArray = new LLCubeMapArray(); - - // We use an extra probe for scratch space on these. - mHeroArray->allocate(mHeroProbeResolution, 3, mHeroProbeCount + 1, true); - - if (mHeroProbe.isNull()) { - mHeroProbe = new LLReflectionMap(); - } - - mHeroProbe->mCubeIndex = 0; - mHeroProbe->mCubeArray = mHeroArray; - mHeroProbe->mDistance = 64.f; - mHeroProbe->mRadius = 4096.f; - mHeroProbe->mProbeIndex = 0; - touch_default_probe(mHeroProbe); - + mProbes.push_back(mDefaultProbe); } if (mVertexBuffer.isNull()) @@ -1294,28 +467,16 @@ void LLHeroProbeManager::cleanup() mTexture = nullptr; mIrradianceMaps = nullptr; - mHeroArray = nullptr; mProbes.clear(); - mKillList.clear(); - mCreateList.clear(); mReflectionMaps.clear(); - mUpdatingFace = 0; mDefaultProbe = nullptr; mUpdatingProbe = nullptr; - - mHeroProbe = nullptr; glDeleteBuffers(1, &mUBO); mUBO = 0; - - glDeleteBuffers(1, &mHeroUBO); - mHeroUBO = 0; - - // note: also called on teleport (not just shutdown), so make sure we're in a good "starting" state - initCubeFree(); } void LLHeroProbeManager::doOcclusion() -- cgit v1.2.3 From d4254538d1bdd5d93a4eadea961a955ce79ab06f Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 21 Aug 2023 04:22:16 -0700 Subject: Further cleanup of the hero probe manager. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 5edf819fff..1773dffa8b 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -106,7 +106,6 @@ void LLHeroProbeManager::update() { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); - // Probe 0 is always our mirror probe. Probe N - 1 is our water probe. mProbes[0]->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); for (U32 j = 0; j < mProbes.size(); j++) @@ -311,8 +310,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) } mMipChain[0].flush(); - - gIrradianceGenProgram.unbind(); } } @@ -466,7 +463,6 @@ void LLHeroProbeManager::cleanup() mMipChain.clear(); mTexture = nullptr; - mIrradianceMaps = nullptr; mProbes.clear(); -- cgit v1.2.3 From 869bb7f16ae3e931f11840332ab00715a4ef27af Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 21 Aug 2023 05:15:48 -0700 Subject: Readd occlusion culling for hero probes. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 1773dffa8b..33a54c797e 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -132,23 +132,8 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) gPipeline.mRT = &gPipeline.mAuxillaryRT; mLightScale = 1.f; - static LLCachedControl max_local_light_ambiance(gSavedSettings, "RenderReflectionProbeMaxLocalLightAmbiance", 8.f); - if (probe->getAmbiance() > max_local_light_ambiance) - { - mLightScale = max_local_light_ambiance / probe->getAmbiance(); - } - { - 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::RENDER_TYPE_AVATAR, LLPipeline::END_RENDER_TYPES); - - probe->update(mRenderTarget.getWidth(), face); - - gPipeline.popRenderTypeMask(); - } + probe->update(mRenderTarget.getWidth(), face); gPipeline.mRT = &gPipeline.mMainRT; @@ -401,7 +386,7 @@ void LLHeroProbeManager::initReflectionMaps() { mReset = false; mReflectionProbeCount = count; - mProbeResolution = nhpo2(llclamp(gSavedSettings.getU32("RenderHeroProbeResolution"), (U32)128, (U32)1024)); + mProbeResolution = nhpo2(1024); mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1 mTexture = new LLCubeMapArray(); -- cgit v1.2.3 From 0eba1396dcc7ec5c32124dbfd48abb75c1a5b524 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 21 Aug 2023 07:59:06 -0700 Subject: Experiment with placement a bit when there's no drawable. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 80 ++++++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 7 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 33a54c797e..0d2e8da294 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -36,6 +36,11 @@ #include "llviewercontrol.h" #include "llenvironment.h" #include "llstartup.h" +#include "llagent.h" +#include "llagentcamera.h" +#include "llviewerwindow.h" +#include "llviewerjoystick.h" +#include "llviewermediafocus.h" extern BOOL gCubeSnapshot; extern BOOL gTeleportDisplay; @@ -98,16 +103,60 @@ void LLHeroProbeManager::update() llassert(mProbes[0] == mDefaultProbe); - LLVector4a camera_pos; - camera_pos.load3(LLViewerCamera::instance().getOrigin().mV); + LLVector3 camera_pos = LLViewerCamera::instance().getOrigin(); + LLVector4a probe_pos; + + LLVector3 focus_point; + + LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); + if (obj && obj->mDrawable && obj->isSelected()) + { // focus on selected media object + S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); + if (obj && obj->mDrawable) + { + LLFace* face = obj->mDrawable->getFace(face_idx); + if (face) + { + focus_point = face->getPositionAgent(); + } + } + } + + if (focus_point.isExactlyZero()) + { + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { // focus on point under cursor + focus_point.set(gDebugRaycastIntersection.getF32ptr()); + } + else if (gAgentCamera.cameraMouselook()) + { // focus on point under mouselook crosshairs + LLVector4a result; + result.clear(); + + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result); + + focus_point.set(result.getF32ptr()); + } + else + { + // focus on alt-zoom target + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); + } + } + } + + probe_pos.load3(((focus_point + camera_pos) / 2).mV); static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); - // Probe 0 is always our mirror probe. Probe N - 1 is our water probe. - mProbes[0]->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime"); + // Probe 0 is always our mirror probe. + mProbes[0]->mOrigin = probe_pos; for (U32 j = 0; j < mProbes.size(); j++) { for (U32 i = 0; i < 6; ++i) @@ -131,8 +180,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; - mLightScale = 1.f; - probe->update(mRenderTarget.getWidth(), face); gPipeline.mRT = &gPipeline.mMainRT; @@ -458,6 +505,9 @@ void LLHeroProbeManager::cleanup() glDeleteBuffers(1, &mUBO); mUBO = 0; + + mHeroList.clear(); + mNearestHero = nullptr; } void LLHeroProbeManager::doOcclusion() @@ -473,3 +523,19 @@ void LLHeroProbeManager::doOcclusion() } } } + +void LLHeroProbeManager::registerHeroDrawable(LLDrawable* drawablep) +{ + if (mHeroList.find(drawablep) == mHeroList.end()) + { + mHeroList.insert(drawablep); + } +} + +void LLHeroProbeManager::unregisterHeroDrawable(LLDrawable *drawablep) +{ + if (mHeroList.find(drawablep) != mHeroList.end()) + { + mHeroList.erase(drawablep); + } +} -- cgit v1.2.3 From 316052024958dde817a8d0809c77e29ec4cef64c Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 24 Aug 2023 12:51:19 -0700 Subject: Fix the probe flashing, and avatars. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 0d2e8da294..729603e960 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -157,6 +157,11 @@ void LLHeroProbeManager::update() LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime"); // Probe 0 is always our mirror probe. mProbes[0]->mOrigin = probe_pos; + + bool radiance_pass = gPipeline.mReflectionMapManager.isRadiancePass(); + + gPipeline.mReflectionMapManager.mRadiancePass = true; + for (U32 j = 0; j < mProbes.size(); j++) { for (U32 i = 0; i < 6; ++i) @@ -164,6 +169,8 @@ void LLHeroProbeManager::update() updateProbeFace(mProbes[j], i); } } + + gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass; } } @@ -180,7 +187,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; - probe->update(mRenderTarget.getWidth(), face); + probe->update(mRenderTarget.getWidth(), face, true); gPipeline.mRT = &gPipeline.mMainRT; -- cgit v1.2.3 From fbecd348f897ee91a5639e7e9fe4f0578d72b8e2 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 29 Aug 2023 03:04:04 -0700 Subject: Add protocol level mirror support, and UI. --- indra/newview/llheroprobemanager.cpp | 87 ++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 34 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 729603e960..6374b10823 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -103,53 +103,71 @@ void LLHeroProbeManager::update() llassert(mProbes[0] == mDefaultProbe); - LLVector3 camera_pos = LLViewerCamera::instance().getOrigin(); - LLVector4a probe_pos; - LLVector3 focus_point; - - LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); - if (obj && obj->mDrawable && obj->isSelected()) - { // focus on selected media object - S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); - if (obj && obj->mDrawable) + if (mHeroList.empty()) + { + LLVector3 focus_point; + + LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); + if (obj && obj->mDrawable && obj->isSelected()) + { // focus on selected media object + S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); + if (obj && obj->mDrawable) + { + LLFace* face = obj->mDrawable->getFace(face_idx); + if (face) + { + focus_point = face->getPositionAgent(); + } + } + } + + if (focus_point.isExactlyZero()) { - LLFace* face = obj->mDrawable->getFace(face_idx); - if (face) + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { // focus on point under cursor + focus_point.set(gDebugRaycastIntersection.getF32ptr()); + } + else if (gAgentCamera.cameraMouselook()) + { // focus on point under mouselook crosshairs + LLVector4a result; + result.clear(); + + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result); + + focus_point.set(result.getF32ptr()); + } + else { - focus_point = face->getPositionAgent(); + // focus on alt-zoom target + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); + } } } + + probe_pos.load3(((focus_point)).mV); } - - if (focus_point.isExactlyZero()) + else { - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { // focus on point under cursor - focus_point.set(gDebugRaycastIntersection.getF32ptr()); - } - else if (gAgentCamera.cameraMouselook()) - { // focus on point under mouselook crosshairs - LLVector4a result; - result.clear(); - - gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result); - - focus_point.set(result.getF32ptr()); - } - else + // Get the nearest hero. + float distance = F32_MAX; + + for (auto drawable : mHeroList) { - // focus on alt-zoom target - LLViewerRegion* region = gAgent.getRegion(); - if (region) + if (drawable.notNull()) { - focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); + if (drawable->mDistanceWRTCamera < distance) + { + probe_pos.load3(drawable->mXform.getPosition().mV); + } } } } - probe_pos.load3(((focus_point + camera_pos) / 2).mV); static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); @@ -464,7 +482,7 @@ void LLHeroProbeManager::initReflectionMaps() mDefaultProbe->mCubeIndex = 0; mDefaultProbe->mCubeArray = mTexture; - mDefaultProbe->mDistance = 64.f; + mDefaultProbe->mDistance = 12.f; mDefaultProbe->mRadius = 4096.f; mDefaultProbe->mProbeIndex = 0; touch_default_probe(mDefaultProbe); @@ -536,6 +554,7 @@ void LLHeroProbeManager::registerHeroDrawable(LLDrawable* drawablep) if (mHeroList.find(drawablep) == mHeroList.end()) { mHeroList.insert(drawablep); + LL_INFOS() << "Added hero drawable." << LL_ENDL; } } -- cgit v1.2.3 From 348d427db6537746c5c8c9a0d1aa021f074afbb5 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 29 Aug 2023 05:08:47 -0700 Subject: Add a probe strength uniform for hero probes. On standard reflection probes this doesn't really do anything. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 73 ++++++++++++------------------------ 1 file changed, 23 insertions(+), 50 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 6374b10823..c385c9a99f 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -104,68 +104,41 @@ void LLHeroProbeManager::update() llassert(mProbes[0] == mDefaultProbe); LLVector4a probe_pos; - - if (mHeroList.empty()) + LLVector3 camera_pos = LLViewerCamera::instance().mOrigin; { - LLVector3 focus_point; + // Get the nearest hero. + float distance = F32_MAX; - LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); - if (obj && obj->mDrawable && obj->isSelected()) - { // focus on selected media object - S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); - if (obj && obj->mDrawable) - { - LLFace* face = obj->mDrawable->getFace(face_idx); - if (face) - { - focus_point = face->getPositionAgent(); - } - } + if (mNearestHero.notNull()) + { + distance = mNearestHero->mDistanceWRTCamera; } - if (focus_point.isExactlyZero()) + for (auto drawable : mHeroList) { - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { // focus on point under cursor - focus_point.set(gDebugRaycastIntersection.getF32ptr()); - } - else if (gAgentCamera.cameraMouselook()) - { // focus on point under mouselook crosshairs - LLVector4a result; - result.clear(); - - gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result); - - focus_point.set(result.getF32ptr()); - } - else + if (drawable.notNull() && drawable != mNearestHero) { - // focus on alt-zoom target - LLViewerRegion* region = gAgent.getRegion(); - if (region) + if (drawable->mDistanceWRTCamera < distance) { - focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); + mIsInTransition = true; + mNearestHero = drawable; } } } - - probe_pos.load3(((focus_point)).mV); + } + + if (mIsInTransition && mHeroProbeStrength > 0.f) + { + mHeroProbeStrength -= 0.05f; } else { - // Get the nearest hero. - float distance = F32_MAX; + if (mNearestHero.notNull()) + probe_pos.set(mNearestHero->mXform.getPosition().mV[0], mNearestHero->mXform.getPosition().mV[1], camera_pos.mV[2]); - for (auto drawable : mHeroList) - { - if (drawable.notNull()) - { - if (drawable->mDistanceWRTCamera < distance) - { - probe_pos.load3(drawable->mXform.getPosition().mV); - } - } - } + + if (mHeroProbeStrength < 1.f) + mHeroProbeStrength += 0.05f; } static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); @@ -328,7 +301,8 @@ void LLHeroProbeManager::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, mHeroProbeStrength); + U32 res = mMipChain[0].getWidth(); for (int i = 0; i < mMipChain.size(); ++i) @@ -554,7 +528,6 @@ void LLHeroProbeManager::registerHeroDrawable(LLDrawable* drawablep) if (mHeroList.find(drawablep) == mHeroList.end()) { mHeroList.insert(drawablep); - LL_INFOS() << "Added hero drawable." << LL_ENDL; } } -- cgit v1.2.3 From 32d1984bf98dce6e4938534342e67dbc40fbb073 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 1 Sep 2023 08:28:57 -0700 Subject: Temporary data model shenanigans. Should help tweak and tune placement with direct community guidance. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 66 +++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 16 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index c385c9a99f..166321930f 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -109,16 +109,16 @@ void LLHeroProbeManager::update() // Get the nearest hero. float distance = F32_MAX; - if (mNearestHero.notNull()) + if (mNearestHero != nullptr) { - distance = mNearestHero->mDistanceWRTCamera; + distance = mNearestHero->mDrawable->mDistanceWRTCamera; } - for (auto drawable : mHeroList) + for (auto drawable : mHeroVOList) { - if (drawable.notNull() && drawable != mNearestHero) + if (drawable != nullptr && drawable != mNearestHero && drawable->mDrawable.notNull()) { - if (drawable->mDistanceWRTCamera < distance) + if (drawable->mDrawable->mDistanceWRTCamera < distance) { mIsInTransition = true; mNearestHero = drawable; @@ -133,8 +133,41 @@ void LLHeroProbeManager::update() } else { - if (mNearestHero.notNull()) - probe_pos.set(mNearestHero->mXform.getPosition().mV[0], mNearestHero->mXform.getPosition().mV[1], camera_pos.mV[2]); + + if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) + { + + LLVector3 hero_pos = mNearestHero->mDrawable->mXform.getPosition(); + switch (mNearestHero->mirrorPlacementMode()) { + case 0: + probe_pos.set(camera_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]); + break; + case 1: + + probe_pos.set(hero_pos.mV[0], camera_pos.mV[1], hero_pos.mV[2]); + break; + case 2: + + probe_pos.set(hero_pos.mV[0], hero_pos.mV[1], camera_pos.mV[2]); + break; + + case 3: + // Find the nearest point relative to the camera on the VOVolume. + LLVector4a hit_pos; + bool hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), + LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), + -1, + FALSE, + FALSE, + FALSE, + NULL, + &hit_pos); + if (hit) + probe_pos = hit_pos; + + break; + } + } if (mHeroProbeStrength < 1.f) @@ -505,7 +538,7 @@ void LLHeroProbeManager::cleanup() glDeleteBuffers(1, &mUBO); mUBO = 0; - mHeroList.clear(); + mHeroVOList.clear(); mNearestHero = nullptr; } @@ -523,18 +556,19 @@ void LLHeroProbeManager::doOcclusion() } } -void LLHeroProbeManager::registerHeroDrawable(LLDrawable* drawablep) +void LLHeroProbeManager::registerHeroDrawable(LLVOVolume* drawablep) { - if (mHeroList.find(drawablep) == mHeroList.end()) - { - mHeroList.insert(drawablep); - } + if (mHeroVOList.find(drawablep) == mHeroVOList.end()) + { + mHeroVOList.insert(drawablep); + LL_INFOS() << "Mirror drawable registered." << LL_ENDL; + } } -void LLHeroProbeManager::unregisterHeroDrawable(LLDrawable *drawablep) +void LLHeroProbeManager::unregisterHeroDrawable(LLVOVolume* drawablep) { - if (mHeroList.find(drawablep) != mHeroList.end()) + if (mHeroVOList.find(drawablep) != mHeroVOList.end()) { - mHeroList.erase(drawablep); + mHeroVOList.erase(drawablep); } } -- cgit v1.2.3 From 25aee5e983a8de712565d8241cbdb18da832a4d1 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 8 Sep 2023 15:54:52 -0700 Subject: Some more modes for mirrors to place the probe. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 165 ++++++++++++++++++++++------------- 1 file changed, 106 insertions(+), 59 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 166321930f..64c9ab1527 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -105,75 +105,121 @@ void LLHeroProbeManager::update() LLVector4a probe_pos; LLVector3 camera_pos = LLViewerCamera::instance().mOrigin; + if (mHeroVOList.size() > 0) { - // Get the nearest hero. - float distance = F32_MAX; - - if (mNearestHero != nullptr) { - distance = mNearestHero->mDrawable->mDistanceWRTCamera; - } - - for (auto drawable : mHeroVOList) - { - if (drawable != nullptr && drawable != mNearestHero && drawable->mDrawable.notNull()) + if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) { - if (drawable->mDrawable->mDistanceWRTCamera < distance) - { - mIsInTransition = true; - mNearestHero = drawable; + LLVector3 hero_pos = mNearestHero->getPosition(); + + // Make sure our camera is clamped to the hero's bounding box. + camera_pos.clamp(mNearestHero->getBoundingBoxAgent().getMinAgent(), mNearestHero->getBoundingBoxAgent().getMaxAgent()); + bool hit = false; + LLVector4a hit_pos; + LLVector3 focus_point; + LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); + LLQuaternion camera_rot; + + switch (mNearestHero->mirrorPlacementMode()) { + case 0: + probe_pos.set(camera_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]); + break; + case 1: + + probe_pos.set(hero_pos.mV[0], camera_pos.mV[1], hero_pos.mV[2]); + break; + case 2: + + probe_pos.set(hero_pos.mV[0], hero_pos.mV[1], camera_pos.mV[2]); + break; + + case 3: + // Find the nearest point relative to the camera on the VOVolume. + hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), + LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), + -1, + FALSE, + FALSE, + FALSE, + NULL, + &hit_pos); + if (hit) + probe_pos = hit_pos; + break; + + case 4: + probe_pos.load3(hero_pos.mV); + break; + case 5: + focus_point.set(hero_pos.mV[0] - mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[0], hero_pos.mV[1], hero_pos.mV[2]); + probe_pos.load3(focus_point.mV); + break; + case 6: + focus_point.set(hero_pos.mV[0] + mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[0], hero_pos.mV[1], hero_pos.mV[2]); + probe_pos.load3(focus_point.mV); + break; + case 7: + + if (obj && obj->mDrawable && obj->isSelected()) + { // focus on selected media object + S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); + if (obj && obj->mDrawable) + { + LLFace* face = obj->mDrawable->getFace(face_idx); + if (face) + { + focus_point = face->getPositionAgent(); + } + } + } + + if (focus_point.isExactlyZero()) + { + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { // focus on point under cursor + focus_point.set(gDebugRaycastIntersection.getF32ptr()); + } + else if (gAgentCamera.cameraMouselook()) + { // focus on point under mouselook crosshairs + LLVector4a result; + result.clear(); + + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, TRUE, NULL, &result); + + focus_point.set(result.getF32ptr()); + } + else + { + // focus on alt-zoom target + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); + } + } + } + + probe_pos.load3(focus_point.mV); + + break; + case 8: + camera_rot.setAngleAxis(180, 0, 0, 1); + focus_point = camera_pos - hero_pos; + focus_point.rotVec(camera_rot); + probe_pos.load3((camera_pos + focus_point).mV); + break; } } + + mHeroProbeStrength = 1; } } - - if (mIsInTransition && mHeroProbeStrength > 0.f) - { - mHeroProbeStrength -= 0.05f; - } else { - - if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) - { - - LLVector3 hero_pos = mNearestHero->mDrawable->mXform.getPosition(); - switch (mNearestHero->mirrorPlacementMode()) { - case 0: - probe_pos.set(camera_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]); - break; - case 1: - - probe_pos.set(hero_pos.mV[0], camera_pos.mV[1], hero_pos.mV[2]); - break; - case 2: - - probe_pos.set(hero_pos.mV[0], hero_pos.mV[1], camera_pos.mV[2]); - break; - - case 3: - // Find the nearest point relative to the camera on the VOVolume. - LLVector4a hit_pos; - bool hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), - LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), - -1, - FALSE, - FALSE, - FALSE, - NULL, - &hit_pos); - if (hit) - probe_pos = hit_pos; - - break; - } - } - - - if (mHeroProbeStrength < 1.f) - mHeroProbeStrength += 0.05f; + probe_pos.load3(camera_pos.mV); } + static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); @@ -224,7 +270,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) LLGLDepthTest depth(GL_FALSE, GL_FALSE); LLGLDisable cull(GL_CULL_FACE); LLGLDisable blend(GL_BLEND); - + // downsample to placeholder map { gGL.matrixMode(gGL.MM_MODELVIEW); @@ -558,6 +604,7 @@ void LLHeroProbeManager::doOcclusion() void LLHeroProbeManager::registerHeroDrawable(LLVOVolume* drawablep) { + mNearestHero = drawablep; if (mHeroVOList.find(drawablep) == mHeroVOList.end()) { mHeroVOList.insert(drawablep); -- cgit v1.2.3 From 091beab79872fbaf4e3e7de39c8e69ef08e5a1c7 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 8 Sep 2023 17:43:24 -0700 Subject: Even more placement modes. Reflected axis modes need work. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 93 +++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 64c9ab1527..caeb9d4e8e 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -159,6 +159,22 @@ void LLHeroProbeManager::update() probe_pos.load3(focus_point.mV); break; case 7: + focus_point.set(hero_pos.mV[0], hero_pos.mV[1] - mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[1], hero_pos.mV[2]); + probe_pos.load3(focus_point.mV); + break; + case 8: + focus_point.set(hero_pos.mV[0], hero_pos.mV[1] + mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[1], hero_pos.mV[2]); + probe_pos.load3(focus_point.mV); + break; + case 9: + focus_point.set(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2] - mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[2]); + probe_pos.load3(focus_point.mV); + break; + case 10: + focus_point.set(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2] + mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[2]); + probe_pos.load3(focus_point.mV); + break; + case 11: if (obj && obj->mDrawable && obj->isSelected()) { // focus on selected media object @@ -202,12 +218,87 @@ void LLHeroProbeManager::update() probe_pos.load3(focus_point.mV); break; - case 8: + case 12: + + hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), + LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), + -1, + FALSE, + FALSE, + FALSE, + NULL, + &hit_pos); + if (hit) + { + hero_pos.mV[0] = hit_pos.getF32ptr()[0]; + hero_pos.mV[1] = hit_pos.getF32ptr()[1]; + hero_pos.mV[2] = hit_pos.getF32ptr()[2]; + } + + camera_rot.setAngleAxis(180, 1, 0, 0); + focus_point = camera_pos - hero_pos; + focus_point.rotVec(camera_rot); + probe_pos.load3((camera_pos + focus_point).mV); + break; + case 13: + + hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), + LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), + -1, + FALSE, + FALSE, + FALSE, + NULL, + &hit_pos); + if (hit) + { + hero_pos.mV[0] = hit_pos.getF32ptr()[0]; + hero_pos.mV[1] = hit_pos.getF32ptr()[1]; + hero_pos.mV[2] = hit_pos.getF32ptr()[2]; + } + + camera_rot.setAngleAxis(180, 0, 1, 0); + focus_point = camera_pos - hero_pos; + focus_point.rotVec(camera_rot); + probe_pos.load3((camera_pos + focus_point).mV); + break; + case 14: + + hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), + LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), + -1, + FALSE, + FALSE, + FALSE, + NULL, + &hit_pos); + if (hit) + { + hero_pos.mV[0] = hit_pos.getF32ptr()[0]; + hero_pos.mV[1] = hit_pos.getF32ptr()[1]; + hero_pos.mV[2] = hit_pos.getF32ptr()[2]; + } + camera_rot.setAngleAxis(180, 0, 0, 1); focus_point = camera_pos - hero_pos; focus_point.rotVec(camera_rot); probe_pos.load3((camera_pos + focus_point).mV); break; + case 15: + probe_pos.set(camera_pos.mV[0], camera_pos.mV[1], hero_pos.mV[2]); + break; + case 16: + probe_pos.set(camera_pos.mV[0], hero_pos.mV[1], camera_pos.mV[2]); + break; + case 17: + probe_pos.set(hero_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]); + break; + case 18: + probe_pos.load3(camera_pos.mV); + break; + case 19: + probe_pos.load3(((camera_pos + hero_pos) / 2).mV); + break; } } -- cgit v1.2.3 From d4c75b9b765631c1ccfc369e765529aefe3e061a Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 8 Sep 2023 21:29:05 -0700 Subject: Mostly fixed placement math. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 210 ++++++++--------------------------- 1 file changed, 44 insertions(+), 166 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index caeb9d4e8e..f1906272b8 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -110,194 +110,57 @@ void LLHeroProbeManager::update() { if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) { - LLVector3 hero_pos = mNearestHero->getPosition(); + LLVector3 hero_pos = mNearestHero->mDrawable->mXform.getWorldPosition(); - // Make sure our camera is clamped to the hero's bounding box. - camera_pos.clamp(mNearestHero->getBoundingBoxAgent().getMinAgent(), mNearestHero->getBoundingBoxAgent().getMaxAgent()); bool hit = false; LLVector4a hit_pos; LLVector3 focus_point; LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); LLQuaternion camera_rot; + F32 angleInRadians = 180 * DEG_TO_RAD; + + LLMatrix4 rotationMatrix; + + LLVector3 translatedPoint; + LLVector3 rotatedTranslatedPoint; + LLVector3 rotatedPoint; switch (mNearestHero->mirrorPlacementMode()) { case 0: - probe_pos.set(camera_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]); - break; - case 1: - probe_pos.set(hero_pos.mV[0], camera_pos.mV[1], hero_pos.mV[2]); - break; - case 2: + hero_pos.mV[1] = camera_pos.mV[1]; - probe_pos.set(hero_pos.mV[0], hero_pos.mV[1], camera_pos.mV[2]); - break; + rotationMatrix.rotate(angleInRadians, LLVector4(1, 0, 0, 0)); - case 3: - // Find the nearest point relative to the camera on the VOVolume. - hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), - LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), - -1, - FALSE, - FALSE, - FALSE, - NULL, - &hit_pos); - if (hit) - probe_pos = hit_pos; - break; + translatedPoint = camera_pos - hero_pos; + rotatedTranslatedPoint = translatedPoint * rotationMatrix; + rotatedPoint = rotatedTranslatedPoint + hero_pos; - case 4: - probe_pos.load3(hero_pos.mV); - break; - case 5: - focus_point.set(hero_pos.mV[0] - mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[0], hero_pos.mV[1], hero_pos.mV[2]); - probe_pos.load3(focus_point.mV); + probe_pos.load3(rotatedPoint.mV); break; - case 6: - focus_point.set(hero_pos.mV[0] + mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[0], hero_pos.mV[1], hero_pos.mV[2]); - probe_pos.load3(focus_point.mV); - break; - case 7: - focus_point.set(hero_pos.mV[0], hero_pos.mV[1] - mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[1], hero_pos.mV[2]); - probe_pos.load3(focus_point.mV); - break; - case 8: - focus_point.set(hero_pos.mV[0], hero_pos.mV[1] + mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[1], hero_pos.mV[2]); - probe_pos.load3(focus_point.mV); - break; - case 9: - focus_point.set(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2] - mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[2]); - probe_pos.load3(focus_point.mV); - break; - case 10: - focus_point.set(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2] + mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[2]); - probe_pos.load3(focus_point.mV); - break; - case 11: - - if (obj && obj->mDrawable && obj->isSelected()) - { // focus on selected media object - S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); - if (obj && obj->mDrawable) - { - LLFace* face = obj->mDrawable->getFace(face_idx); - if (face) - { - focus_point = face->getPositionAgent(); - } - } - } - - if (focus_point.isExactlyZero()) - { - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { // focus on point under cursor - focus_point.set(gDebugRaycastIntersection.getF32ptr()); - } - else if (gAgentCamera.cameraMouselook()) - { // focus on point under mouselook crosshairs - LLVector4a result; - result.clear(); - - gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, TRUE, NULL, &result); - - focus_point.set(result.getF32ptr()); - } - else - { - // focus on alt-zoom target - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); - } - } - } + case 1: - probe_pos.load3(focus_point.mV); + hero_pos.mV[2] = camera_pos.mV[2]; - break; - case 12: + rotationMatrix.rotate(angleInRadians, LLVector4(0, 1, 0, 0)); - hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), - LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), - -1, - FALSE, - FALSE, - FALSE, - NULL, - &hit_pos); - if (hit) - { - hero_pos.mV[0] = hit_pos.getF32ptr()[0]; - hero_pos.mV[1] = hit_pos.getF32ptr()[1]; - hero_pos.mV[2] = hit_pos.getF32ptr()[2]; - } + translatedPoint = camera_pos - hero_pos; + rotatedTranslatedPoint = translatedPoint * rotationMatrix; + rotatedPoint = rotatedTranslatedPoint + hero_pos; - camera_rot.setAngleAxis(180, 1, 0, 0); - focus_point = camera_pos - hero_pos; - focus_point.rotVec(camera_rot); - probe_pos.load3((camera_pos + focus_point).mV); + probe_pos.load3(rotatedPoint.mV); break; - case 13: + case 2: - hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), - LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), - -1, - FALSE, - FALSE, - FALSE, - NULL, - &hit_pos); - if (hit) - { - hero_pos.mV[0] = hit_pos.getF32ptr()[0]; - hero_pos.mV[1] = hit_pos.getF32ptr()[1]; - hero_pos.mV[2] = hit_pos.getF32ptr()[2]; - } + hero_pos.mV[0] = camera_pos.mV[0]; - camera_rot.setAngleAxis(180, 0, 1, 0); - focus_point = camera_pos - hero_pos; - focus_point.rotVec(camera_rot); - probe_pos.load3((camera_pos + focus_point).mV); - break; - case 14: + rotationMatrix.rotate(angleInRadians, LLVector4(0, 0, 1, 0)); - hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), - LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), - -1, - FALSE, - FALSE, - FALSE, - NULL, - &hit_pos); - if (hit) - { - hero_pos.mV[0] = hit_pos.getF32ptr()[0]; - hero_pos.mV[1] = hit_pos.getF32ptr()[1]; - hero_pos.mV[2] = hit_pos.getF32ptr()[2]; - } + translatedPoint = camera_pos - hero_pos; + rotatedTranslatedPoint = translatedPoint * rotationMatrix; + rotatedPoint = rotatedTranslatedPoint + hero_pos; - camera_rot.setAngleAxis(180, 0, 0, 1); - focus_point = camera_pos - hero_pos; - focus_point.rotVec(camera_rot); - probe_pos.load3((camera_pos + focus_point).mV); - break; - case 15: - probe_pos.set(camera_pos.mV[0], camera_pos.mV[1], hero_pos.mV[2]); - break; - case 16: - probe_pos.set(camera_pos.mV[0], hero_pos.mV[1], camera_pos.mV[2]); - break; - case 17: - probe_pos.set(hero_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]); - break; - case 18: - probe_pos.load3(camera_pos.mV); - break; - case 19: - probe_pos.load3(((camera_pos + hero_pos) / 2).mV); + probe_pos.load3(rotatedPoint.mV); break; } } @@ -345,6 +208,14 @@ void LLHeroProbeManager::update() // In effect this simulates single-bounce lighting. void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) { + // Make our object invisible. + + if (mNearestHero) + { + mNearestHero->setDrawableState(LLDrawable::FORCE_INVISIBLE, true); + gPipeline.markRebuild( mNearestHero->mDrawable, LLDrawable::REBUILD_ALL); + } + // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; @@ -353,7 +224,8 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) gPipeline.mRT = &gPipeline.mMainRT; S32 sourceIdx = mReflectionProbeCount; - + + // Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes. sourceIdx += 1; @@ -512,6 +384,12 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) mMipChain[0].flush(); } + + if (mNearestHero) + { + mNearestHero->clearDrawableState(LLDrawable::FORCE_INVISIBLE, true); + gPipeline.markRebuild( mNearestHero->mDrawable, LLDrawable::REBUILD_ALL); + } } void LLHeroProbeManager::updateUniforms() -- cgit v1.2.3 From 7761ebea4836e0e30148711159ea744bcaea28a9 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 8 Sep 2023 21:55:15 -0700 Subject: Update llheroprobemanager.cpp DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index f1906272b8..13faf13a0f 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -112,10 +112,8 @@ void LLHeroProbeManager::update() { LLVector3 hero_pos = mNearestHero->mDrawable->mXform.getWorldPosition(); - bool hit = false; LLVector4a hit_pos; LLVector3 focus_point; - LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); LLQuaternion camera_rot; F32 angleInRadians = 180 * DEG_TO_RAD; -- cgit v1.2.3 From d6f15179d1a5c7bdb8977652aee557b3bd051cf7 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Sat, 9 Sep 2023 14:51:12 -0700 Subject: Remove the rebuild on the drawable. Wasn't working as expected anyways. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 13faf13a0f..7c616593fc 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -206,14 +206,6 @@ void LLHeroProbeManager::update() // In effect this simulates single-bounce lighting. void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) { - // Make our object invisible. - - if (mNearestHero) - { - mNearestHero->setDrawableState(LLDrawable::FORCE_INVISIBLE, true); - gPipeline.markRebuild( mNearestHero->mDrawable, LLDrawable::REBUILD_ALL); - } - // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; @@ -382,12 +374,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) mMipChain[0].flush(); } - - if (mNearestHero) - { - mNearestHero->clearDrawableState(LLDrawable::FORCE_INVISIBLE, true); - gPipeline.markRebuild( mNearestHero->mDrawable, LLDrawable::REBUILD_ALL); - } } void LLHeroProbeManager::updateUniforms() -- cgit v1.2.3 From 3ff3e1a3537a5d051180aaf6223f5ddd8b540d35 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 20 Sep 2023 14:57:25 -0700 Subject: Remove some unnecessary irradiance map bits, also fix the leak. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 7c616593fc..687ebbf168 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -300,12 +300,9 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) { LL_PROFILE_GPU_ZONE("probe mip copy"); mTexture->bind(0); - //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res); - //if (i == 0) - //{ - //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); - //} + mTexture->unbind(); } mMipChain[i].flush(); @@ -458,7 +455,7 @@ void LLHeroProbeManager::renderDebug() void LLHeroProbeManager::initReflectionMaps() { - U32 count = LL_MAX_REFLECTION_PROBE_COUNT; + U32 count = LL_MAX_HERO_PROBE_COUNT; if (mTexture.isNull() || mReflectionProbeCount != count || mReset) { @@ -472,9 +469,6 @@ void LLHeroProbeManager::initReflectionMaps() // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source) mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2); - mIrradianceMaps = new LLCubeMapArray(); - mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, FALSE); - if (mDefaultProbe.isNull()) { llassert(mProbes.empty()); // default probe MUST be the first probe created -- cgit v1.2.3 From d092f3e1dc1c322a0c3c1e55b9b6e1792d6b0f59 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 25 Sep 2023 12:18:02 -0700 Subject: Get the average normal of the face. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 687ebbf168..c3d7ce6e76 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -118,11 +118,20 @@ void LLHeroProbeManager::update() F32 angleInRadians = 180 * DEG_TO_RAD; LLMatrix4 rotationMatrix; + + rotationMatrix.rotate(angleInRadians, LLVector4(mNearestHero->mDrawable->getFace(0)->getAverageNormal())); LLVector3 translatedPoint; LLVector3 rotatedTranslatedPoint; LLVector3 rotatedPoint; + translatedPoint = camera_pos - hero_pos; + rotatedTranslatedPoint = translatedPoint * rotationMatrix; + rotatedPoint = rotatedTranslatedPoint + hero_pos; + + probe_pos.load3(rotatedPoint.mV); + + /* switch (mNearestHero->mirrorPlacementMode()) { case 0: @@ -161,6 +170,7 @@ void LLHeroProbeManager::update() probe_pos.load3(rotatedPoint.mV); break; } + */ } mHeroProbeStrength = 1; -- cgit v1.2.3 From 18b219cf83a1cd405cf36b9f58fc48f717409598 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 25 Sep 2023 19:20:46 -0700 Subject: Start removing the concept of placement mode - it's either a mirror or not. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index c3d7ce6e76..fe9f669365 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -110,7 +110,8 @@ void LLHeroProbeManager::update() { if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) { - LLVector3 hero_pos = mNearestHero->mDrawable->mXform.getWorldPosition(); + + LLVector3 hero_pos = mNearestHero->mDrawable->getFace(mNearestHero->mirrorPlacementMode())->getPositionAgent(); LLVector4a hit_pos; LLVector3 focus_point; @@ -119,7 +120,7 @@ void LLHeroProbeManager::update() LLMatrix4 rotationMatrix; - rotationMatrix.rotate(angleInRadians, LLVector4(mNearestHero->mDrawable->getFace(0)->getAverageNormal())); + rotationMatrix.rotate(angleInRadians, LLVector4(mNearestHero->mDrawable->getFace(mNearestHero->mirrorPlacementMode())->getAverageNormal())); LLVector3 translatedPoint; LLVector3 rotatedTranslatedPoint; -- cgit v1.2.3 From 80df1d681e7fd83fe0806f51a3f96275b10c0a5a Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 29 Sep 2023 04:11:25 -0700 Subject: Can you say, generic reflectors? DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 100 +++++++++++------------------------ 1 file changed, 32 insertions(+), 68 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index fe9f669365..59345ca35f 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -92,7 +92,7 @@ void LLHeroProbeManager::update() { U32 res = mProbeResolution; U32 count = log2((F32)res) + 0.5f; - + mMipChain.resize(count); for (int i = 0; i < count; ++i) { @@ -102,80 +102,44 @@ void LLHeroProbeManager::update() } llassert(mProbes[0] == mDefaultProbe); - + LLVector4a probe_pos; LLVector3 camera_pos = LLViewerCamera::instance().mOrigin; if (mHeroVOList.size() > 0) { + if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) { - if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) - { + U8 mode = mNearestHero->mirrorPlacementMode(); + mode = llmin(mNearestHero->mDrawable->getNumFaces() - 1, mode); - LLVector3 hero_pos = mNearestHero->mDrawable->getFace(mNearestHero->mirrorPlacementMode())->getPositionAgent(); - - LLVector4a hit_pos; - LLVector3 focus_point; - LLQuaternion camera_rot; - F32 angleInRadians = 180 * DEG_TO_RAD; - - LLMatrix4 rotationMatrix; - - rotationMatrix.rotate(angleInRadians, LLVector4(mNearestHero->mDrawable->getFace(mNearestHero->mirrorPlacementMode())->getAverageNormal())); - - LLVector3 translatedPoint; - LLVector3 rotatedTranslatedPoint; - LLVector3 rotatedPoint; - - translatedPoint = camera_pos - hero_pos; - rotatedTranslatedPoint = translatedPoint * rotationMatrix; - rotatedPoint = rotatedTranslatedPoint + hero_pos; - - probe_pos.load3(rotatedPoint.mV); - - /* - switch (mNearestHero->mirrorPlacementMode()) { - case 0: - - hero_pos.mV[1] = camera_pos.mV[1]; - - rotationMatrix.rotate(angleInRadians, LLVector4(1, 0, 0, 0)); - - translatedPoint = camera_pos - hero_pos; - rotatedTranslatedPoint = translatedPoint * rotationMatrix; - rotatedPoint = rotatedTranslatedPoint + hero_pos; - - probe_pos.load3(rotatedPoint.mV); - break; - case 1: - - hero_pos.mV[2] = camera_pos.mV[2]; - - rotationMatrix.rotate(angleInRadians, LLVector4(0, 1, 0, 0)); - - translatedPoint = camera_pos - hero_pos; - rotatedTranslatedPoint = translatedPoint * rotationMatrix; - rotatedPoint = rotatedTranslatedPoint + hero_pos; - - probe_pos.load3(rotatedPoint.mV); - break; - case 2: - - hero_pos.mV[0] = camera_pos.mV[0]; - - rotationMatrix.rotate(angleInRadians, LLVector4(0, 0, 1, 0)); - - translatedPoint = camera_pos - hero_pos; - rotatedTranslatedPoint = translatedPoint * rotationMatrix; - rotatedPoint = rotatedTranslatedPoint + hero_pos; - - probe_pos.load3(rotatedPoint.mV); - break; - } - */ - } - - mHeroProbeStrength = 1; + LLFace *face = mNearestHero->mDrawable->getFace(mode); + LLVector3 hero_pos = face->getPositionAgent(); + + + // Calculate the average normal. + LLVector4a *posp = face->getViewerObject()->getVolume()->getVolumeFace(face->getTEOffset()).mPositions; + U16 *indp = face->getViewerObject()->getVolume()->getVolumeFace(face->getTEOffset()).mIndices; + // get first three vertices (first triangle) + LLVector4a v0 = posp[indp[0]]; + LLVector4a v1 = posp[indp[1]]; + LLVector4a v2 = posp[indp[2]]; + + v1.sub(v0); + v2.sub(v0); + LLVector3 face_normal = LLVector3(v1[0], v1[1], v1[2]) % LLVector3(v2[0], v2[1], v2[2]); + + face_normal.normalize(); + face_normal *= face->getXform()->getWorldRotation(); + + LLVector3 offset = camera_pos - hero_pos; + LLVector3 project = face_normal * (offset * face_normal); + LLVector3 reject = offset - project; + LLVector3 point = (reject - project) + hero_pos; + + probe_pos.load3(point.mV); } + + mHeroProbeStrength = 1; } else { -- cgit v1.2.3 From 052d5c2802fa427ad97bc26ed4ec114b7fd1b80e Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 29 Sep 2023 04:33:11 -0700 Subject: Wire up the debug settings. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 59345ca35f..dec75f5d2b 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -436,7 +436,7 @@ void LLHeroProbeManager::initReflectionMaps() { mReset = false; mReflectionProbeCount = count; - mProbeResolution = nhpo2(1024); + mProbeResolution = gSavedSettings.getS32("RenderHeroProbeResolution"); mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1 mTexture = new LLCubeMapArray(); @@ -457,7 +457,7 @@ void LLHeroProbeManager::initReflectionMaps() mDefaultProbe->mCubeIndex = 0; mDefaultProbe->mCubeArray = mTexture; - mDefaultProbe->mDistance = 12.f; + mDefaultProbe->mDistance = gSavedSettings.getF32("RenderHeroProbeDistance"); mDefaultProbe->mRadius = 4096.f; mDefaultProbe->mProbeIndex = 0; touch_default_probe(mDefaultProbe); -- cgit v1.2.3 From 1d3d94a514a74b41f1fafaef45e105774d5d8505 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 29 Sep 2023 16:25:25 -0700 Subject: Add probe near clipping. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 41 ++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 23 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index dec75f5d2b..15b54ec6bc 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -83,8 +83,8 @@ void LLHeroProbeManager::update() if (!mRenderTarget.isComplete()) { - U32 color_fmt = GL_RGB16F; - U32 targetRes = mProbeResolution * 4; // super sample + U32 color_fmt = GL_RGBA16F; + U32 targetRes = mProbeResolution; // super sample mRenderTarget.allocate(targetRes, targetRes, color_fmt, true); } @@ -96,7 +96,7 @@ void LLHeroProbeManager::update() mMipChain.resize(count); for (int i = 0; i < count; ++i) { - mMipChain[i].allocate(res, res, GL_RGB16F); + mMipChain[i].allocate(res, res, GL_RGBA16F); res /= 2; } } @@ -105,6 +105,7 @@ void LLHeroProbeManager::update() LLVector4a probe_pos; LLVector3 camera_pos = LLViewerCamera::instance().mOrigin; + F32 near_clip = 0.1f; if (mHeroVOList.size() > 0) { if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) @@ -136,6 +137,8 @@ void LLHeroProbeManager::update() LLVector3 reject = offset - project; LLVector3 point = (reject - project) + hero_pos; + near_clip = abs(dist_vec(hero_pos, point)) - gSavedSettings.getF32("RenderHeroProbeNearClipOffset"); + probe_pos.load3(point.mV); } @@ -163,7 +166,7 @@ void LLHeroProbeManager::update() { for (U32 i = 0; i < 6; ++i) { - updateProbeFace(mProbes[j], i); + updateProbeFace(mProbes[j], i, near_clip); } } @@ -179,12 +182,12 @@ void LLHeroProbeManager::update() // The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain. // At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe. // In effect this simulates single-bounce lighting. -void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) +void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip) { // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; - probe->update(mRenderTarget.getWidth(), face, true); + probe->update(mRenderTarget.getWidth(), face, true, near_clip); gPipeline.mRT = &gPipeline.mMainRT; @@ -217,7 +220,8 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) static LLStaticHashedString znear("znear"); static LLStaticHashedString zfar("zfar"); - LLRenderTarget* screen_rt = &gPipeline.mAuxillaryRT.screen; + LLRenderTarget *screen_rt = &gPipeline.mAuxillaryRT.screen; + LLRenderTarget *depth_rt = &gPipeline.mAuxillaryRT.deferredScreen; // perform a gaussian blur on the super sampled render before downsampling { @@ -247,6 +251,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) gReflectionMipProgram.bind(); S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); + S32 depthChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_TEXTURE); for (int i = 0; i < mMipChain.size(); ++i) { @@ -261,8 +266,11 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) gGL.getTexUnit(diffuseChannel)->bind(&(mMipChain[i - 1])); } + gGL.getTexUnit(depthChannel)->bind(depth_rt, true); - gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2)); + gReflectionMipProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); + gReflectionMipProgram.uniform1f(znear, probe->getNearClip()); + gReflectionMipProgram.uniform1f(zfar, MAX_FAR_CLIP); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -315,10 +323,12 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) static LLStaticHashedString sMipLevel("mipLevel"); static LLStaticHashedString sRoughness("roughness"); static LLStaticHashedString sWidth("u_width"); + static LLStaticHashedString sStrength("probe_strength"); gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); gRadianceGenProgram.uniform1f(sMipLevel, i); gRadianceGenProgram.uniform1i(sWidth, mProbeResolution); + gRadianceGenProgram.uniform1f(sStrength, 1); for (int cf = 0; cf < 6; ++cf) { // for each cube face @@ -385,21 +395,6 @@ void LLHeroProbeManager::updateUniforms() glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); } - -#if 0 - if (!gCubeSnapshot) - { - for (auto& probe : mProbes) - { - LLViewerObject* vobj = probe->mViewerObject; - if (vobj) - { - F32 time = (F32)gFrameTimeSeconds - probe->mLastUpdateTime; - vobj->setDebugText(llformat("%d/%d/%d/%.1f - %.1f/%.1f", probe->mCubeIndex, probe->mProbeIndex, (U32) probe->mNeighbors.size(), probe->mMinDepth, probe->mMaxDepth, time), time > 1.f ? LLColor4::white : LLColor4::green); - } - } - } -#endif } void LLHeroProbeManager::setUniforms() -- cgit v1.2.3 From e612d70fad8c6ec9335c109223211d516ebdf6f4 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 6 Oct 2023 06:21:53 -0700 Subject: Fix for probe stealing, and also make sure we're not super sampling. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 41 ++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 7 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 15b54ec6bc..91d5f9b800 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -108,6 +108,34 @@ void LLHeroProbeManager::update() F32 near_clip = 0.1f; if (mHeroVOList.size() > 0) { + // Find our nearest hero candidate. + + float last_distance = 99999.f; + + for (auto vo : mHeroVOList) + { + if (vo) + { + if (vo->mDrawable.notNull()) + { + if (vo->mDrawable->mDistanceWRTCamera < last_distance) + { + mNearestHero = vo; + last_distance = vo->mDrawable->mDistanceWRTCamera; + } + } + else + { + // Valid drawables only please. Unregister this one. + unregisterHeroDrawable(vo); + } + } + else + { + unregisterHeroDrawable(vo); + } + } + if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) { U8 mode = mNearestHero->mirrorPlacementMode(); @@ -226,7 +254,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n // perform a gaussian blur on the super sampled render before downsampling { gGaussianProgram.bind(); - gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); + gGaussianProgram.uniform1f(resScale, 1.f / mProbeResolution); S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); // horizontal @@ -521,12 +549,11 @@ void LLHeroProbeManager::doOcclusion() void LLHeroProbeManager::registerHeroDrawable(LLVOVolume* drawablep) { - mNearestHero = drawablep; - if (mHeroVOList.find(drawablep) == mHeroVOList.end()) - { - mHeroVOList.insert(drawablep); - LL_INFOS() << "Mirror drawable registered." << LL_ENDL; - } + if (mHeroVOList.find(drawablep) == mHeroVOList.end()) + { + mHeroVOList.insert(drawablep); + LL_INFOS() << "Mirror drawable registered." << LL_ENDL; + } } void LLHeroProbeManager::unregisterHeroDrawable(LLVOVolume* drawablep) -- cgit v1.2.3 From e841c73a9972fc184487c061e8a80add3a18aff1 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 16 Oct 2023 08:45:48 -0700 Subject: Tons of masking changes and tweaks. We now support masking mirrors in the GBuffer. We also now support the concept of one arbitrary clip plane. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 91d5f9b800..b6db123cd9 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -141,13 +141,13 @@ void LLHeroProbeManager::update() U8 mode = mNearestHero->mirrorPlacementMode(); mode = llmin(mNearestHero->mDrawable->getNumFaces() - 1, mode); - LLFace *face = mNearestHero->mDrawable->getFace(mode); - LLVector3 hero_pos = face->getPositionAgent(); + mCurrentFace = mNearestHero->mDrawable->getFace(mode); + LLVector3 hero_pos = mCurrentFace->getPositionAgent(); // Calculate the average normal. - LLVector4a *posp = face->getViewerObject()->getVolume()->getVolumeFace(face->getTEOffset()).mPositions; - U16 *indp = face->getViewerObject()->getVolume()->getVolumeFace(face->getTEOffset()).mIndices; + LLVector4a *posp = mCurrentFace->getViewerObject()->getVolume()->getVolumeFace(mCurrentFace->getTEOffset()).mPositions; + U16 *indp = mCurrentFace->getViewerObject()->getVolume()->getVolumeFace(mCurrentFace->getTEOffset()).mIndices; // get first three vertices (first triangle) LLVector4a v0 = posp[indp[0]]; LLVector4a v1 = posp[indp[1]]; @@ -158,14 +158,27 @@ void LLHeroProbeManager::update() LLVector3 face_normal = LLVector3(v1[0], v1[1], v1[2]) % LLVector3(v2[0], v2[1], v2[2]); face_normal.normalize(); - face_normal *= face->getXform()->getWorldRotation(); + face_normal *= mCurrentFace->getXform()->getWorldRotation(); LLVector3 offset = camera_pos - hero_pos; LLVector3 project = face_normal * (offset * face_normal); LLVector3 reject = offset - project; LLVector3 point = (reject - project) + hero_pos; - near_clip = abs(dist_vec(hero_pos, point)) - gSavedSettings.getF32("RenderHeroProbeNearClipOffset"); + glh::matrix4f mat = copy_matrix(gGLModelView); + glh::vec4f tc(face_normal.mV); + mat.mult_matrix_vec(tc); + + LLVector3 mirror_normal; + mirror_normal.set(tc.v); + + LLVector3 hero_pos_render; + tc = glh::vec4f(hero_pos.mV); + + mat.mult_matrix_vec(tc); + hero_pos_render.set(tc.v); + + mCurrentClipPlane.setVec(hero_pos_render, mirror_normal); probe_pos.load3(point.mV); } @@ -189,7 +202,7 @@ void LLHeroProbeManager::update() bool radiance_pass = gPipeline.mReflectionMapManager.isRadiancePass(); gPipeline.mReflectionMapManager.mRadiancePass = true; - + mRenderingMirror = true; for (U32 j = 0; j < mProbes.size(); j++) { for (U32 i = 0; i < 6; ++i) @@ -197,6 +210,7 @@ void LLHeroProbeManager::update() updateProbeFace(mProbes[j], i, near_clip); } } + mRenderingMirror = false; gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass; } @@ -563,3 +577,8 @@ void LLHeroProbeManager::unregisterHeroDrawable(LLVOVolume* drawablep) mHeroVOList.erase(drawablep); } } + +bool LLHeroProbeManager::isViableMirror(LLFace* face) const +{ + return face == mCurrentFace; +} -- cgit v1.2.3 From 4d39d889976dcc3b7aa7098bc70ab7ebb881c0a8 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 24 Jan 2024 15:50:13 -0800 Subject: https://github.com/secondlife/viewer/issues/671 Wire up the RenderMirrors debug setting. --- indra/newview/llheroprobemanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index b6db123cd9..fdf782adee 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -67,7 +67,7 @@ LLHeroProbeManager::LLHeroProbeManager() // helper class to seed octree with probes void LLHeroProbeManager::update() { - if (!LLPipeline::sReflectionProbesEnabled || gTeleportDisplay || LLStartUp::getStartupState() < STATE_PRECACHE) + if (!LLPipeline::RenderMirrors || gTeleportDisplay || LLStartUp::getStartupState() < STATE_PRECACHE) { return; } -- cgit v1.2.3 From a888531fd1fbf7de0d71b4d04195d4267c882154 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 24 Jan 2024 16:22:45 -0800 Subject: https://github.com/secondlife/viewer-issues/issues/23 Make the face selection for mirrors actually reflect what it does --- indra/newview/llheroprobemanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index fdf782adee..1ecafd4f54 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -138,7 +138,7 @@ void LLHeroProbeManager::update() if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) { - U8 mode = mNearestHero->mirrorPlacementMode(); + U8 mode = mNearestHero->mirrorFace(); mode = llmin(mNearestHero->mDrawable->getNumFaces() - 1, mode); mCurrentFace = mNearestHero->mDrawable->getFace(mode); -- cgit v1.2.3 From 476cbaed6a876c308baa057b50af2631668f7293 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 31 Jan 2024 15:54:14 -0800 Subject: #677 Some clipping WIP --- indra/newview/llheroprobemanager.cpp | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 1ecafd4f54..bbe493f6a9 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -165,20 +165,10 @@ void LLHeroProbeManager::update() LLVector3 reject = offset - project; LLVector3 point = (reject - project) + hero_pos; - glh::matrix4f mat = copy_matrix(gGLModelView); - glh::vec4f tc(face_normal.mV); - mat.mult_matrix_vec(tc); - - LLVector3 mirror_normal; - mirror_normal.set(tc.v); - - LLVector3 hero_pos_render; - tc = glh::vec4f(hero_pos.mV); - - mat.mult_matrix_vec(tc); - hero_pos_render.set(tc.v); - - mCurrentClipPlane.setVec(hero_pos_render, mirror_normal); + mCurrentClipPlane.setVec(hero_pos, face_normal); + mMirrorPosition = hero_pos; + mMirrorNormal = LLVector3(0, 0, 1); + probe_pos.load3(point.mV); } -- cgit v1.2.3 From a4225663ac3feb641fb8fb416889fd46b52763f5 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Thu, 1 Feb 2024 10:16:52 -0600 Subject: #677 Set mirror pass flag in llsettingsvo --- indra/newview/llheroprobemanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index bbe493f6a9..ed37a67c85 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -166,7 +166,7 @@ void LLHeroProbeManager::update() LLVector3 point = (reject - project) + hero_pos; mCurrentClipPlane.setVec(hero_pos, face_normal); - mMirrorPosition = hero_pos; + mMirrorPosition = mNearestHero->getPositionAgent(); mMirrorNormal = LLVector3(0, 0, 1); -- cgit v1.2.3 From fac63e473a4b2b7b9b361c4d5656c94d47d88ef0 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 1 Feb 2024 12:11:20 -0800 Subject: #684 Fix pixellation on mirrors regardless of mirror resolution. --- indra/newview/llheroprobemanager.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index ed37a67c85..42c8d4fb3f 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -217,7 +217,7 @@ void LLHeroProbeManager::update() void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip) { // hacky hot-swap of camera specific render targets - gPipeline.mRT = &gPipeline.mAuxillaryRT; + gPipeline.mRT = &gPipeline.mHeroProbeRT; probe->update(mRenderTarget.getWidth(), face, true, near_clip); @@ -252,9 +252,10 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n static LLStaticHashedString znear("znear"); static LLStaticHashedString zfar("zfar"); - LLRenderTarget *screen_rt = &gPipeline.mAuxillaryRT.screen; - LLRenderTarget *depth_rt = &gPipeline.mAuxillaryRT.deferredScreen; + LLRenderTarget *screen_rt = &gPipeline.mHeroProbeRT.screen; + LLRenderTarget *depth_rt = &gPipeline.mHeroProbeRT.deferredScreen; + /* // perform a gaussian blur on the super sampled render before downsampling { gGaussianProgram.bind(); @@ -277,7 +278,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); screen_rt->flush(); } - + */ S32 mips = log2((F32)mProbeResolution) + 0.5f; @@ -338,14 +339,14 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n { //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) - gRadianceGenProgram.bind(); + gHeroRadianceGenProgram.bind(); mVertexBuffer->setBuffer(); - S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + S32 channel = gHeroRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); mTexture->bind(channel); - gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); - gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); - gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, mHeroProbeStrength); + gHeroRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); + gHeroRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); + gHeroRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, mHeroProbeStrength); U32 res = mMipChain[0].getWidth(); @@ -357,10 +358,10 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n static LLStaticHashedString sWidth("u_width"); static LLStaticHashedString sStrength("probe_strength"); - gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); - gRadianceGenProgram.uniform1f(sMipLevel, i); - gRadianceGenProgram.uniform1i(sWidth, mProbeResolution); - gRadianceGenProgram.uniform1f(sStrength, 1); + gHeroRadianceGenProgram.uniform1f(sRoughness, (F32) i / (F32) (mMipChain.size() - 1)); + gHeroRadianceGenProgram.uniform1f(sMipLevel, i); + gHeroRadianceGenProgram.uniform1i(sWidth, mProbeResolution); + gHeroRadianceGenProgram.uniform1f(sStrength, 1); for (int cf = 0; cf < 6; ++cf) { // for each cube face @@ -383,7 +384,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n } } - gRadianceGenProgram.unbind(); + gHeroRadianceGenProgram.unbind(); } mMipChain[0].flush(); -- cgit v1.2.3 From aab98046b9971717ecdc739b2230377278c83da3 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 1 Feb 2024 13:03:28 -0800 Subject: #677 More clipping fixes. --- indra/newview/llheroprobemanager.cpp | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 42c8d4fb3f..39f5bdec5a 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -167,7 +167,7 @@ void LLHeroProbeManager::update() mCurrentClipPlane.setVec(hero_pos, face_normal); mMirrorPosition = mNearestHero->getPositionAgent(); - mMirrorNormal = LLVector3(0, 0, 1); + mMirrorNormal = face_normal; probe_pos.load3(point.mV); @@ -255,31 +255,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n LLRenderTarget *screen_rt = &gPipeline.mHeroProbeRT.screen; LLRenderTarget *depth_rt = &gPipeline.mHeroProbeRT.deferredScreen; - /* - // perform a gaussian blur on the super sampled render before downsampling - { - gGaussianProgram.bind(); - gGaussianProgram.uniform1f(resScale, 1.f / mProbeResolution); - S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); - - // horizontal - gGaussianProgram.uniform2f(direction, 1.f, 0.f); - gGL.getTexUnit(diffuseChannel)->bind(screen_rt); - mRenderTarget.bindTarget(); - gPipeline.mScreenTriangleVB->setBuffer(); - gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - mRenderTarget.flush(); - - // vertical - gGaussianProgram.uniform2f(direction, 0.f, 1.f); - gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); - screen_rt->bindTarget(); - gPipeline.mScreenTriangleVB->setBuffer(); - gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - screen_rt->flush(); - } - */ - S32 mips = log2((F32)mProbeResolution) + 0.5f; gReflectionMipProgram.bind(); -- cgit v1.2.3 From 739ff27c0649af9c74e00f31934d89405ff14373 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 6 Feb 2024 02:53:57 -0800 Subject: #740 Make sure we evaluate if the probe is a mirror probe or not. #682 Re-enable gaussian filtering, and reduce the mirror resolution back to 1024. Also just generally clean up the code a bit. --- indra/newview/llheroprobemanager.cpp | 65 +++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 30 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 39f5bdec5a..c9728b8d93 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -127,38 +127,22 @@ void LLHeroProbeManager::update() else { // Valid drawables only please. Unregister this one. - unregisterHeroDrawable(vo); + unregisterViewerObject(vo); } } else { - unregisterHeroDrawable(vo); + unregisterViewerObject(vo); } } if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) { - U8 mode = mNearestHero->mirrorFace(); - mode = llmin(mNearestHero->mDrawable->getNumFaces() - 1, mode); - - mCurrentFace = mNearestHero->mDrawable->getFace(mode); - LLVector3 hero_pos = mCurrentFace->getPositionAgent(); - - - // Calculate the average normal. - LLVector4a *posp = mCurrentFace->getViewerObject()->getVolume()->getVolumeFace(mCurrentFace->getTEOffset()).mPositions; - U16 *indp = mCurrentFace->getViewerObject()->getVolume()->getVolumeFace(mCurrentFace->getTEOffset()).mIndices; - // get first three vertices (first triangle) - LLVector4a v0 = posp[indp[0]]; - LLVector4a v1 = posp[indp[1]]; - LLVector4a v2 = posp[indp[2]]; - - v1.sub(v0); - v2.sub(v0); - LLVector3 face_normal = LLVector3(v1[0], v1[1], v1[2]) % LLVector3(v2[0], v2[1], v2[2]); + LLVector3 hero_pos = mNearestHero->getPositionAgent(); + LLVector3 face_normal = LLVector3(0, 0, 1); + face_normal *= mNearestHero->mDrawable->getXform()->getWorldRotation(); face_normal.normalize(); - face_normal *= mCurrentFace->getXform()->getWorldRotation(); LLVector3 offset = camera_pos - hero_pos; LLVector3 project = face_normal * (offset * face_normal); @@ -166,7 +150,7 @@ void LLHeroProbeManager::update() LLVector3 point = (reject - project) + hero_pos; mCurrentClipPlane.setVec(hero_pos, face_normal); - mMirrorPosition = mNearestHero->getPositionAgent(); + mMirrorPosition = hero_pos; mMirrorNormal = face_normal; @@ -254,6 +238,30 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n LLRenderTarget *screen_rt = &gPipeline.mHeroProbeRT.screen; LLRenderTarget *depth_rt = &gPipeline.mHeroProbeRT.deferredScreen; + + // perform a gaussian blur on the super sampled render before downsampling + { + gGaussianProgram.bind(); + gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); + S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); + + // horizontal + gGaussianProgram.uniform2f(direction, 1.f, 0.f); + gGL.getTexUnit(diffuseChannel)->bind(screen_rt); + mRenderTarget.bindTarget(); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + mRenderTarget.flush(); + + // vertical + gGaussianProgram.uniform2f(direction, 0.f, 1.f); + gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); + screen_rt->bindTarget(); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + screen_rt->flush(); + gGaussianProgram.unbind(); + } S32 mips = log2((F32)mProbeResolution) + 0.5f; @@ -527,24 +535,21 @@ void LLHeroProbeManager::doOcclusion() } } -void LLHeroProbeManager::registerHeroDrawable(LLVOVolume* drawablep) +void LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep) { + llassert(drawablep != nullptr); + if (mHeroVOList.find(drawablep) == mHeroVOList.end()) { + // Probe isn't in our list for consideration. Add it. mHeroVOList.insert(drawablep); - LL_INFOS() << "Mirror drawable registered." << LL_ENDL; } } -void LLHeroProbeManager::unregisterHeroDrawable(LLVOVolume* drawablep) +void LLHeroProbeManager::unregisterViewerObject(LLVOVolume* drawablep) { if (mHeroVOList.find(drawablep) != mHeroVOList.end()) { mHeroVOList.erase(drawablep); } } - -bool LLHeroProbeManager::isViableMirror(LLFace* face) const -{ - return face == mCurrentFace; -} -- cgit v1.2.3 From 97d2b216212b3e106bb9129689e8eb162f9f68f5 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 8 Feb 2024 11:39:35 -0800 Subject: #671 Setup the viewer to respect the MirrorsEnabled simulator feature. --- indra/newview/llheroprobemanager.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index c9728b8d93..a105fd2fa8 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -72,6 +72,18 @@ void LLHeroProbeManager::update() return; } + // This should be moved elsewhere. + LLSD features; + gAgent.getRegion()->getSimulatorFeatures(features); + if (mHasMirrors != features.has("MirrorsEnabled")) + { + mHasMirrors = features.has("MirrorsEnabled"); + LLViewerShaderMgr::instance()->setShaders(); + } + + if (!mHasMirrors) + return; + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(!gCubeSnapshot); // assert a snapshot is not in progress if (LLAppViewer::instance()->logoutRequestSent()) -- cgit v1.2.3 From c721152c444ee7a13e4217f86dfcce34b7488ee5 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Thu, 8 Feb 2024 14:54:01 -0600 Subject: Fix for crash in LLHeroProbeManager --- indra/newview/llheroprobemanager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index a105fd2fa8..c66054f618 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -126,7 +126,7 @@ void LLHeroProbeManager::update() for (auto vo : mHeroVOList) { - if (vo) + if (vo && !vo->isDead()) { if (vo->mDrawable.notNull()) { @@ -148,7 +148,7 @@ void LLHeroProbeManager::update() } } - if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) + if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull()) { LLVector3 hero_pos = mNearestHero->getPositionAgent(); LLVector3 face_normal = LLVector3(0, 0, 1); @@ -168,6 +168,10 @@ void LLHeroProbeManager::update() probe_pos.load3(point.mV); } + else + { + mNearestHero = nullptr; + } mHeroProbeStrength = 1; } -- cgit v1.2.3 From a7310ae7417b2f6e7013762a1cfe3211a163a8d7 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Thu, 8 Feb 2024 15:07:54 -0600 Subject: #671 Nudge RenderMirrors and clear shader cache as needed based on SimulatorFeatures --- indra/newview/llheroprobemanager.cpp | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index c66054f618..2a81919856 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -72,18 +72,6 @@ void LLHeroProbeManager::update() return; } - // This should be moved elsewhere. - LLSD features; - gAgent.getRegion()->getSimulatorFeatures(features); - if (mHasMirrors != features.has("MirrorsEnabled")) - { - mHasMirrors = features.has("MirrorsEnabled"); - LLViewerShaderMgr::instance()->setShaders(); - } - - if (!mHasMirrors) - return; - LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(!gCubeSnapshot); // assert a snapshot is not in progress if (LLAppViewer::instance()->logoutRequestSent()) -- cgit v1.2.3 From 7a9cdf2b52ca95c8e269e2bb4ed01379b76434d6 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 15 Feb 2024 09:38:29 -0800 Subject: #682 Do conservative updates on probes. --- indra/newview/llheroprobemanager.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 2a81919856..1f050a5166 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -155,6 +155,25 @@ void LLHeroProbeManager::update() probe_pos.load3(point.mV); + + // Collect the list of faces that need updating based upon the camera's rotation. + LLVector3 cam_direction = LLVector3(0, 0, -1) * LLViewerCamera::instance().getQuaternion(); + + static LLVector3 cubeFaces[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) + }; + + for (int i = 0; i < 6; i++) + { + bool shouldUpdate = (cam_direction * cubeFaces[i]) > 0; + + mFaceUpdateList[i] = shouldUpdate; + } } else { @@ -185,7 +204,8 @@ void LLHeroProbeManager::update() { for (U32 i = 0; i < 6; ++i) { - updateProbeFace(mProbes[j], i, near_clip); + if (mFaceUpdateList[i]) + updateProbeFace(mProbes[j], i, near_clip); } } mRenderingMirror = false; -- cgit v1.2.3 From 8cea28511448eb750561252f202f96ae815e37f8 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 20 Feb 2024 18:21:45 -0800 Subject: #682 Separate out the radiance gen. --- indra/newview/llheroprobemanager.cpp | 45 ++++++++++++------------------------ 1 file changed, 15 insertions(+), 30 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 1f050a5166..929364be44 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -157,7 +157,7 @@ void LLHeroProbeManager::update() probe_pos.load3(point.mV); // Collect the list of faces that need updating based upon the camera's rotation. - LLVector3 cam_direction = LLVector3(0, 0, -1) * LLViewerCamera::instance().getQuaternion(); + LLVector3 cam_direction = LLVector3(-1, -1, -1) * LLViewerCamera::instance().getQuaternion(); static LLVector3 cubeFaces[6] = { LLVector3(1, 0, 0), @@ -207,6 +207,7 @@ void LLHeroProbeManager::update() if (mFaceUpdateList[i]) updateProbeFace(mProbes[j], i, near_clip); } + generateRadiance(mProbes[j]); } mRenderingMirror = false; @@ -262,30 +263,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n LLRenderTarget *screen_rt = &gPipeline.mHeroProbeRT.screen; LLRenderTarget *depth_rt = &gPipeline.mHeroProbeRT.deferredScreen; - - // perform a gaussian blur on the super sampled render before downsampling - { - gGaussianProgram.bind(); - gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); - S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); - - // horizontal - gGaussianProgram.uniform2f(direction, 1.f, 0.f); - gGL.getTexUnit(diffuseChannel)->bind(screen_rt); - mRenderTarget.bindTarget(); - gPipeline.mScreenTriangleVB->setBuffer(); - gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - mRenderTarget.flush(); - - // vertical - gGaussianProgram.uniform2f(direction, 0.f, 1.f); - gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); - screen_rt->bindTarget(); - gPipeline.mScreenTriangleVB->setBuffer(); - gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - screen_rt->flush(); - gGaussianProgram.unbind(); - } S32 mips = log2((F32)mProbeResolution) + 0.5f; @@ -338,14 +315,22 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n gGL.getTexUnit(diffuseChannel)->unbind(LLTexUnit::TT_TEXTURE); gReflectionMipProgram.unbind(); } +} - if (face == 5) +void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe) +{ + S32 sourceIdx = mReflectionProbeCount; + + // Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes. + sourceIdx += 1; { mMipChain[0].bindTarget(); static LLStaticHashedString sSourceIdx("sourceIdx"); { - //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) + + + // generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) gHeroRadianceGenProgram.bind(); mVertexBuffer->setBuffer(); @@ -354,10 +339,10 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n gHeroRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gHeroRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); gHeroRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, mHeroProbeStrength); - + U32 res = mMipChain[0].getWidth(); - for (int i = 0; i < mMipChain.size(); ++i) + for (int i = 0; i < mMipChain.size() / 4; ++i) { LL_PROFILE_GPU_ZONE("probe radiance gen"); static LLStaticHashedString sMipLevel("mipLevel"); @@ -371,7 +356,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n gHeroRadianceGenProgram.uniform1f(sStrength, 1); for (int cf = 0; cf < 6; ++cf) - { // for each cube face + { // for each cube face LLCoordFrame frame; frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); -- cgit v1.2.3 From e68735ad3a6da635a447eb9ed1981e5c360fd2f2 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 21 Feb 2024 11:51:46 -0800 Subject: #682 Add an update rate parameter to help throttle mirror updates. So far 4 seems like a good balance for performance and quality. 2 is great for quality, with 6 or 8 being for higher performance. Also bring back the gaussian filter - may end up adding the FXAA filter though instead. --- indra/newview/llheroprobemanager.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 929364be44..0d9efb860a 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -264,6 +264,30 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n LLRenderTarget *screen_rt = &gPipeline.mHeroProbeRT.screen; LLRenderTarget *depth_rt = &gPipeline.mHeroProbeRT.deferredScreen; + // perform a gaussian blur on the super sampled render before downsampling + { + gGaussianProgram.bind(); + gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); + S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); + + // horizontal + gGaussianProgram.uniform2f(direction, 1.f, 0.f); + gGL.getTexUnit(diffuseChannel)->bind(screen_rt); + mRenderTarget.bindTarget(); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + mRenderTarget.flush(); + + // vertical + gGaussianProgram.uniform2f(direction, 0.f, 1.f); + gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); + screen_rt->bindTarget(); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + screen_rt->flush(); + gGaussianProgram.unbind(); + } + S32 mips = log2((F32)mProbeResolution) + 0.5f; gReflectionMipProgram.bind(); -- cgit v1.2.3 From 320258729757e9ef14e9509c22eca1ce6a0da856 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Sun, 25 Feb 2024 22:52:23 -0800 Subject: #682 Add a low priority path for conservative probe face updates. This will update the "low priority" faces at half of the the probe update rate. Useful for less planar reflection geometry. --- indra/newview/llheroprobemanager.cpp | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 0d9efb860a..f350b28bf5 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -114,7 +114,7 @@ void LLHeroProbeManager::update() for (auto vo : mHeroVOList) { - if (vo && !vo->isDead()) + if (vo && (!vo->isDead() || vo != nullptr)) { if (vo->mDrawable.notNull()) { @@ -135,7 +135,7 @@ void LLHeroProbeManager::update() unregisterViewerObject(vo); } } - + if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull()) { LLVector3 hero_pos = mNearestHero->getPositionAgent(); @@ -205,7 +205,16 @@ void LLHeroProbeManager::update() for (U32 i = 0; i < 6; ++i) { if (mFaceUpdateList[i]) + { updateProbeFace(mProbes[j], i, near_clip); + } + else + { + if (mLowPriorityFaceThrottle > 0 && mCurrentProbeUpdateFrame % mLowPriorityFaceThrottle == 0) { + updateProbeFace(mProbes[j], i, near_clip); + mCurrentProbeUpdateFrame = 0; + } + } } generateRadiance(mProbes[j]); } @@ -213,6 +222,8 @@ void LLHeroProbeManager::update() gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass; } + + mCurrentProbeUpdateFrame++; } // Do the reflection map update render passes. @@ -568,21 +579,25 @@ void LLHeroProbeManager::doOcclusion() } } -void LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep) +bool LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep) { llassert(drawablep != nullptr); - if (mHeroVOList.find(drawablep) == mHeroVOList.end()) + if (std::find(mHeroVOList.begin(), mHeroVOList.end(), drawablep) == mHeroVOList.end()) { // Probe isn't in our list for consideration. Add it. - mHeroVOList.insert(drawablep); + mHeroVOList.push_back(drawablep); + return true; } + + return false; } void LLHeroProbeManager::unregisterViewerObject(LLVOVolume* drawablep) { - if (mHeroVOList.find(drawablep) != mHeroVOList.end()) + std::vector::iterator found_itr = std::find(mHeroVOList.begin(), mHeroVOList.end(), drawablep); + if (found_itr != mHeroVOList.end()) { - mHeroVOList.erase(drawablep); + mHeroVOList.erase(found_itr); } } -- cgit v1.2.3 From 2ba5449b8b888b64ed87ef801426f7eab6e0be95 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Sun, 25 Feb 2024 23:38:11 -0800 Subject: #889 Start removing mDrawable references. These may be null. --- indra/newview/llheroprobemanager.cpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index f350b28bf5..feb81394cf 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -116,18 +116,11 @@ void LLHeroProbeManager::update() { if (vo && (!vo->isDead() || vo != nullptr)) { - if (vo->mDrawable.notNull()) + float distance = (LLViewerCamera::instance().getOrigin() - vo->getPositionAgent()).magVec(); + if (distance < last_distance) { - if (vo->mDrawable->mDistanceWRTCamera < last_distance) - { - mNearestHero = vo; - last_distance = vo->mDrawable->mDistanceWRTCamera; - } - } - else - { - // Valid drawables only please. Unregister this one. - unregisterViewerObject(vo); + mNearestHero = vo; + last_distance = distance; } } else @@ -136,12 +129,12 @@ void LLHeroProbeManager::update() } } - if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull()) + if (mNearestHero != nullptr && !mNearestHero->isDead()) { LLVector3 hero_pos = mNearestHero->getPositionAgent(); LLVector3 face_normal = LLVector3(0, 0, 1); - face_normal *= mNearestHero->mDrawable->getXform()->getWorldRotation(); + face_normal *= mNearestHero->getWorldRotation(); face_normal.normalize(); LLVector3 offset = camera_pos - hero_pos; @@ -210,7 +203,8 @@ void LLHeroProbeManager::update() } else { - if (mLowPriorityFaceThrottle > 0 && mCurrentProbeUpdateFrame % mLowPriorityFaceThrottle == 0) { + if (mLowPriorityFaceThrottle > 0 && mCurrentProbeUpdateFrame % mLowPriorityFaceThrottle == 0) + { updateProbeFace(mProbes[j], i, near_clip); mCurrentProbeUpdateFrame = 0; } @@ -352,6 +346,9 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n } } +// Separate out radiance generation as a separate stage. +// This is to better enable independent control over how we generate radiance vs. having it coupled with processing the final face of the probe. +// Useful when we may not always be rendering a full set of faces of the probe. void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe) { S32 sourceIdx = mReflectionProbeCount; -- cgit v1.2.3 From 1b8523a7b6293db89b16ca8e08330969cf1d9166 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 26 Feb 2024 00:30:44 -0800 Subject: #890 Make sure we're doing the correct distance check. #682 Improve the conservative update functionality for mirror faces. Make it attenuate depending on how much the camera is facing that specific cubemap face. --- indra/newview/llheroprobemanager.cpp | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index feb81394cf..3adf460432 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -114,7 +114,7 @@ void LLHeroProbeManager::update() for (auto vo : mHeroVOList) { - if (vo && (!vo->isDead() || vo != nullptr)) + if (vo && !vo->isDead() && vo->mDrawable.notNull()) { float distance = (LLViewerCamera::instance().getOrigin() - vo->getPositionAgent()).magVec(); if (distance < last_distance) @@ -129,12 +129,12 @@ void LLHeroProbeManager::update() } } - if (mNearestHero != nullptr && !mNearestHero->isDead()) + if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull()) { LLVector3 hero_pos = mNearestHero->getPositionAgent(); LLVector3 face_normal = LLVector3(0, 0, 1); - - face_normal *= mNearestHero->getWorldRotation(); + + face_normal *= mNearestHero->mDrawable->getWorldRotation(); face_normal.normalize(); LLVector3 offset = camera_pos - hero_pos; @@ -150,7 +150,7 @@ void LLHeroProbeManager::update() probe_pos.load3(point.mV); // Collect the list of faces that need updating based upon the camera's rotation. - LLVector3 cam_direction = LLVector3(-1, -1, -1) * LLViewerCamera::instance().getQuaternion(); + LLVector3 cam_direction = LLVector3(0, 0, 1) * LLViewerCamera::instance().getQuaternion(); static LLVector3 cubeFaces[6] = { LLVector3(1, 0, 0), @@ -163,9 +163,11 @@ void LLHeroProbeManager::update() for (int i = 0; i < 6; i++) { - bool shouldUpdate = (cam_direction * cubeFaces[i]) > 0; - - mFaceUpdateList[i] = shouldUpdate; + float shouldUpdate = cam_direction * cubeFaces[i] * 0.5 + 0.5; + + int updateRate = fmaxf(1, (1 - shouldUpdate) * 8); + + mFaceUpdateList[i] = updateRate; } } else @@ -197,17 +199,10 @@ void LLHeroProbeManager::update() { for (U32 i = 0; i < 6; ++i) { - if (mFaceUpdateList[i]) + if (mFaceUpdateList[i] > 0 && mCurrentProbeUpdateFrame % mFaceUpdateList[i] == 0) { updateProbeFace(mProbes[j], i, near_clip); - } - else - { - if (mLowPriorityFaceThrottle > 0 && mCurrentProbeUpdateFrame % mLowPriorityFaceThrottle == 0) - { - updateProbeFace(mProbes[j], i, near_clip); - mCurrentProbeUpdateFrame = 0; - } + mCurrentProbeUpdateFrame = 0; } } generateRadiance(mProbes[j]); -- cgit v1.2.3 From 8c79297a8957fec13fadd2a2932b4b03b148d5a5 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 26 Feb 2024 01:21:41 -0800 Subject: #682 Further tweak the conservative update mechanism. --- indra/newview/llheroprobemanager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 3adf460432..a00b6d6b5d 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -165,7 +165,12 @@ void LLHeroProbeManager::update() { float shouldUpdate = cam_direction * cubeFaces[i] * 0.5 + 0.5; - int updateRate = fmaxf(1, (1 - shouldUpdate) * 8); + int updateRate = ceilf((1 - shouldUpdate) * gPipeline.RenderHeroProbeConservativeUpdateMultiplier); + + // Chances are this is a face that's non-visible to the camera when it's being reflected. + // Set it to 0. It will be skipped below. + if (updateRate == gPipeline.RenderHeroProbeConservativeUpdateMultiplier) + updateRate = 0; mFaceUpdateList[i] = updateRate; } -- cgit v1.2.3 From b3283036af886de56f45c731ab21e2b16383a770 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 26 Feb 2024 04:02:09 -0800 Subject: #681 Start adding blending boilerplate. --- indra/newview/llheroprobemanager.cpp | 37 +++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index a00b6d6b5d..ee993c6ba1 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -417,7 +417,7 @@ void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe) void LLHeroProbeManager::updateUniforms() { - if (!LLPipeline::sReflectionProbesEnabled) + if (!gPipeline.RenderMirrors) { return; } @@ -426,8 +426,11 @@ void LLHeroProbeManager::updateUniforms() struct HeroProbeData { - LLVector4 heroPosition[1]; - GLint heroProbeCount = 1; + LLMatrix4 heroBox[1]; + LLVector4 heroSphere[1]; + GLint heroShape[1]; + GLint heroMipCount; + GLint heroProbeCount; }; HeroProbeData hpd; @@ -437,8 +440,32 @@ void LLHeroProbeManager::updateUniforms() LLVector4a oa; // scratch space for transformed origin oa.set(0, 0, 0, 0); hpd.heroProbeCount = 1; - modelview.affineTransform(mProbes[0]->mOrigin, oa); - hpd.heroPosition[0].set(oa.getF32ptr()); + + if (mNearestHero != nullptr) + { + mProbes[0]->mViewerObject = mNearestHero; + if (mNearestHero->getReflectionProbeIsBox()) + { + LLVector3 s = mNearestHero->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f)); + mProbes[0]->mRadius = s.magVec(); + } + else + { + mProbes[0]->mRadius = mNearestHero->getScale().mV[0] * 0.5f; + } + + modelview.affineTransform(mProbes[0]->mOrigin, oa); + hpd.heroShape[0] = 0; + if (!mProbes[0]->getBox(hpd.heroBox[0])) + { + hpd.heroShape[0] = 1; + } + + hpd.heroSphere[0].set(oa.getF32ptr()); + hpd.heroSphere[0].mV[3] = mProbes[0]->mRadius; + } + + hpd.heroMipCount = mMipChain.size(); //copy rpd into uniform buffer object if (mUBO == 0) -- cgit v1.2.3 From 1fc45a50ff15e6f31a4554da83256b7f59b1af15 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 6 Mar 2024 17:56:16 -0800 Subject: #681 Add probe blending for mirrors. --- indra/newview/llheroprobemanager.cpp | 62 +++++++----------------------------- 1 file changed, 12 insertions(+), 50 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index ee993c6ba1..8f1c1848cc 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -151,6 +151,7 @@ void LLHeroProbeManager::update() // Collect the list of faces that need updating based upon the camera's rotation. LLVector3 cam_direction = LLVector3(0, 0, 1) * LLViewerCamera::instance().getQuaternion(); + cam_direction.normalize(); static LLVector3 cubeFaces[6] = { LLVector3(1, 0, 0), @@ -163,7 +164,7 @@ void LLHeroProbeManager::update() for (int i = 0; i < 6; i++) { - float shouldUpdate = cam_direction * cubeFaces[i] * 0.5 + 0.5; + float shouldUpdate = fminf(1, (fmaxf(-1, cam_direction * cubeFaces[i]) * 0.5 + 0.5)); int updateRate = ceilf((1 - shouldUpdate) * gPipeline.RenderHeroProbeConservativeUpdateMultiplier); @@ -215,6 +216,9 @@ void LLHeroProbeManager::update() mRenderingMirror = false; gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass; + + mProbes[0]->mViewerObject = mNearestHero; + mProbes[0]->autoAdjustOrigin(); } mCurrentProbeUpdateFrame++; @@ -424,26 +428,14 @@ void LLHeroProbeManager::updateUniforms() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - struct HeroProbeData - { - LLMatrix4 heroBox[1]; - LLVector4 heroSphere[1]; - GLint heroShape[1]; - GLint heroMipCount; - GLint heroProbeCount; - }; - - HeroProbeData hpd; - LLMatrix4a modelview; modelview.loadu(gGLModelView); LLVector4a oa; // scratch space for transformed origin oa.set(0, 0, 0, 0); - hpd.heroProbeCount = 1; + mHeroData.heroProbeCount = 1; if (mNearestHero != nullptr) { - mProbes[0]->mViewerObject = mNearestHero; if (mNearestHero->getReflectionProbeIsBox()) { LLVector3 s = mNearestHero->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f)); @@ -455,44 +447,17 @@ void LLHeroProbeManager::updateUniforms() } modelview.affineTransform(mProbes[0]->mOrigin, oa); - hpd.heroShape[0] = 0; - if (!mProbes[0]->getBox(hpd.heroBox[0])) + mHeroData.heroShape = 0; + if (!mProbes[0]->getBox(mHeroData.heroBox)) { - hpd.heroShape[0] = 1; + mHeroData.heroShape = 1; } - hpd.heroSphere[0].set(oa.getF32ptr()); - hpd.heroSphere[0].mV[3] = mProbes[0]->mRadius; + mHeroData.heroSphere.set(oa.getF32ptr()); + mHeroData.heroSphere.mV[3] = mProbes[0]->mRadius; } - hpd.heroMipCount = mMipChain.size(); - - //copy rpd into uniform buffer object - if (mUBO == 0) - { - glGenBuffers(1, &mUBO); - } - - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer"); - glBindBuffer(GL_UNIFORM_BUFFER, mUBO); - glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - } -} - -void LLHeroProbeManager::setUniforms() -{ - if (!LLPipeline::sReflectionProbesEnabled) - { - return; - } - - if (mUBO == 0) - { - updateUniforms(); - } - glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO); + mHeroData.heroMipCount = mMipChain.size(); } void LLHeroProbeManager::renderDebug() @@ -581,9 +546,6 @@ void LLHeroProbeManager::cleanup() mDefaultProbe = nullptr; mUpdatingProbe = nullptr; - - glDeleteBuffers(1, &mUBO); - mUBO = 0; mHeroVOList.clear(); mNearestHero = nullptr; -- cgit v1.2.3 From 4b738a619a475447af8b917644357cb49dc22fb9 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 6 Mar 2024 18:24:36 -0800 Subject: #681 Small fix for if a viewer object may be dead. --- indra/newview/llheroprobemanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 8f1c1848cc..10b743ceef 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -434,7 +434,7 @@ void LLHeroProbeManager::updateUniforms() oa.set(0, 0, 0, 0); mHeroData.heroProbeCount = 1; - if (mNearestHero != nullptr) + if (mNearestHero != nullptr && !mNearestHero->isDead()) { if (mNearestHero->getReflectionProbeIsBox()) { -- cgit v1.2.3 From ef755235551d68b2790ed7c5363038f46a226306 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Wed, 13 Mar 2024 12:22:12 -0500 Subject: 983 add debug setting to control the maximum download resolution (#986) * Create RenderMaxTextureResolution.md * #983 Add RenderMaxTextureResolution setting. Incidental crash fix. --- indra/newview/llheroprobemanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 10b743ceef..13c12b5e55 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -581,7 +581,7 @@ bool LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep) void LLHeroProbeManager::unregisterViewerObject(LLVOVolume* drawablep) { - std::vector::iterator found_itr = std::find(mHeroVOList.begin(), mHeroVOList.end(), drawablep); + std::vector>::iterator found_itr = std::find(mHeroVOList.begin(), mHeroVOList.end(), drawablep); if (found_itr != mHeroVOList.end()) { mHeroVOList.erase(found_itr); -- cgit v1.2.3 From 7ef2b43802da07b8f30b455448cb84bd1c26320d Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 10 Apr 2024 15:21:59 -0700 Subject: Multiple fixes for mirrors. (#1192) * #1064 Fix for mirror surfaces going black when the roughness is set too high. * #1130 Fix for the user's avatar not appearing in mouselook in a mirror. * #1059 Disable mirrors on low settings per the feature table. * #860 Modify the settings UI to better reflect that we only have two AA modes: off and FXAA. * #1191 Add some settings for mirrors in preferences. * #1185 Add support for runtime mirror resolution changing. Useful for quality settings, and auto-FPS. --- indra/newview/llheroprobemanager.cpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 13c12b5e55..dd29b416fb 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -64,6 +64,14 @@ LLHeroProbeManager::LLHeroProbeManager() { } +LLHeroProbeManager::~LLHeroProbeManager() +{ + cleanup(); + + mHeroVOList.clear(); + mNearestHero = nullptr; +} + // helper class to seed octree with probes void LLHeroProbeManager::update() { @@ -84,8 +92,7 @@ void LLHeroProbeManager::update() if (!mRenderTarget.isComplete()) { U32 color_fmt = GL_RGBA16F; - U32 targetRes = mProbeResolution; // super sample - mRenderTarget.allocate(targetRes, targetRes, color_fmt, true); + mRenderTarget.allocate(mProbeResolution, mProbeResolution, color_fmt, true); } if (mMipChain.empty()) @@ -472,12 +479,19 @@ void LLHeroProbeManager::renderDebug() gDebugProgram.unbind(); } + void LLHeroProbeManager::initReflectionMaps() { U32 count = LL_MAX_HERO_PROBE_COUNT; - if (mTexture.isNull() || mReflectionProbeCount != count || mReset) + if ((mTexture.isNull() || mReflectionProbeCount != count || mReset) && LLPipeline::RenderMirrors) { + + if (mReset) + { + cleanup(); + } + mReset = false; mReflectionProbeCount = count; mProbeResolution = gSavedSettings.getS32("RenderHeroProbeResolution"); @@ -546,9 +560,8 @@ void LLHeroProbeManager::cleanup() mDefaultProbe = nullptr; mUpdatingProbe = nullptr; - - mHeroVOList.clear(); - mNearestHero = nullptr; + /* + */ } void LLHeroProbeManager::doOcclusion() @@ -565,6 +578,11 @@ void LLHeroProbeManager::doOcclusion() } } +void LLHeroProbeManager::reset() +{ + mReset = true; +} + bool LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep) { llassert(drawablep != nullptr); -- cgit v1.2.3 From ca5e89d741b3618ab1dc681ecb6f75e5884988d7 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 8 May 2024 11:28:51 -0700 Subject: Even more mirror fixes. (#1429) #1271 Add support for mirrors that do not have avatars in them. It does this based on if the probe is set to dynamic or not. #1370 More optimization work to reduce GPU utilization. #1058 - Removed sim feature flag that was overriding mirrors enabled flags secondlife/viewer-private#128 - Locally cache the mirror probe #679 Add additional options to the build floater for mirror probes, including descriptions. --- indra/newview/llheroprobemanager.cpp | 73 ++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 24 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index dd29b416fb..55539a49d8 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -113,22 +113,40 @@ void LLHeroProbeManager::update() LLVector4a probe_pos; LLVector3 camera_pos = LLViewerCamera::instance().mOrigin; F32 near_clip = 0.1f; + bool probe_present = false; + LLQuaternion cameraOrientation = LLViewerCamera::instance().getQuaternion(); + LLVector3 cameraDirection = LLVector3::z_axis * cameraOrientation; + if (mHeroVOList.size() > 0) { // Find our nearest hero candidate. - float last_distance = 99999.f; - + float camera_center_distance = 99999.f; for (auto vo : mHeroVOList) { if (vo && !vo->isDead() && vo->mDrawable.notNull()) { float distance = (LLViewerCamera::instance().getOrigin() - vo->getPositionAgent()).magVec(); - if (distance < last_distance) + float center_distance = cameraDirection * (vo->getPositionAgent() - camera_pos); + + if (distance > LLViewerCamera::instance().getFar()) + continue; + + LLVector4a center; + center.load3(vo->getPositionAgent().mV); + LLVector4a size; + + size.load3(vo->getScale().mV); + + bool visible = LLViewerCamera::instance().AABBInFrustum(center, size); + + if (distance < last_distance && center_distance < camera_center_distance && visible) { - mNearestHero = vo; - last_distance = distance; - } + probe_present = true; + mNearestHero = vo; + last_distance = distance; + camera_center_distance = center_distance; + } } else { @@ -136,6 +154,10 @@ void LLHeroProbeManager::update() } } + // Don't even try to do anything if we didn't find a single mirror present. + if (!probe_present) + return; + if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull()) { LLVector3 hero_pos = mNearestHero->getPositionAgent(); @@ -152,14 +174,12 @@ void LLHeroProbeManager::update() mCurrentClipPlane.setVec(hero_pos, face_normal); mMirrorPosition = hero_pos; mMirrorNormal = face_normal; - probe_pos.load3(point.mV); - // Collect the list of faces that need updating based upon the camera's rotation. - LLVector3 cam_direction = LLVector3(0, 0, 1) * LLViewerCamera::instance().getQuaternion(); - cam_direction.normalize(); + // Detect visible faces of a cube based on camera direction and distance + // Define the cube faces static LLVector3 cubeFaces[6] = { LLVector3(1, 0, 0), LLVector3(-1, 0, 0), @@ -169,17 +189,21 @@ void LLHeroProbeManager::update() LLVector3(0, 0, -1) }; + // Iterate through each face of the cube for (int i = 0; i < 6; i++) { - float shouldUpdate = fminf(1, (fmaxf(-1, cam_direction * cubeFaces[i]) * 0.5 + 0.5)); - - int updateRate = ceilf((1 - shouldUpdate) * gPipeline.RenderHeroProbeConservativeUpdateMultiplier); - - // Chances are this is a face that's non-visible to the camera when it's being reflected. - // Set it to 0. It will be skipped below. - if (updateRate == gPipeline.RenderHeroProbeConservativeUpdateMultiplier) + float cube_facing = fmax(-1, fmin(1.0f, cameraDirection * cubeFaces[i])) * 0.6 + 0.4; + + float updateRate; + if (cube_facing < 0.1f) + { updateRate = 0; - + } + else + { + updateRate = ceilf(cube_facing * gPipeline.RenderHeroProbeConservativeUpdateMultiplier); + } + mFaceUpdateList[i] = updateRate; } } @@ -199,6 +223,7 @@ void LLHeroProbeManager::update() static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); + if (mNearestHero != nullptr) { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime"); // Probe 0 is always our mirror probe. @@ -208,13 +233,16 @@ void LLHeroProbeManager::update() gPipeline.mReflectionMapManager.mRadiancePass = true; mRenderingMirror = true; + + doOcclusion(); + for (U32 j = 0; j < mProbes.size(); j++) { for (U32 i = 0; i < 6; ++i) { if (mFaceUpdateList[i] > 0 && mCurrentProbeUpdateFrame % mFaceUpdateList[i] == 0) { - updateProbeFace(mProbes[j], i, near_clip); + updateProbeFace(mProbes[j], i, mNearestHero->getReflectionProbeIsDynamic() && sDetail > 0, near_clip); mCurrentProbeUpdateFrame = 0; } } @@ -239,18 +267,17 @@ void LLHeroProbeManager::update() // The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain. // At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe. // In effect this simulates single-bounce lighting. -void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip) +void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool is_dynamic, F32 near_clip) { // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mHeroProbeRT; - probe->update(mRenderTarget.getWidth(), face, true, near_clip); + probe->update(mRenderTarget.getWidth(), face, is_dynamic, near_clip); gPipeline.mRT = &gPipeline.mMainRT; S32 sourceIdx = mReflectionProbeCount; - // Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes. sourceIdx += 1; @@ -371,8 +398,6 @@ void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe) static LLStaticHashedString sSourceIdx("sourceIdx"); { - - // generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) gHeroRadianceGenProgram.bind(); mVertexBuffer->setBuffer(); -- cgit v1.2.3 From b06a99f7c76950484972e25d9dbbee8660a6a6c3 Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Wed, 15 May 2024 12:47:27 +0300 Subject: Post-merge spaces fix --- indra/newview/llheroprobemanager.cpp | 78 ++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 39 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 55539a49d8..208dfe45bd 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -66,7 +66,7 @@ LLHeroProbeManager::LLHeroProbeManager() LLHeroProbeManager::~LLHeroProbeManager() { - cleanup(); + cleanup(); mHeroVOList.clear(); mNearestHero = nullptr; @@ -130,7 +130,7 @@ void LLHeroProbeManager::update() float center_distance = cameraDirection * (vo->getPositionAgent() - camera_pos); if (distance > LLViewerCamera::instance().getFar()) - continue; + continue; LLVector4a center; center.load3(vo->getPositionAgent().mV); @@ -142,18 +142,18 @@ void LLHeroProbeManager::update() if (distance < last_distance && center_distance < camera_center_distance && visible) { - probe_present = true; - mNearestHero = vo; - last_distance = distance; + probe_present = true; + mNearestHero = vo; + last_distance = distance; camera_center_distance = center_distance; - } + } } else { unregisterViewerObject(vo); } } - + // Don't even try to do anything if we didn't find a single mirror present. if (!probe_present) return; @@ -162,7 +162,7 @@ void LLHeroProbeManager::update() { LLVector3 hero_pos = mNearestHero->getPositionAgent(); LLVector3 face_normal = LLVector3(0, 0, 1); - + face_normal *= mNearestHero->mDrawable->getWorldRotation(); face_normal.normalize(); @@ -180,8 +180,8 @@ void LLHeroProbeManager::update() // Detect visible faces of a cube based on camera direction and distance // Define the cube faces - static LLVector3 cubeFaces[6] = { - LLVector3(1, 0, 0), + static LLVector3 cubeFaces[6] = { + LLVector3(1, 0, 0), LLVector3(-1, 0, 0), LLVector3(0, 1, 0), LLVector3(0, -1, 0), @@ -193,7 +193,7 @@ void LLHeroProbeManager::update() for (int i = 0; i < 6; i++) { float cube_facing = fmax(-1, fmin(1.0f, cameraDirection * cubeFaces[i])) * 0.6 + 0.4; - + float updateRate; if (cube_facing < 0.1f) { @@ -208,18 +208,18 @@ void LLHeroProbeManager::update() } } else - { + { mNearestHero = nullptr; } - + mHeroProbeStrength = 1; } else { probe_pos.load3(camera_pos.mV); } - - + + static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); @@ -228,9 +228,9 @@ void LLHeroProbeManager::update() LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime"); // Probe 0 is always our mirror probe. mProbes[0]->mOrigin = probe_pos; - + bool radiance_pass = gPipeline.mReflectionMapManager.isRadiancePass(); - + gPipeline.mReflectionMapManager.mRadiancePass = true; mRenderingMirror = true; @@ -249,19 +249,19 @@ void LLHeroProbeManager::update() generateRadiance(mProbes[j]); } mRenderingMirror = false; - + gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass; mProbes[0]->mViewerObject = mNearestHero; mProbes[0]->autoAdjustOrigin(); } - + mCurrentProbeUpdateFrame++; } // Do the reflection map update render passes. // For every 12 calls of this function, one complete reflection probe radiance map and irradiance map is generated -// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate +// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate // a simple mip chain (not convolution filter). // At the end of these passes, an irradiance map is generated for this probe and placed into the irradiance cube map array at the index for this probe // The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain. @@ -273,11 +273,11 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool gPipeline.mRT = &gPipeline.mHeroProbeRT; probe->update(mRenderTarget.getWidth(), face, is_dynamic, near_clip); - + gPipeline.mRT = &gPipeline.mMainRT; S32 sourceIdx = mReflectionProbeCount; - + // Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes. sourceIdx += 1; @@ -285,7 +285,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool LLGLDepthTest depth(GL_FALSE, GL_FALSE); LLGLDisable cull(GL_CULL_FACE); LLGLDisable blend(GL_BLEND); - + // downsample to placeholder map { gGL.matrixMode(gGL.MM_MODELVIEW); @@ -351,14 +351,14 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool } gGL.getTexUnit(depthChannel)->bind(depth_rt, true); - + gReflectionMipProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); gReflectionMipProgram.uniform1f(znear, probe->getNearClip()); gReflectionMipProgram.uniform1f(zfar, MAX_FAR_CLIP); - + gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - + res /= 2; S32 mip = i - (mMipChain.size() - mips); @@ -459,13 +459,13 @@ void LLHeroProbeManager::updateUniforms() } LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - + LLMatrix4a modelview; modelview.loadu(gGLModelView); LLVector4a oa; // scratch space for transformed origin oa.set(0, 0, 0, 0); mHeroData.heroProbeCount = 1; - + if (mNearestHero != nullptr && !mNearestHero->isDead()) { if (mNearestHero->getReflectionProbeIsBox()) @@ -477,18 +477,18 @@ void LLHeroProbeManager::updateUniforms() { mProbes[0]->mRadius = mNearestHero->getScale().mV[0] * 0.5f; } - + modelview.affineTransform(mProbes[0]->mOrigin, oa); mHeroData.heroShape = 0; if (!mProbes[0]->getBox(mHeroData.heroBox)) { mHeroData.heroShape = 1; } - + mHeroData.heroSphere.set(oa.getF32ptr()); mHeroData.heroSphere.mV[3] = mProbes[0]->mRadius; } - + mHeroData.heroMipCount = mMipChain.size(); } @@ -537,14 +537,14 @@ void LLHeroProbeManager::initReflectionMaps() llassert(mProbes[0] == mDefaultProbe); // For hero probes, we treat this as the main mirror probe. - + mDefaultProbe->mCubeIndex = 0; mDefaultProbe->mCubeArray = mTexture; mDefaultProbe->mDistance = gSavedSettings.getF32("RenderHeroProbeDistance"); mDefaultProbe->mRadius = 4096.f; mDefaultProbe->mProbeIndex = 0; touch_default_probe(mDefaultProbe); - + mProbes.push_back(mDefaultProbe); } @@ -555,9 +555,9 @@ void LLHeroProbeManager::initReflectionMaps() buff->allocateBuffer(4, 0); LLStrider v; - + buff->getVertexStrider(v); - + v[0] = LLVector3(-1, -1, -1); v[1] = LLVector3(1, -1, -1); v[2] = LLVector3(-1, 1, -1); @@ -569,8 +569,8 @@ void LLHeroProbeManager::initReflectionMaps() } } -void LLHeroProbeManager::cleanup() -{ +void LLHeroProbeManager::cleanup() +{ mVertexBuffer = nullptr; mRenderTarget.release(); mHeroRenderTarget.release(); @@ -582,7 +582,7 @@ void LLHeroProbeManager::cleanup() mProbes.clear(); mReflectionMaps.clear(); - + mDefaultProbe = nullptr; mUpdatingProbe = nullptr; /* @@ -618,7 +618,7 @@ bool LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep) mHeroVOList.push_back(drawablep); return true; } - + return false; } -- cgit v1.2.3 From 33bb511ab4acd5867fbe5f11393a01e438b72293 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 28 May 2024 14:19:18 -0700 Subject: Improvements to mirror probe update rates (#1570) #1494 Fix for mirror updates getting "stuck" on some faces. --- indra/newview/llheroprobemanager.cpp | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 208dfe45bd..1c08424868 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -112,7 +112,6 @@ void LLHeroProbeManager::update() LLVector4a probe_pos; LLVector3 camera_pos = LLViewerCamera::instance().mOrigin; - F32 near_clip = 0.1f; bool probe_present = false; LLQuaternion cameraOrientation = LLViewerCamera::instance().getQuaternion(); LLVector3 cameraDirection = LLVector3::z_axis * cameraOrientation; @@ -192,20 +191,15 @@ void LLHeroProbeManager::update() // Iterate through each face of the cube for (int i = 0; i < 6; i++) { - float cube_facing = fmax(-1, fmin(1.0f, cameraDirection * cubeFaces[i])) * 0.6 + 0.4; + float cube_facing = fmax(-1, fmin(1.0f, cameraDirection * cubeFaces[i])); - float updateRate; - if (cube_facing < 0.1f) - { - updateRate = 0; - } - else - { - updateRate = ceilf(cube_facing * gPipeline.RenderHeroProbeConservativeUpdateMultiplier); - } + cube_facing = 1 - cube_facing; - mFaceUpdateList[i] = updateRate; + mFaceUpdateList[i] = ceilf(cube_facing * gPipeline.RenderHeroProbeConservativeUpdateMultiplier); } + + + mProbes[0]->mOrigin = probe_pos; } else { @@ -214,25 +208,23 @@ void LLHeroProbeManager::update() mHeroProbeStrength = 1; } - else - { - probe_pos.load3(camera_pos.mV); - } - +} +void LLHeroProbeManager::renderProbes() +{ static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); - if (mNearestHero != nullptr) + F32 near_clip = 0.01f; + if (mNearestHero != nullptr && (gPipeline.RenderHeroProbeUpdateRate == 0 || (gFrameCount % gPipeline.RenderHeroProbeUpdateRate) == 0) && + !gTeleportDisplay && !gDisconnected && !LLAppViewer::instance()->logoutRequestSent()) { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime"); - // Probe 0 is always our mirror probe. - mProbes[0]->mOrigin = probe_pos; bool radiance_pass = gPipeline.mReflectionMapManager.isRadiancePass(); gPipeline.mReflectionMapManager.mRadiancePass = true; - mRenderingMirror = true; + mRenderingMirror = true; doOcclusion(); @@ -585,8 +577,6 @@ void LLHeroProbeManager::cleanup() mDefaultProbe = nullptr; mUpdatingProbe = nullptr; - /* - */ } void LLHeroProbeManager::doOcclusion() -- cgit v1.2.3 From 01c82642ac01342114f41f2428890042c3040c9b Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 29 May 2024 19:31:58 -0700 Subject: #1581 Only render mirrors when reflection probes are enabled. (#1592) --- indra/newview/llheroprobemanager.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 1c08424868..ff47ca87ec 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -75,7 +75,7 @@ LLHeroProbeManager::~LLHeroProbeManager() // helper class to seed octree with probes void LLHeroProbeManager::update() { - if (!LLPipeline::RenderMirrors || gTeleportDisplay || LLStartUp::getStartupState() < STATE_PRECACHE) + if (!LLPipeline::RenderMirrors || !LLPipeline::sReflectionProbesEnabled || gTeleportDisplay || LLStartUp::getStartupState() < STATE_PRECACHE) { return; } @@ -212,6 +212,12 @@ void LLHeroProbeManager::update() void LLHeroProbeManager::renderProbes() { + if (!LLPipeline::RenderMirrors || !LLPipeline::sReflectionProbesEnabled || gTeleportDisplay || + LLStartUp::getStartupState() < STATE_PRECACHE) + { + return; + } + static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); -- cgit v1.2.3 From c413458fd48ff209f7bd536924a2df2c4dfe8716 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 4 Jun 2024 15:22:38 -0700 Subject: #1628 Disable spherical mirror probes for the time being. (#1631) --- indra/newview/llheroprobemanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index ff47ca87ec..efe72128d4 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -123,7 +123,7 @@ void LLHeroProbeManager::update() float camera_center_distance = 99999.f; for (auto vo : mHeroVOList) { - if (vo && !vo->isDead() && vo->mDrawable.notNull()) + if (vo && !vo->isDead() && vo->mDrawable.notNull() && vo->isReflectionProbe() && vo->getReflectionProbeIsBox()) { float distance = (LLViewerCamera::instance().getOrigin() - vo->getPositionAgent()).magVec(); float center_distance = cameraDirection * (vo->getPositionAgent() - camera_pos); -- cgit v1.2.3