summaryrefslogtreecommitdiff
path: root/indra/newview/llreflectionmapmanager.cpp
diff options
context:
space:
mode:
authormobserveur <mobserveur@gmail.com>2025-08-30 01:59:43 +0200
committerErik Kundiman <erik@megapahit.org>2025-09-09 07:07:09 +0800
commit317dcdea1ca8d1f540187af47fc23a36ad8232aa (patch)
tree5bdea032c8c2476760efd8b861f72ad3b37c6538 /indra/newview/llreflectionmapmanager.cpp
parent03140ed619c5d49eb3851284ae53bbea73a8b831 (diff)
Performance Optimisations, Bloom effect, Visuals Panel
This commit contains performance optimisations in the the pipeline, framebuffer, vertexbuffer, reflection probes, shadows. It also fixes many opengl errors, modifies the opengl debugging, and adds a visuals effects panel.
Diffstat (limited to 'indra/newview/llreflectionmapmanager.cpp')
-rw-r--r--indra/newview/llreflectionmapmanager.cpp395
1 files changed, 347 insertions, 48 deletions
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index c1815ad57e..d247d3260e 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -54,6 +54,7 @@
#endif
LLPointer<LLImageGL> gEXRImage;
+//LLTrace::BlockTimerStatHandle FTM_RENDER_RADIANCE("Render Radiance");
void load_exr(const std::string& filename)
{
@@ -226,6 +227,25 @@ void LLReflectionMapManager::update()
static LLCachedControl<S32> sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3);
static LLCachedControl<U32> sReflectionProbeCount(gSavedSettings, "RenderReflectionProbeCount", 256U);
static LLCachedControl<S32> sProbeDynamicAllocation(gSavedSettings, "RenderReflectionProbeDynamicAllocation", -1);
+
+ static LLCachedControl<F32> sProbeUpdateSlowDown(gSavedSettings, "MPRenderProbeSlowDown", 0.f);
+
+ bool realtime = sDetail >= (S32)LLReflectionMapManager::DetailLevel::REALTIME;
+
+ if(sProbeUpdateSlowDown > 0.0)
+ {
+ if ( mLastUpdate > 0.f )
+ {
+ F32 elapsed = gFrameTimeSeconds - mLastUpdate;
+ if (elapsed > 0.0 && elapsed < sProbeUpdateSlowDown)
+ {
+ return;
+ }
+ }
+ }
+
+ mLastUpdate = gFrameTimeSeconds;
+
mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds * 2.f), 1.f);
{
@@ -275,9 +295,16 @@ void LLReflectionMapManager::update()
static LLCachedControl<bool> render_hdr(gSavedSettings, "RenderHDREnabled", true);
+ U32 color_fmt = render_hdr ? GL_R11F_G11F_B10F : GL_RGB8;
+
+ static LLCachedControl<bool> MPLowColorPrecision(gSavedSettings, "MPLowColorPrecision", 0);
+ if(MPLowColorPrecision)
+ {
+ color_fmt = GL_RGB8;
+ }
+
if (!mRenderTarget.isComplete())
{
- U32 color_fmt = render_hdr ? GL_R11F_G11F_B10F : GL_RGB8;
U32 targetRes = mProbeResolution * 4; // super sample
mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
}
@@ -290,7 +317,7 @@ void LLReflectionMapManager::update()
mMipChain.resize(count);
for (U32 i = 0; i < count; ++i)
{
- mMipChain[i].allocate(res, res, render_hdr ? GL_R11F_G11F_B10F : GL_RGB8);
+ mMipChain[i].allocate(res, res, color_fmt);
res /= 2;
}
}
@@ -328,8 +355,6 @@ void LLReflectionMapManager::update()
bool did_update = false;
- bool realtime = sDetail >= (S32)LLReflectionMapManager::DetailLevel::REALTIME;
-
LLReflectionMap* closestDynamic = nullptr;
LLReflectionMap* oldestProbe = nullptr;
@@ -362,6 +387,9 @@ void LLReflectionMapManager::update()
probe->mCubeArray = nullptr;
probe->mCubeIndex = -1;
probe->mComplete = false;
+ probe->mCompletedCount = 0;
+ probe->mLastUpdateTime = 0.0;
+ probe->mNextUpdateTime = 0.0;
probe->mFadeIn = 0;
}
}
@@ -385,6 +413,9 @@ void LLReflectionMapManager::update()
mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds * 2.f), 1.f);
+ static LLCachedControl<F32> sDefaultUpdatePeriod(gSavedSettings, "RenderDefaultProbeUpdatePeriod", 2.f);
+ static LLCachedControl<F32> sMPUpdatePeriod(gSavedSettings, "MPRenderProbeUpdatePeriod", 2.f);
+
for (unsigned int i = 0; i < mProbes.size(); ++i)
{
LLReflectionMap* probe = mProbes[i];
@@ -401,6 +432,8 @@ void LLReflectionMapManager::update()
continue;
}
+ // Calculating distance
+
LLVector4a d;
if (probe != mDefaultProbe)
@@ -412,13 +445,14 @@ void LLReflectionMapManager::update()
d.setSub(camera_pos, probe->mOrigin);
probe->mDistance = d.getLength3().getF32() - probe->mRadius;
}
- else if (probe->mComplete)
+ else if (mDefaultProbe->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->mNextUpdateTime = 0.f;
probe->mDistance = -4096.f; //boost priority of default probe when it's not complete
}
@@ -427,8 +461,13 @@ void LLReflectionMapManager::update()
probe->autoAdjustOrigin();
probe->mFadeIn = llmin((F32) (probe->mFadeIn + gFrameIntervalSeconds), 1.f);
}
+
+ // Guess oldest probe
+
if (probe->mOccluded && probe->mComplete)
{
+ // occluded probe
+
if (oldestOccluded == nullptr)
{
oldestOccluded = probe;
@@ -465,6 +504,8 @@ void LLReflectionMapManager::update()
}
}
+ // realtime
+
if (realtime && closestDynamic != nullptr)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime");
@@ -480,16 +521,17 @@ void LLReflectionMapManager::update()
{
updateProbeFace(closestDynamic, i);
}
+ if(mRealtimeRadiancePass) updateProbeRadiance(closestDynamic);
+ else updateProbeIrradiance(closestDynamic);
mRealtimeRadiancePass = !mRealtimeRadiancePass;
// restore "isRadiancePass"
mRadiancePass = radiance_pass;
}
- static LLCachedControl<F32> sUpdatePeriod(gSavedSettings, "RenderDefaultProbeUpdatePeriod", 2.f);
- if ((gFrameTimeSeconds - mDefaultProbe->mLastUpdateTime) < sUpdatePeriod)
+ if ((gFrameTimeSeconds - mDefaultProbe->mLastUpdateTime) < sDefaultUpdatePeriod)
{
- if (sLevel == 0)
+ if (sLevel == 0 && mDefaultProbe->mComplete)
{ // when probes are disabled don't update the default probe more often than the prescribed update period
oldestProbe = nullptr;
}
@@ -505,11 +547,33 @@ void LLReflectionMapManager::update()
LLReflectionMap* probe = oldestProbe;
llassert(probe->mCubeIndex != -1);
+ bool shouldUpdate = true;
+
+ if( probe->mNextUpdateTime > 0.f && gFrameTimeSeconds < probe->mNextUpdateTime)
+ {
+ shouldUpdate = false;
+ }
+
+ if(shouldUpdate)
+ {
probe->autoAdjustOrigin();
sUpdateCount++;
mUpdatingProbe = probe;
+
+ if(probe->mCompletedCount < 2)
+ {
+ LL_WARNS() << "we program a short delay for this probe" << LL_ENDL;
+ probe->mNextUpdateTime = gFrameTimeSeconds + fmax( ((F32)sMPUpdatePeriod / 2.0), 0.25);
+ }
+ else
+ {
+ LL_WARNS() << "we program a long delay for this probe" << LL_ENDL;
+ probe->mNextUpdateTime = gFrameTimeSeconds + fmax( (F32)sMPUpdatePeriod, 0.25);
+ }
+
doProbeUpdate();
+ }
}
if (oldestOccluded)
@@ -717,11 +781,32 @@ void LLReflectionMapManager::doProbeUpdate()
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
llassert(mUpdatingProbe != nullptr);
- updateProbeFace(mUpdatingProbe, mUpdatingFace);
+ static LLCachedControl<bool> mp_progressive(gSavedSettings, "MPRenderProbeProgressive", false);
+
+ if(mUpdatingFace < 6)
+ {
+ updateProbeFace(mUpdatingProbe, mUpdatingFace, mp_progressive);
+ }
+ else if(mp_progressive)
+ {
+ if(isRadiancePass())
+ {
+ //updateProbeRadiance(mUpdatingProbe);
+ }
+ else updateProbeIrradiance(mUpdatingProbe);
+ }
+ else
+ {
+ if(isRadiancePass())
+ {
+ updateProbeRadiance(mUpdatingProbe);
+ }
+ else updateProbeIrradiance(mUpdatingProbe);
+ }
bool debug_updates = gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PROBE_UPDATES) && mUpdatingProbe->mViewerObject;
- if (++mUpdatingFace == 6)
+ if (mUpdatingFace == 6)
{
if (debug_updates)
{
@@ -732,17 +817,24 @@ void LLReflectionMapManager::doProbeUpdate()
if (isRadiancePass())
{
mUpdatingProbe->mComplete = true;
+ mUpdatingProbe->mCompletedCount++;
mUpdatingProbe = nullptr;
mRadiancePass = false;
+ LL_WARNS() << "probe updated !" << LL_ENDL;
}
else
{
mRadiancePass = true;
}
}
- else if (debug_updates)
+ else
{
+ ++mUpdatingFace;
+
+ if (debug_updates)
+ {
mUpdatingProbe->mViewerObject->setDebugText(llformat("%.1f", (F32)gFrameTimeSeconds), LLColor4(1, 1, 0, 1));
+ }
}
}
@@ -754,7 +846,7 @@ 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, bool progressive)
{
// hacky hot-swap of camera specific render targets
gPipeline.mRT = &gPipeline.mAuxillaryRT;
@@ -795,7 +887,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
sourceIdx += 1;
}
- gGL.setColorMask(true, true);
+ gGL.setColorMask(true, false);
LLGLDepthTest depth(GL_FALSE, GL_FALSE);
LLGLDisable cull(GL_CULL_FACE);
LLGLDisable blend(GL_BLEND);
@@ -829,7 +921,8 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
// horizontal
gGaussianProgram.uniform2f(direction, 1.f, 0.f);
gGL.getTexUnit(diffuseChannel)->bind(screen_rt);
- mRenderTarget.bindTarget();
+ mRenderTarget.bindTarget("", 1);
+ mRenderTarget.clear(0);
gPipeline.mScreenTriangleVB->setBuffer();
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
mRenderTarget.flush();
@@ -837,7 +930,8 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
// vertical
gGaussianProgram.uniform2f(direction, 0.f, 1.f);
gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget);
- screen_rt->bindTarget();
+ screen_rt->bindTarget("", 1);
+ screen_rt->clear(0);
gPipeline.mScreenTriangleVB->setBuffer();
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
screen_rt->flush();
@@ -852,7 +946,10 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
for (int i = 0; i < mMipChain.size(); ++i)
{
LL_PROFILE_GPU_ZONE("probe mip");
- mMipChain[i].bindTarget();
+
+ mMipChain[i].bindTarget("probe face ", 0);
+ mMipChain[i].clear(0);
+
if (i == 0)
{
gGL.getTexUnit(diffuseChannel)->bind(screen_rt);
@@ -897,16 +994,127 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gReflectionMipProgram.unbind();
}
- if (face == 5)
+ if(progressive)
{
- mMipChain[0].bindTarget();
- static LLStaticHashedString sSourceIdx("sourceIdx");
+ if(isRadiancePass()) updateProbeRadianceOnFace(probe, face, sourceIdx);
+ }
- if (isRadiancePass())
+ // if(isRadiancePass()) updateProbeRadianceOnFace(probe, face, sourceIdx);
+ // else updateProbeIrradianceOnFace(probe, face, sourceIdx);
+}
+
+// ===================== IRRADIANCE ================================
+
+void LLReflectionMapManager::updateProbeIrradiance(LLReflectionMap* probe)
+{
+ LL_PROFILE_GPU_ZONE("probe irradiance gen");
+
+ static LLStaticHashedString sMipLevel("mipLevel");
+ static LLStaticHashedString sRoughness("roughness");
+ static LLStaticHashedString sWidth("u_width");
+
+ S32 sourceIdx = mReflectionProbeCount;
+
+ if (probe != mUpdatingProbe)
+ { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel
+ sourceIdx += 1;
+ }
+
+ gGL.setColorMask(true, false);
+ LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
+ LLGLDisable blend(GL_BLEND);
+
+ static LLStaticHashedString sSourceIdx("sourceIdx");
+
+ LL_WARNS() << "IRRADIANCE 1" << LL_ENDL;
+
+ mMipChain[0].bindTarget("irradiance", 0);
+ mMipChain[0].clear(0);
+
+ gIrradianceGenProgram.bind();
+
+#if GL_VERSION_4_0
+ S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
+ mTexture->bind(channel);
+#endif
+
+ 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)
{
- //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map)
- gRadianceGenProgram.bind();
- mVertexBuffer->setBuffer();
+ break;
+ }
+ }
+
+ 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)
+ {
+ 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();
+#if GL_VERSION_4_0
+ 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);
+#endif
+ //mMipChain[0].clear(0);
+ }
+
+ mMipChain[0].flush();
+ gIrradianceGenProgram.unbind();
+}
+
+// ==================== RADIANCE ===========================
+
+void LLReflectionMapManager::updateProbeRadiance(LLReflectionMap* probe)
+{
+ LL_PROFILE_GPU_ZONE("probe radiance gen");
+ static LLStaticHashedString sMipLevel("mipLevel");
+ static LLStaticHashedString sRoughness("roughness");
+ static LLStaticHashedString sWidth("u_width");
+
+ S32 sourceIdx = mReflectionProbeCount;
+
+ if (probe != mUpdatingProbe)
+ { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel
+ sourceIdx += 1;
+ }
+
+ gGL.setColorMask(true, false);
+ LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
+ LLGLDisable blend(GL_BLEND);
+
+ static LLStaticHashedString sSourceIdx("sourceIdx");
+
+ LL_WARNS() << "RADIANCE" << LL_ENDL;
+ //LL_RECORD_BLOCK_TIME(FTM_RENDER_RADIANCE);
+
+ mMipChain[0].bindTarget("radiance", 0);
+ mMipChain[0].clear();
+
+ gRadianceGenProgram.bind();
+ mVertexBuffer->setBuffer();
#if GL_VERSION_4_0
S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
@@ -915,22 +1123,19 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, 1.f);
+ gRadianceGenProgram.uniform1i(sWidth, mProbeResolution);
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");
+ glViewport(0, 0, res, res);
- gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1));
gRadianceGenProgram.uniform1f(sMipLevel, (GLfloat)i);
- gRadianceGenProgram.uniform1i(sWidth, mProbeResolution);
+ gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1));
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]);
@@ -943,21 +1148,44 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
#if GL_VERSION_4_0
glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res);
#endif
+ LOG_GLERROR("glCopyTexSubImage3D");
}
if (i != mMipChain.size() - 1)
{
res /= 2;
- glViewport(0, 0, res, res);
}
- }
+ }
gRadianceGenProgram.unbind();
- }
- else
- {
- //generate irradiance map
+ mMipChain[0].flush();
+ //mTexture->unbind();
+}
+
+// ================== PER FACE =======================
+
+void LLReflectionMapManager::updateProbeIrradianceOnFace(LLReflectionMap* probe, U32 face, S32 sourceIdx)
+{
+ LL_PROFILE_GPU_ZONE("probe irradiance gen");
+
+ static LLStaticHashedString sMipLevel("mipLevel");
+ static LLStaticHashedString sRoughness("roughness");
+ static LLStaticHashedString sWidth("u_width");
+
+ gGL.setColorMask(true, false);
+ LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
+ LLGLDisable blend(GL_BLEND);
+
+ static LLStaticHashedString sSourceIdx("sourceIdx");
+
+ //LL_WARNS() << "IRRADIANCE" << LL_ENDL;
+
+ mMipChain[0].bindTarget("irradiance", 0);
+ //mMipChain[0].clear();
+
gIrradianceGenProgram.bind();
+
#if GL_VERSION_4_0
S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
mTexture->bind(channel);
@@ -977,13 +1205,11 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
}
}
- //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
+
+ int cf = face;
+ {
LLCoordFrame frame;
frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]);
@@ -993,20 +1219,81 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4);
- S32 res = mMipChain[i].getWidth();
#if GL_VERSION_4_0
+ 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);
#endif
- }
}
- }
mMipChain[0].flush();
gIrradianceGenProgram.unbind();
+ mTexture->unbind();
+}
+
+void LLReflectionMapManager::updateProbeRadianceOnFace(LLReflectionMap* probe, U32 face, S32 sourceIdx)
+{
+ LL_PROFILE_GPU_ZONE("probe radiance gen");
+ static LLStaticHashedString sMipLevel("mipLevel");
+ static LLStaticHashedString sRoughness("roughness");
+ static LLStaticHashedString sWidth("u_width");
+
+ gGL.setColorMask(true, false);
+ LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
+ LLGLDisable blend(GL_BLEND);
+
+ static LLStaticHashedString sSourceIdx("sourceIdx");
+
+ mMipChain[0].bindTarget("radiance", 0);
+ mMipChain[0].clear(0);
+
+ gRadianceGenProgram.bind();
+ mVertexBuffer->setBuffer();
+
+ S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
+ mTexture->bind(channel);
+
+ gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
+ gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
+ gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, 1.f);
+ gRadianceGenProgram.uniform1i(sWidth, mProbeResolution);
+
+ U32 res = mMipChain[0].getWidth();
+
+ for (int i = 0; i < mMipChain.size(); ++i)
+ {
+ glViewport(0, 0, res, res);
+
+ gRadianceGenProgram.uniform1f(sMipLevel, (GLfloat)i);
+ gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1));
+
+ int cf = 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);
+ LOG_GLERROR("glCopyTexSubImage3D");
+ //mMipChain[0].clear(0);
+ }
+
+ if (i != mMipChain.size() - 1)
+ {
+ res /= 2;
+ }
}
+
+ gRadianceGenProgram.unbind();
+ mMipChain[0].flush();
+ mTexture->unbind();
}
void LLReflectionMapManager::reset()
@@ -1426,8 +1713,13 @@ void LLReflectionMapManager::initReflectionMaps()
{
static LLCachedControl<U32> ref_probe_res(gSavedSettings, "RenderReflectionProbeResolution", 128U);
U32 probe_resolution = nhpo2(llclamp(ref_probe_res(), (U32)64, (U32)512));
- if (mTexture.isNull() || mReflectionProbeCount != mDynamicProbeCount || mProbeResolution != probe_resolution || mReset)
+
+ bool shouldInit = mTexture.isNull() || mReflectionProbeCount != mDynamicProbeCount || mProbeResolution != probe_resolution || mReset;
+
+ if (shouldInit)
{
+ //LL_WARNS() << "====== initReflectionMaps() =======" << LL_ENDL;
+
if(mProbeResolution != probe_resolution)
{
mRenderTarget.release();
@@ -1444,6 +1736,8 @@ void LLReflectionMapManager::initReflectionMaps()
mTexture->getWidth() != mProbeResolution ||
mReflectionProbeCount + 2 != mTexture->getCount())
{
+ static LLCachedControl<bool> render_hdr(gSavedSettings, "RenderHDREnabled", true);
+
if (mTexture)
{
mTexture = new LLCubeMapArray(*mTexture, mProbeResolution, mReflectionProbeCount + 2);
@@ -1454,8 +1748,6 @@ void LLReflectionMapManager::initReflectionMaps()
{
mTexture = new LLCubeMapArray();
- static LLCachedControl<bool> render_hdr(gSavedSettings, "RenderHDREnabled", true);
-
// 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, true, render_hdr);
@@ -1477,7 +1769,9 @@ void LLReflectionMapManager::initReflectionMaps()
for (auto& probe : mProbes)
{
probe->mLastUpdateTime = 0.f;
+ probe->mNextUpdateTime = 0.f;
probe->mComplete = false;
+ probe->mCompletedCount = 0;
probe->mProbeIndex = -1;
probe->mCubeArray = nullptr;
probe->mCubeIndex = -1;
@@ -1503,8 +1797,13 @@ void LLReflectionMapManager::initReflectionMaps()
mDefaultProbe->mRadius = 4096.f;
mDefaultProbe->mProbeIndex = 0;
mDefaultProbe->mComplete = default_complete;
+ mDefaultProbe->mCompletedCount = 0;
+ mDefaultProbe->mLastUpdateTime = 0.f;
+ mDefaultProbe->mNextUpdateTime = 0.f;
touch_default_probe(mDefaultProbe);
+
+ LL_WARNS() << "====== END initReflectionMaps() =======" << LL_ENDL;
}
if (mVertexBuffer.isNull())