summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2022-06-10 01:13:41 -0500
committerDave Parks <davep@lindenlab.com>2022-06-10 01:13:41 -0500
commit509476f95ed75ce8289ecd69b4c94d9912e1d3df (patch)
treefe24ef1046fef41e9e9c5ca8a8c9ef8fdc79bfe3
parent03d85bfb33f53e658256d8bedcf0b4262226cf90 (diff)
SL-17574 Add probe detail combo box to advanced graphics preferences. Fix spot light shadows not working in probes.
-rw-r--r--indra/llrender/llrendertarget.cpp4
-rw-r--r--indra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl13
-rw-r--r--indra/newview/llpanelvolume.cpp6
-rw-r--r--indra/newview/llreflectionmap.cpp26
-rw-r--r--indra/newview/llreflectionmap.h8
-rw-r--r--indra/newview/llreflectionmapmanager.cpp63
-rw-r--r--indra/newview/llreflectionmapmanager.h11
-rw-r--r--indra/newview/llspatialpartition.cpp17
-rw-r--r--indra/newview/llspatialpartition.h3
-rw-r--r--indra/newview/llviewercamera.h13
-rw-r--r--indra/newview/pipeline.cpp387
-rw-r--r--indra/newview/pipeline.h16
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml38
14 files changed, 350 insertions, 266 deletions
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 85d6209964..fa46e0f7d0 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -473,6 +473,8 @@ void LLRenderTarget::release()
void LLRenderTarget::bindTarget()
{
+ llassert(mFBO);
+
if (mFBO)
{
stop_glerror();
@@ -514,6 +516,7 @@ void LLRenderTarget::bindTarget()
void LLRenderTarget::clear(U32 mask_in)
{
LL_PROFILE_GPU_ZONE("clear");
+ llassert(mFBO);
U32 mask = GL_COLOR_BUFFER_BIT;
if (mUseDepth)
{
@@ -579,6 +582,7 @@ void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilt
void LLRenderTarget::flush(bool fetch_depth)
{
gGL.flush();
+ llassert(mFBO);
if (!mFBO)
{
gGL.getTexUnit(0)->bind(this);
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 327dfe6955..35a79f12de 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10280,6 +10280,17 @@
<key>Value</key>
<integer>2</integer>
</map>
+ <key>RenderReflectionProbeDetail</key>
+ <map>
+ <key>Comment</key>
+ <string>Detail of reflections.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>RenderReflectionProbeDrawDistance</key>
<map>
diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
index 3fd001e7f5..b3396baeba 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
@@ -74,6 +74,8 @@ bool isAbove(vec3 pos, vec4 plane)
return (dot(plane.xyz, pos) + plane.w) > 0;
}
+int max_priority = 0;
+
// return true if probe at index i influences position pos
bool shouldSampleProbe(int i, vec3 pos)
{
@@ -86,6 +88,8 @@ bool shouldSampleProbe(int i, vec3 pos)
{
return false;
}
+
+ max_priority = max(max_priority, -refIndex[i].w);
}
else
{
@@ -98,6 +102,8 @@ bool shouldSampleProbe(int i, vec3 pos)
{ //outside bounding sphere
return false;
}
+
+ max_priority = max(max_priority, refIndex[i].w);
}
return true;
@@ -343,8 +349,13 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight)
for (int idx = 0; idx < probeInfluences; ++idx)
{
int i = probeIndex[idx];
+ if (refIndex[i].w < max_priority)
+ {
+ continue;
+ }
float r = refSphere[i].w; // radius of sphere volume
float p = float(abs(refIndex[i].w)); // priority
+
float rr = r*r; // radius squred
float r1 = r * 0.1; // 75% of radius (outer sphere to start interpolating down)
vec3 delta = pos.xyz-refSphere[i].xyz;
@@ -358,7 +369,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight)
float atten = 1.0-max(d2-r2, 0.0)/(rr-r2);
w *= atten;
- w *= p; // boost weight based on priority
+ //w *= p; // boost weight based on priority
col += refcol*w*max(minweight, refParams[i].x);
wsum += w;
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index ddce22fa20..956539cd98 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -152,8 +152,6 @@ BOOL LLPanelVolume::postBuild()
childSetCommitCallback("Probe Volume Type", onCommitProbe, this);
childSetCommitCallback("Probe Ambiance", onCommitProbe, this);
childSetCommitCallback("Probe Near Clip", onCommitProbe, this);
-
-
}
// PHYSICS Parameters
@@ -695,7 +693,7 @@ void LLPanelVolume::clearCtrls()
getChildView("Light Radius")->setEnabled(false);
getChildView("Light Falloff")->setEnabled(false);
- getChildView("Reflection Probe Checkbox Ctrl")->setEnabled(false);;
+ getChildView("Reflection Probe")->setEnabled(false);;
getChildView("Probe Volume Type")->setEnabled(false);
getChildView("Probe Dynamic")->setEnabled(false);
getChildView("Probe Ambiance")->setEnabled(false);
@@ -746,7 +744,7 @@ void LLPanelVolume::sendIsReflectionProbe()
}
LLVOVolume* volobjp = (LLVOVolume*)objectp;
- BOOL value = getChild<LLUICtrl>("Reflection Probe Checkbox Ctrl")->getValue();
+ BOOL value = getChild<LLUICtrl>("Reflection Probe")->getValue();
volobjp->setIsReflectionProbe(value);
LL_INFOS() << "update reflection probe sent" << LL_ENDL;
}
diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp
index 39e0841fc5..500485fc70 100644
--- a/indra/newview/llreflectionmap.cpp
+++ b/indra/newview/llreflectionmap.cpp
@@ -54,28 +54,6 @@ void LLReflectionMap::update(U32 resolution, U32 face)
gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip(), getIsDynamic());
}
-bool LLReflectionMap::shouldUpdate()
-{
- const F32 TIMEOUT_INTERVAL = 30.f; // update no less than this often
- const F32 RENDER_TIMEOUT = 1.f; // don't update if hasn't been used for rendering for this long
-
- if (mLastBindTime > gFrameTimeSeconds - RENDER_TIMEOUT)
- {
- if (mLastUpdateTime < gFrameTimeSeconds - TIMEOUT_INTERVAL)
- {
- return true;
- }
- }
-
- return false;
-}
-
-void LLReflectionMap::dirty()
-{
- mDirty = true;
- mLastUpdateTime = gFrameTimeSeconds;
-}
-
void LLReflectionMap::autoAdjustOrigin()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
@@ -245,7 +223,9 @@ F32 LLReflectionMap::getNearClip()
bool LLReflectionMap::getIsDynamic()
{
- if (mViewerObject && mViewerObject->getVolume())
+ if (gSavedSettings.getS32("RenderReflectionProbeDetail") > (S32) LLReflectionMapManager::DetailLevel::STATIC_ONLY &&
+ mViewerObject &&
+ mViewerObject->getVolume())
{
return ((LLVOVolume*)mViewerObject)->getReflectionProbeIsDynamic();
}
diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h
index 071568e53c..cf0bc2ff27 100644
--- a/indra/newview/llreflectionmap.h
+++ b/indra/newview/llreflectionmap.h
@@ -43,12 +43,6 @@ public:
// resolution - size of cube map to generate
void update(U32 resolution, U32 face);
- // return true if this probe should update *now*
- bool shouldUpdate();
-
- // Mark this reflection map as needing an update (resets last update time, so spamming this call will cause a cube map to never update)
- void dirty();
-
// for volume partition probes, try to place this probe in the best spot
void autoAdjustOrigin();
@@ -104,7 +98,5 @@ public:
// what priority should this probe have (higher is higher priority)
U32 mPriority = 1;
-
- bool mDirty = true;
};
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index 60396b6c60..dc733687c3 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -96,11 +96,13 @@ void LLReflectionMapManager::update()
mRenderTarget.allocate(targetRes, targetRes, color_fmt, use_depth_buffer, use_stencil_buffer, LLTexUnit::TT_RECT_TEXTURE);
// hack to allocate render targets using gPipeline code
+ gCubeSnapshot = TRUE;
auto* old_rt = gPipeline.mRT;
gPipeline.mRT = &gProbeRT;
gPipeline.allocateScreenBuffer(targetRes, targetRes);
gPipeline.allocateShadowBuffer(targetRes, targetRes);
gPipeline.mRT = old_rt;
+ gCubeSnapshot = FALSE;
}
if (mMipChain.empty())
@@ -154,6 +156,10 @@ void LLReflectionMapManager::update()
bool did_update = false;
+ bool realtime = gSavedSettings.getS32("RenderReflectionProbeDetail") >= (S32)LLReflectionMapManager::DetailLevel::REALTIME;
+
+ LLReflectionMap* closestDynamic = nullptr;
+
LLReflectionMap* oldestProbe = nullptr;
if (mUpdatingProbe != nullptr)
@@ -183,11 +189,30 @@ void LLReflectionMapManager::update()
oldestProbe = probe;
}
+ if (realtime &&
+ closestDynamic == nullptr &&
+ probe->mCubeArray.notNull() &&
+ probe->getIsDynamic())
+ {
+ closestDynamic = probe;
+ }
+
d.setSub(camera_pos, probe->mOrigin);
probe->mDistance = d.getLength3().getF32()-probe->mRadius;
}
-#if 1
+ if (realtime && closestDynamic != nullptr)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime");
+ // update the closest dynamic probe realtime
+ closestDynamic->autoAdjustOrigin();
+ for (U32 i = 0; i < 6; ++i)
+ {
+ updateProbeFace(closestDynamic, i);
+ }
+ }
+
+ // switch to updating the next oldest probe
if (!did_update && oldestProbe != nullptr)
{
LLReflectionMap* probe = oldestProbe;
@@ -201,9 +226,7 @@ void LLReflectionMapManager::update()
mUpdatingProbe = probe;
doProbeUpdate();
- probe->mDirty = false;
}
-#endif
// update distance to camera for all probes
std::sort(mProbes.begin(), mProbes.end(), CompareProbeDistance());
@@ -214,7 +237,6 @@ LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group)
LLReflectionMap* probe = new LLReflectionMap();
probe->mGroup = group;
probe->mOrigin = group->getOctreeNode()->getCenter();
- probe->mDirty = true;
if (gCubeSnapshot)
{ //snapshot is in progress, mProbes is being iterated over, defer insertion until next update
@@ -295,7 +317,6 @@ LLReflectionMap* LLReflectionMapManager::registerViewerObject(LLViewerObject* vo
LLReflectionMap* probe = new LLReflectionMap();
probe->mViewerObject = vobj;
probe->mOrigin.load3(vobj->getPositionAgent().mV);
- probe->mDirty = true;
if (gCubeSnapshot)
{ //snapshot is in progress, mProbes is being iterated over, defer insertion until next update
@@ -368,10 +389,23 @@ void LLReflectionMapManager::doProbeUpdate()
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
llassert(mUpdatingProbe != nullptr);
+ updateProbeFace(mUpdatingProbe, mUpdatingFace);
+
+ if (++mUpdatingFace == 6)
+ {
+ updateNeighbors(mUpdatingProbe);
+ mUpdatingProbe = nullptr;
+ mUpdatingFace = 0;
+ }
+}
+
+void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
+{
mRenderTarget.bindTarget();
+ // hacky hot-swap of camera specific render targets
auto* old_rt = gPipeline.mRT;
gPipeline.mRT = &gProbeRT;
- mUpdatingProbe->update(mRenderTarget.getWidth(), mUpdatingFace);
+ probe->update(mRenderTarget.getWidth(), face);
gPipeline.mRT = old_rt;
mRenderTarget.flush();
@@ -390,9 +424,9 @@ void LLReflectionMapManager::doProbeUpdate()
gGL.loadIdentity();
gGL.flush();
- U32 res = LL_REFLECTION_PROBE_RESOLUTION*2;
+ U32 res = LL_REFLECTION_PROBE_RESOLUTION * 2;
- S32 mips = log2((F32) LL_REFLECTION_PROBE_RESOLUTION)+0.5f;
+ S32 mips = log2((F32)LL_REFLECTION_PROBE_RESOLUTION) + 0.5f;
for (int i = 0; i < mMipChain.size(); ++i)
{
@@ -409,10 +443,10 @@ void LLReflectionMapManager::doProbeUpdate()
}
gGL.begin(gGL.QUADS);
-
+
gGL.texCoord2f(0, 0);
gGL.vertex2f(-1, -1);
-
+
gGL.texCoord2f(res, 0);
gGL.vertex2f(1, -1);
@@ -431,7 +465,7 @@ void LLReflectionMapManager::doProbeUpdate()
if (mip >= 0)
{
mTexture->bind(0);
- glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, mUpdatingProbe->mCubeIndex * 6 + mUpdatingFace, 0, 0, res, res);
+ glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res);
mTexture->unbind();
}
mMipChain[i].flush();
@@ -443,13 +477,6 @@ void LLReflectionMapManager::doProbeUpdate()
gReflectionMipProgram.unbind();
}
-
- if (++mUpdatingFace == 6)
- {
- updateNeighbors(mUpdatingProbe);
- mUpdatingProbe = nullptr;
- mUpdatingFace = 0;
- }
}
void LLReflectionMapManager::rebuild()
diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h
index bf963f3486..3b5cdc5520 100644
--- a/indra/newview/llreflectionmapmanager.h
+++ b/indra/newview/llreflectionmapmanager.h
@@ -46,6 +46,13 @@ class alignas(16) LLReflectionMapManager
{
LL_ALIGN_NEW
public:
+ enum class DetailLevel
+ {
+ STATIC_ONLY = 0,
+ STATIC_AND_DYNAMIC,
+ REALTIME = 2
+ };
+
// allocate an environment map of the given resolution
LLReflectionMapManager();
@@ -115,6 +122,9 @@ private:
// perform an update on the currently updating Probe
void doProbeUpdate();
+
+ // update the specified face of the specified probe
+ void updateProbeFace(LLReflectionMap* probe, U32 face);
// list of active reflection maps
std::vector<LLPointer<LLReflectionMap> > mProbes;
@@ -133,6 +143,5 @@ private:
LLReflectionMap* mUpdatingProbe = nullptr;
U32 mUpdatingFace = 0;
-
};
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index a9e807e0f6..f445bc98eb 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -738,17 +738,8 @@ BOOL LLSpatialGroup::changeLOD()
return FALSE;
}
-void LLSpatialGroup::dirtyReflectionProbe()
-{
- if (mReflectionProbe != nullptr)
- {
- mReflectionProbe->dirty();
- }
-}
-
void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* entry)
{
- dirtyReflectionProbe();
addObject((LLDrawable*)entry->getDrawable());
unbound();
setState(OBJECT_DIRTY);
@@ -756,7 +747,6 @@ void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry*
void LLSpatialGroup::handleRemoval(const TreeNode* node, LLViewerOctreeEntry* entry)
{
- dirtyReflectionProbe();
removeObject((LLDrawable*)entry->getDrawable(), TRUE);
LLViewerOctreeGroup::handleRemoval(node, entry);
}
@@ -793,8 +783,6 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL
- dirtyReflectionProbe();
-
if (child->getListenerCount() == 0)
{
new LLSpatialGroup(child, getSpatialPartition());
@@ -809,11 +797,6 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c
assert_states_valid(this);
}
-void LLSpatialGroup::handleChildRemoval(const oct_node* parent, const oct_node* child)
-{
- dirtyReflectionProbe();
-}
-
void LLSpatialGroup::destroyGL(bool keep_occlusion)
{
setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY);
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index bebd8aec85..07d62be7af 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -333,7 +333,6 @@ public:
virtual void handleRemoval(const TreeNode* node, LLViewerOctreeEntry* face);
virtual void handleDestruction(const TreeNode* node);
virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
- virtual void handleChildRemoval(const oct_node* parent, const oct_node* child);
public:
LL_ALIGN_16(LLVector4a mViewAngle);
@@ -341,8 +340,6 @@ public:
F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3()
- void dirtyReflectionProbe();
-
protected:
virtual ~LLSpatialGroup();
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index 549778a841..b5841772ed 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -47,15 +47,14 @@ public:
typedef enum
{
CAMERA_WORLD = 0,
- CAMERA_SHADOW0,
- CAMERA_SHADOW1,
- CAMERA_SHADOW2,
- CAMERA_SHADOW3,
- CAMERA_SHADOW4,
- CAMERA_SHADOW5,
+ CAMERA_SUN_SHADOW0,
+ CAMERA_SUN_SHADOW1,
+ CAMERA_SUN_SHADOW2,
+ CAMERA_SUN_SHADOW3,
+ CAMERA_SPOT_SHADOW0,
+ CAMERA_SPOT_SHADOW1,
CAMERA_WATER0,
CAMERA_WATER1,
- CAMERA_GI_SOURCE,
NUM_CAMERAS
} eCameraID;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 28dc3781ba..8bac5131cf 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -739,7 +739,8 @@ void LLPipeline::requestResizeShadowTexture()
void LLPipeline::resizeShadowTexture()
{
- releaseShadowTargets();
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
allocateShadowBuffer(mRT->width, mRT->height);
gResizeShadowTexture = FALSE;
}
@@ -754,7 +755,8 @@ void LLPipeline::resizeScreenTexture()
if (gResizeScreenTexture || (resX != mRT->screen.getWidth()) || (resY != mRT->screen.getHeight()))
{
releaseScreenBuffers();
- releaseShadowTargets();
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
allocateScreenBuffer(resX,resY);
gResizeScreenTexture = FALSE;
}
@@ -913,7 +915,8 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
{
mRT->deferredLight.release();
- releaseShadowTargets();
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
mRT->fxaaBuffer.release();
mRT->screen.release();
@@ -942,66 +945,66 @@ inline U32 BlurHappySize(U32 x, F32 scale) { return U32( x * scale + 16.0f) & ~0
bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
- if (LLPipeline::sRenderDeferred)
- {
- S32 shadow_detail = RenderShadowDetail;
+ if (LLPipeline::sRenderDeferred)
+ {
+ S32 shadow_detail = RenderShadowDetail;
- const U32 occlusion_divisor = 3;
+ const U32 occlusion_divisor = 3;
- F32 scale = llmax(0.f,RenderShadowResolutionScale);
- U32 sun_shadow_map_width = BlurHappySize(resX, scale);
- U32 sun_shadow_map_height = BlurHappySize(resY, scale);
+ F32 scale = llmax(0.f, RenderShadowResolutionScale);
+ U32 sun_shadow_map_width = BlurHappySize(resX, scale);
+ U32 sun_shadow_map_height = BlurHappySize(resY, scale);
- if (shadow_detail > 0)
- { //allocate 4 sun shadow maps
- for (U32 i = 0; i < 4; i++)
- {
- if (!mRT->shadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
+ if (shadow_detail > 0)
+ { //allocate 4 sun shadow maps
+ for (U32 i = 0; i < 4; i++)
+ {
+ if (!mRT->shadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
{
return false;
}
- if (!mRT->shadowOcclusion[i].allocate(sun_shadow_map_width/occlusion_divisor, sun_shadow_map_height/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
+ if (!mRT->shadowOcclusion[i].allocate(sun_shadow_map_width / occlusion_divisor, sun_shadow_map_height / occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
{
return false;
}
- }
- }
- else
- {
- for (U32 i = 0; i < 4; i++)
- {
- releaseShadowTarget(i);
- }
- }
+ }
+ }
+ else
+ {
+ for (U32 i = 0; i < 4; i++)
+ {
+ releaseSunShadowTarget(i);
+ }
+ }
- U32 width = (U32) (resX*scale);
- U32 height = width;
+ if (!gCubeSnapshot) // hack to not allocate spot shadow maps during ReflectionMapManager init
+ {
+ U32 width = (U32)(resX * scale);
+ U32 height = width;
- if (shadow_detail > 1)
- { //allocate two spot shadow maps
- U32 spot_shadow_map_width = width;
- U32 spot_shadow_map_height = height;
- for (U32 i = 4; i < 6; i++)
- {
- if (!mRT->shadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, TRUE, FALSE))
- {
- return false;
- }
- if (!mRT->shadowOcclusion[i].allocate(spot_shadow_map_width/occlusion_divisor, height/occlusion_divisor, 0, TRUE, FALSE))
- {
- return false;
- }
- }
+ if (shadow_detail > 1)
+ { //allocate two spot shadow maps
+ U32 spot_shadow_map_width = width;
+ U32 spot_shadow_map_height = height;
+ for (U32 i = 0; i < 2; i++)
+ {
+ if (!mSpotShadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, TRUE, FALSE))
+ {
+ return false;
+ }
+ if (!mSpotShadowOcclusion[i].allocate(spot_shadow_map_width / occlusion_divisor, height / occlusion_divisor, 0, TRUE, FALSE))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ releaseSpotShadowTargets();
+ }
}
- else
- {
- for (U32 i = 4; i < 6; i++)
- {
- releaseShadowTarget(i);
- }
- }
- }
+ }
return true;
}
@@ -1175,7 +1178,8 @@ void LLPipeline::releaseLUTBuffers()
void LLPipeline::releaseShadowBuffers()
{
- releaseShadowTargets();
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
}
void LLPipeline::releaseScreenBuffers()
@@ -1191,20 +1195,33 @@ void LLPipeline::releaseScreenBuffers()
}
-void LLPipeline::releaseShadowTarget(U32 index)
+void LLPipeline::releaseSunShadowTarget(U32 index)
{
+ llassert(index < 4);
mRT->shadow[index].release();
mRT->shadowOcclusion[index].release();
}
-void LLPipeline::releaseShadowTargets()
+void LLPipeline::releaseSunShadowTargets()
{
- for (U32 i = 0; i < 6; i++)
+ for (U32 i = 0; i < 4; i++)
{
- releaseShadowTarget(i);
+ releaseSunShadowTarget(i);
}
}
+void LLPipeline::releaseSpotShadowTargets()
+{
+ if (!gCubeSnapshot) // hack to avoid freeing spot shadows during ReflectionMapManager init
+ {
+ for (U32 i = 0; i < 2; i++)
+ {
+ mSpotShadow[i].release();
+ mSpotShadowOcclusion[i].release();
+ }
+ }
+}
+
void LLPipeline::createGLBuffers()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
@@ -8162,7 +8179,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
for (U32 i = 0; i < 4; i++)
{
- LLRenderTarget* shadow_target = getShadowTarget(i);
+ LLRenderTarget* shadow_target = getSunShadowTarget(i);
if (shadow_target)
{
channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_TEXTURE);
@@ -8170,7 +8187,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
if (channel > -1)
{
stop_glerror();
- gGL.getTexUnit(channel)->bind(getShadowTarget(i), TRUE);
+ gGL.getTexUnit(channel)->bind(getSunShadowTarget(i), TRUE);
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
stop_glerror();
@@ -8182,27 +8199,27 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
}
}
- for (U32 i = 4; i < 6; i++)
- {
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i);
- stop_glerror();
- if (channel > -1)
- {
- stop_glerror();
- LLRenderTarget* shadow_target = getShadowTarget(i);
- if (shadow_target)
- {
- gGL.getTexUnit(channel)->bind(shadow_target, TRUE);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
- gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
- stop_glerror();
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
- stop_glerror();
- }
- }
- }
+ for (U32 i = 4; i < 6; i++)
+ {
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0 + i);
+ stop_glerror();
+ if (channel > -1)
+ {
+ stop_glerror();
+ LLRenderTarget* shadow_target = getSpotShadowTarget(i-4);
+ if (shadow_target)
+ {
+ gGL.getTexUnit(channel)->bind(shadow_target, TRUE);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+ gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+ stop_glerror();
+ }
+ }
+ }
stop_glerror();
@@ -8313,7 +8330,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV);
shader.uniform3fv(LLShaderMgr::DEFERRED_MOON_DIR, 1, mTransformedMoonDir.mV);
shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mRT->shadow[0].getWidth(), mRT->shadow[0].getHeight());
- shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mRT->shadow[4].getWidth(), mRT->shadow[4].getHeight());
+ shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mSpotShadow[0].getWidth(), mSpotShadow[0].getHeight());
shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff);
shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff);
@@ -9077,7 +9094,7 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f);
}
- if (!gCubeSnapshot)
+ //if (!gCubeSnapshot)
{
LLDrawable* potential = drawablep;
//determine if this is a good light for casting shadows
@@ -9668,7 +9685,9 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
gDeferredShadowCubeProgram.bind();
}
- LLRenderTarget& occlusion_target = mRT->shadowOcclusion[LLViewerCamera::sCurCameraID - 1];
+ LLRenderTarget& occlusion_target = LLViewerCamera::sCurCameraID >= LLViewerCamera::CAMERA_SPOT_SHADOW0 ?
+ mSpotShadowOcclusion[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SPOT_SHADOW0] :
+ mRT->shadowOcclusion[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SUN_SHADOW0];
occlusion_target.bindTarget();
updateCull(shadow_cam, result);
@@ -9812,7 +9831,9 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
gGLLastMatrix = NULL;
gGL.loadMatrix(gGLModelView);
- LLRenderTarget& occlusion_source = mRT->shadow[LLViewerCamera::sCurCameraID - 1];
+ LLRenderTarget& occlusion_source = LLViewerCamera::sCurCameraID >= LLViewerCamera::CAMERA_SPOT_SHADOW0 ?
+ mSpotShadow[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SPOT_SHADOW0] :
+ mRT->shadow[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SUN_SHADOW0];
if (occlude > 1)
{
@@ -10087,11 +10108,18 @@ void LLPipeline::generateHighlight(LLCamera& camera)
}
}
-LLRenderTarget* LLPipeline::getShadowTarget(U32 i)
+LLRenderTarget* LLPipeline::getSunShadowTarget(U32 i)
{
+ llassert(i < 4);
return &mRT->shadow[i];
}
+LLRenderTarget* LLPipeline::getSpotShadowTarget(U32 i)
+{
+ llassert(i < 2);
+ return &mSpotShadow[i];
+}
+
static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW("Gen Sun Shadow");
static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW_SPOT_RENDER("Spot Shadow Render");
@@ -10371,7 +10399,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
mShadowFrustPoints[j].clear();
}
- LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0+j);
+ LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SUN_SHADOW0+j);
//restore render matrices
set_current_modelview(saved_view);
@@ -10745,116 +10773,119 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
{
if (!gCubeSnapshot) //skip updating spot shadow maps during cubemap updates
{
- LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat();
- F32 fade_amt = gFrameIntervalSeconds.value()
- * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0);
-
- //update shadow targets
- for (U32 i = 0; i < 2; i++)
- { //for each current shadow
- LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW4+i);
-
- if (mShadowSpotLight[i].notNull() &&
- (mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
- mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
- { //keep this spotlight
- mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f);
- }
- else
- { //fade out this light
- mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f);
-
- if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
- { //faded out, grab one of the pending spots (whichever one isn't already taken)
- if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2])
- {
- mShadowSpotLight[i] = mTargetShadowSpotLight[0];
- }
- else
- {
- mShadowSpotLight[i] = mTargetShadowSpotLight[1];
- }
- }
- }
- }
-
- for (S32 i = 0; i < 2; i++)
- {
- set_current_modelview(saved_view);
- set_current_projection(saved_proj);
+ LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat();
+ F32 fade_amt = gFrameIntervalSeconds.value()
+ * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0);
+
+ //update shadow targets
+ for (U32 i = 0; i < 2; i++)
+ { //for each current shadow
+ LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SPOT_SHADOW0 + i);
+
+ if (mShadowSpotLight[i].notNull() &&
+ (mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
+ mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
+ { //keep this spotlight
+ mSpotLightFade[i] = llmin(mSpotLightFade[i] + fade_amt, 1.f);
+ }
+ else
+ { //fade out this light
+ mSpotLightFade[i] = llmax(mSpotLightFade[i] - fade_amt, 0.f);
- if (mShadowSpotLight[i].isNull())
- {
- continue;
+ if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
+ { //faded out, grab one of the pending spots (whichever one isn't already taken)
+ if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i + 1) % 2])
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[0];
+ }
+ else
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[1];
+ }
+ }
}
+ }
+ }
- LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
+ for (S32 i = 0; i < 2; i++)
+ {
+ set_current_modelview(saved_view);
+ set_current_projection(saved_proj);
- if (!volume)
- {
- mShadowSpotLight[i] = NULL;
- continue;
- }
+ if (mShadowSpotLight[i].isNull())
+ {
+ continue;
+ }
- LLDrawable* drawable = mShadowSpotLight[i];
+ LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
- LLVector3 params = volume->getSpotLightParams();
- F32 fov = params.mV[0];
+ if (!volume)
+ {
+ mShadowSpotLight[i] = NULL;
+ continue;
+ }
- //get agent->light space matrix (modelview)
- LLVector3 center = drawable->getPositionAgent();
- LLQuaternion quat = volume->getRenderRotation();
+ LLDrawable* drawable = mShadowSpotLight[i];
- //get near clip plane
- LLVector3 scale = volume->getScale();
- LLVector3 at_axis(0, 0, -scale.mV[2] * 0.5f);
- at_axis *= quat;
+ LLVector3 params = volume->getSpotLightParams();
+ F32 fov = params.mV[0];
- LLVector3 np = center + at_axis;
- at_axis.normVec();
+ //get agent->light space matrix (modelview)
+ LLVector3 center = drawable->getPositionAgent();
+ LLQuaternion quat = volume->getRenderRotation();
- //get origin that has given fov for plane np, at_axis, and given scale
- F32 dist = (scale.mV[1] * 0.5f) / tanf(fov * 0.5f);
+ //get near clip plane
+ LLVector3 scale = volume->getScale();
+ LLVector3 at_axis(0, 0, -scale.mV[2] * 0.5f);
+ at_axis *= quat;
- LLVector3 origin = np - at_axis * dist;
+ LLVector3 np = center + at_axis;
+ at_axis.normVec();
- LLMatrix4 mat(quat, LLVector4(origin, 1.f));
+ //get origin that has given fov for plane np, at_axis, and given scale
+ F32 dist = (scale.mV[1] * 0.5f) / tanf(fov * 0.5f);
- view[i + 4] = glh::matrix4f((F32*)mat.mMatrix);
+ LLVector3 origin = np - at_axis * dist;
- view[i + 4] = view[i + 4].inverse();
+ LLMatrix4 mat(quat, LLVector4(origin, 1.f));
- //get perspective matrix
- F32 near_clip = dist + 0.01f;
- F32 width = scale.mV[VX];
- F32 height = scale.mV[VY];
- F32 far_clip = dist + volume->getLightRadius() * 1.5f;
+ view[i + 4] = glh::matrix4f((F32*)mat.mMatrix);
- F32 fovy = fov * RAD_TO_DEG;
- F32 aspect = width / height;
+ view[i + 4] = view[i + 4].inverse();
- proj[i + 4] = gl_perspective(fovy, aspect, near_clip, far_clip);
+ //get perspective matrix
+ F32 near_clip = dist + 0.01f;
+ F32 width = scale.mV[VX];
+ F32 height = scale.mV[VY];
+ F32 far_clip = dist + volume->getLightRadius() * 1.5f;
- //translate and scale to from [-1, 1] to [0, 1]
- glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
- 0.f, 0.5f, 0.f, 0.5f,
- 0.f, 0.f, 0.5f, 0.5f,
- 0.f, 0.f, 0.f, 1.f);
+ F32 fovy = fov * RAD_TO_DEG;
+ F32 aspect = width / height;
- set_current_modelview(view[i + 4]);
- set_current_projection(proj[i + 4]);
+ proj[i + 4] = gl_perspective(fovy, aspect, near_clip, far_clip);
- mSunShadowMatrix[i + 4] = trans * proj[i + 4] * view[i + 4] * inv_view;
+ //translate and scale to from [-1, 1] to [0, 1]
+ glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
- for (U32 j = 0; j < 16; j++)
- {
- gGLLastModelView[j] = mShadowModelview[i + 4].m[j];
- gGLLastProjection[j] = mShadowProjection[i + 4].m[j];
- }
+ set_current_modelview(view[i + 4]);
+ set_current_projection(proj[i + 4]);
- mShadowModelview[i + 4] = view[i + 4];
- mShadowProjection[i + 4] = proj[i + 4];
+ mSunShadowMatrix[i + 4] = trans * proj[i + 4] * view[i + 4] * inv_view;
+ for (U32 j = 0; j < 16; j++)
+ {
+ gGLLastModelView[j] = mShadowModelview[i + 4].m[j];
+ gGLLastProjection[j] = mShadowProjection[i + 4].m[j];
+ }
+
+ mShadowModelview[i + 4] = view[i + 4];
+ mShadowProjection[i + 4] = proj[i + 4];
+
+ if (!gCubeSnapshot) //skip updating spot shadow maps during cubemap updates
+ {
LLCamera shadow_cam = camera;
shadow_cam.setFar(far_clip);
shadow_cam.setOrigin(origin);
@@ -10863,15 +10894,17 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
stop_glerror();
- mRT->shadow[i + 4].bindTarget();
- mRT->shadow[i + 4].getViewport(gGLViewport);
- mRT->shadow[i + 4].clear();
+ //
+
+ mSpotShadow[i].bindTarget();
+ mSpotShadow[i].getViewport(gGLViewport);
+ mSpotShadow[i].clear();
- U32 target_width = mRT->shadow[i + 4].getWidth();
+ U32 target_width = mSpotShadow[i].getWidth();
static LLCullResult result[2];
- LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0 + i + 4);
+ LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SPOT_SHADOW0 + i);
RenderSpotLight = drawable;
@@ -10879,7 +10912,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
RenderSpotLight = nullptr;
- mRT->shadow[i + 4].flush();
+ mSpotShadow[i].flush();
}
}
}
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index f4c55bde7d..f05b7aec8e 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -218,8 +218,9 @@ public:
U32 addObject(LLViewerObject *obj);
void enableShadows(const bool enable_shadows);
- void releaseShadowTargets();
- void releaseShadowTarget(U32 index);
+ void releaseSpotShadowTargets();
+ void releaseSunShadowTargets();
+ void releaseSunShadowTarget(U32 index);
// void setLocalLighting(const bool local_lighting);
// bool isLocalLightingEnabled() const;
@@ -304,7 +305,8 @@ public:
void generateWaterReflection(LLCamera& camera);
void generateSunShadow(LLCamera& camera);
- LLRenderTarget* getShadowTarget(U32 i);
+ LLRenderTarget* getSunShadowTarget(U32 i);
+ LLRenderTarget* getSpotShadowTarget(U32 i);
void generateHighlight(LLCamera& camera);
void renderHighlight(const LLViewerObject* obj, F32 fade);
@@ -660,12 +662,15 @@ public:
LLRenderTarget deferredLight;
//sun shadow map
- LLRenderTarget shadow[6];
- LLRenderTarget shadowOcclusion[6];
+ LLRenderTarget shadow[4];
+ LLRenderTarget shadowOcclusion[4];
};
RenderTargetPack* mRT;
+ LLRenderTarget mSpotShadow[2];
+ LLRenderTarget mSpotShadowOcclusion[2];
+
LLRenderTarget mHighlight;
LLRenderTarget mPhysicsDisplay;
@@ -688,6 +693,7 @@ public:
LLVector3 mShadowFrustOrigin[4];
LLCamera mShadowCamera[8];
LLVector3 mShadowExtents[4][2];
+ // TODO : separate Sun Shadow and Spot Shadow matrices
glh::matrix4f mSunShadowMatrix[6];
glh::matrix4f mShadowModelview[6];
glh::matrix4f mShadowProjection[6];
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index d1e167df64..8e12a01c6f 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -863,8 +863,42 @@
name="2"
value="2"/>
</combo_box>
-
-<!-- End of Advanced Settings block -->
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="480"
+ name="RenderReflectionDetailText"
+ text_readonly_color="LabelDisabledColor"
+ top_delta="16"
+ width="128">
+ Reflections:
+ </text>
+ <combo_box
+ control_name="RenderReflectionProbeDetail"
+ height="18"
+ layout="topleft"
+ left_delta="130"
+ top_delta="0"
+ name="ReflectionDetial"
+ width="150">
+ <combo_box.item
+ label="Static Only"
+ name="0"
+ value="0"/>
+ <combo_box.item
+ label="Static+Dynamic"
+ name="1"
+ value="1"/>
+ <combo_box.item
+ label="Realtime"
+ name="2"
+ value="2"/>
+ </combo_box>
+
+ <!-- End of Advanced Settings block -->
<view_border
bevel_style="in"
height="0"