From d8dd4d9c0cd4554704cbe15b5502f4d87a4674ad Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 27 Jun 2023 20:01:52 -0700 Subject: Just about got hero reflection maps working. DRTVWR-583 --- indra/llprimitive/llprimitive.cpp | 5 + indra/llprimitive/llprimitive.h | 1 + indra/llprimitive/llprimtexturelist.cpp | 10 ++ indra/llprimitive/llprimtexturelist.h | 1 + indra/llprimitive/lltextureentry.cpp | 19 +++ indra/llprimitive/lltextureentry.h | 12 +- indra/llrender/llglslshader.cpp | 4 +- indra/llrender/llglslshader.h | 1 + indra/llrender/llshadermgr.cpp | 9 ++ indra/llrender/llshadermgr.h | 1 + indra/newview/app_settings/settings.xml | 11 ++ .../shaders/class3/deferred/reflectionProbeF.glsl | 8 ++ .../shaders/class3/deferred/softenLightF.glsl | 12 +- indra/newview/llpanelface.cpp | 18 +++ indra/newview/llpanelface.h | 4 +- indra/newview/llreflectionmap.h | 11 ++ indra/newview/llreflectionmapmanager.cpp | 135 +++++++++++++++++---- indra/newview/llreflectionmapmanager.h | 15 ++- indra/newview/llselectmgr.cpp | 41 +++++++ indra/newview/llselectmgr.h | 1 + indra/newview/llviewerobject.cpp | 22 ++++ indra/newview/llviewerobject.h | 1 + indra/newview/llviewershadermgr.cpp | 2 + indra/newview/llvovolume.cpp | 10 ++ indra/newview/llvovolume.h | 1 + indra/newview/pipeline.cpp | 7 ++ 26 files changed, 331 insertions(+), 31 deletions(-) diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 5dfce4ae16..b45ead92d3 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -404,6 +404,11 @@ S32 LLPrimitive::setTEFullbright(const U8 index, const U8 fullbright) return mTextureList.setFullbright(index, fullbright); } +S32 LLPrimitive::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target) +{ + return mTextureList.setRenderableTarget(te, target); +} + S32 LLPrimitive::setTEMediaFlags(const U8 index, const U8 media_flags) { return mTextureList.setMediaFlags(index, media_flags); diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index d2adfa4a3d..520c7c7ac8 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -485,6 +485,7 @@ public: virtual S32 setTETexGen(const U8 te, const U8 texgen); virtual S32 setTEShiny(const U8 te, const U8 shiny); virtual S32 setTEFullbright(const U8 te, const U8 fullbright); + virtual S32 setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target); virtual S32 setTEMediaFlags(const U8 te, const U8 flags); virtual S32 setTEGlow(const U8 te, const F32 glow); virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp index f4f08248b8..49b59e35cb 100644 --- a/indra/llprimitive/llprimtexturelist.cpp +++ b/indra/llprimitive/llprimtexturelist.cpp @@ -341,6 +341,16 @@ S32 LLPrimTextureList::setFullbright(const U8 index, const U8 fullbright) return TEM_CHANGE_NONE; } +S32 LLPrimTextureList::setRenderableTarget(const U8 index, const U8 target) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setRenderableTarget((LLTextureEntry::eRenderableTarget)target); + } + + return TEM_CHANGE_NONE; +} + S32 LLPrimTextureList::setMediaFlags(const U8 index, const U8 media_flags) { if (index < mEntryList.size()) diff --git a/indra/llprimitive/llprimtexturelist.h b/indra/llprimitive/llprimtexturelist.h index 49c636e40f..34b87d879f 100644 --- a/indra/llprimitive/llprimtexturelist.h +++ b/indra/llprimitive/llprimtexturelist.h @@ -102,6 +102,7 @@ public: S32 setTexGen(const U8 index, const U8 texgen); S32 setShiny(const U8 index, const U8 shiny); S32 setFullbright(const U8 index, const U8 t); + S32 setRenderableTarget(const U8 index, const U8 target); S32 setMediaFlags(const U8 index, const U8 media_flags); S32 setGlow(const U8 index, const F32 glow); S32 setMaterialID(const U8 index, const LLMaterialID& pMaterialID); diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index 71caff1686..d057e5ab29 100644 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -504,6 +504,16 @@ S32 LLTextureEntry::setFullbright(U8 fullbright) return TEM_CHANGE_NONE; } +S32 LLTextureEntry::setRenderableTarget(eRenderableTarget target) +{ + if (getRenderableTarget() != target) { + mRenderableTarget = target; + return TEM_CHANGE_TEXTURE; + } + + return TEM_CHANGE_NONE; +} + S32 LLTextureEntry::setShiny(U8 shiny) { shiny &= TEM_SHINY_MASK; @@ -685,6 +695,15 @@ S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams) mMaterialUpdatePending = true; } mMaterial = pMaterialParams; + + // TODO: GZ: We should avoid magic UUIDs in the future, but for development we're using one for the time being. Remove this later. + if (mMaterial->getSpecularID().asString() == "da7ecda1-e780-423f-ce27-26df7dc69cb6") + { + setRenderableTarget(RT_MIRROR); + } else { + setRenderableTarget(RT_DISABLED); + } + return TEM_CHANGE_TEXTURE; } diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h index f5f2c0172d..2c0832e1d4 100644 --- a/indra/llprimitive/lltextureentry.h +++ b/indra/llprimitive/lltextureentry.h @@ -80,6 +80,12 @@ public: TEX_GEN_SPHERICAL = 0x04, TEX_GEN_CYLINDRICAL = 0x06 } eTexGen; + + + typedef enum e_renderable_target { + RT_DISABLED = 0x00, + RT_MIRROR = 0x02 + } eRenderableTarget; LLTextureEntry(); LLTextureEntry(const LLUUID& tex_id); @@ -134,7 +140,9 @@ public: S32 setGlow(F32 glow); S32 setMaterialID(const LLMaterialID& pMaterialID); S32 setMaterialParams(const LLMaterialPtr pMaterialParams); - + + S32 setRenderableTarget(eRenderableTarget target); + virtual const LLUUID &getID() const { return mID; } const LLColor4 &getColor() const { return mColor; } const F32 getAlpha() const { return mColor.mV[VALPHA]; } @@ -152,6 +160,7 @@ public: U8 getBumpmap() const { return mBump & TEM_BUMP_MASK; } U8 getFullbright() const { return (mBump>>TEM_FULLBRIGHT_SHIFT) & TEM_FULLBRIGHT_MASK; } + eRenderableTarget getRenderableTarget() const { return mRenderableTarget; } U8 getShiny() const { return (mBump>>TEM_SHINY_SHIFT) & TEM_SHINY_MASK; } U8 getBumpShiny() const { return mBump & TEM_BUMP_SHINY_MASK; } U8 getBumpShinyFullbright() const { return mBump; } @@ -233,6 +242,7 @@ protected: LLColor4 mColor; U8 mBump; // Bump map, shiny, and fullbright U8 mMediaFlags; // replace with web page, movie, etc. + eRenderableTarget mRenderableTarget; F32 mGlow; bool mMaterialUpdatePending; LLMaterialID mMaterialID; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index ccfb8f69be..be5ad08fbe 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1184,12 +1184,14 @@ S32 LLGLSLShader::getTextureChannel(S32 uniform) const S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - + if (uniform < 0 || uniform >= (S32)mTexture.size()) { LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; return -1; } + + S32 index = mTexture[uniform]; if (index != -1) { diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index b8071248e2..71b9b0f4fb 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -57,6 +57,7 @@ public: bool hasAlphaMask = false; bool hasReflectionProbes = false; bool attachNothing = false; + bool hasHeroProbes = false; }; // ============= Structure for caching shader uniforms =============== diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 75d6ef6c46..177cad2508 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -238,6 +238,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) return FALSE; } } + + if (features->hasHeroProbes) + { + if (!shader->attachFragmentObject("deferred/heroProbesUtil.glsl")) + { + return FALSE; + } + } if (features->hasShadows) { @@ -1260,6 +1268,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("sceneDepth"); mReservedUniforms.push_back("reflectionProbes"); mReservedUniforms.push_back("irradianceProbes"); + mReservedUniforms.push_back("heroProbes"); mReservedUniforms.push_back("cloud_noise_texture"); mReservedUniforms.push_back("cloud_noise_texture_next"); mReservedUniforms.push_back("fullbright"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 46f352aa58..cfa824c361 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -96,6 +96,7 @@ public: SCENE_DEPTH, // "sceneDepth" REFLECTION_PROBES, // "reflectionProbes" IRRADIANCE_PROBES, // "irradianceProbes" + HERO_PROBE, // "heroProbes" CLOUD_NOISE_MAP, // "cloud_noise_texture" CLOUD_NOISE_MAP_NEXT, // "cloud_noise_texture_next" FULLBRIGHT, // "fullbright" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2b2a2d9d1b..270d5e6869 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9175,6 +9175,17 @@ 0.00 + RenderMirrors + + Comment + Renders realtime mirrors. + Persist + 1 + Type + Boolean + Value + 1 + RenderScreenSpaceReflections Comment diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 1b2a34ef01..298ddf92a7 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -31,6 +31,7 @@ float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, uniform samplerCubeArray reflectionProbes; uniform samplerCubeArray irradianceProbes; + uniform sampler2D sceneMap; uniform int cube_snapshot; uniform float max_probe_lod; @@ -70,6 +71,9 @@ layout (std140) uniform ReflectionProbes // number of reflection probes present in refSphere int refmapCount; + + vec4 heroPosition[1]; + int heroProbeCount; }; // Inputs @@ -513,6 +517,10 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c, v = env_mat * v; +#if defined(HERO_PROBES) + vec3 mirror = textureLod(heroProbes, vec4(v.xyz, 0), lod).rgb; +#endif + vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod) * refParams[i].y; return ret.rgb; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 4ef003e0cb..a63d445115 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -32,6 +32,14 @@ uniform sampler2D specularRect; uniform sampler2D normalMap; uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl +uniform samplerCubeArray heroProbes; + +layout (std140) uniform HeroProbeData +{ + vec4 heroPosition[1]; + int heroProbeCount; +}; + const float M_PI = 3.14159265; #if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO) @@ -290,7 +298,7 @@ void main() vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom)); color = fogged.rgb; #endif - - frag_color.rgb = max(color.rgb, vec3(0)); //output linear since local lights will be added to this shader's results + frag_color.rgb = textureLod(heroProbes, vec4(norm.xyz, 0), 0).rgb; + //frag_color.rgb = max(color.rgb, vec3(0)); //output linear since local lights will be added to this shader's results frag_color.a = 0.0; } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 7d6015f557..6b737b6895 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -592,6 +592,17 @@ void LLPanelFace::sendFullbright() LLSelectMgr::getInstance()->selectionSetFullbright( fullbright ); } +void LLPanelFace::sendMirror() +{ + LLCheckBoxCtrl* mCheckMirror = getChild("checkbox mirror"); + + if (!mCheckMirror) + return; + + LLTextureEntry::eRenderableTarget target = mCheckMirror->get() ? LLTextureEntry::RT_MIRROR : LLTextureEntry::RT_DISABLED; + LLSelectMgr::getInstance()->selectionSetRenderableTarget(target); +} + void LLPanelFace::sendColor() { @@ -1686,6 +1697,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) getChild("shinyOffsetV")->setValue(offset_y); getChild("glossiness")->setValue(material->getSpecularLightExponent()); getChild("environment")->setValue(material->getEnvironmentIntensity()); + getChild("mirror")->setValue(material->getEnvironmentIntensity()); updateShinyControls(!material->getSpecularID().isNull(), true); } @@ -2994,6 +3006,12 @@ void LLPanelFace::onCommitFullbright(LLUICtrl* ctrl, void* userdata) self->sendFullbright(); } +void LLPanelFace::onCommitMirror(LLUICtrl* ctrl, void* userdata) +{ + LLPanelFace* self = (LLPanelFace*) userdata; + self->sendMirror(); +} + // static void LLPanelFace::onCommitGlow(LLUICtrl* ctrl, void* userdata) { diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 106259b84a..f6d6d99d9f 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -138,6 +138,7 @@ protected: void sendTexGen(); // applies and sends bump map void sendShiny(U32 shininess); // applies and sends shininess void sendFullbright(); // applies and sends full bright + void sendMirror(); void sendGlow(); void alignTestureLayer(); @@ -227,7 +228,8 @@ protected: static void onCommitShiny( LLUICtrl* ctrl, void* userdata); static void onCommitAlphaMode( LLUICtrl* ctrl, void* userdata); static void onCommitFullbright( LLUICtrl* ctrl, void* userdata); - static void onCommitGlow( LLUICtrl* ctrl, void *userdata); + static void onCommitMirror(LLUICtrl* ctrl, void* userdata); + static void onCommitGlow( LLUICtrl* ctrl, void *userdata); static void onCommitPlanarAlign( LLUICtrl* ctrl, void* userdata); static void onCommitRepeatsPerMeter( LLUICtrl* ctrl, void* userinfo); diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index 7ea0fe6187..831a6358ee 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -36,6 +36,15 @@ class alignas(16) LLReflectionMap : public LLRefCount { LL_ALIGN_NEW public: + + enum class ProbeType + { + ALL = 0, + RADIANCE, + IRRADIANCE, + REFLECTION + }; + // allocate an environment map of the given resolution LLReflectionMap(); @@ -127,5 +136,7 @@ public: GLuint mOcclusionQuery = 0; bool mOccluded = false; U32 mOcclusionPendingFrames = 0; + + ProbeType mType; }; diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index e30aba3df7..8e7d073167 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -130,6 +130,13 @@ void LLReflectionMapManager::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()) { @@ -315,7 +322,7 @@ void LLReflectionMapManager::update() mRadiancePass = mRealtimeRadiancePass; for (U32 i = 0; i < 6; ++i) { - updateProbeFace(closestDynamic, i); + updateProbeFace(closestDynamic, i, mProbeResolution); } mRealtimeRadiancePass = !mRealtimeRadiancePass; @@ -354,6 +361,10 @@ void LLReflectionMapManager::update() oldestOccluded->autoAdjustOrigin(); oldestOccluded->mLastUpdateTime = gFrameTimeSeconds; } + + + doHeroProbeUpdate(); + } LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group) @@ -528,7 +539,7 @@ void LLReflectionMapManager::doProbeUpdate() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(mUpdatingProbe != nullptr); - updateProbeFace(mUpdatingProbe, mUpdatingFace); + updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution); if (++mUpdatingFace == 6) { @@ -547,6 +558,21 @@ void LLReflectionMapManager::doProbeUpdate() } } +void LLReflectionMapManager::doHeroProbeUpdate() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + llassert(mHeroProbe != nullptr); + + touch_default_probe(mHeroProbe); + + for (int i = 0; i < 6; i++) + { + gPipeline.mRT = &gPipeline.mAuxillaryRT; + mHeroProbe->update(mHeroProbeResolution, i); + gPipeline.mRT = &gPipeline.mMainRT; + } +} + // 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 @@ -555,10 +581,20 @@ void LLReflectionMapManager::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 LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) +void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray) { // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; + + LLRenderTarget* target = &mRenderTarget; + + S32 sourceIdx = mReflectionProbeCount; + + if (probeResolution == mHeroProbeResolution) + { + sourceIdx = 0; + target = &mHeroRenderTarget; + } mLightScale = 1.f; static LLCachedControl max_local_light_ambiance(gSavedSettings, "RenderReflectionProbeMaxLocalLightAmbiance", 8.f); @@ -577,20 +613,18 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY, LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::END_RENDER_TYPES); - probe->update(mRenderTarget.getWidth(), face); + probe->update(target->getWidth(), face); gPipeline.popRenderTypeMask(); } else { - probe->update(mRenderTarget.getWidth(), face); + probe->update(target->getWidth(), face); } gPipeline.mRT = &gPipeline.mMainRT; - S32 sourceIdx = mReflectionProbeCount; - - if (probe != mUpdatingProbe) + 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; } @@ -611,7 +645,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gGL.loadIdentity(); gGL.flush(); - U32 res = mProbeResolution * 2; + U32 res = probeResolution * 2; static LLStaticHashedString resScale("resScale"); static LLStaticHashedString direction("direction"); @@ -623,20 +657,20 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) // 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 / (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); - mRenderTarget.bindTarget(); + target->bindTarget(); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - mRenderTarget.flush(); + target->flush(); // vertical gGaussianProgram.uniform2f(direction, 0.f, 1.f); - gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); + gGL.getTexUnit(diffuseChannel)->bind(target); screen_rt->bindTarget(); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -644,7 +678,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) } - S32 mips = log2((F32)mProbeResolution) + 0.5f; + S32 mips = log2((F32)probeResolution) + 0.5f; gReflectionMipProgram.bind(); S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); @@ -663,7 +697,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) } - gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2)); + gReflectionMipProgram.uniform1f(resScale, 1.f/(probeResolution*2)); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -675,14 +709,14 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) if (mip >= 0) { LL_PROFILE_GPU_ZONE("probe mip copy"); - mTexture->bind(0); + probe->mCubeArray->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(); + probe->mCubeArray->unbind(); } mMipChain[i].flush(); } @@ -695,7 +729,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gReflectionMipProgram.unbind(); } - if (face == 5) + if (face == 5 && probe->mType != LLReflectionMap::ProbeType::REFLECTION) { mMipChain[0].bindTarget(); static LLStaticHashedString sSourceIdx("sourceIdx"); @@ -707,7 +741,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) mVertexBuffer->setBuffer(); S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - mTexture->bind(channel); + probe->mCubeArray->bind(channel); gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); @@ -722,7 +756,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); gRadianceGenProgram.uniform1f(sMipLevel, i); - gRadianceGenProgram.uniform1i(sWidth, mProbeResolution); + gRadianceGenProgram.uniform1i(sWidth, probeResolution); for (int cf = 0; cf < 6; ++cf) { // for each cube face @@ -752,7 +786,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) //generate irradiance map gIrradianceGenProgram.bind(); S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - mTexture->bind(channel); + probe->mCubeArray->bind(channel); gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); @@ -787,7 +821,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) 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); - mTexture->bind(channel); + probe->mCubeArray->bind(channel); } } } @@ -890,7 +924,7 @@ void LLReflectionMapManager::updateUniforms() GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth // numbrer of active refmaps - GLint refmapCount; + GLint refmapCount; }; mReflectionMaps.resize(mReflectionProbeCount); @@ -1068,7 +1102,7 @@ void LLReflectionMapManager::updateUniforms() #endif rpd.refmapCount = count; - + //copy rpd into uniform buffer object if (mUBO == 0) { @@ -1081,7 +1115,35 @@ void LLReflectionMapManager::updateUniforms() 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) { @@ -1214,7 +1276,7 @@ void LLReflectionMapManager::initReflectionMaps() { U32 count = LL_MAX_REFLECTION_PROBE_COUNT; - if (mTexture.isNull() || mReflectionProbeCount != count || mReset) + if (mTexture.isNull() || mReflectionProbeCount != count || mReset || mHeroArray.isNull()) { mReset = false; mReflectionProbeCount = count; @@ -1263,6 +1325,22 @@ void LLReflectionMapManager::initReflectionMaps() mDefaultProbe->mRadius = 4096.f; mDefaultProbe->mProbeIndex = 0; touch_default_probe(mDefaultProbe); + + mHeroProbeResolution = 512; + + mHeroArray = new LLCubeMapArray(); + mHeroArray->allocate(mHeroProbeResolution, 3, 1); + + 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); } @@ -1291,11 +1369,13 @@ void LLReflectionMapManager::cleanup() { mVertexBuffer = nullptr; mRenderTarget.release(); + mHeroRenderTarget.release(); mMipChain.clear(); mTexture = nullptr; mIrradianceMaps = nullptr; + mHeroArray = nullptr; mProbes.clear(); mKillList.clear(); @@ -1306,9 +1386,14 @@ void LLReflectionMapManager::cleanup() 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(); diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 5a3901cae9..2ca9a8d598 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -125,11 +125,15 @@ private: // render target for cube snapshots // used to generate mipmaps without doing a copy-to-texture LLRenderTarget mRenderTarget; + + LLRenderTarget mHeroRenderTarget; std::vector mMipChain; // storage for reflection probe radiance maps (plus two scratch space cubemaps) LLPointer mTexture; + + LLPointer mHeroArray; // vertex buffer for pushing verts to filter shaders LLPointer mVertexBuffer; @@ -142,9 +146,11 @@ private: // perform an update on the currently updating Probe void doProbeUpdate(); + + void doHeroProbeUpdate(); // update the specified face of the specified probe - void updateProbeFace(LLReflectionMap* probe, U32 face); + void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution); // list of active reflection maps std::vector > mProbes; @@ -157,6 +163,9 @@ private: // handle to UBO U32 mUBO = 0; + + // Hero UBO + U32 mHeroUBO = 0; // list of maps being used for rendering std::vector mReflectionMaps; @@ -176,12 +185,16 @@ private: bool mRealtimeRadiancePass = false; LLPointer mDefaultProbe; // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0) + + LLPointer mHeroProbe; // number of reflection probes to use for rendering U32 mReflectionProbeCount; // resolution of reflection probes U32 mProbeResolution = 128; + + U32 mHeroProbeResolution = 512; // maximum LoD of reflection probes (mip levels - 1) F32 mMaxProbeLOD = 6.f; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index dca341e5a2..19ce8f6a55 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -2347,6 +2347,47 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright) getSelection()->applyToObjects(&sendfunc); } +void LLSelectMgr::selectionSetRenderableTarget(LLTextureEntry::eRenderableTarget target) +{ + struct f : public LLSelectedTEFunctor + { + LLTextureEntry::eRenderableTarget mRenderableTarget; + + f(const LLTextureEntry::eRenderableTarget& t) : mRenderableTarget(t) {} + + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + object->setTERenderableTarget(te, mRenderableTarget); + } + + return true; + } + } setfunc(target); + + getSelection()->applyToTEs(&setfunc); + + struct g : public LLSelectedObjectFunctor + { + LLTextureEntry::eRenderableTarget mRenderableTarget; + + g(const LLTextureEntry::eRenderableTarget& t) : mRenderableTarget(t) {} + + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->sendTEUpdate(); + } + + return true; + } + } sendfunc(target); + + getSelection()->applyToObjects(&sendfunc); +} + // This function expects media_data to be a map containing relevant // media data name/value pairs (e.g. home_url, etc.) void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data) diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index ca9a32f0db..93d750215b 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -653,6 +653,7 @@ public: void selectionSetGlow(const F32 glow); void selectionSetMaterialParams(LLSelectedTEMaterialFunctor* material_func, int specific_te = -1); void selectionRemoveMaterial(); + void selectionSetRenderableTarget(LLTextureEntry::eRenderableTarget target); void selectionSetObjectPermissions(U8 perm_field, BOOL set, U32 perm_mask, BOOL override = FALSE); void selectionSetObjectName(const std::string& name); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index e67750af7c..8930b2453b 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5284,6 +5284,28 @@ S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright) return retval; } +S32 LLViewerObject::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target) +{ + S32 retval = 0; + + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + } + else if (target != tep->getRenderableTarget()) + { + retval = LLPrimitive::setTERenderableTarget(te, target); + setChanged(TEXTURE); + if (mDrawable.notNull() && retval) + { + //gPipeline.markMirror(mDrawable); + } + } + + return retval; +} + S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags) { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index bf82c43cd3..f4f596bfd0 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -359,6 +359,7 @@ public: /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media ); // *FIXME: this confusingly acts upon a superset of setTETexGen's flags without absorbing its semantics /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny ); /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright ); + /*virtual*/ S32 setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target); /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags ); /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 5eae1dfb18..f6f1cf6854 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -2228,6 +2228,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredSoftenProgram.addPermutation("LOCAL_LIGHT_KILL", "1"); } + + gDeferredSoftenProgram.addPermutation("HERO_PROBES", "1"); if (gSavedSettings.getBOOL("RenderDeferredSSAO")) { //if using SSAO, take screen space light map into account as if shadows are enabled diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 8160785d75..8eacdd2162 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -2344,6 +2344,16 @@ S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright) return res; } +S32 LLVOVolume::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget mirror) +{ + S32 res = LLViewerObject::setTERenderableTarget(te, mirror); + if (res) + { + //gPipeline.markMirror(mDrawable); + } + return res; +} + S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump) { S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump); diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index acba18383f..f2162ef244 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -209,6 +209,7 @@ public: /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump) override; /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny) override; /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright) override; + /*virtual*/ S32 setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target) override; /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump) override; /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags) override; /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow) override; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 38f27d4dfa..d6e0bf1b09 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8419,6 +8419,13 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader) mReflectionMapManager.mIrradianceMaps->bind(channel); bound = true; } + + channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY); + if (channel > -1 && mReflectionMapManager.mHeroArray.notNull()) + { + mReflectionMapManager.mHeroArray->bind(channel); + bound = true; + } if (bound) { -- cgit v1.2.3 From 5ade456ee796aeb779302016b9ee9d418c728a22 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 28 Jun 2023 13:27:15 -0400 Subject: Make sure we're passing the cube array as a parameter to updateProbeFace. DRTVWR-583 --- indra/newview/llreflectionmapmanager.cpp | 36 ++++++++++++++++++++++++-------- indra/newview/llreflectionmapmanager.h | 2 +- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 8e7d073167..783ff69073 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -322,7 +322,7 @@ void LLReflectionMapManager::update() mRadiancePass = mRealtimeRadiancePass; for (U32 i = 0; i < 6; ++i) { - updateProbeFace(closestDynamic, i, mProbeResolution); + updateProbeFace(closestDynamic, i, mProbeResolution, mTexture); } mRealtimeRadiancePass = !mRealtimeRadiancePass; @@ -362,8 +362,26 @@ void LLReflectionMapManager::update() oldestOccluded->mLastUpdateTime = gFrameTimeSeconds; } - - doHeroProbeUpdate(); + if (mHeroProbe != 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 + mHeroProbe->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(mHeroProbe, i, mProbeResolution, mHeroArray); + } + mRealtimeRadiancePass = !mRealtimeRadiancePass; + + // restore "isRadiancePass" + mRadiancePass = radiance_pass; + } } @@ -539,7 +557,7 @@ void LLReflectionMapManager::doProbeUpdate() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(mUpdatingProbe != nullptr); - updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution); + updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution, mTexture); if (++mUpdatingFace == 6) { @@ -709,14 +727,14 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U if (mip >= 0) { LL_PROFILE_GPU_ZONE("probe mip copy"); - probe->mCubeArray->bind(0); + cubeArray->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); //} - probe->mCubeArray->unbind(); + cubeArray->unbind(); } mMipChain[i].flush(); } @@ -741,7 +759,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U mVertexBuffer->setBuffer(); S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - probe->mCubeArray->bind(channel); + cubeArray->bind(channel); gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); @@ -786,7 +804,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U //generate irradiance map gIrradianceGenProgram.bind(); S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - probe->mCubeArray->bind(channel); + cubeArray->bind(channel); gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); @@ -821,7 +839,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U 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); - probe->mCubeArray->bind(channel); + cubeArray->bind(channel); } } } diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 2ca9a8d598..1275617e0a 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -150,7 +150,7 @@ private: void doHeroProbeUpdate(); // update the specified face of the specified probe - void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution); + void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray); // list of active reflection maps std::vector > mProbes; -- cgit v1.2.3 From 53b2efd13143f85c447320fa35d192df466b16ca Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 29 Jun 2023 17:35:24 -0400 Subject: Remove doHeroProbeUpdate DRTVWR-583 --- indra/newview/llreflectionmapmanager.cpp | 60 ++++++++++++-------------------- indra/newview/llreflectionmapmanager.h | 2 -- 2 files changed, 23 insertions(+), 39 deletions(-) diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 783ff69073..fe3ea15352 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -329,6 +329,28 @@ void LLReflectionMapManager::update() // restore "isRadiancePass" mRadiancePass = radiance_pass; } + + + { + 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 + mHeroProbe->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(mHeroProbe, i, mHeroProbeResolution, mHeroArray); + } + + mRealtimeRadiancePass = !mRealtimeRadiancePass; + + // restore "isRadiancePass" + mRadiancePass = radiance_pass; + } static LLCachedControl sUpdatePeriod(gSavedSettings, "RenderDefaultProbeUpdatePeriod", 2.f); if ((gFrameTimeSeconds - mDefaultProbe->mLastUpdateTime) < sUpdatePeriod) @@ -361,28 +383,6 @@ void LLReflectionMapManager::update() oldestOccluded->autoAdjustOrigin(); oldestOccluded->mLastUpdateTime = gFrameTimeSeconds; } - - if (mHeroProbe != 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 - mHeroProbe->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(mHeroProbe, i, mProbeResolution, mHeroArray); - } - mRealtimeRadiancePass = !mRealtimeRadiancePass; - - // restore "isRadiancePass" - mRadiancePass = radiance_pass; - } - } LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group) @@ -576,21 +576,6 @@ void LLReflectionMapManager::doProbeUpdate() } } -void LLReflectionMapManager::doHeroProbeUpdate() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - llassert(mHeroProbe != nullptr); - - touch_default_probe(mHeroProbe); - - for (int i = 0; i < 6; i++) - { - gPipeline.mRT = &gPipeline.mAuxillaryRT; - mHeroProbe->update(mHeroProbeResolution, i); - gPipeline.mRT = &gPipeline.mMainRT; - } -} - // 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 @@ -1190,6 +1175,7 @@ void LLReflectionMapManager::setUniforms() updateUniforms(); } glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO); + glBindBufferBase(GL_UNIFORM_BUFFER, 1, mHeroUBO); } diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 1275617e0a..81b0ef8ed8 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -146,8 +146,6 @@ private: // perform an update on the currently updating Probe void doProbeUpdate(); - - void doHeroProbeUpdate(); // update the specified face of the specified probe void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray); -- cgit v1.2.3 From f7f9601567ce089f3335407f1d3c7d32dbb18c60 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 17 Jul 2023 15:05:47 -0700 Subject: Got hero probes rendering from the camera. DRTVWR-583 --- indra/llplugin/llpluginprocessparent.cpp | 2 +- .../shaders/class3/deferred/softenLightF.glsl | 9 ++++---- indra/newview/llreflectionmapmanager.cpp | 26 ++++++++-------------- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 756d0b5db8..f5966b71de 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -582,7 +582,7 @@ void LLPluginProcessParent::idle(void) params.args.add("-e"); params.args.add("tell application \"Terminal\""); params.args.add("-e"); - params.args.add(STRINGIZE("set win to do script \"gdb -pid " + params.args.add(STRINGIZE("set win to do script \"lldb -pid " << mProcess->getProcessID() << "\"")); params.args.add("-e"); params.args.add("do script \"continue\" in win"); diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index a63d445115..d8118fab82 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -117,8 +117,8 @@ vec3 pbrBaseLight(vec3 diffuseColor, vec3 additive, vec3 atten); -vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, - float perceptualRoughness, +vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, + float perceptualRoughness, float metallic, vec3 n, // normal vec3 v, // surface point to camera @@ -193,7 +193,7 @@ void main() if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR)) { - vec3 orm = texture(specularRect, tc).rgb; + vec3 orm = texture(specularRect, tc).rgb; float perceptualRoughness = orm.g; float metallic = orm.b; float ao = orm.r; @@ -298,7 +298,6 @@ void main() vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom)); color = fogged.rgb; #endif - frag_color.rgb = textureLod(heroProbes, vec4(norm.xyz, 0), 0).rgb; - //frag_color.rgb = max(color.rgb, vec3(0)); //output linear since local lights will be added to this shader's results + frag_color.rgb = max(color.rgb, vec3(0)); //output linear since local lights will be added to this shader's results frag_color.a = 0.0; } diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index fe3ea15352..45489fb35b 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -333,20 +333,14 @@ void LLReflectionMapManager::update() { 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 - mHeroProbe->autoAdjustOrigin(); - - // store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set - // lighting values etc + + mHeroProbe->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); bool radiance_pass = isRadiancePass(); - mRadiancePass = mRealtimeRadiancePass; + mRadiancePass = true; for (U32 i = 0; i < 6; ++i) { updateProbeFace(mHeroProbe, i, mHeroProbeResolution, mHeroArray); } - - mRealtimeRadiancePass = !mRealtimeRadiancePass; // restore "isRadiancePass" mRadiancePass = radiance_pass; @@ -713,12 +707,9 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U { LL_PROFILE_GPU_ZONE("probe mip copy"); cubeArray->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); - //} + cubeArray->unbind(); } mMipChain[i].flush(); @@ -732,7 +723,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U gReflectionMipProgram.unbind(); } - if (face == 5 && probe->mType != LLReflectionMap::ProbeType::REFLECTION) + if (face == 5) { mMipChain[0].bindTarget(); static LLStaticHashedString sSourceIdx("sourceIdx"); @@ -1330,10 +1321,11 @@ void LLReflectionMapManager::initReflectionMaps() mDefaultProbe->mProbeIndex = 0; touch_default_probe(mDefaultProbe); - mHeroProbeResolution = 512; + mHeroProbeResolution = 128; mHeroArray = new LLCubeMapArray(); - mHeroArray->allocate(mHeroProbeResolution, 3, 1); + // Revise when we have both water and mirrors in hero probes. + mHeroArray->allocate(mHeroProbeResolution, 3, 2, true); if (mHeroProbe.isNull()) { mHeroProbe = new LLReflectionMap(); -- cgit v1.2.3 From 3d73326516c73f880f46e28f14b6c515307ede91 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 18 Jul 2023 00:14:34 -0700 Subject: Fix for irradiance breaking. Still need to fix the problem with individual faces getting tossed around though. Will work on that tomorrow. DRTVWR-583 --- indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl | 3 +-- indra/newview/llpanelface.cpp | 2 +- indra/newview/llreflectionmapmanager.cpp | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index d8118fab82..0152c0612a 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -217,6 +217,7 @@ void main() { color = atmosFragLightingLinear(color, additive, atten); } + color = texture(heroProbes, vec4(norm.xyz * env_mat, 0), 0).xyz; } else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { @@ -291,9 +292,7 @@ void main() color = atmosFragLightingLinear(color, additive, atten); } } - - #ifdef WATER_FOG vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom)); color = fogged.rgb; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 721b1482d9..9140888cc1 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1035,7 +1035,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) mComboMatMedia->setEnabled(editable); LLRadioGroup* radio_mat_type = getChild("radio_material_type"); - + if (radio_mat_type->getSelectedIndex() < MATTYPE_DIFFUSE) { radio_mat_type->selectNthItem(MATTYPE_DIFFUSE); diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 6550686a32..99ebcf5231 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -1171,7 +1171,6 @@ void LLReflectionMapManager::setUniforms() updateUniforms(); } glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO); - glBindBufferBase(GL_UNIFORM_BUFFER, 1, mHeroUBO); } -- cgit v1.2.3 From b861832102abf469963bd3c56f7b009ba4432d6a Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Sun, 6 Aug 2023 23:33:29 -0700 Subject: Making more progress, need to add the heroprobe manager. DRTVWR-583 --- indra/llprimitive/lltextureentry.cpp | 8 ------ .../shaders/class3/deferred/softenLightF.glsl | 4 ++- indra/newview/lldrawable.h | 1 + indra/newview/llreflectionmapmanager.cpp | 20 +++++++++------ indra/newview/llreflectionmapmanager.h | 4 ++- indra/newview/llviewerobject.h | 1 + indra/newview/llvovolume.cpp | 30 +++++++++++++++++++++- indra/newview/llvovolume.h | 2 ++ indra/newview/pipeline.cpp | 22 ++++++++++++++++ indra/newview/pipeline.h | 5 ++++ 10 files changed, 78 insertions(+), 19 deletions(-) diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index d057e5ab29..fdf3774bfa 100644 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -696,14 +696,6 @@ S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams) } mMaterial = pMaterialParams; - // TODO: GZ: We should avoid magic UUIDs in the future, but for development we're using one for the time being. Remove this later. - if (mMaterial->getSpecularID().asString() == "da7ecda1-e780-423f-ce27-26df7dc69cb6") - { - setRenderableTarget(RT_MIRROR); - } else { - setRenderableTarget(RT_DISABLED); - } - return TEM_CHANGE_TEXTURE; } diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 0152c0612a..e485c26e9b 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -217,7 +217,9 @@ void main() { color = atmosFragLightingLinear(color, additive, atten); } - color = texture(heroProbes, vec4(norm.xyz * env_mat, 0), 0).xyz; + + vec3 refnormpersp = reflect(pos.xyz, norm.xyz); + color = texture(heroProbes, vec4(env_mat * refnormpersp, 0), 0).xyz; } else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 970e8c8b2a..fc182fc2e2 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -286,6 +286,7 @@ public: ANIMATED_CHILD = 0x01000000, ACTIVE_CHILD = 0x02000000, FOR_UNLOAD = 0x04000000, //should be unload from memory + MIRROR = 0x08000000, // Used as a mirror, needs a hero probe position to be calculated. } EDrawableFlags; public: diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 99ebcf5231..ad4d3d94e2 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -140,7 +140,7 @@ void LLReflectionMapManager::update() if (mMipChain.empty()) { - U32 res = mProbeResolution; + U32 res = mHeroProbeResolution; U32 count = log2((F32)res) + 0.5f; mMipChain.resize(count); @@ -326,7 +326,7 @@ void LLReflectionMapManager::update() mRadiancePass = mRealtimeRadiancePass; for (U32 i = 0; i < 6; ++i) { - updateProbeFace(closestDynamic, i, mProbeResolution, mTexture); + updateProbeFace(closestDynamic, i, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); } mRealtimeRadiancePass = !mRealtimeRadiancePass; @@ -343,7 +343,7 @@ void LLReflectionMapManager::update() mRadiancePass = true; for (U32 i = 0; i < 6; ++i) { - updateProbeFace(mHeroProbe, i, mHeroProbeResolution, mHeroArray); + updateProbeFace(mHeroProbe, i, mHeroProbeResolution, mHeroArray, mMipChain, mHeroProbeCount); } // restore "isRadiancePass" @@ -555,7 +555,7 @@ void LLReflectionMapManager::doProbeUpdate() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(mUpdatingProbe != nullptr); - updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution, mTexture); + updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); if (++mUpdatingFace == 6) { @@ -582,14 +582,14 @@ void LLReflectionMapManager::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 LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray) +void LLReflectionMapManager::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 = mReflectionProbeCount; + S32 sourceIdx = probeCount; if (probeResolution == mHeroProbeResolution) { @@ -1327,9 +1327,13 @@ void LLReflectionMapManager::initReflectionMaps() mHeroProbeResolution = 128; - mHeroArray = new LLCubeMapArray(); // Revise when we have both water and mirrors in hero probes. - mHeroArray->allocate(mHeroProbeResolution, 3, 2, true); + 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(); diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 81b0ef8ed8..9f48ce3cfd 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -148,7 +148,7 @@ private: void doProbeUpdate(); // update the specified face of the specified probe - void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray); + void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount); // list of active reflection maps std::vector > mProbes; @@ -188,6 +188,8 @@ private: // number of reflection probes to use for rendering U32 mReflectionProbeCount; + + U32 mHeroProbeCount; // resolution of reflection probes U32 mProbeResolution = 128; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 4d49c61b23..fe33047218 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -257,6 +257,7 @@ public: virtual BOOL isRiggedMesh() const { return FALSE; } virtual BOOL hasLightTexture() const { return FALSE; } virtual BOOL isReflectionProbe() const { return FALSE; } + virtual BOOL isMirror() const { return FALSE; } // This method returns true if the object is over land owned by // the agent, one of its groups, or it encroaches and diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 556ec083a7..254e945243 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1044,7 +1044,9 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) { updateReflectionProbePtr(); } - + + gPipeline.setMirror(mDrawable, isMirror()); + updateRadius(); bool force_update = true; // avoid non-alpha mDistance update being optimized away mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update); @@ -3377,6 +3379,30 @@ F32 LLVOVolume::getLightCutoff() const } } +BOOL LLVOVolume::isMirror() const +{ + S32 faceCount = getNumFaces(); + + // Temporary hack to set the object to mirror. + for (int i = 0; i < faceCount; i++) + { + const LLTextureEntry* te = getTE(i); + + if (te->getMaterialParams().notNull()) + { + LLViewerTexture* specularp = getTESpecularMap(0); + + if (specularp && specularp->getID() == "da7ecda1-e780-423f-ce27-26df7dc69cb6") + { + LL_INFOS() << "BELLADONNA OF SADNESS" << LL_ENDL; + return TRUE; + } + } + } + + return FALSE; +} + BOOL LLVOVolume::isReflectionProbe() const { return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE); @@ -4427,6 +4453,8 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u } updateReflectionProbePtr(); + + gPipeline.setMirror(mDrawable, isMirror()); } void LLVOVolume::updateReflectionProbePtr() diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 93aba9b8cb..cecf726763 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -308,6 +308,8 @@ public: F32 getReflectionProbeNearClip() const; bool getReflectionProbeIsBox() const; bool getReflectionProbeIsDynamic() const; + + BOOL isMirror() const override; // Flexible Objects U32 getVolumeInterfaceID() const; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index d7188c0fe7..e742992c1d 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2761,6 +2761,23 @@ void LLPipeline::markShift(LLDrawable *drawablep) } } +void LLPipeline::setMirror(LLDrawable *drawablep, bool is_mirror) +{ + if (drawablep && assertInitialized()) + { + if (is_mirror) + { + drawablep->setState(LLDrawable::MIRROR); + mMirrorList.insert(drawablep); + } + else + { + mMirrorList.erase(drawablep); + drawablep->clearState(LLDrawable::MIRROR); + } + } +} + void LLPipeline::shiftObjects(const LLVector3 &offset) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; @@ -5812,6 +5829,11 @@ void LLPipeline::findReferences(LLDrawable *drawablep) { LL_INFOS() << "In mRetexturedList" << LL_ENDL; } + + if (std::find(mMirrorList.begin(), mMirrorList.end(), drawablep) != mMirrorList.end()) + { + LL_INFOS() << "In mMirrorList" << LL_ENDL; + } if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end()) { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index c0559ce83b..f3b35e0325 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -357,6 +357,7 @@ public: void shiftObjects(const LLVector3 &offset); void setLight(LLDrawable *drawablep, bool is_light); + void setMirror(LLDrawable *drawablep, bool is_mirror); bool hasRenderBatches(const U32 type) const; LLCullResult::drawinfo_iterator beginRenderMap(U32 type); @@ -818,6 +819,10 @@ protected: LLDrawable::ordered_drawable_set_t mLights; light_set_t mNearbyLights; // lights near camera LLColor4 mHWLightColors[8]; + + + LLDrawable::ordered_drawable_set_t mMirrorList; + LLDrawable* mNearestMirror; ///////////////////////////////////////////// // -- cgit v1.2.3 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/CMakeLists.txt | 2 + indra/newview/llheroprobemanager.cpp | 1333 ++++++++++++++++++++++++++++++ indra/newview/llheroprobemanager.h | 208 +++++ indra/newview/llreflectionmapmanager.cpp | 168 +--- indra/newview/llreflectionmapmanager.h | 25 +- indra/newview/pipeline.cpp | 3 +- 6 files changed, 1594 insertions(+), 145 deletions(-) create mode 100644 indra/newview/llheroprobemanager.cpp create mode 100644 indra/newview/llheroprobemanager.h diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index c6d82ea260..7a57fe8fef 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -515,6 +515,7 @@ set(viewer_SOURCE_FILES llrecentpeople.cpp llreflectionmap.cpp llreflectionmapmanager.cpp + llheroprobemanager.cpp llregioninfomodel.cpp llregionposition.cpp llremoteparcelrequest.cpp @@ -1149,6 +1150,7 @@ set(viewer_HEADER_FILES llrecentpeople.h llreflectionmap.h llreflectionmapmanager.h + llheroprobemanager.h llregioninfomodel.h llregionposition.h llremoteparcelrequest.h 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); + } + } +} diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h new file mode 100644 index 0000000000..be761a680e --- /dev/null +++ b/indra/newview/llheroprobemanager.h @@ -0,0 +1,208 @@ +/** + * @file llheroprobemanager.h + * @brief LLHeroProbeManager class declaration + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#pragma once + +#include "llreflectionmap.h" +#include "llrendertarget.h" +#include "llcubemaparray.h" +#include "llcubemap.h" + +class LLSpatialGroup; +class LLViewerObject; + +// number of reflection probes to keep in vram +#define LL_MAX_REFLECTION_PROBE_COUNT 256 + +// reflection probe resolution +#define LL_IRRADIANCE_MAP_RESOLUTION 64 + +// reflection probe mininum scale +#define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f; + +class alignas(16) LLHeroProbeManager +{ + LL_ALIGN_NEW +public: + enum class DetailLevel + { + STATIC_ONLY = 0, + STATIC_AND_DYNAMIC, + REALTIME = 2 + }; + + // allocate an environment map of the given resolution + LLHeroProbeManager(); + + // release any GL state + void cleanup(); + + // maintain reflection probes + void update(); + + // add a probe for the given spatial group + LLReflectionMap* addProbe(LLSpatialGroup* group = nullptr); + + // Populate "maps" with the N most relevant Reflection Maps where N is no more than maps.size() + // If less than maps.size() ReflectionMaps are available, will assign trailing elements to nullptr. + // maps -- presized array of Reflection Map pointers + void getReflectionMaps(std::vector& maps); + + // called by LLSpatialGroup constructor + // If spatial group should receive a Reflection Probe, will create one for the specified spatial group + LLReflectionMap* registerSpatialGroup(LLSpatialGroup* group); + + // presently hacked into LLViewerObject::setTE + // Used by LLViewerObjects that are Reflection Probes + // vobj must not be null + // Guaranteed to not return null + LLReflectionMap* registerViewerObject(LLViewerObject* vobj); + + // reset all state on the next update + void reset(); + + // called on region crossing to "shift" probes into new coordinate frame + void shift(const LLVector4a& offset); + + // debug display, called from llspatialpartition if reflection + // probe debug display is active + void renderDebug(); + + // call once at startup to allocate cubemap arrays + void initReflectionMaps(); + + // True if currently updating a radiance map, false if currently updating an irradiance map + bool isRadiancePass() { return mRadiancePass; } + + // perform occlusion culling on all active reflection probes + void doOcclusion(); + +private: + friend class LLPipeline; + + // initialize mCubeFree array to default values + void initCubeFree(); + + // delete the probe with the given index in mProbes + void deleteProbe(U32 i); + + // get a free cube index + // returns -1 if allocation failed + S32 allocateCubeIndex(); + + // update the neighbors of the given probe + void updateNeighbors(LLReflectionMap* probe); + + // update UBO used for rendering (call only once per render pipe flush) + void updateUniforms(); + + // bind UBO used for rendering + void setUniforms(); + + // render target for cube snapshots + // used to generate mipmaps without doing a copy-to-texture + LLRenderTarget mRenderTarget; + + LLRenderTarget mHeroRenderTarget; + + std::vector mMipChain; + + // storage for reflection probe radiance maps (plus two scratch space cubemaps) + LLPointer mTexture; + + LLPointer mHeroArray; + + // vertex buffer for pushing verts to filter shaders + LLPointer mVertexBuffer; + + // storage for reflection probe irradiance maps + LLPointer mIrradianceMaps; + + // list of free cubemap indices + std::list mCubeFree; + + // perform an update on the currently updating Probe + void doProbeUpdate(); + + // update the specified face of the specified probe + void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount); + + // list of active reflection maps + std::vector > mProbes; + + // list of reflection maps to kill + std::vector > mKillList; + + // list of reflection maps to create + std::vector > mCreateList; + + // handle to UBO + U32 mUBO = 0; + + // Hero UBO + U32 mHeroUBO = 0; + + // list of maps being used for rendering + std::vector mReflectionMaps; + + LLReflectionMap* mUpdatingProbe = nullptr; + U32 mUpdatingFace = 0; + + // if true, we're generating the radiance map for the current probe, otherwise we're generating the irradiance map. + // Update sequence should be to generate the irradiance map from render of the world that has no irradiance, + // then generate the radiance map from a render of the world that includes irradiance. + // This should avoid feedback loops and ensure that the colors in the radiance maps match the colors in the environment. + bool mRadiancePass = false; + + // same as above, but for the realtime probe. + // Realtime probes should update all six sides of the irradiance map on "odd" frames and all six sides of the + // radiance map on "even" frames. + bool mRealtimeRadiancePass = false; + + LLPointer mDefaultProbe; // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0) + + LLPointer mHeroProbe; + + // number of reflection probes to use for rendering + U32 mReflectionProbeCount; + + U32 mHeroProbeCount; + + // resolution of reflection probes + U32 mProbeResolution = 128; + + U32 mHeroProbeResolution = 512; + + // maximum LoD of reflection probes (mip levels - 1) + F32 mMaxProbeLOD = 6.f; + + // amount to scale local lights during an irradiance map update (set during updateProbeFace and used by LLPipeline) + F32 mLightScale = 1.f; + + // if true, reset all probe render state on the next update (for teleports and sky changes) + bool mReset = false; +}; + diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index ad4d3d94e2..e855be8fbd 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -130,17 +130,10 @@ void LLReflectionMapManager::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); @@ -304,8 +297,8 @@ void LLReflectionMapManager::update() } } - if (realtime && - closestDynamic == nullptr && + if (realtime && + closestDynamic == nullptr && probe->mCubeIndex != -1 && probe->getIsDynamic()) { @@ -320,35 +313,19 @@ void LLReflectionMapManager::update() // 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 + // 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); + updateProbeFace(closestDynamic, i); } 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) @@ -555,7 +532,7 @@ void LLReflectionMapManager::doProbeUpdate() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(mUpdatingProbe != nullptr); - updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); + updateProbeFace(mUpdatingProbe, mUpdatingFace); if (++mUpdatingFace == 6) { @@ -576,26 +553,16 @@ void LLReflectionMapManager::doProbeUpdate() // 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. // 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 LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount) +void LLReflectionMapManager::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); @@ -614,18 +581,20 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U 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); + probe->update(mRenderTarget.getWidth(), face); gPipeline.popRenderTypeMask(); } else { - probe->update(target->getWidth(), face); + probe->update(mRenderTarget.getWidth(), face); } gPipeline.mRT = &gPipeline.mMainRT; - if (probe != mUpdatingProbe && probe->mType != LLReflectionMap::ProbeType::REFLECTION) + S32 sourceIdx = mReflectionProbeCount; + + if (probe != mUpdatingProbe) { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel sourceIdx += 1; } @@ -646,7 +615,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U gGL.loadIdentity(); gGL.flush(); - U32 res = probeResolution * 2; + U32 res = mProbeResolution * 2; static LLStaticHashedString resScale("resScale"); static LLStaticHashedString direction("direction"); @@ -658,20 +627,20 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U // 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); @@ -679,7 +648,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U } - 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); @@ -698,7 +667,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U } - gReflectionMipProgram.uniform1f(resScale, 1.f/(probeResolution*2)); + gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2)); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -710,11 +679,14 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U 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(); } @@ -739,7 +711,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U 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); @@ -754,7 +726,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U 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 @@ -784,7 +756,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U //generate irradiance map gIrradianceGenProgram.bind(); S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - cubeArray->bind(channel); + mTexture->bind(channel); gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); @@ -819,7 +791,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U 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); + mTexture->bind(channel); } } } @@ -896,14 +868,14 @@ void LLReflectionMapManager::updateUniforms() // 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 + // 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]; + 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]; + LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT]; - // extra parameters + // extra parameters // x - irradiance scale // y - radiance scale // z - fade in @@ -915,10 +887,10 @@ void LLReflectionMapManager::updateUniforms() // [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]; + GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4]; // list of neighbor indices - GLint refNeighbor[4096]; + GLint refNeighbor[4096]; GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth // numbrer of active refmaps @@ -1101,7 +1073,7 @@ void LLReflectionMapManager::updateUniforms() #endif rpd.refmapCount = count; - + //copy rpd into uniform buffer object if (mUBO == 0) { @@ -1114,35 +1086,7 @@ void LLReflectionMapManager::updateUniforms() 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) { @@ -1167,7 +1111,7 @@ void LLReflectionMapManager::setUniforms() } if (mUBO == 0) - { + { updateUniforms(); } glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO); @@ -1275,7 +1219,7 @@ void LLReflectionMapManager::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; @@ -1324,27 +1268,6 @@ void LLReflectionMapManager::initReflectionMaps() 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); } @@ -1369,17 +1292,15 @@ void LLReflectionMapManager::initReflectionMaps() } } -void LLReflectionMapManager::cleanup() -{ +void LLReflectionMapManager::cleanup() +{ mVertexBuffer = nullptr; mRenderTarget.release(); - mHeroRenderTarget.release(); mMipChain.clear(); mTexture = nullptr; mIrradianceMaps = nullptr; - mHeroArray = nullptr; mProbes.clear(); mKillList.clear(); @@ -1390,14 +1311,9 @@ void LLReflectionMapManager::cleanup() 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(); diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 9f48ce3cfd..7b17112814 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -43,21 +43,23 @@ class LLViewerObject; // reflection probe mininum scale #define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f; +void renderReflectionProbe(LLReflectionMap* probe); + class alignas(16) LLReflectionMapManager { LL_ALIGN_NEW public: - enum class DetailLevel + enum class DetailLevel { STATIC_ONLY = 0, STATIC_AND_DYNAMIC, REALTIME = 2 }; - // allocate an environment map of the given resolution + // allocate an environment map of the given resolution LLReflectionMapManager(); - // release any GL state + // release any GL state void cleanup(); // maintain reflection probes @@ -113,7 +115,7 @@ private: // returns -1 if allocation failed S32 allocateCubeIndex(); - // update the neighbors of the given probe + // update the neighbors of the given probe void updateNeighbors(LLReflectionMap* probe); // update UBO used for rendering (call only once per render pipe flush) @@ -125,15 +127,11 @@ private: // render target for cube snapshots // used to generate mipmaps without doing a copy-to-texture LLRenderTarget mRenderTarget; - - LLRenderTarget mHeroRenderTarget; std::vector mMipChain; // storage for reflection probe radiance maps (plus two scratch space cubemaps) LLPointer mTexture; - - LLPointer mHeroArray; // vertex buffer for pushing verts to filter shaders LLPointer mVertexBuffer; @@ -148,7 +146,7 @@ private: void doProbeUpdate(); // update the specified face of the specified probe - void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount); + void updateProbeFace(LLReflectionMap* probe, U32 face); // list of active reflection maps std::vector > mProbes; @@ -161,9 +159,6 @@ private: // handle to UBO U32 mUBO = 0; - - // Hero UBO - U32 mHeroUBO = 0; // list of maps being used for rendering std::vector mReflectionMaps; @@ -183,18 +178,12 @@ private: bool mRealtimeRadiancePass = false; LLPointer mDefaultProbe; // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0) - - LLPointer mHeroProbe; // number of reflection probes to use for rendering U32 mReflectionProbeCount; - - U32 mHeroProbeCount; // resolution of reflection probes U32 mProbeResolution = 128; - - U32 mHeroProbeResolution = 512; // maximum LoD of reflection probes (mip levels - 1) F32 mMaxProbeLOD = 6.f; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index e742992c1d..909c0f9aaa 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8461,13 +8461,14 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader) mReflectionMapManager.mIrradianceMaps->bind(channel); bound = true; } - + /* channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY); if (channel > -1 && mReflectionMapManager.mHeroArray.notNull()) { mReflectionMapManager.mHeroArray->bind(channel); bound = true; } + */ if (bound) { -- 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/llappviewer.cpp | 1 + indra/newview/llheroprobemanager.cpp | 923 ++--------------------------------- indra/newview/llheroprobemanager.h | 87 +--- indra/newview/pipeline.cpp | 31 +- indra/newview/pipeline.h | 2 + 5 files changed, 75 insertions(+), 969 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 343778fe03..3b0ba77ea2 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1517,6 +1517,7 @@ bool LLAppViewer::doFrame() LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Snapshot"); pingMainloopTimeout("Main:Snapshot"); gPipeline.mReflectionMapManager.update(); + gPipeline.mHeroProbeManager.update(); LLFloaterSnapshot::update(); // take snapshots LLFloaterSimpleOutfitSnapshot::update(); gGLActive = FALSE; 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() diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index be761a680e..95e3963d1a 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -35,13 +35,7 @@ class LLSpatialGroup; class LLViewerObject; // number of reflection probes to keep in vram -#define LL_MAX_REFLECTION_PROBE_COUNT 256 - -// reflection probe resolution -#define LL_IRRADIANCE_MAP_RESOLUTION 64 - -// reflection probe mininum scale -#define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f; +#define LL_MAX_HERO_PROBE_COUNT 2 class alignas(16) LLHeroProbeManager { @@ -63,30 +57,6 @@ public: // maintain reflection probes void update(); - // add a probe for the given spatial group - LLReflectionMap* addProbe(LLSpatialGroup* group = nullptr); - - // Populate "maps" with the N most relevant Reflection Maps where N is no more than maps.size() - // If less than maps.size() ReflectionMaps are available, will assign trailing elements to nullptr. - // maps -- presized array of Reflection Map pointers - void getReflectionMaps(std::vector& maps); - - // called by LLSpatialGroup constructor - // If spatial group should receive a Reflection Probe, will create one for the specified spatial group - LLReflectionMap* registerSpatialGroup(LLSpatialGroup* group); - - // presently hacked into LLViewerObject::setTE - // Used by LLViewerObjects that are Reflection Probes - // vobj must not be null - // Guaranteed to not return null - LLReflectionMap* registerViewerObject(LLViewerObject* vobj); - - // reset all state on the next update - void reset(); - - // called on region crossing to "shift" probes into new coordinate frame - void shift(const LLVector4a& offset); - // debug display, called from llspatialpartition if reflection // probe debug display is active void renderDebug(); @@ -94,28 +64,12 @@ public: // call once at startup to allocate cubemap arrays void initReflectionMaps(); - // True if currently updating a radiance map, false if currently updating an irradiance map - bool isRadiancePass() { return mRadiancePass; } - // perform occlusion culling on all active reflection probes void doOcclusion(); private: friend class LLPipeline; - - // initialize mCubeFree array to default values - void initCubeFree(); - - // delete the probe with the given index in mProbes - void deleteProbe(U32 i); - - // get a free cube index - // returns -1 if allocation failed - S32 allocateCubeIndex(); - - // update the neighbors of the given probe - void updateNeighbors(LLReflectionMap* probe); - + // update UBO used for rendering (call only once per render pipe flush) void updateUniforms(); @@ -132,8 +86,6 @@ private: // storage for reflection probe radiance maps (plus two scratch space cubemaps) LLPointer mTexture; - - LLPointer mHeroArray; // vertex buffer for pushing verts to filter shaders LLPointer mVertexBuffer; @@ -141,61 +93,28 @@ private: // storage for reflection probe irradiance maps LLPointer mIrradianceMaps; - // list of free cubemap indices - std::list mCubeFree; - - // perform an update on the currently updating Probe - void doProbeUpdate(); - // update the specified face of the specified probe - void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount); + void updateProbeFace(LLReflectionMap* probe, U32 face); // list of active reflection maps std::vector > mProbes; - // list of reflection maps to kill - std::vector > mKillList; - - // list of reflection maps to create - std::vector > mCreateList; - // handle to UBO U32 mUBO = 0; - - // Hero UBO - U32 mHeroUBO = 0; // list of maps being used for rendering std::vector mReflectionMaps; LLReflectionMap* mUpdatingProbe = nullptr; - U32 mUpdatingFace = 0; - - // if true, we're generating the radiance map for the current probe, otherwise we're generating the irradiance map. - // Update sequence should be to generate the irradiance map from render of the world that has no irradiance, - // then generate the radiance map from a render of the world that includes irradiance. - // This should avoid feedback loops and ensure that the colors in the radiance maps match the colors in the environment. - bool mRadiancePass = false; - - // same as above, but for the realtime probe. - // Realtime probes should update all six sides of the irradiance map on "odd" frames and all six sides of the - // radiance map on "even" frames. - bool mRealtimeRadiancePass = false; LLPointer mDefaultProbe; // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0) - - LLPointer mHeroProbe; // number of reflection probes to use for rendering U32 mReflectionProbeCount; - - U32 mHeroProbeCount; // resolution of reflection probes U32 mProbeResolution = 128; - U32 mHeroProbeResolution = 512; - // maximum LoD of reflection probes (mip levels - 1) F32 mMaxProbeLOD = 6.f; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 909c0f9aaa..4c951a9dea 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -642,6 +642,7 @@ void LLPipeline::cleanup() mCubeVB = NULL; mReflectionMapManager.cleanup(); + mHeroProbeManager.cleanup(); } //============================================================================ @@ -772,6 +773,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) { // hacky -- allocate auxillary buffer gCubeSnapshot = TRUE; mReflectionMapManager.initReflectionMaps(); + mHeroProbeManager.initReflectionMaps(); mRT = &mAuxillaryRT; U32 res = mReflectionMapManager.mProbeResolution * 4; //multiply by 4 because probes will be 16x super sampled allocateScreenBuffer(res, res, samples); @@ -2441,6 +2443,26 @@ void LLPipeline::doOcclusion(LLCamera& camera) gGL.setColorMask(true, true); } + + if (sReflectionProbesEnabled && sUseOcclusion > 1 && !LLPipeline::sShadowRender && !gCubeSnapshot) + { + gGL.setColorMask(false, false); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + LLGLDisable cull(GL_CULL_FACE); + + gOcclusionCubeProgram.bind(); + + if (mCubeVB.isNull()) + { //cube VB will be used for issuing occlusion queries + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX); + } + mCubeVB->setBuffer(); + + mHeroProbeManager.doOcclusion(); + gOcclusionCubeProgram.unbind(); + + gGL.setColorMask(true, true); + } if (LLPipeline::sUseOcclusion > 1 && (sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck)) @@ -3809,6 +3831,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) { //update reflection probe uniform mReflectionMapManager.updateUniforms(); + mHeroProbeManager.updateUniforms(); } U32 cur_type = 0; @@ -8461,14 +8484,14 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader) mReflectionMapManager.mIrradianceMaps->bind(channel); bound = true; } - /* + channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY); - if (channel > -1 && mReflectionMapManager.mHeroArray.notNull()) + if (channel > -1 && mHeroProbeManager.mTexture.notNull()) { - mReflectionMapManager.mHeroArray->bind(channel); + mHeroProbeManager.mTexture->bind(channel); bound = true; } - */ + if (bound) { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index f3b35e0325..bfb9b95f4d 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -39,6 +39,7 @@ #include "lldrawable.h" #include "llrendertarget.h" #include "llreflectionmapmanager.h" +#include "llheroprobemanager.h" #include @@ -454,6 +455,7 @@ public: void handleShadowDetailChanged(); LLReflectionMapManager mReflectionMapManager; + LLHeroProbeManager mHeroProbeManager; private: void unloadShaders(); -- 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/app_settings/settings.xml | 11 +++++++++++ indra/newview/llheroprobemanager.cpp | 4 ---- indra/newview/pipeline.cpp | 20 -------------------- 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f5e7f865ab..8b9c5b50ae 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10390,6 +10390,17 @@ Value 0 + RenderHeroProbeResolution + + Comment + Resolution to render hero probes used for mirrors, water, etc. + Persist + 1 + Type + S32 + Value + 512 + RenderReflectionProbeVolumes Comment 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(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4c951a9dea..9f8cd2c7fd 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2443,26 +2443,6 @@ void LLPipeline::doOcclusion(LLCamera& camera) gGL.setColorMask(true, true); } - - if (sReflectionProbesEnabled && sUseOcclusion > 1 && !LLPipeline::sShadowRender && !gCubeSnapshot) - { - gGL.setColorMask(false, false); - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - LLGLDisable cull(GL_CULL_FACE); - - gOcclusionCubeProgram.bind(); - - if (mCubeVB.isNull()) - { //cube VB will be used for issuing occlusion queries - mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX); - } - mCubeVB->setBuffer(); - - mHeroProbeManager.doOcclusion(); - gOcclusionCubeProgram.unbind(); - - gGL.setColorMask(true, true); - } if (LLPipeline::sUseOcclusion > 1 && (sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck)) -- 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 ++----------------- indra/newview/pipeline.cpp | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 17 deletions(-) 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(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9f8cd2c7fd..4c951a9dea 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2443,6 +2443,26 @@ void LLPipeline::doOcclusion(LLCamera& camera) gGL.setColorMask(true, true); } + + if (sReflectionProbesEnabled && sUseOcclusion > 1 && !LLPipeline::sShadowRender && !gCubeSnapshot) + { + gGL.setColorMask(false, false); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + LLGLDisable cull(GL_CULL_FACE); + + gOcclusionCubeProgram.bind(); + + if (mCubeVB.isNull()) + { //cube VB will be used for issuing occlusion queries + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX); + } + mCubeVB->setBuffer(); + + mHeroProbeManager.doOcclusion(); + gOcclusionCubeProgram.unbind(); + + gGL.setColorMask(true, true); + } if (LLPipeline::sUseOcclusion > 1 && (sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck)) -- 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 --- .../shaders/class3/deferred/softenLightF.glsl | 5 +- indra/newview/llheroprobemanager.cpp | 80 ++++++++++++++++++++-- indra/newview/llheroprobemanager.h | 10 ++- indra/newview/llvovolume.cpp | 7 +- indra/newview/pipeline.cpp | 22 ------ indra/newview/pipeline.h | 5 -- 6 files changed, 88 insertions(+), 41 deletions(-) diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index e485c26e9b..742b52b074 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -213,13 +213,14 @@ void main() vec3 v = -normalize(pos.xyz); color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten); + vec3 refnormpersp = reflect(pos.xyz, norm.xyz); + color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - gloss) * 11).xyz * specularColor; + if (do_atmospherics) { color = atmosFragLightingLinear(color, additive, atten); } - vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - color = texture(heroProbes, vec4(env_mat * refnormpersp, 0), 0).xyz; } else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { 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); + } +} diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 95e3963d1a..c6df963cfd 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -30,6 +30,7 @@ #include "llrendertarget.h" #include "llcubemaparray.h" #include "llcubemap.h" +#include "lldrawable.h" class LLSpatialGroup; class LLViewerObject; @@ -67,6 +68,9 @@ public: // perform occlusion culling on all active reflection probes void doOcclusion(); + void registerHeroDrawable(LLDrawable* drawablep); + void unregisterHeroDrawable(LLDrawable* drawablep); + private: friend class LLPipeline; @@ -118,10 +122,10 @@ private: // maximum LoD of reflection probes (mip levels - 1) F32 mMaxProbeLOD = 6.f; - // amount to scale local lights during an irradiance map update (set during updateProbeFace and used by LLPipeline) - F32 mLightScale = 1.f; - // if true, reset all probe render state on the next update (for teleports and sky changes) bool mReset = false; + + LLDrawable::ordered_drawable_set_t mHeroList; + LLDrawable* mNearestHero; }; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 254e945243..2589beefe9 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1045,7 +1045,7 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) updateReflectionProbePtr(); } - gPipeline.setMirror(mDrawable, isMirror()); + gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); updateRadius(); bool force_update = true; // avoid non-alpha mDistance update being optimized away @@ -4454,7 +4454,10 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u updateReflectionProbePtr(); - gPipeline.setMirror(mDrawable, isMirror()); + if (isMirror()) + gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); + else + gPipeline.mHeroProbeManager.unregisterHeroDrawable(mDrawable); } void LLVOVolume::updateReflectionProbePtr() diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4c951a9dea..792cad02bd 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2783,23 +2783,6 @@ void LLPipeline::markShift(LLDrawable *drawablep) } } -void LLPipeline::setMirror(LLDrawable *drawablep, bool is_mirror) -{ - if (drawablep && assertInitialized()) - { - if (is_mirror) - { - drawablep->setState(LLDrawable::MIRROR); - mMirrorList.insert(drawablep); - } - else - { - mMirrorList.erase(drawablep); - drawablep->clearState(LLDrawable::MIRROR); - } - } -} - void LLPipeline::shiftObjects(const LLVector3 &offset) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; @@ -5852,11 +5835,6 @@ void LLPipeline::findReferences(LLDrawable *drawablep) { LL_INFOS() << "In mRetexturedList" << LL_ENDL; } - - if (std::find(mMirrorList.begin(), mMirrorList.end(), drawablep) != mMirrorList.end()) - { - LL_INFOS() << "In mMirrorList" << LL_ENDL; - } if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end()) { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index bfb9b95f4d..1361441844 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -358,7 +358,6 @@ public: void shiftObjects(const LLVector3 &offset); void setLight(LLDrawable *drawablep, bool is_light); - void setMirror(LLDrawable *drawablep, bool is_mirror); bool hasRenderBatches(const U32 type) const; LLCullResult::drawinfo_iterator beginRenderMap(U32 type); @@ -821,10 +820,6 @@ protected: LLDrawable::ordered_drawable_set_t mLights; light_set_t mNearbyLights; // lights near camera LLColor4 mHWLightColors[8]; - - - LLDrawable::ordered_drawable_set_t mMirrorList; - LLDrawable* mNearestMirror; ///////////////////////////////////////////// // -- 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 ++++++++- indra/newview/llreflectionmap.cpp | 5 +++-- indra/newview/llreflectionmap.h | 2 +- indra/newview/llreflectionmapmanager.h | 1 + 4 files changed, 13 insertions(+), 4 deletions(-) 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; diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index efaf068bd2..022b7d11d8 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -49,7 +49,7 @@ LLReflectionMap::~LLReflectionMap() } } -void LLReflectionMap::update(U32 resolution, U32 face) +void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; mLastUpdateTime = gFrameTimeSeconds; @@ -63,7 +63,8 @@ void LLReflectionMap::update(U32 resolution, U32 face) { resolution /= 2; } - gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip(), getIsDynamic()); + + gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip(), getIsDynamic() || force_dynamic); } void LLReflectionMap::autoAdjustOrigin() diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index 831a6358ee..a23bdc3a98 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -52,7 +52,7 @@ public: // update this environment map // resolution - size of cube map to generate - void update(U32 resolution, U32 face); + void update(U32 resolution, U32 face, bool force_dynamic = false); // for volume partition probes, try to place this probe in the best spot void autoAdjustOrigin(); diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 7b17112814..4ef6c5fdff 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -104,6 +104,7 @@ public: private: friend class LLPipeline; + friend class LLHeroProbeManager; // initialize mCubeFree array to default values void initCubeFree(); -- 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/llprimitive/llprimitive.cpp | 39 ++++++++-- indra/llprimitive/llprimitive.h | 12 ++- indra/llprimitive/llprimtexturelist.cpp | 10 --- indra/llprimitive/llprimtexturelist.h | 1 - indra/llprimitive/lltextureentry.cpp | 10 --- indra/llprimitive/lltextureentry.h | 10 --- indra/newview/llheroprobemanager.cpp | 87 +++++++++++++--------- indra/newview/llpanelface.cpp | 17 ----- indra/newview/llpanelface.h | 2 - indra/newview/llpanelvolume.cpp | 34 +++++++++ indra/newview/llpanelvolume.h | 2 + indra/newview/llselectmgr.cpp | 41 ---------- indra/newview/llselectmgr.h | 1 - indra/newview/llviewerobject.cpp | 28 ++----- indra/newview/llviewerobject.h | 1 - indra/newview/llvovolume.cpp | 60 ++++++++------- indra/newview/llvovolume.h | 5 +- .../newview/skins/default/xui/en/floater_tools.xml | 10 ++- 18 files changed, 185 insertions(+), 185 deletions(-) diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index b45ead92d3..703584ed62 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -404,11 +404,6 @@ S32 LLPrimitive::setTEFullbright(const U8 index, const U8 fullbright) return mTextureList.setFullbright(index, fullbright); } -S32 LLPrimitive::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target) -{ - return mTextureList.setRenderableTarget(te, target); -} - S32 LLPrimitive::setTEMediaFlags(const U8 index, const U8 media_flags) { return mTextureList.setMediaFlags(index, media_flags); @@ -1828,6 +1823,40 @@ bool LLLightParams::fromLLSD(LLSD& sd) //============================================================================ +LLMirrorParams::LLMirrorParams() +{ + mType = PARAMS_MIRROR; +} + +BOOL LLMirrorParams::pack(LLDataPacker &dp) const +{ + return TRUE; +} + +BOOL LLMirrorParams::unpack(LLDataPacker &dp) +{ + return TRUE; +} + +bool LLMirrorParams::operator==(const LLNetworkData& data) const +{ + if (data.mType != PARAMS_REFLECTION_PROBE) + { + return false; + } + return true; +} + +void LLMirrorParams::copy(const LLNetworkData& data) +{ + const LLMirrorParams *param = (LLMirrorParams*)&data; + mType = param->mType; +} + +//============================================================================ + +//============================================================================ + LLReflectionProbeParams::LLReflectionProbeParams() { mType = PARAMS_REFLECTION_PROBE; diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 520c7c7ac8..1af9bca42e 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -109,6 +109,7 @@ public: PARAMS_EXTENDED_MESH = 0x70, PARAMS_RENDER_MATERIAL = 0x80, PARAMS_REFLECTION_PROBE = 0x90, + PARAMS_MIRROR = 0x100, }; public: @@ -172,6 +173,16 @@ public: F32 getCutoff() const { return mCutoff; } }; +class LLMirrorParams : public LLNetworkData +{ +public: + LLMirrorParams(); + /*virtual*/ BOOL pack(LLDataPacker &dp) const; + /*virtual*/ BOOL unpack(LLDataPacker &dp); + /*virtual*/ bool operator==(const LLNetworkData& data) const; + /*virtual*/ void copy(const LLNetworkData& data); +}; + extern const F32 REFLECTION_PROBE_MIN_AMBIANCE; extern const F32 REFLECTION_PROBE_MAX_AMBIANCE; extern const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE; @@ -485,7 +496,6 @@ public: virtual S32 setTETexGen(const U8 te, const U8 texgen); virtual S32 setTEShiny(const U8 te, const U8 shiny); virtual S32 setTEFullbright(const U8 te, const U8 fullbright); - virtual S32 setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target); virtual S32 setTEMediaFlags(const U8 te, const U8 flags); virtual S32 setTEGlow(const U8 te, const F32 glow); virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp index 49b59e35cb..f4f08248b8 100644 --- a/indra/llprimitive/llprimtexturelist.cpp +++ b/indra/llprimitive/llprimtexturelist.cpp @@ -341,16 +341,6 @@ S32 LLPrimTextureList::setFullbright(const U8 index, const U8 fullbright) return TEM_CHANGE_NONE; } -S32 LLPrimTextureList::setRenderableTarget(const U8 index, const U8 target) -{ - if (index < mEntryList.size()) - { - return mEntryList[index]->setRenderableTarget((LLTextureEntry::eRenderableTarget)target); - } - - return TEM_CHANGE_NONE; -} - S32 LLPrimTextureList::setMediaFlags(const U8 index, const U8 media_flags) { if (index < mEntryList.size()) diff --git a/indra/llprimitive/llprimtexturelist.h b/indra/llprimitive/llprimtexturelist.h index 34b87d879f..49c636e40f 100644 --- a/indra/llprimitive/llprimtexturelist.h +++ b/indra/llprimitive/llprimtexturelist.h @@ -102,7 +102,6 @@ public: S32 setTexGen(const U8 index, const U8 texgen); S32 setShiny(const U8 index, const U8 shiny); S32 setFullbright(const U8 index, const U8 t); - S32 setRenderableTarget(const U8 index, const U8 target); S32 setMediaFlags(const U8 index, const U8 media_flags); S32 setGlow(const U8 index, const F32 glow); S32 setMaterialID(const U8 index, const LLMaterialID& pMaterialID); diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index fdf3774bfa..ee2a4c769a 100644 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -504,16 +504,6 @@ S32 LLTextureEntry::setFullbright(U8 fullbright) return TEM_CHANGE_NONE; } -S32 LLTextureEntry::setRenderableTarget(eRenderableTarget target) -{ - if (getRenderableTarget() != target) { - mRenderableTarget = target; - return TEM_CHANGE_TEXTURE; - } - - return TEM_CHANGE_NONE; -} - S32 LLTextureEntry::setShiny(U8 shiny) { shiny &= TEM_SHINY_MASK; diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h index 2c0832e1d4..0935147688 100644 --- a/indra/llprimitive/lltextureentry.h +++ b/indra/llprimitive/lltextureentry.h @@ -80,12 +80,6 @@ public: TEX_GEN_SPHERICAL = 0x04, TEX_GEN_CYLINDRICAL = 0x06 } eTexGen; - - - typedef enum e_renderable_target { - RT_DISABLED = 0x00, - RT_MIRROR = 0x02 - } eRenderableTarget; LLTextureEntry(); LLTextureEntry(const LLUUID& tex_id); @@ -141,8 +135,6 @@ public: S32 setMaterialID(const LLMaterialID& pMaterialID); S32 setMaterialParams(const LLMaterialPtr pMaterialParams); - S32 setRenderableTarget(eRenderableTarget target); - virtual const LLUUID &getID() const { return mID; } const LLColor4 &getColor() const { return mColor; } const F32 getAlpha() const { return mColor.mV[VALPHA]; } @@ -160,7 +152,6 @@ public: U8 getBumpmap() const { return mBump & TEM_BUMP_MASK; } U8 getFullbright() const { return (mBump>>TEM_FULLBRIGHT_SHIFT) & TEM_FULLBRIGHT_MASK; } - eRenderableTarget getRenderableTarget() const { return mRenderableTarget; } U8 getShiny() const { return (mBump>>TEM_SHINY_SHIFT) & TEM_SHINY_MASK; } U8 getBumpShiny() const { return mBump & TEM_BUMP_SHINY_MASK; } U8 getBumpShinyFullbright() const { return mBump; } @@ -242,7 +233,6 @@ protected: LLColor4 mColor; U8 mBump; // Bump map, shiny, and fullbright U8 mMediaFlags; // replace with web page, movie, etc. - eRenderableTarget mRenderableTarget; F32 mGlow; bool mMaterialUpdatePending; LLMaterialID mMaterialID; 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; } } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 9233ec6277..25f42e6dae 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -596,17 +596,6 @@ void LLPanelFace::sendFullbright() LLSelectMgr::getInstance()->selectionSetFullbright( fullbright ); } -void LLPanelFace::sendMirror() -{ - LLCheckBoxCtrl* mCheckMirror = getChild("checkbox mirror"); - - if (!mCheckMirror) - return; - - LLTextureEntry::eRenderableTarget target = mCheckMirror->get() ? LLTextureEntry::RT_MIRROR : LLTextureEntry::RT_DISABLED; - LLSelectMgr::getInstance()->selectionSetRenderableTarget(target); -} - void LLPanelFace::sendColor() { @@ -3007,12 +2996,6 @@ void LLPanelFace::onCommitFullbright(LLUICtrl* ctrl, void* userdata) self->sendFullbright(); } -void LLPanelFace::onCommitMirror(LLUICtrl* ctrl, void* userdata) -{ - LLPanelFace* self = (LLPanelFace*) userdata; - self->sendMirror(); -} - // static void LLPanelFace::onCommitGlow(LLUICtrl* ctrl, void* userdata) { diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 0b7486232d..5cad8cefcf 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -139,7 +139,6 @@ protected: void sendShiny(U32 shininess); // applies and sends shininess void sendFullbright(); // applies and sends full bright - void sendMirror(); void sendGlow(); void alignTestureLayer(); @@ -229,7 +228,6 @@ protected: static void onCommitShiny( LLUICtrl* ctrl, void* userdata); static void onCommitAlphaMode( LLUICtrl* ctrl, void* userdata); static void onCommitFullbright( LLUICtrl* ctrl, void* userdata); - static void onCommitMirror(LLUICtrl* ctrl, void* userdata); static void onCommitGlow( LLUICtrl* ctrl, void *userdata); static void onCommitPlanarAlign( LLUICtrl* ctrl, void* userdata); static void onCommitRepeatsPerMeter( LLUICtrl* ctrl, void* userinfo); diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index ed244f773c..d62a640b5c 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -114,6 +114,11 @@ BOOL LLPanelVolume::postBuild() getChild("FlexForceZ")->setValidateBeforeCommit(precommitValidate); } + // Mirror Parameters + { + childSetCommitCallback("Mirror Checkbox Ctrl", onCommitIsMirror, this); + } + // LIGHT Parameters { childSetCommitCallback("Light Checkbox Ctrl",onCommitIsLight,this); @@ -305,6 +310,10 @@ void LLPanelVolume::getState( ) getChildView("select_single")->setEnabled(true); } + BOOL is_mirror = volobjp && volobjp->isMirror(); + getChild("Mirror Checkbox Ctrl")->setValue(is_mirror); + getChildView("Mirror Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp); + // Light properties BOOL is_light = volobjp && volobjp->getIsLight(); getChild("Light Checkbox Ctrl")->setValue(is_light); @@ -737,6 +746,25 @@ void LLPanelVolume::sendIsLight() LL_INFOS() << "update light sent" << LL_ENDL; } +void LLPanelVolume::sendIsMirror() +{ + LLViewerObject* objectp = mObject; + if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) + { + return; + } + LLVOVolume *volobjp = (LLVOVolume *)objectp; + + // Quick hack to set the mirror locally. + + gPipeline.mHeroProbeManager.registerHeroDrawable(volobjp->mDrawable); + + BOOL value = getChild("Mirror Checkbox Ctrl")->getValue(); + volobjp->setIsMirror(value); + LL_INFOS() << "update mirror sent" << LL_ENDL; +} + + void LLPanelVolume::sendIsReflectionProbe() { LLViewerObject* objectp = mObject; @@ -1403,6 +1431,12 @@ void LLPanelVolume::onCommitIsLight( LLUICtrl* ctrl, void* userdata ) self->sendIsLight(); } +void LLPanelVolume::onCommitIsMirror( LLUICtrl* ctrl, void* userdata ) +{ + LLPanelVolume* self = (LLPanelVolume*) userdata; + self->sendIsMirror(); +} + // static void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item_id, LLVOVolume* volobjp) { diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h index 01b7ebb75c..a658351624 100644 --- a/indra/newview/llpanelvolume.h +++ b/indra/newview/llpanelvolume.h @@ -58,6 +58,7 @@ public: void sendIsLight(); + void sendIsMirror(); // when an object is becoming a refleciton probe, present a dialog asking for confirmation // otherwise, send the reflection probe update immediately void sendIsReflectionProbe(); @@ -71,6 +72,7 @@ public: static void onCommitIsLight( LLUICtrl* ctrl, void* userdata); static void onCommitLight( LLUICtrl* ctrl, void* userdata); + static void onCommitIsMirror( LLUICtrl* ctrl, void* userdata); static void onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata); static void onCommitProbe(LLUICtrl* ctrl, void* userdata); void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 2b1b4b79b2..5c1a339570 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -2355,47 +2355,6 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright) getSelection()->applyToObjects(&sendfunc); } -void LLSelectMgr::selectionSetRenderableTarget(LLTextureEntry::eRenderableTarget target) -{ - struct f : public LLSelectedTEFunctor - { - LLTextureEntry::eRenderableTarget mRenderableTarget; - - f(const LLTextureEntry::eRenderableTarget& t) : mRenderableTarget(t) {} - - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - object->setTERenderableTarget(te, mRenderableTarget); - } - - return true; - } - } setfunc(target); - - getSelection()->applyToTEs(&setfunc); - - struct g : public LLSelectedObjectFunctor - { - LLTextureEntry::eRenderableTarget mRenderableTarget; - - g(const LLTextureEntry::eRenderableTarget& t) : mRenderableTarget(t) {} - - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->sendTEUpdate(); - } - - return true; - } - } sendfunc(target); - - getSelection()->applyToObjects(&sendfunc); -} - // This function expects media_data to be a map containing relevant // media data name/value pairs (e.g. home_url, etc.) void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data) diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 8ce59c6654..327134a487 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -653,7 +653,6 @@ public: void selectionSetGlow(const F32 glow); void selectionSetMaterialParams(LLSelectedTEMaterialFunctor* material_func, int specific_te = -1); void selectionRemoveMaterial(); - void selectionSetRenderableTarget(LLTextureEntry::eRenderableTarget target); void selectionSetObjectPermissions(U8 perm_field, BOOL set, U32 perm_mask, BOOL override = FALSE); void selectionSetObjectName(const std::string& name); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 7871815fda..68162f83c0 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5296,29 +5296,6 @@ S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright) return retval; } -S32 LLViewerObject::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target) -{ - S32 retval = 0; - - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; - } - else if (target != tep->getRenderableTarget()) - { - retval = LLPrimitive::setTERenderableTarget(te, target); - setChanged(TEXTURE); - if (mDrawable.notNull() && retval) - { - //gPipeline.markMirror(mDrawable); - } - } - - return retval; -} - - S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags) { // this might need work for media type @@ -6251,6 +6228,11 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para { new_block = new LLReflectionProbeParams(); break; + } + case LLNetworkData::PARAMS_MIRROR: + { + new_block = new LLMirrorParams(); + break; } default: { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index fe33047218..a87644476f 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -360,7 +360,6 @@ public: /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media ); // *FIXME: this confusingly acts upon a superset of setTETexGen's flags without absorbing its semantics /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny ); /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright ); - /*virtual*/ S32 setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target); /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags ); /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 2589beefe9..175ce93b14 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1045,7 +1045,10 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) updateReflectionProbePtr(); } - gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); + if (isMirror()) + { + gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); + } updateRadius(); bool force_update = true; // avoid non-alpha mDistance update being optimized away @@ -2369,16 +2372,6 @@ S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright) return res; } -S32 LLVOVolume::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget mirror) -{ - S32 res = LLViewerObject::setTERenderableTarget(te, mirror); - if (res) - { - //gPipeline.markMirror(mDrawable); - } - return res; -} - S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump) { S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump); @@ -3379,28 +3372,41 @@ F32 LLVOVolume::getLightCutoff() const } } -BOOL LLVOVolume::isMirror() const +bool LLVOVolume::setIsMirror(BOOL is_mirror) { - S32 faceCount = getNumFaces(); - - // Temporary hack to set the object to mirror. - for (int i = 0; i < faceCount; i++) + BOOL was_mirror = isMirror(); + if (is_mirror != was_mirror) { - const LLTextureEntry* te = getTE(i); - - if (te->getMaterialParams().notNull()) + if (is_mirror) { - LLViewerTexture* specularp = getTESpecularMap(0); - - if (specularp && specularp->getID() == "da7ecda1-e780-423f-ce27-26df7dc69cb6") - { - LL_INFOS() << "BELLADONNA OF SADNESS" << LL_ENDL; - return TRUE; - } + setParameterEntryInUse(LLNetworkData::PARAMS_MIRROR, TRUE, true); + } + else + { + setParameterEntryInUse(LLNetworkData::PARAMS_MIRROR, FALSE, true); } } - return FALSE; + updateMirrorDrawable(); + + return was_mirror != is_mirror; +} + +void LLVOVolume::updateMirrorDrawable() +{ + if (isMirror()) + { + gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); + } + else + { + gPipeline.mHeroProbeManager.unregisterHeroDrawable(mDrawable); + } +} + +BOOL LLVOVolume::isMirror() const +{ + return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE); } BOOL LLVOVolume::isReflectionProbe() const diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index cecf726763..32c89ddae2 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -209,7 +209,6 @@ public: /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump) override; /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny) override; /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright) override; - /*virtual*/ S32 setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target) override; /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump) override; /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags) override; /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow) override; @@ -295,6 +294,10 @@ public: F32 getLightRadius() const; F32 getLightFalloff(const F32 fudge_factor = 1.f) const; F32 getLightCutoff() const; + + // Mirrors + bool setIsMirror(BOOL is_mirror); + void updateMirrorDrawable(); // Reflection Probes bool setIsReflectionProbe(BOOL is_probe); diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 5e999ed245..4094a487a9 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2406,7 +2406,15 @@ even though the user gets a free copy. name="object_horizontal" top_pad="10" width="278" /> - + 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/llrender/llshadermgr.cpp | 1 + indra/llrender/llshadermgr.h | 1 + .../shaders/class1/interface/radianceGenF.glsl | 2 + indra/newview/llheroprobemanager.cpp | 73 +++++++--------------- indra/newview/llheroprobemanager.h | 7 ++- indra/newview/llreflectionmapmanager.cpp | 1 + indra/newview/llvovolume.cpp | 2 +- 7 files changed, 34 insertions(+), 53 deletions(-) diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 6730a12d6c..8bb5be0332 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1460,6 +1460,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("cloud_variance"); mReservedUniforms.push_back("reflection_probe_ambiance"); mReservedUniforms.push_back("max_probe_lod"); + mReservedUniforms.push_back("probe_strength"); mReservedUniforms.push_back("sh_input_r"); mReservedUniforms.push_back("sh_input_g"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 53c8323cff..6a5243a898 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -278,6 +278,7 @@ public: REFLECTION_PROBE_AMBIANCE, // "reflection_probe_ambiance" REFLECTION_PROBE_MAX_LOD, // "max_probe_lod" + REFLECTION_PROBE_STRENGTH, // "probe_strength" SH_INPUT_L1R, // "sh_input_r" SH_INPUT_L1G, // "sh_input_g" SH_INPUT_L1B, // "sh_input_b" diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl index 9ecdf0bf77..cb6f34713c 100644 --- a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl @@ -38,6 +38,7 @@ in vec3 vary_dir; uniform float mipLevel; uniform int u_width; uniform float max_probe_lod; +uniform float probe_strength; // ============================================================================================================= @@ -163,5 +164,6 @@ void main() { vec3 N = normalize(vary_dir); frag_color = max(prefilterEnvMap(N), vec4(0)); + frag_color.a *= probe_strength; } // ============================================================================================================= 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; } } diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index c6df963cfd..24246af3d3 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -117,15 +117,18 @@ private: U32 mReflectionProbeCount; // resolution of reflection probes - U32 mProbeResolution = 128; + U32 mProbeResolution = 1024; // maximum LoD of reflection probes (mip levels - 1) F32 mMaxProbeLOD = 6.f; + + F32 mHeroProbeStrength = 1.f; + bool mIsInTransition = false; // if true, reset all probe render state on the next update (for teleports and sky changes) bool mReset = false; LLDrawable::ordered_drawable_set_t mHeroList; - LLDrawable* mNearestHero; + LLPointer mNearestHero; }; diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index e855be8fbd..61143c61e8 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -714,6 +714,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) mTexture->bind(channel); gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); + gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, 1.f); U32 res = mMipChain[0].getWidth(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 6db1ae07de..3c3d8d5123 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1045,7 +1045,7 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) updateReflectionProbePtr(); } - if (isMirror()) + //if (isMirror()) { gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); } -- 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 +++++++++++++++++++++++++++--------- indra/newview/llheroprobemanager.h | 8 ++--- indra/newview/llpanelvolume.cpp | 4 --- indra/newview/llviewerobject.cpp | 34 ++++++++++++++++++- indra/newview/llviewerobject.h | 4 +++ indra/newview/llvovolume.cpp | 22 ++++++++---- indra/newview/llvovolume.h | 1 + 7 files changed, 107 insertions(+), 32 deletions(-) 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); } } diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 24246af3d3..b817b2396f 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -68,8 +68,8 @@ public: // perform occlusion culling on all active reflection probes void doOcclusion(); - void registerHeroDrawable(LLDrawable* drawablep); - void unregisterHeroDrawable(LLDrawable* drawablep); + void registerHeroDrawable(LLVOVolume* drawablep); + void unregisterHeroDrawable(LLVOVolume* drawablep); private: friend class LLPipeline; @@ -128,7 +128,7 @@ private: // if true, reset all probe render state on the next update (for teleports and sky changes) bool mReset = false; - LLDrawable::ordered_drawable_set_t mHeroList; - LLPointer mNearestHero; + std::set mHeroVOList; + LLVOVolume* mNearestHero; }; diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index d62a640b5c..74c02099f8 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -755,10 +755,6 @@ void LLPanelVolume::sendIsMirror() } LLVOVolume *volobjp = (LLVOVolume *)objectp; - // Quick hack to set the mirror locally. - - gPipeline.mHeroProbeManager.registerHeroDrawable(volobjp->mDrawable); - BOOL value = getChild("Mirror Checkbox Ctrl")->getValue(); volobjp->setIsMirror(value); LL_INFOS() << "update mirror sent" << LL_ENDL; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 59a61f0c63..7032ce41d5 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1524,11 +1524,43 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, std::string temp_string; mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num ); + std::stringstream ss(temp_string); + std::string word; + bool mirror_detected = false; + while (ss >> word) + { + if (word == "Mirror") + { + mirror_detected = true; + mIsMirror = true; + } + else if (word == "XAlign" && mIsMirror) + { + mMirrorPlacementMode = 0; + } + else if (word == "YAlign" && mIsMirror) + { + mMirrorPlacementMode = 1; + } + else if (word == "ZAlign" && mIsMirror) + { + mMirrorPlacementMode = 2; + } + else if (word == "NearestPoint" && mIsMirror) + { + mMirrorPlacementMode = 3; + } + } + LLColor4U coloru; mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num); - + // alpha was flipped so that it zero encoded better coloru.mV[3] = 255 - coloru.mV[3]; + + if (mirror_detected) + coloru.mV[3] = 0; + mText->setColor(LLColor4(coloru)); mText->setString(temp_string); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 7175b088d9..c165f164a8 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -258,6 +258,7 @@ public: virtual BOOL hasLightTexture() const { return FALSE; } virtual BOOL isReflectionProbe() const { return FALSE; } virtual BOOL isMirror() const { return FALSE; } + virtual U8 mirrorPlacementMode() const { return 0; } // This method returns true if the object is over land owned by // the agent, one of its groups, or it encroaches and @@ -878,6 +879,9 @@ protected: F32 mPhysicsCost; F32 mLinksetPhysicsCost; + bool mIsMirror; + U8 mMirrorPlacementMode; + // If true, "shrink wrap" this volume in its spatial partition. See "shrinkWrap" bool mShouldShrinkWrap = false; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 3c3d8d5123..23580c4ec0 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -249,6 +249,9 @@ LLVOVolume::~LLVOVolume() mTextureAnimp = NULL; delete mVolumeImpl; mVolumeImpl = NULL; + + if (mIsMirror) + gPipeline.mHeroProbeManager.unregisterHeroDrawable(this); gMeshRepo.unregisterMesh(this); @@ -1045,9 +1048,9 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) updateReflectionProbePtr(); } - //if (isMirror()) + if (isMirror()) { - gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); + gPipeline.mHeroProbeManager.registerHeroDrawable(this); } updateRadius(); @@ -3396,17 +3399,22 @@ void LLVOVolume::updateMirrorDrawable() { if (isMirror()) { - gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); + gPipeline.mHeroProbeManager.registerHeroDrawable(this); } else { - gPipeline.mHeroProbeManager.unregisterHeroDrawable(mDrawable); + gPipeline.mHeroProbeManager.unregisterHeroDrawable(this); } } BOOL LLVOVolume::isMirror() const { - return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE); + return mIsMirror; +} + +U8 LLVOVolume::mirrorPlacementMode() const +{ + return mMirrorPlacementMode; } BOOL LLVOVolume::isReflectionProbe() const @@ -4461,9 +4469,9 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u updateReflectionProbePtr(); if (isMirror()) - gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); + gPipeline.mHeroProbeManager.registerHeroDrawable(this); else - gPipeline.mHeroProbeManager.unregisterHeroDrawable(mDrawable); + gPipeline.mHeroProbeManager.unregisterHeroDrawable(this); } void LLVOVolume::updateReflectionProbePtr() diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 32c89ddae2..848f455e2a 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -298,6 +298,7 @@ public: // Mirrors bool setIsMirror(BOOL is_mirror); void updateMirrorDrawable(); + U8 mirrorPlacementMode() const override; // Reflection Probes bool setIsReflectionProbe(BOOL is_probe); -- 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 --- .../shaders/class3/deferred/softenLightF.glsl | 3 + indra/newview/llheroprobemanager.cpp | 165 +++++++++++++-------- indra/newview/llviewerobject.cpp | 93 ++++++++---- 3 files changed, 171 insertions(+), 90 deletions(-) diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 742b52b074..2483355205 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -280,6 +280,9 @@ void main() // add radiance map applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz); + + color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - spec.a) * 11).xyz * spec.rgb; + } color.rgb = mix(color.rgb, baseColor.rgb, baseColor.a); 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); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 7032ce41d5..adb4683af0 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -314,7 +314,9 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mLastUpdateCached(FALSE), mCachedMuteListUpdateTime(0), mCachedOwnerInMuteList(false), - mRiggedAttachedWarned(false) + mRiggedAttachedWarned(false), +mIsMirror(false), +mMirrorPlacementMode(3) { if (!is_global) { @@ -1148,6 +1150,61 @@ U32 LLViewerObject::extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector return parent_id; } +void detectMirror(const std::string &str, bool &mirror, U8 &mode) +{ + + std::stringstream ss(str); + std::string word; + while (ss >> word) + { + if (word == "IsMirror") + { + mirror = true; + } + else if (word == "XAlign" && mirror) + { + LL_INFOS() << "Mirror wants camera X placement." << LL_ENDL; + mode = 0; + } + else if (word == "YAlign" && mirror) + { + LL_INFOS() << "Mirror wants camera Y placement." << LL_ENDL; + mode = 1; + } + else if (word == "ZAlign" && mirror) + { + LL_INFOS() << "Mirror wants camera Z placement." << LL_ENDL; + mode = 2; + } + else if (word == "NearestPoint" && mirror) + { + LL_INFOS() << "Mirror wants nearest point placement." << LL_ENDL; + mode = 3; + } + else if (word == "Center" && mirror) + { + LL_INFOS() << "Mirror wants center of object." << LL_ENDL; + mode = 4; + } + else if (word == "XMin" && mirror) + { + mode = 5; + } + else if (word == "XMax" && mirror) + { + mode = 6; + } + else if (word == "FocusPoint" && mirror) + { + mode = 7; + } + else if (word == "Reflected" && mirror) + { + mode = 8; + } + } +} + U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, @@ -1524,33 +1581,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, std::string temp_string; mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num ); - std::stringstream ss(temp_string); - std::string word; - bool mirror_detected = false; - while (ss >> word) - { - if (word == "Mirror") - { - mirror_detected = true; - mIsMirror = true; - } - else if (word == "XAlign" && mIsMirror) - { - mMirrorPlacementMode = 0; - } - else if (word == "YAlign" && mIsMirror) - { - mMirrorPlacementMode = 1; - } - else if (word == "ZAlign" && mIsMirror) - { - mMirrorPlacementMode = 2; - } - else if (word == "NearestPoint" && mIsMirror) - { - mMirrorPlacementMode = 3; - } - } + detectMirror(temp_string, mIsMirror, mMirrorPlacementMode); LLColor4U coloru; mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num); @@ -1558,9 +1589,6 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // alpha was flipped so that it zero encoded better coloru.mV[3] = 255 - coloru.mV[3]; - if (mirror_detected) - coloru.mV[3] = 0; - mText->setColor(LLColor4(coloru)); mText->setString(temp_string); @@ -1940,6 +1968,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, { std::string temp_string; dp->unpackString(temp_string, "Text"); + + detectMirror(temp_string, mIsMirror, mMirrorPlacementMode); + LLColor4U coloru; dp->unpackBinaryDataFixed(coloru.mV, 4, "Color"); coloru.mV[3] = 255 - coloru.mV[3]; -- 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 +++++++++++++++++++++++++++++++++++- indra/newview/llviewerobject.cpp | 53 +++++++++++++++++--- 2 files changed, 138 insertions(+), 8 deletions(-) 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; } } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index adb4683af0..950c672a42 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1163,27 +1163,22 @@ void detectMirror(const std::string &str, bool &mirror, U8 &mode) } else if (word == "XAlign" && mirror) { - LL_INFOS() << "Mirror wants camera X placement." << LL_ENDL; mode = 0; } else if (word == "YAlign" && mirror) { - LL_INFOS() << "Mirror wants camera Y placement." << LL_ENDL; mode = 1; } else if (word == "ZAlign" && mirror) { - LL_INFOS() << "Mirror wants camera Z placement." << LL_ENDL; mode = 2; } else if (word == "NearestPoint" && mirror) { - LL_INFOS() << "Mirror wants nearest point placement." << LL_ENDL; mode = 3; } else if (word == "Center" && mirror) { - LL_INFOS() << "Mirror wants center of object." << LL_ENDL; mode = 4; } else if (word == "XMin" && mirror) @@ -1194,14 +1189,58 @@ void detectMirror(const std::string &str, bool &mirror, U8 &mode) { mode = 6; } - else if (word == "FocusPoint" && mirror) + else if (word == "YMin" && mirror) { mode = 7; } - else if (word == "Reflected" && mirror) + else if (word == "YMax" && mirror) { mode = 8; } + else if (word == "ZMin" && mirror) + { + mode = 9; + } + else if (word == "ZMax" && mirror) + { + mode = 10; + } + else if (word == "FocusPoint" && mirror) + { + mode = 11; + } + else if (word == "ReflectedX" && mirror) + { + mode = 12; + } + else if (word == "ReflectedY" && mirror) + { + mode = 13; + } + else if (word == "ReflectedZ" && mirror) + { + mode = 14; + } + else if (word == "XYAlign" && mirror) + { + mode = 15; + } + else if (word == "XZAlign" && mirror) + { + mode = 16; + } + else if (word == "ZYAlign" && mirror) + { + mode = 17; + } + else if (word == "XYZAlign" && mirror) + { + mode = 18; + } + else if (word == "XYZAlignCenter" && mirror) + { + mode = 19; + } } } -- 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 ++++++++--------------------------- indra/newview/llviewerobject.cpp | 74 +----------- 2 files changed, 47 insertions(+), 237 deletions(-) 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() diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 950c672a42..dcdb66a6d4 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1161,85 +1161,17 @@ void detectMirror(const std::string &str, bool &mirror, U8 &mode) { mirror = true; } - else if (word == "XAlign" && mirror) - { - mode = 0; - } - else if (word == "YAlign" && mirror) - { - mode = 1; - } - else if (word == "ZAlign" && mirror) - { - mode = 2; - } - else if (word == "NearestPoint" && mirror) - { - mode = 3; - } - else if (word == "Center" && mirror) - { - mode = 4; - } - else if (word == "XMin" && mirror) - { - mode = 5; - } - else if (word == "XMax" && mirror) - { - mode = 6; - } - else if (word == "YMin" && mirror) - { - mode = 7; - } - else if (word == "YMax" && mirror) - { - mode = 8; - } - else if (word == "ZMin" && mirror) - { - mode = 9; - } - else if (word == "ZMax" && mirror) - { - mode = 10; - } - else if (word == "FocusPoint" && mirror) - { - mode = 11; - } else if (word == "ReflectedX" && mirror) { - mode = 12; + mode = 0; } else if (word == "ReflectedY" && mirror) { - mode = 13; + mode = 1; } else if (word == "ReflectedZ" && mirror) { - mode = 14; - } - else if (word == "XYAlign" && mirror) - { - mode = 15; - } - else if (word == "XZAlign" && mirror) - { - mode = 16; - } - else if (word == "ZYAlign" && mirror) - { - mode = 17; - } - else if (word == "XYZAlign" && mirror) - { - mode = 18; - } - else if (word == "XYZAlignCenter" && mirror) - { - mode = 19; + mode = 2; } } } -- 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(-) 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 1433434bf134b76220fa2c31c16f36459b463e32 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 8 Sep 2023 23:01:16 -0700 Subject: Update reflectionProbeF.glsl DRTVWR-583 --- .../app_settings/shaders/class3/deferred/reflectionProbeF.glsl | 7 ------- 1 file changed, 7 deletions(-) diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index adbf7abdd1..549ac50280 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -71,9 +71,6 @@ layout (std140) uniform ReflectionProbes // number of reflection probes present in refSphere int refmapCount; - - vec4 heroPosition[1]; - int heroProbeCount; }; // Inputs @@ -523,10 +520,6 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c, v = env_mat * v; -#if defined(HERO_PROBES) - vec3 mirror = textureLod(heroProbes, vec4(v.xyz, 0), lod).rgb; -#endif - vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod) * refParams[i].y; return ret.rgb; -- 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(-) 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 +++--------- indra/newview/llheroprobemanager.h | 3 --- 2 files changed, 3 insertions(+), 12 deletions(-) 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 diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index b817b2396f..30943f739b 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -94,9 +94,6 @@ private: // vertex buffer for pushing verts to filter shaders LLPointer mVertexBuffer; - // storage for reflection probe irradiance maps - LLPointer mIrradianceMaps; - // update the specified face of the specified probe void updateProbeFace(LLReflectionMap* probe, U32 face); -- 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/llface.cpp | 27 +++++++++++++++++++++++++++ indra/newview/llface.h | 5 +++++ indra/newview/llheroprobemanager.cpp | 10 ++++++++++ 3 files changed, 42 insertions(+) diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index c1776705f9..4dd991ee60 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -488,6 +488,33 @@ U16 LLFace::getGeometry(LLStrider &vertices, LLStrider &no return mGeomIndex; } +LLVector3 LLFace::getAverageNormal() +{ + if (!mHasAverageNormal) + { + if (mVertexBuffer.notNull()) + { + if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL)) + { + LLStrider normals; + mVertexBuffer->getNormalStrider(normals, mGeomIndex, mGeomCount); + LLVector3 normal_total; + + for (int i = 0; i < mVertexBuffer->getNumVerts(); i++) + { + normal_total += *normals.get(); + normals++; + } + + mAverageNormal = normal_total / mVertexBuffer->getNumVerts(); + mHasAverageNormal = true; + } + } + } + + return mAverageNormal; +} + void LLFace::updateCenterAgent() { if (mDrawablep->isActive()) diff --git a/indra/newview/llface.h b/indra/newview/llface.h index eb3b47d6d6..d4f4313073 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -176,6 +176,8 @@ public: LLStrider &normals, LLStrider &texCoords, LLStrider &indices); + + LLVector3 getAverageNormal(); S32 getColors(LLStrider &colors); S32 getIndices(LLStrider &indices); @@ -278,6 +280,9 @@ private: U32 mIndicesCount; U32 mIndicesIndex; // index into mVertexBuffer's index array S32 mIndexInTex[LLRender::NUM_TEXTURE_CHANNELS]; + + LLVector3 mAverageNormal; + bool mHasAverageNormal; LLXformMatrix* mXform; 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/llface.cpp | 31 ++++++++----------------------- indra/newview/llheroprobemanager.cpp | 5 +++-- indra/newview/llviewerobject.cpp | 31 +++++++++++++++++++------------ 3 files changed, 30 insertions(+), 37 deletions(-) diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 4dd991ee60..2c04224fa0 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -490,28 +490,6 @@ U16 LLFace::getGeometry(LLStrider &vertices, LLStrider &no LLVector3 LLFace::getAverageNormal() { - if (!mHasAverageNormal) - { - if (mVertexBuffer.notNull()) - { - if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL)) - { - LLStrider normals; - mVertexBuffer->getNormalStrider(normals, mGeomIndex, mGeomCount); - LLVector3 normal_total; - - for (int i = 0; i < mVertexBuffer->getNumVerts(); i++) - { - normal_total += *normals.get(); - normals++; - } - - mAverageNormal = normal_total / mVertexBuffer->getNumVerts(); - mHasAverageNormal = true; - } - } - } - return mAverageNormal; } @@ -1916,14 +1894,21 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, F32* normals = (F32*) norm.get(); LLVector4a* src = vf.mNormals; LLVector4a* end = src+num_vertices; - + + LLVector4a normal_total; + while (src < end) { LLVector4a normal; mat_normal.rotate(*src++, normal); normal.store4a(normals); + normal_total.add(normal); normals += 4; } + + normal_total.div(LLVector4a(num_vertices)); + + mAverageNormal = LLVector3(normal_total[0], normal_total[1], normal_total[2]); } if (rebuild_tangent) 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; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index dcdb66a6d4..9ac9ef7ea6 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1161,18 +1161,25 @@ void detectMirror(const std::string &str, bool &mirror, U8 &mode) { mirror = true; } - else if (word == "ReflectedX" && mirror) - { - mode = 0; - } - else if (word == "ReflectedY" && mirror) - { - mode = 1; - } - else if (word == "ReflectedZ" && mirror) - { - mode = 2; - } + + if (mirror) + { + bool num = false; + std::string::const_iterator it = word.begin(); + while (it != word.end()) + { + num = std::isdigit(*it); + ++it; + + if (!num) + break; + } + + if (num) + { + mode = atoi(word.c_str()); + } + } } } -- 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(-) 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/app_settings/settings.xml | 13 ++++++++++++- indra/newview/llheroprobemanager.cpp | 4 ++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f4e0682ee6..709dfd3844 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10421,8 +10421,19 @@ Type S32 Value - 512 + 1024 + RenderHeroProbeDistance + + Comment + Distance in meters for hero probes to render out to. + Persist + 1 + Type + F32 + Value + 16 + RenderReflectionProbeVolumes Comment 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/app_settings/settings.xml | 11 +++++++++ indra/newview/llheroprobemanager.cpp | 41 +++++++++++++++------------------ indra/newview/llheroprobemanager.h | 2 +- indra/newview/llreflectionmap.cpp | 6 +++-- indra/newview/llreflectionmap.h | 2 +- 5 files changed, 35 insertions(+), 27 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 709dfd3844..82545a5dda 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10434,6 +10434,17 @@ Value 16 + RenderHeroProbeNearClipOffset + + Comment + Distance offset in meters for hero probes to near clip. + Persist + 1 + Type + F32 + Value + 2.1 + RenderReflectionProbeVolumes Comment 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() diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 30943f739b..4a243e6cf2 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -95,7 +95,7 @@ private: LLPointer mVertexBuffer; // update the specified face of the specified probe - void updateProbeFace(LLReflectionMap* probe, U32 face); + void updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip); // list of active reflection maps std::vector > mProbes; diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index 07c712a9a6..06624e8fea 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -49,7 +49,7 @@ LLReflectionMap::~LLReflectionMap() } } -void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic) +void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 near_clip) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; mLastUpdateTime = gFrameTimeSeconds; @@ -63,8 +63,10 @@ void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic) { resolution /= 2; } + + F32 clip = (near_clip > 0) ? near_clip : getNearClip(); - gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip(), getIsDynamic() || force_dynamic); + gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, clip, getIsDynamic() || force_dynamic); } void LLReflectionMap::autoAdjustOrigin() diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index a23bdc3a98..e97b28c855 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -52,7 +52,7 @@ public: // update this environment map // resolution - size of cube map to generate - void update(U32 resolution, U32 face, bool force_dynamic = false); + void update(U32 resolution, U32 face, bool force_dynamic = false, F32 near_clip = -1.f); // for volume partition probes, try to place this probe in the best spot void autoAdjustOrigin(); -- 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(-) 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/llrender/llshadermgr.cpp | 4 +++ indra/llrender/llshadermgr.h | 3 ++ .../shaders/class1/deferred/materialV.glsl | 17 +++-------- .../shaders/class1/deferred/pbropaqueF.glsl | 27 ++++++++++++++++++ .../shaders/class3/deferred/materialF.glsl | 30 ++++++++++++++++++-- .../shaders/class3/deferred/softenLightF.glsl | 6 ++-- indra/newview/lldrawpoolmaterials.cpp | 13 +++++++++ indra/newview/llfetchedgltfmaterial.cpp | 1 + indra/newview/llheroprobemanager.cpp | 33 +++++++++++++++++----- indra/newview/llheroprobemanager.h | 11 ++++++++ indra/newview/llreflectionmap.cpp | 4 +-- indra/newview/llreflectionmap.h | 2 +- indra/newview/llviewerdisplay.cpp | 2 +- indra/newview/llviewerwindow.cpp | 15 +++++++++- indra/newview/llviewerwindow.h | 3 +- scripts/messages/message_template.msg.sha1 | 2 +- 16 files changed, 141 insertions(+), 32 deletions(-) diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 645a78bfac..8ae23989c9 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -651,6 +651,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_SKIP_ATMOS 0.0 \n"); // atmo kill extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_ATMOS 0.34\n"); // bit 0 extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_PBR 0.67\n"); // bit 1 + extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_MIRROR 1.0\n"); // bit 2 extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (abs(norm.w-flag)< 0.1)\n"); if (defines) @@ -1256,6 +1257,9 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("emissiveColor"); mReservedUniforms.push_back("metallicFactor"); mReservedUniforms.push_back("roughnessFactor"); + mReservedUniforms.push_back("mirror_flag"); + mReservedUniforms.push_back("clipPlane"); + mReservedUniforms.push_back("clipSign"); mReservedUniforms.push_back("diffuseMap"); mReservedUniforms.push_back("altDiffuseMap"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index a326a5593d..5824c03e2a 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -85,6 +85,9 @@ public: EMISSIVE_COLOR, // "emissiveColor" METALLIC_FACTOR, // "metallicFactor" ROUGHNESS_FACTOR, // "roughnessFactor" + MIRROR_FLAG, // "mirror_flag" + CLIP_PLANE, // "clipPlane" + CLIP_SIGN, // "clipSign" DIFFUSE_MAP, // "diffuseMap" ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap" SPECULAR_MAP, // "specularMap" diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl index 7cdddfe8db..65706e2c3f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl @@ -28,25 +28,18 @@ #define DIFFUSE_ALPHA_MODE_MASK 2 #define DIFFUSE_ALPHA_MODE_EMISSIVE 3 -#ifdef HAS_SKIN uniform mat4 modelview_matrix; uniform mat4 projection_matrix; +uniform mat4 modelview_projection_matrix; + +#ifdef HAS_SKIN mat4 getObjectSkinnedTransform(); #else uniform mat3 normal_matrix; -uniform mat4 modelview_projection_matrix; -#endif - -#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) - -#if !defined(HAS_SKIN) -uniform mat4 modelview_matrix; #endif out vec3 vary_position; -#endif - uniform mat4 texture_matrix0; in vec3 position; @@ -133,10 +126,8 @@ void main() vertex_color = diffuse_color; -#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) #if !defined(HAS_SKIN) - vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; -#endif + vary_position = (projection_matrix*vec4(position.xyz, 1.0)).xyz; #endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl index faa273b834..9b98a37925 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl @@ -58,10 +58,37 @@ vec2 encode_normal(vec3 n); vec3 linear_to_srgb(vec3 c); vec3 srgb_to_linear(vec3 c); +uniform vec4 clipPlane; +uniform float clipSign; +uniform float mirror_flag; +void applyClip(vec3 pos) +{ + if (mirror_flag > 0) + { + // TODO: make this less branchy + if (clipSign > 0) + { + if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) < 0.0) + { + discard; + } + } + else + { + if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) > 0.0) + { + discard; + } + } + } +} + uniform mat3 normal_matrix; void main() { + applyClip(vary_position); + vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba; if (basecolor.a < minimum_alpha) { diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index 319f2f25b7..af49e76984 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -51,6 +51,23 @@ vec3 linear_to_srgb(vec3 cs); vec3 legacy_adjust(vec3 c); vec3 legacy_adjust_fullbright(vec3 c); +uniform vec4 clipPlane; +uniform float clipSign; +uniform float mirror_flag; +void applyClip(vec3 pos) +{ + float funnyClip = 0; + if (mirror_flag > 0) + { + if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) > 0.0) + { + discard; + } + } +} + +in vec3 vary_position; + #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) out vec4 frag_color; @@ -72,12 +89,12 @@ uniform vec4 morphFactor; uniform vec3 camPosLocal; uniform mat3 env_mat; +uniform float is_mirror; + uniform vec3 sun_dir; uniform vec3 moon_dir; in vec2 vary_fragcoord; -in vec3 vary_position; - uniform mat4 proj_mat; uniform mat4 inv_proj; uniform vec2 screen_res; @@ -291,6 +308,7 @@ float getShadow(vec3 pos, vec3 norm) void main() { + applyClip(vary_position); waterClip(); // diffcol == diffuse map combined with vertex color @@ -419,9 +437,15 @@ void main() #else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer // deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl + + float flag = GBUFFER_FLAG_HAS_ATMOS; + + if (mirror_flag > 0) + flag = 1; + frag_data[0] = vec4(diffcol.rgb, emissive); // gbuffer is sRGB for legacy materials frag_data[1] = vec4(spec.rgb, glossiness); // XYZ = Specular color. W = Specular exponent. - frag_data[2] = vec4(encode_normal(norm), env, GBUFFER_FLAG_HAS_ATMOS);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog) + frag_data[2] = vec4(encode_normal(norm), env, flag);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog) frag_data[3] = vec4(0); #endif } diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 20a5ad66b6..d42388ae78 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -191,7 +191,7 @@ void main() vec3 irradiance = vec3(0); vec3 radiance = vec3(0); - if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR)) + if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR) || GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_MIRROR)) { vec3 orm = texture(specularRect, tc).rgb; float perceptualRoughness = orm.g; @@ -214,7 +214,9 @@ void main() color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten); vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - gloss) * 11).xyz * specularColor; + + if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_MIRROR)) + color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - gloss) * 11).xyz * specularColor; if (do_atmospherics) { diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index 6a7e05ac74..373103ce0a 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -190,6 +190,19 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass) glUniform4fv(specular, 1, lastSpecular.mV); } + if (gPipeline.mHeroProbeManager.isMirrorPass()) + { + glUniform1f(LLShaderMgr::MIRROR_FLAG, 1); + } + + LLVector4 clipPlane = LLVector4(gPipeline.mHeroProbeManager.currentMirrorClip()[0], + gPipeline.mHeroProbeManager.currentMirrorClip()[1], + gPipeline.mHeroProbeManager.currentMirrorClip()[2], + gPipeline.mHeroProbeManager.currentMirrorClip()[3]); + + mShader->uniform4fv(LLShaderMgr::CLIP_PLANE, + 1, clipPlane.mV); + LLVOAvatar* lastAvatar = nullptr; for (LLCullResult::drawinfo_iterator i = begin; i != end; ) diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index 1fb3577dd7..9590066b55 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -128,6 +128,7 @@ void LLFetchedGLTFMaterial::bind(LLViewerTexture* media_tex) shader->uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, mRoughnessFactor); shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, mMetallicFactor); shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, mEmissiveColor.mV); + shader->uniform1f(LLShaderMgr::MIRROR_FLAG, 0); F32 normal_packed[8]; mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed); 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; +} diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 4a243e6cf2..68cfdbfd99 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -70,6 +70,12 @@ public: void registerHeroDrawable(LLVOVolume* drawablep); void unregisterHeroDrawable(LLVOVolume* drawablep); + + bool isViableMirror(LLFace* face) const; + + bool isMirrorPass() const { return mRenderingMirror; } + + LLPlane currentMirrorClip() const { return mCurrentClipPlane; } private: friend class LLPipeline; @@ -94,6 +100,8 @@ private: // vertex buffer for pushing verts to filter shaders LLPointer mVertexBuffer; + LLPlane mCurrentClipPlane; + // update the specified face of the specified probe void updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip); @@ -124,8 +132,11 @@ private: // if true, reset all probe render state on the next update (for teleports and sky changes) bool mReset = false; + + bool mRenderingMirror = false; std::set mHeroVOList; LLVOVolume* mNearestHero; + LLFace* mCurrentFace; }; diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index 06624e8fea..5fc9851709 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -49,7 +49,7 @@ LLReflectionMap::~LLReflectionMap() } } -void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 near_clip) +void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 near_clip, bool useClipPlane, LLPlane clipPlane) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; mLastUpdateTime = gFrameTimeSeconds; @@ -66,7 +66,7 @@ void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 n F32 clip = (near_clip > 0) ? near_clip : getNearClip(); - gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, clip, getIsDynamic() || force_dynamic); + gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, clip, getIsDynamic() || force_dynamic, useClipPlane, clipPlane); } void LLReflectionMap::autoAdjustOrigin() diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index e97b28c855..9e888f20d0 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -52,7 +52,7 @@ public: // update this environment map // resolution - size of cube map to generate - void update(U32 resolution, U32 face, bool force_dynamic = false, F32 near_clip = -1.f); + void update(U32 resolution, U32 face, bool force_dynamic = false, F32 near_clip = -1.f, bool useClipPlane = false, LLPlane clipPlane = LLPlane(LLVector3(0, 0, 0), LLVector3(0, 0, 1))); // for volume partition probes, try to place this probe in the best spot void autoAdjustOrigin(); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 04ca62e0ec..a1e7d69ae4 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1063,7 +1063,7 @@ void display_cube_face() LLSpatialGroup::sNoDelete = TRUE; S32 occlusion = LLPipeline::sUseOcclusion; - LLPipeline::sUseOcclusion = 0; // occlusion data is from main camera point of view, don't read or write it during cube snapshots + LLPipeline::sUseOcclusion = 1; // occlusion data is from main camera point of view, don't read or write it during cube snapshots //gDepthDirty = TRUE; //let "real" render pipe know it can't trust the depth buffer for occlusion data static LLCullResult result; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index ba2b6e1c7c..e0ec8eec25 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -5304,7 +5304,7 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_ void display_cube_face(); -BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face, F32 near_clip, bool dynamic_render) +BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face, F32 near_clip, bool dynamic_render, bool useCustomClipPlane, LLPlane clipPlane) { // NOTE: implementation derived from LLFloater360Capture::capture360Images() and simpleSnapshot LL_PROFILE_ZONE_SCOPED_CATEGORY_APP; @@ -5335,6 +5335,14 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea camera->setOrigin(origin); camera->setNear(near_clip); + LLPlane previousClipPlane; + + if (useCustomClipPlane) + { + previousClipPlane = camera->getUserClipPlane(); + camera->setUserClipPlane(clipPlane); + } + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // stencil buffer is deprecated | GL_STENCIL_BUFFER_BIT); U32 dynamic_render_types[] = { @@ -5441,6 +5449,11 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea gPipeline.resetDrawOrders(); mWorldViewRectRaw = window_rect; + + if (useCustomClipPlane) + { + camera->setUserClipPlane(previousClipPlane); + } // restore original view/camera/avatar settings settings *camera = saved_camera; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 6e8a5b2f4e..4da6a1360f 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -374,7 +374,8 @@ public: // index - cube index in the array to use (cube index, not face-layer) // face - which cube face to update // near_clip - near clip setting to use - BOOL cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 index, S32 face, F32 near_clip, bool render_avatars); + BOOL cubeSnapshot(const LLVector3 &origin, LLCubeMapArray *cubearray, S32 index, S32 face, F32 near_clip, bool render_avatars, + bool customCullingPlane = false, LLPlane cullingPlane = LLPlane(LLVector3(0, 0, 0), LLVector3(0, 0, 1))); // special implementation of simpleSnapshot for reflection maps diff --git a/scripts/messages/message_template.msg.sha1 b/scripts/messages/message_template.msg.sha1 index 5ad85458e9..8dd2aba32a 100755 --- a/scripts/messages/message_template.msg.sha1 +++ b/scripts/messages/message_template.msg.sha1 @@ -1 +1 @@ -e3bd0529a647d938ab6d48f26d21dd52c07ebc6e \ No newline at end of file +e11941c09b42eb7cc9c56dae08afc03cbf1a22d8 \ No newline at end of file -- cgit v1.2.3 From 0bfeb74172b172fc3202d67fab04df25e23591b0 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 16 Oct 2023 08:48:00 -0700 Subject: Revert an accidental message template sha1 update. DRTVWR-583 --- scripts/messages/message_template.msg.sha1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/messages/message_template.msg.sha1 b/scripts/messages/message_template.msg.sha1 index 8dd2aba32a..5ad85458e9 100755 --- a/scripts/messages/message_template.msg.sha1 +++ b/scripts/messages/message_template.msg.sha1 @@ -1 +1 @@ -e11941c09b42eb7cc9c56dae08afc03cbf1a22d8 \ No newline at end of file +e3bd0529a647d938ab6d48f26d21dd52c07ebc6e \ No newline at end of file -- 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/app_settings/settings.xml | 2 +- .../app_settings/shaders/class3/deferred/softenLightF.glsl | 11 ++++++----- indra/newview/llheroprobemanager.cpp | 2 +- indra/newview/llviewershadermgr.cpp | 5 ++++- indra/newview/pipeline.cpp | 14 ++++++++++---- indra/newview/pipeline.h | 1 + 6 files changed, 23 insertions(+), 12 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 493ccec560..242e274daf 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9206,7 +9206,7 @@ Type Boolean Value - 1 + 0 RenderScreenSpaceReflections diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index f5541df227..79d9000482 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -34,11 +34,13 @@ uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal uniform samplerCubeArray heroProbes; +#if defined(HERO_PROBES) layout (std140) uniform HeroProbeData { vec4 heroPosition[1]; int heroProbeCount; }; +#endif const float M_PI = 3.14159265; @@ -196,15 +198,12 @@ void main() vec3 v = -normalize(pos.xyz); color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten); + #ifdef HERO_PROBES vec3 refnormpersp = reflect(pos.xyz, norm.xyz); if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_MIRROR)) color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - gloss) * 11).xyz * specularColor; - - if (do_atmospherics) - { - color = atmosFragLightingLinear(color, additive, atten); - } + #endif } else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { @@ -263,7 +262,9 @@ void main() // add radiance map applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz); + #ifdef HERO_PROBES color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - spec.a) * 11).xyz * spec.rgb; + #endif } 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; } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 693297d1e1..48c54f3dcc 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -1805,7 +1805,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSoftenProgram.addPermutation("HAS_SUN_SHADOW", "1"); } - gDeferredSoftenProgram.addPermutation("HERO_PROBES", "1"); + if (LLPipeline::RenderMirrors) + { + gDeferredSoftenProgram.addPermutation("HERO_PROBES", "1"); + } if (gSavedSettings.getBOOL("RenderDeferredSSAO")) { //if using SSAO, take screen space light map into account as if shadows are enabled diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9e6af24f80..94f2dc4a2a 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -199,6 +199,7 @@ F32 LLPipeline::RenderScreenSpaceReflectionDepthRejectBias; F32 LLPipeline::RenderScreenSpaceReflectionAdaptiveStepMultiplier; S32 LLPipeline::RenderScreenSpaceReflectionGlossySamples; S32 LLPipeline::RenderBufferVisualization; +bool LLPipeline::RenderMirrors; LLTrace::EventStatHandle LLPipeline::sStatBatchSize("renderbatchsize"); const U32 LLPipeline::MAX_BAKE_WIDTH = 512; @@ -559,6 +560,7 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("RenderScreenSpaceReflectionAdaptiveStepMultiplier"); connectRefreshCachedSettingsSafe("RenderScreenSpaceReflectionGlossySamples"); connectRefreshCachedSettingsSafe("RenderBufferVisualization"); + connectRefreshCachedSettingsSafe("RenderMirrors"); gSavedSettings.getControl("RenderAutoHideSurfaceAreaLimit")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); } @@ -1058,6 +1060,7 @@ void LLPipeline::refreshCachedSettings() RenderScreenSpaceReflectionAdaptiveStepMultiplier = gSavedSettings.getF32("RenderScreenSpaceReflectionAdaptiveStepMultiplier"); RenderScreenSpaceReflectionGlossySamples = gSavedSettings.getS32("RenderScreenSpaceReflectionGlossySamples"); RenderBufferVisualization = gSavedSettings.getS32("RenderBufferVisualization"); + RenderMirrors = gSavedSettings.getBOOL("RenderMirrors"); sReflectionProbesEnabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionsEnabled") && gSavedSettings.getBOOL("RenderReflectionsEnabled"); RenderSpotLight = nullptr; @@ -8645,11 +8648,14 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader) bound = true; } - channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY); - if (channel > -1 && mHeroProbeManager.mTexture.notNull()) + if (RenderMirrors) { - mHeroProbeManager.mTexture->bind(channel); - bound = true; + channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY); + if (channel > -1 && mHeroProbeManager.mTexture.notNull()) + { + mHeroProbeManager.mTexture->bind(channel); + bound = true; + } } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 30bc95ad19..21c1d9a25d 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -1051,6 +1051,7 @@ public: static F32 RenderScreenSpaceReflectionAdaptiveStepMultiplier; static S32 RenderScreenSpaceReflectionGlossySamples; static S32 RenderBufferVisualization; + static bool RenderMirrors; }; void render_bbox(const LLVector3 &min, const LLVector3 &max); -- cgit v1.2.3 From 42b51bfd2cccba1dfdc820a4a033481fd42c1907 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 24 Jan 2024 16:02:31 -0800 Subject: https://github.com/secondlife/viewer-issues/issues/23 Fix for merge up to the featurettes branch, and reflection probes being "hazy" --- .../shaders/class3/deferred/softenLightF.glsl | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 79d9000482..f1de0b88d6 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -114,8 +114,8 @@ vec3 pbrBaseLight(vec3 diffuseColor, vec3 additive, vec3 atten); -vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, - float perceptualRoughness, +vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, + float perceptualRoughness, float metallic, vec3 n, // normal vec3 v, // surface point to camera @@ -176,9 +176,9 @@ void main() vec3 irradiance = vec3(0); vec3 radiance = vec3(0); - if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR) || GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_MIRROR)) + if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR)) { - vec3 orm = texture(specularRect, tc).rgb; + vec3 orm = texture(specularRect, tc).rgb; float perceptualRoughness = orm.g; float metallic = orm.b; float ao = orm.r; @@ -275,12 +275,7 @@ void main() applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity); } } - - #ifdef WATER_FOG - vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom)); - color = fogged.rgb; - #endif - + frag_color.rgb = max(color.rgb, vec3(0)); //output linear since local lights will be added to this shader's results frag_color.a = 0.0; } -- 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 +- indra/newview/llviewerobject.cpp | 8 ++++---- indra/newview/llviewerobject.h | 4 ++-- indra/newview/llvovolume.cpp | 4 ++-- indra/newview/llvovolume.h | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) 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); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 88494f419c..691a2e14d3 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -314,8 +314,8 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mCachedMuteListUpdateTime(0), mCachedOwnerInMuteList(false), mRiggedAttachedWarned(false), -mIsMirror(false), -mMirrorPlacementMode(3) + mIsMirror(false), + mMirrorFace(3) { if (!is_global) { @@ -1558,7 +1558,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, std::string temp_string; mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num ); - detectMirror(temp_string, mIsMirror, mMirrorPlacementMode); + detectMirror(temp_string, mIsMirror, mMirrorFace); LLColor4U coloru; mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num); @@ -1946,7 +1946,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, std::string temp_string; dp->unpackString(temp_string, "Text"); - detectMirror(temp_string, mIsMirror, mMirrorPlacementMode); + detectMirror(temp_string, mIsMirror, mMirrorFace); LLColor4U coloru; dp->unpackBinaryDataFixed(coloru.mV, 4, "Color"); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 6ed37bf014..f3c00e83dc 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -258,7 +258,7 @@ public: virtual BOOL hasLightTexture() const { return FALSE; } virtual BOOL isReflectionProbe() const { return FALSE; } virtual BOOL isMirror() const { return FALSE; } - virtual U8 mirrorPlacementMode() const { return 0; } + virtual U8 mirrorFace() const { return 0; } // This method returns true if the object is over land owned by // the agent, one of its groups, or it encroaches and @@ -881,7 +881,7 @@ protected: F32 mLinksetPhysicsCost; bool mIsMirror; - U8 mMirrorPlacementMode; + U8 mMirrorFace; // If true, "shrink wrap" this volume in its spatial partition. See "shrinkWrap" bool mShouldShrinkWrap = false; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 91e64d611c..9813039145 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3364,9 +3364,9 @@ BOOL LLVOVolume::isMirror() const return mIsMirror; } -U8 LLVOVolume::mirrorPlacementMode() const +U8 LLVOVolume::mirrorFace() const { - return mMirrorPlacementMode; + return mMirrorFace; } BOOL LLVOVolume::isReflectionProbe() const diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 848f455e2a..b03fc4b862 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -298,7 +298,7 @@ public: // Mirrors bool setIsMirror(BOOL is_mirror); void updateMirrorDrawable(); - U8 mirrorPlacementMode() const override; + U8 mirrorFace() const override; // Reflection Probes bool setIsReflectionProbe(BOOL is_probe); -- cgit v1.2.3 From 2510134f40c2edd2eea40f486f094517b8ffaa51 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 24 Jan 2024 17:07:56 -0800 Subject: https://github.com/secondlife/viewer-issues/issues/23 Cleaning out some unused code. --- indra/newview/llface.cpp | 12 ------------ indra/newview/llface.h | 5 ----- 2 files changed, 17 deletions(-) diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 2c04224fa0..69e43bb458 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -488,11 +488,6 @@ U16 LLFace::getGeometry(LLStrider &vertices, LLStrider &no return mGeomIndex; } -LLVector3 LLFace::getAverageNormal() -{ - return mAverageNormal; -} - void LLFace::updateCenterAgent() { if (mDrawablep->isActive()) @@ -1895,20 +1890,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLVector4a* src = vf.mNormals; LLVector4a* end = src+num_vertices; - LLVector4a normal_total; - while (src < end) { LLVector4a normal; mat_normal.rotate(*src++, normal); normal.store4a(normals); - normal_total.add(normal); normals += 4; } - - normal_total.div(LLVector4a(num_vertices)); - - mAverageNormal = LLVector3(normal_total[0], normal_total[1], normal_total[2]); } if (rebuild_tangent) diff --git a/indra/newview/llface.h b/indra/newview/llface.h index d4f4313073..eb3b47d6d6 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -176,8 +176,6 @@ public: LLStrider &normals, LLStrider &texCoords, LLStrider &indices); - - LLVector3 getAverageNormal(); S32 getColors(LLStrider &colors); S32 getIndices(LLStrider &indices); @@ -280,9 +278,6 @@ private: U32 mIndicesCount; U32 mIndicesIndex; // index into mVertexBuffer's index array S32 mIndexInTex[LLRender::NUM_TEXTURE_CHANNELS]; - - LLVector3 mAverageNormal; - bool mHasAverageNormal; LLXformMatrix* mXform; -- cgit v1.2.3