Even more mirror fixes. (#1429)

#1271 Add support for mirrors that do not have avatars in them.  It does this based on if the probe is set to dynamic or not.

#1370 More optimization work to reduce GPU utilization.

#1058 - Removed sim feature flag that was overriding mirrors enabled flags

secondlife/viewer-private#128 - Locally cache the mirror probe

#679 Add additional options to the build floater for mirror probes, including descriptions.
master
Jonathan "Geenz" Goodman 2024-05-08 11:28:51 -07:00 committed by GitHub
parent 812e2cda54
commit ca5e89d741
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 91 additions and 55 deletions

View File

@ -75,6 +75,7 @@ RenderGLMultiThreadedTextures 1 0
RenderGLMultiThreadedMedia 1 1
RenderReflectionProbeResolution 1 128
RenderScreenSpaceReflections 1 1
RenderMirrors 1 1
//
@ -251,8 +252,8 @@ RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 1
RenderScreenSpaceReflections 1 0
RenderReflectionProbeLevel 1 3
RenderMirrors 1 0
RenderHeroProbeResolution 1 1024
RenderMirrors 1 1
RenderHeroProbeResolution 1 512
RenderHeroProbeDistance 1 8
RenderHeroProbeUpdateRate 1 2
RenderHeroProbeConservativeUpdateMultiplier 1 8
@ -287,7 +288,7 @@ RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 1
RenderScreenSpaceReflections 1 0
RenderReflectionProbeLevel 1 3
RenderMirrors 1 0
RenderMirrors 1 1
RenderHeroProbeResolution 1 1024
RenderHeroProbeDistance 1 16
RenderHeroProbeUpdateRate 1 1

View File

@ -74,6 +74,7 @@ RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 2
RenderScreenSpaceReflections 1 1
RenderReflectionProbeLevel 1 3
RenderMirrors 1 1
//
// Low Graphics Settings
@ -249,8 +250,8 @@ RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 1
RenderScreenSpaceReflections 1 0
RenderReflectionProbeLevel 1 1
RenderMirrors 1 0
RenderHeroProbeResolution 1 1024
RenderMirrors 1 1
RenderHeroProbeResolution 1 512
RenderHeroProbeDistance 1 8
RenderHeroProbeUpdateRate 1 2
RenderHeroProbeConservativeUpdateMultiplier 1 8
@ -285,8 +286,8 @@ RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 1
RenderScreenSpaceReflections 1 0
RenderReflectionProbeLevel 1 2
RenderMirrors 1 0
RenderHeroProbeResolution 1 1024
RenderMirrors 1 1
RenderHeroProbeResolution 1 512
RenderHeroProbeDistance 1 16
RenderHeroProbeUpdateRate 1 1
RenderHeroProbeConservativeUpdateMultiplier 1 4
@ -322,7 +323,7 @@ RenderReflectionProbeDetail 1 1
RenderScreenSpaceReflections 1 0
RenderReflectionProbeLevel 1 3
RenderMirrors 1 1
RenderHeroProbeResolution 1 2048
RenderHeroProbeResolution 1 1024
RenderHeroProbeDistance 1 16
RenderHeroProbeUpdateRate 1 1
RenderHeroProbeConservativeUpdateMultiplier 1 4

View File

@ -113,22 +113,40 @@ void LLHeroProbeManager::update()
LLVector4a probe_pos;
LLVector3 camera_pos = LLViewerCamera::instance().mOrigin;
F32 near_clip = 0.1f;
bool probe_present = false;
LLQuaternion cameraOrientation = LLViewerCamera::instance().getQuaternion();
LLVector3 cameraDirection = LLVector3::z_axis * cameraOrientation;
if (mHeroVOList.size() > 0)
{
// Find our nearest hero candidate.
float last_distance = 99999.f;
float camera_center_distance = 99999.f;
for (auto vo : mHeroVOList)
{
if (vo && !vo->isDead() && vo->mDrawable.notNull())
{
float distance = (LLViewerCamera::instance().getOrigin() - vo->getPositionAgent()).magVec();
if (distance < last_distance)
float center_distance = cameraDirection * (vo->getPositionAgent() - camera_pos);
if (distance > LLViewerCamera::instance().getFar())
continue;
LLVector4a center;
center.load3(vo->getPositionAgent().mV);
LLVector4a size;
size.load3(vo->getScale().mV);
bool visible = LLViewerCamera::instance().AABBInFrustum(center, size);
if (distance < last_distance && center_distance < camera_center_distance && visible)
{
mNearestHero = vo;
last_distance = distance;
}
probe_present = true;
mNearestHero = vo;
last_distance = distance;
camera_center_distance = center_distance;
}
}
else
{
@ -136,6 +154,10 @@ void LLHeroProbeManager::update()
}
}
// Don't even try to do anything if we didn't find a single mirror present.
if (!probe_present)
return;
if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull())
{
LLVector3 hero_pos = mNearestHero->getPositionAgent();
@ -152,14 +174,12 @@ void LLHeroProbeManager::update()
mCurrentClipPlane.setVec(hero_pos, face_normal);
mMirrorPosition = hero_pos;
mMirrorNormal = face_normal;
probe_pos.load3(point.mV);
// Collect the list of faces that need updating based upon the camera's rotation.
LLVector3 cam_direction = LLVector3(0, 0, 1) * LLViewerCamera::instance().getQuaternion();
cam_direction.normalize();
// Detect visible faces of a cube based on camera direction and distance
// Define the cube faces
static LLVector3 cubeFaces[6] = {
LLVector3(1, 0, 0),
LLVector3(-1, 0, 0),
@ -169,17 +189,21 @@ void LLHeroProbeManager::update()
LLVector3(0, 0, -1)
};
// Iterate through each face of the cube
for (int i = 0; i < 6; i++)
{
float shouldUpdate = fminf(1, (fmaxf(-1, cam_direction * cubeFaces[i]) * 0.5 + 0.5));
int updateRate = ceilf((1 - shouldUpdate) * gPipeline.RenderHeroProbeConservativeUpdateMultiplier);
// Chances are this is a face that's non-visible to the camera when it's being reflected.
// Set it to 0. It will be skipped below.
if (updateRate == gPipeline.RenderHeroProbeConservativeUpdateMultiplier)
float cube_facing = fmax(-1, fmin(1.0f, cameraDirection * cubeFaces[i])) * 0.6 + 0.4;
float updateRate;
if (cube_facing < 0.1f)
{
updateRate = 0;
}
else
{
updateRate = ceilf(cube_facing * gPipeline.RenderHeroProbeConservativeUpdateMultiplier);
}
mFaceUpdateList[i] = updateRate;
}
}
@ -199,6 +223,7 @@ void LLHeroProbeManager::update()
static LLCachedControl<S32> sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1);
static LLCachedControl<S32> sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3);
if (mNearestHero != nullptr)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime");
// Probe 0 is always our mirror probe.
@ -208,13 +233,16 @@ void LLHeroProbeManager::update()
gPipeline.mReflectionMapManager.mRadiancePass = true;
mRenderingMirror = true;
doOcclusion();
for (U32 j = 0; j < mProbes.size(); j++)
{
for (U32 i = 0; i < 6; ++i)
{
if (mFaceUpdateList[i] > 0 && mCurrentProbeUpdateFrame % mFaceUpdateList[i] == 0)
{
updateProbeFace(mProbes[j], i, near_clip);
updateProbeFace(mProbes[j], i, mNearestHero->getReflectionProbeIsDynamic() && sDetail > 0, near_clip);
mCurrentProbeUpdateFrame = 0;
}
}
@ -239,18 +267,17 @@ void LLHeroProbeManager::update()
// The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain.
// At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe.
// In effect this simulates single-bounce lighting.
void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip)
void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool is_dynamic, F32 near_clip)
{
// hacky hot-swap of camera specific render targets
gPipeline.mRT = &gPipeline.mHeroProbeRT;
probe->update(mRenderTarget.getWidth(), face, true, near_clip);
probe->update(mRenderTarget.getWidth(), face, is_dynamic, near_clip);
gPipeline.mRT = &gPipeline.mMainRT;
S32 sourceIdx = mReflectionProbeCount;
// Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes.
sourceIdx += 1;
@ -371,8 +398,6 @@ void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe)
static LLStaticHashedString sSourceIdx("sourceIdx");
{
// generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map)
gHeroRadianceGenProgram.bind();
mVertexBuffer->setBuffer();

View File

@ -116,7 +116,7 @@ private:
// update the specified face of the specified probe
void updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip);
void updateProbeFace(LLReflectionMap* probe, U32 face, bool is_dynamic, F32 near_clip);
void generateRadiance(LLReflectionMap *probe);
// list of active reflection maps

View File

@ -424,19 +424,21 @@ void LLPanelVolume::getState( )
volume_type = "Sphere";
}
std::string update_type;
if (volobjp->getReflectionProbeIsDynamic())
std::string update_type = "Static";
if (volobjp->getReflectionProbeIsDynamic() && !volobjp->getReflectionProbeIsMirror())
{
update_type = "Dynamic";
}
else if (volobjp->getReflectionProbeIsMirror())
else if (volobjp->getReflectionProbeIsMirror() && !volobjp->getReflectionProbeIsDynamic())
{
update_type = "Mirror";
}
else
{
update_type = "Static";
else if (volobjp->getReflectionProbeIsDynamic() && volobjp->getReflectionProbeIsMirror())
{
update_type = "Dynamic Mirror";
}
getChildView("Probe Ambiance")->setEnabled(update_type != "Mirror");
@ -1200,6 +1202,7 @@ void LLPanelVolume::onCopyLight()
clipboard["reflection_probe"]["ambiance"] = volobjp->getReflectionProbeAmbiance();
clipboard["reflection_probe"]["near_clip"] = volobjp->getReflectionProbeNearClip();
clipboard["reflection_probe"]["dynamic"] = volobjp->getReflectionProbeIsDynamic();
clipboard["reflection_probe"]["mirror"] = volobjp->getReflectionProbeIsMirror();
}
mClipboardParams["light"] = clipboard;
@ -1257,6 +1260,7 @@ void LLPanelVolume::onPasteLight()
volobjp->setReflectionProbeAmbiance((F32)clipboard["reflection_probe"]["ambiance"].asReal());
volobjp->setReflectionProbeNearClip((F32)clipboard["reflection_probe"]["near_clip"].asReal());
volobjp->setReflectionProbeIsDynamic(clipboard["reflection_probe"]["dynamic"].asBoolean());
volobjp->setReflectionProbeIsMirror(clipboard["reflection_probe"]["mirror"].asBoolean());
}
else
{
@ -1428,11 +1432,13 @@ void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata)
std::string update_type = self->getChild<LLUICtrl>("Probe Update Type")->getValue().asString();
volobjp->setReflectionProbeIsDynamic(update_type == "Dynamic");
volobjp->setReflectionProbeIsMirror(update_type == "Mirror");
bool is_mirror = update_type.find("Mirror") != std::string::npos;
self->getChildView("Probe Ambiance")->setEnabled(update_type != "Mirror");
self->getChildView("Probe Near Clip")->setEnabled(update_type != "Mirror");
volobjp->setReflectionProbeIsDynamic(update_type.find("Dynamic") != std::string::npos);
volobjp->setReflectionProbeIsMirror(is_mirror);
self->getChildView("Probe Ambiance")->setEnabled(!is_mirror);
self->getChildView("Probe Near Clip")->setEnabled(!is_mirror);
std::string shape_type = self->getChild<LLUICtrl>("Probe Volume Type")->getValue().asString();

View File

@ -2469,14 +2469,6 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features)
gSavedSettings.setS32("max_texture_dimension_Y", 1024);
}
bool mirrors_enabled = false;
if (features.has("MirrorsEnabled"))
{
mirrors_enabled = features["MirrorsEnabled"].asBoolean();
}
gSavedSettings.setBOOL("RenderMirrors", mirrors_enabled);
if (features.has("PBRTerrainEnabled"))
{
bool enabled = features["PBRTerrainEnabled"];

View File

@ -3420,8 +3420,15 @@ bool LLVOVolume::setReflectionProbeIsMirror(bool is_mirror)
{
if (param_block->getIsMirror() != is_mirror)
{
LL_INFOS() << "Setting reflection probe mirror to " << is_mirror << LL_ENDL;
param_block->setIsMirror(is_mirror);
parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
if (!is_mirror)
gPipeline.mHeroProbeManager.unregisterViewerObject(this);
else
gPipeline.mHeroProbeManager.registerViewerObject(this);
return true;
}
}

View File

@ -2549,7 +2549,7 @@ even though the user gets a free copy.
follows="left|top"
name="Probe Volume Type"
tool_tip="Choose the probe influence volume"
width="108">
width="140">
<combo_box.item
label="Sphere"
name="Sphere"
@ -2589,8 +2589,8 @@ even though the user gets a free copy.
left="144"
follows="left|top"
name="Probe Update Type"
tool_tip="Determines how the probe updates. Static updates the slowest and without avatars. Dynamic updates more frequently, with avatars visible in the probes. Mirror turns this probe into a realtime planar projected mirror probe, but does not calculate ambiance."
width="108">
tool_tip="Determines how the probe updates. Static updates the slowest and without avatars. Dynamic updates more frequently, with avatars visible in the probes. Mirror (Environment) turns this probe into a realtime planar projected probe that only reflects the environment, but does not calculate ambiance. Mirror (Everything) is similar to Mirror (Environment), but it reflects particles and avatars."
width="140">
<combo_box.item
label="Static"
name="Static"
@ -2600,9 +2600,13 @@ even though the user gets a free copy.
name="Dynamic"
value="Dynamic"/>
<combo_box.item
label="Mirror"
label="Mirror (Environment)"
name="Mirror"
value="Mirror"/>
<combo_box.item
label="Mirror (Everything)"
name="Dynamic Mirror"
value="Dynamic Mirror"/>
</combo_box>
<spinner bottom_delta="17"
decimal_digits="3"