Prototype code for "simple imposter" mode rendering of avatars.
Reviewed by Kellymeow-7.2.2
parent
5dbb0a31da
commit
8e54ae95d1
|
|
@ -9370,7 +9370,7 @@
|
|||
<key>RenderAutoMuteRenderCostLimit</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Maximum render cost before an avatar is automatically visually muted (0 for no limit).</string>
|
||||
<string>Maximum render weight before an avatar is automatically visually muted (0 to not use this limit).</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -9381,7 +9381,7 @@
|
|||
<key>RenderAutoMuteSurfaceAreaLimit</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Maximum surface area of attachments before an avatar is automatically visually muted (0 for no limit).</string>
|
||||
<string>Maximum surface area of attachments before an avatar is automatically visually muted (0 to not use this limit).</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -9389,6 +9389,28 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderAutoMuteEnabled</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Apply visual muting to high cost, non-friends, not in IM, or somewhat distant avatars</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderAutoMuteVisibilityRank</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Number of avatars to show normally for visual muting mode.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
|
||||
<key>RenderAutoHideSurfaceAreaLimit</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -1163,87 +1163,84 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
|
|||
}
|
||||
else if (pass >= 3 && pass <= 9)
|
||||
{ //render rigged attachments
|
||||
if (!avatarp->isVisuallyMuted())
|
||||
if (!avatarp->isVisuallyMuted()) // These details are skipped for visually muted (plain imposter) avatars
|
||||
{
|
||||
if (pass == 3)
|
||||
{
|
||||
if (is_deferred_render)
|
||||
{
|
||||
renderDeferredRiggedSimple(avatarp);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderRiggedSimple(avatarp);
|
||||
}
|
||||
}
|
||||
if (pass == 3) // To do - use switch statement
|
||||
{
|
||||
if (is_deferred_render)
|
||||
{
|
||||
renderDeferredRiggedSimple(avatarp);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderRiggedSimple(avatarp);
|
||||
}
|
||||
}
|
||||
else if (pass == 4)
|
||||
{
|
||||
if (is_deferred_render)
|
||||
{
|
||||
renderDeferredRiggedBump(avatarp);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderRiggedFullbright(avatarp);
|
||||
}
|
||||
}
|
||||
{
|
||||
if (is_deferred_render)
|
||||
{
|
||||
renderDeferredRiggedBump(avatarp);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderRiggedFullbright(avatarp);
|
||||
}
|
||||
}
|
||||
else if (pass == 5)
|
||||
{
|
||||
renderRiggedShinySimple(avatarp);
|
||||
}
|
||||
{
|
||||
renderRiggedShinySimple(avatarp);
|
||||
}
|
||||
else if (pass == 6)
|
||||
{
|
||||
renderRiggedFullbrightShiny(avatarp);
|
||||
}
|
||||
else if (pass >= 7 && pass < 9)
|
||||
{
|
||||
if (pass == 7)
|
||||
{
|
||||
renderRiggedAlpha(avatarp);
|
||||
}
|
||||
else if (pass == 8)
|
||||
{
|
||||
renderRiggedFullbrightAlpha(avatarp);
|
||||
}
|
||||
}
|
||||
{
|
||||
renderRiggedFullbrightShiny(avatarp);
|
||||
}
|
||||
else if (pass == 7)
|
||||
{
|
||||
renderRiggedAlpha(avatarp);
|
||||
}
|
||||
else if (pass == 8)
|
||||
{
|
||||
renderRiggedFullbrightAlpha(avatarp);
|
||||
}
|
||||
else if (pass == 9)
|
||||
{
|
||||
renderRiggedGlow(avatarp);
|
||||
}
|
||||
{
|
||||
renderRiggedGlow(avatarp);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
|
||||
{
|
||||
LLMatrix4 rot_mat;
|
||||
LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat);
|
||||
LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
|
||||
rot_mat *= cfr;
|
||||
if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
|
||||
{
|
||||
LLMatrix4 rot_mat;
|
||||
LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat);
|
||||
LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
|
||||
rot_mat *= cfr;
|
||||
|
||||
LLVector4 wind;
|
||||
wind.setVec(avatarp->mWindVec);
|
||||
wind.mV[VW] = 0;
|
||||
wind = wind * rot_mat;
|
||||
wind.mV[VW] = avatarp->mWindVec.mV[VW];
|
||||
LLVector4 wind;
|
||||
wind.setVec(avatarp->mWindVec);
|
||||
wind.mV[VW] = 0;
|
||||
wind = wind * rot_mat;
|
||||
wind.mV[VW] = avatarp->mWindVec.mV[VW];
|
||||
|
||||
sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_WIND, 1, wind.mV);
|
||||
F32 phase = -1.f * (avatarp->mRipplePhase);
|
||||
sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_WIND, 1, wind.mV);
|
||||
F32 phase = -1.f * (avatarp->mRipplePhase);
|
||||
|
||||
F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f);
|
||||
LLVector4 sin_params(freq, freq, freq, phase);
|
||||
sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_SINWAVE, 1, sin_params.mV);
|
||||
F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f);
|
||||
LLVector4 sin_params(freq, freq, freq, phase);
|
||||
sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_SINWAVE, 1, sin_params.mV);
|
||||
|
||||
LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f);
|
||||
gravity = gravity * rot_mat;
|
||||
sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_GRAVITY, 1, gravity.mV);
|
||||
LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f);
|
||||
gravity = gravity * rot_mat;
|
||||
sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_GRAVITY, 1, gravity.mV);
|
||||
}
|
||||
|
||||
if( !single_avatar || (avatarp == single_avatar) )
|
||||
{
|
||||
avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
|
||||
}
|
||||
}
|
||||
|
||||
if( !single_avatar || (avatarp == single_avatar) )
|
||||
{
|
||||
avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)
|
||||
|
|
|
|||
|
|
@ -2934,6 +2934,63 @@ bool enable_object_unmute()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// 0 = normal, 1 = always, 2 = never
|
||||
class LLAvatarCheckImposterMode : public view_listener_t
|
||||
{
|
||||
bool handleEvent(const LLSD& userdata)
|
||||
{
|
||||
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
|
||||
if (!object) return false;
|
||||
|
||||
LLVOAvatar* avatar = find_avatar_from_object(object);
|
||||
if (!avatar) return false;
|
||||
|
||||
U32 mode = userdata.asInteger();
|
||||
switch (mode)
|
||||
{
|
||||
case 0:
|
||||
return (avatar->getVisualMuteSettings() == LLVOAvatar::VISUAL_MUTE_NOT_SET);
|
||||
case 1:
|
||||
return (avatar->getVisualMuteSettings() == LLVOAvatar::ALWAYS_VISUAL_MUTE);
|
||||
case 2:
|
||||
return (avatar->getVisualMuteSettings() == LLVOAvatar::NEVER_VISUAL_MUTE);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} // handleEvent()
|
||||
};
|
||||
|
||||
// 0 = normal, 1 = always, 2 = never
|
||||
class LLAvatarSetImposterMode : public view_listener_t
|
||||
{
|
||||
bool handleEvent(const LLSD& userdata)
|
||||
{
|
||||
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
|
||||
if (!object) return false;
|
||||
|
||||
LLVOAvatar* avatar = find_avatar_from_object(object);
|
||||
if (!avatar) return false;
|
||||
|
||||
U32 mode = userdata.asInteger();
|
||||
switch (mode)
|
||||
{
|
||||
case 0:
|
||||
avatar->setVisualMuteSettings(LLVOAvatar::VISUAL_MUTE_NOT_SET);
|
||||
return true;
|
||||
case 1:
|
||||
avatar->setVisualMuteSettings(LLVOAvatar::VISUAL_MUTE_NOT_SET);
|
||||
return true;
|
||||
case 2:
|
||||
avatar->setVisualMuteSettings(LLVOAvatar::NEVER_VISUAL_MUTE);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} // handleEvent()
|
||||
};
|
||||
|
||||
|
||||
class LLObjectMute : public view_listener_t
|
||||
{
|
||||
bool handleEvent(const LLSD& userdata)
|
||||
|
|
@ -8644,6 +8701,8 @@ void initialize_menus()
|
|||
view_listener_t::addMenu( new LLCheckPanelPeopleTab(), "SideTray.CheckPanelPeopleTab");
|
||||
|
||||
// Avatar pie menu
|
||||
view_listener_t::addMenu(new LLAvatarCheckImposterMode(), "Avatar.CheckImposterMode");
|
||||
view_listener_t::addMenu(new LLAvatarSetImposterMode(), "Avatar.SetImposterMode");
|
||||
view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute");
|
||||
view_listener_t::addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend");
|
||||
view_listener_t::addMenu(new LLAvatarAddContact(), "Avatar.AddContact");
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@
|
|||
#include "llhudmanager.h"
|
||||
#include "llhudnametag.h"
|
||||
#include "llhudtext.h" // for mText/mDebugText
|
||||
#include "llimview.h"
|
||||
#include "llinitparam.h"
|
||||
#include "llkeyframefallmotion.h"
|
||||
#include "llkeyframestandmotion.h"
|
||||
|
|
@ -784,6 +785,13 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
|||
mLastPelvisToFoot = 0.0f;
|
||||
mPelvisFixup = 0.0f;
|
||||
mLastPelvisFixup = 0.0f;
|
||||
|
||||
mCachedVisualMute = !isSelf();
|
||||
mCachedVisualMuteUpdateTime = LLFrameTimer::getTotalSeconds() + 5.0;
|
||||
mVisuallyMuteSetting = VISUAL_MUTE_NOT_SET;
|
||||
|
||||
F32 color_value = (F32) (getID().mData[0]);
|
||||
mMutedAVColor = calcMutedAVColor(color_value, 0, 256);
|
||||
}
|
||||
|
||||
std::string LLVOAvatar::avString() const
|
||||
|
|
@ -3435,24 +3443,82 @@ void LLVOAvatar::slamPosition()
|
|||
mRoot.updateWorldMatrixChildren();
|
||||
}
|
||||
|
||||
bool LLVOAvatar::isVisuallyMuted() const
|
||||
bool LLVOAvatar::isVisuallyMuted()
|
||||
{
|
||||
bool ret = false;
|
||||
bool muted = false;
|
||||
|
||||
// Priority order (highest priority first)
|
||||
// * own avatar is never visually muted
|
||||
// * if on the "always draw normally" list, draw them normally
|
||||
// * if on the "always visually mute" list, mute them
|
||||
// * draw them normally if they meet the following criteria:
|
||||
// - within the closest N avatars OR on friends list OR in an IM chat
|
||||
// - AND aren't over the thresholds
|
||||
// * otherwise visually mute all other avatars
|
||||
|
||||
if (!isSelf())
|
||||
{
|
||||
static LLCachedControl<bool> render_mute_enabled(gSavedSettings, "RenderAutoMuteEnabled");
|
||||
static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit");
|
||||
static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit");
|
||||
static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit");
|
||||
|
||||
U32 max_cost = (U32) (max_render_cost*(LLVOAvatar::sLODFactor+0.5));
|
||||
static LLCachedControl<U32> visibility_rank(gSavedSettings, "RenderAutoMuteVisibilityRank");
|
||||
|
||||
ret = LLMuteList::getInstance()->isMuted(getID()) ||
|
||||
(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) ||
|
||||
(mVisualComplexity > max_cost && max_render_cost > 0);
|
||||
if (mVisuallyMuteSetting == ALWAYS_VISUAL_MUTE)
|
||||
{ // Always want to see this AV as an imposter
|
||||
muted = true;
|
||||
}
|
||||
else if (mVisuallyMuteSetting == NEVER_VISUAL_MUTE)
|
||||
{ // Never show as imposter
|
||||
muted = false;
|
||||
}
|
||||
else if (render_mute_enabled)
|
||||
{
|
||||
F64 now = LLFrameTimer::getTotalSeconds();
|
||||
|
||||
if (now < mCachedVisualMuteUpdateTime)
|
||||
{ // Use cached mute value
|
||||
muted = mCachedVisualMute;
|
||||
}
|
||||
else
|
||||
{ // Determine if visually muted or not
|
||||
|
||||
U32 max_cost = (U32) (max_render_cost*(LLVOAvatar::sLODFactor+0.5));
|
||||
|
||||
muted = LLMuteList::getInstance()->isMuted(getID()) ||
|
||||
(mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) ||
|
||||
(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) ||
|
||||
(mVisualComplexity > max_cost && max_render_cost > 0);
|
||||
|
||||
// Could be part of the grand || collection above, but yanked out to make the logic visible
|
||||
if (!muted)
|
||||
{
|
||||
if (visibility_rank > 0)
|
||||
{ // They are above the visibilty rank - mute them
|
||||
muted = (mVisibilityRank > visibility_rank);
|
||||
}
|
||||
|
||||
if (muted || // Don't mute friends or IMs
|
||||
visibility_rank == 0)
|
||||
{
|
||||
muted = !(LLAvatarTracker::instance().isBuddy(getID()));
|
||||
if (muted)
|
||||
{ // Not a friend, so they are muted ... are they in an IM?
|
||||
LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL,getID());
|
||||
muted = !gIMMgr->hasSession(session_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save visual mute state and set interval for updating
|
||||
const F64 SECONDS_BETWEEN_RENDER_AUTO_MUTE_UPDATES = 1.5;
|
||||
mCachedVisualMuteUpdateTime = now + SECONDS_BETWEEN_RENDER_AUTO_MUTE_UPDATES;
|
||||
mCachedVisualMute = muted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return muted;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
|
@ -3509,7 +3575,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
|||
// the rest should only be done occasionally for far away avatars
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
if (visible && (!isSelf() || isVisuallyMuted()) && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)
|
||||
bool visually_muted = isVisuallyMuted();
|
||||
if (visible && (!isSelf() || visually_muted) && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)
|
||||
{
|
||||
const LLVector4a* ext = mDrawable->getSpatialExtents();
|
||||
LLVector4a size;
|
||||
|
|
@ -3518,8 +3585,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
|||
|
||||
|
||||
F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f);
|
||||
if (isVisuallyMuted())
|
||||
{ // muted avatars update at 16 hz
|
||||
if (visually_muted)
|
||||
{ // visually muted avatars update at 16 hz
|
||||
mUpdatePeriod = 16;
|
||||
}
|
||||
else if (mVisibilityRank <= LLVOAvatar::sMaxVisible ||
|
||||
|
|
@ -4295,23 +4362,23 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
|
|||
BOOL first_pass = TRUE;
|
||||
if (!LLDrawPoolAvatar::sSkipOpaque)
|
||||
{
|
||||
bool muted = isVisuallyMuted();
|
||||
bool visually_muted = isVisuallyMuted();
|
||||
|
||||
if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
|
||||
{
|
||||
if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy || muted)
|
||||
if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy || visually_muted)
|
||||
{
|
||||
num_indices += mMeshLOD[MESH_ID_HEAD]->render(mAdjustedPixelArea, TRUE, mIsDummy);
|
||||
first_pass = FALSE;
|
||||
}
|
||||
}
|
||||
if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy || muted)
|
||||
if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy || visually_muted)
|
||||
{
|
||||
num_indices += mMeshLOD[MESH_ID_UPPER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy);
|
||||
first_pass = FALSE;
|
||||
}
|
||||
|
||||
if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy || muted)
|
||||
if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy || visually_muted)
|
||||
{
|
||||
num_indices += mMeshLOD[MESH_ID_LOWER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy);
|
||||
first_pass = FALSE;
|
||||
|
|
@ -8396,7 +8463,7 @@ void LLVOAvatar::updateImpostors()
|
|||
LLCharacter::sAllowInstancesChange = TRUE ;
|
||||
}
|
||||
|
||||
BOOL LLVOAvatar::isImpostor() const
|
||||
BOOL LLVOAvatar::isImpostor()
|
||||
{
|
||||
return sUseImpostors && (isVisuallyMuted() || (mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE;
|
||||
}
|
||||
|
|
@ -8441,15 +8508,13 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d
|
|||
angle.mV[2] = da;
|
||||
}
|
||||
|
||||
|
||||
void LLVOAvatar::idleUpdateRenderCost()
|
||||
{
|
||||
static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit");
|
||||
|
||||
static const U32 ARC_BODY_PART_COST = 200;
|
||||
static const U32 ARC_LIMIT = 20000;
|
||||
|
||||
static std::set<LLUUID> all_textures;
|
||||
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES))
|
||||
{ //set debug text to attachment geometry bytes here so render cost will override
|
||||
setDebugText(llformat("%.1f KB, %.2f m^2", mAttachmentGeometryBytes/1024.f, mAttachmentSurfaceArea));
|
||||
|
|
@ -8460,6 +8525,69 @@ void LLVOAvatar::idleUpdateRenderCost()
|
|||
return;
|
||||
}
|
||||
|
||||
calculateUpdateRenderCost(); // Update mVisualComplexity if needed
|
||||
|
||||
doRenderCostNagging(max_render_cost); // Remind the user their AV is too complex
|
||||
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
|
||||
{
|
||||
std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus());
|
||||
setDebugText(llformat("%s %d", viz_string.c_str(), mVisualComplexity));
|
||||
F32 green = 1.f-llclamp(((F32) mVisualComplexity-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f);
|
||||
F32 red = llmin((F32) mVisualComplexity/(F32)ARC_LIMIT, 1.f);
|
||||
mText->setColor(LLColor4(red,green,0,1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Remind the user about their expensive avatar
|
||||
void LLVOAvatar::doRenderCostNagging(U32 max_render_cost)
|
||||
{
|
||||
if (isSelf())
|
||||
{
|
||||
static S32 sOldComplexity = 0;
|
||||
static F64 sLastRenderCostNagTime = 0.0;
|
||||
|
||||
const F64 RENDER_NAG_INTERVAL = 60.0;
|
||||
|
||||
F64 now = LLFrameTimer::getTotalSeconds();
|
||||
if (sLastRenderCostNagTime > 0.0 &&
|
||||
(now - sLastRenderCostNagTime) > RENDER_NAG_INTERVAL &&
|
||||
sOldComplexity != mVisualComplexity)
|
||||
{
|
||||
sOldComplexity = mVisualComplexity;
|
||||
|
||||
if (max_render_cost > 0)
|
||||
{ //pop up notification that you have exceeded a render cost limit
|
||||
if (mVisualComplexity > max_render_cost+max_render_cost/2)
|
||||
{
|
||||
LLNotificationsUtil::add("ExceededHighDetailRenderCost");
|
||||
sLastRenderCostNagTime = now;
|
||||
}
|
||||
else if (mVisualComplexity > max_render_cost)
|
||||
{
|
||||
LLNotificationsUtil::add("ExceededMidDetailRenderCost");
|
||||
sLastRenderCostNagTime = now;
|
||||
}
|
||||
else if (mVisualComplexity > max_render_cost/2)
|
||||
{
|
||||
LLNotificationsUtil::add("ExceededLowDetailRenderCost");
|
||||
sLastRenderCostNagTime = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Calculations for mVisualComplexity value
|
||||
void LLVOAvatar::calculateUpdateRenderCost()
|
||||
{
|
||||
static const U32 ARC_BODY_PART_COST = 200;
|
||||
|
||||
// Diagnostic list of all textures on our avatar
|
||||
static std::set<LLUUID> all_textures;
|
||||
|
||||
if (mVisualComplexityStale)
|
||||
{
|
||||
mVisualComplexityStale = FALSE;
|
||||
|
|
@ -8526,8 +8654,6 @@ void LLVOAvatar::idleUpdateRenderCost()
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Diagnostic output to identify all avatar-related textures.
|
||||
// Does not affect rendering cost calculation.
|
||||
// Could be wrapped in a debug option if output becomes problematic.
|
||||
|
|
@ -8568,34 +8694,37 @@ void LLVOAvatar::idleUpdateRenderCost()
|
|||
}
|
||||
}
|
||||
|
||||
if (isSelf() && max_render_cost > 0 && mVisualComplexity != cost)
|
||||
{ //pop up notification that you have exceeded a render cost limit
|
||||
if (cost > max_render_cost+max_render_cost/2)
|
||||
{
|
||||
LLNotificationsUtil::add("ExceededHighDetailRenderCost");
|
||||
}
|
||||
else if (cost > max_render_cost)
|
||||
{
|
||||
LLNotificationsUtil::add("ExceededMidDetailRenderCost");
|
||||
}
|
||||
else if (cost > max_render_cost/2)
|
||||
{
|
||||
LLNotificationsUtil::add("ExceededLowDetailRenderCost");
|
||||
}
|
||||
}
|
||||
|
||||
mVisualComplexity = cost;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
|
||||
{
|
||||
std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus());
|
||||
setDebugText(llformat("%s %d", viz_string.c_str(), mVisualComplexity));
|
||||
F32 green = 1.f-llclamp(((F32) mVisualComplexity-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f);
|
||||
F32 red = llmin((F32) mVisualComplexity/(F32)ARC_LIMIT, 1.f);
|
||||
mText->setColor(LLColor4(red,green,0,1));
|
||||
}
|
||||
|
||||
// static
|
||||
LLColor4 LLVOAvatar::calcMutedAVColor(F32 value, S32 range_low, S32 range_high)
|
||||
{
|
||||
F32 clamped_value = llmin(value, (F32) range_high);
|
||||
clamped_value = llmax(value, (F32) range_low);
|
||||
F32 spectrum = (clamped_value / range_high); // spectrum is between 0 and 1.f
|
||||
|
||||
// Array of colors. These are arranged so only one RGB color changes between each step,
|
||||
// and it loops back to red so there is an even distribution. It is not a heat map
|
||||
const S32 NUM_SPECTRUM_COLORS = 7;
|
||||
static LLColor4 * spectrum_color[NUM_SPECTRUM_COLORS] = { &LLColor4::red, &LLColor4::magenta, &LLColor4::blue, &LLColor4::cyan, &LLColor4::green, &LLColor4::yellow, &LLColor4::red };
|
||||
|
||||
spectrum = spectrum * (NUM_SPECTRUM_COLORS - 1); // Scale to range of number of colors
|
||||
S32 spectrum_index_1 = floor(spectrum); // Desired color will be after this index
|
||||
S32 spectrum_index_2 = spectrum_index_1 + 1; // and before this index (inclusive)
|
||||
F32 fractBetween = spectrum - (F32)(spectrum_index_1); // distance between the two indexes (0-1)
|
||||
|
||||
LLColor4 new_color = lerp(*spectrum_color[spectrum_index_1], *spectrum_color[spectrum_index_2], fractBetween);
|
||||
//new_color.normalize();
|
||||
|
||||
//llinfos << "From value " << std::setprecision(3) << value << " returning color " << new_color
|
||||
// << " using indexes " << spectrum_index_1 << ", " << spectrum_index_2
|
||||
// << " and fractBetween " << fractBetween
|
||||
// << llendl;
|
||||
|
||||
return new_color;
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
|||
|
|
@ -253,7 +253,14 @@ public:
|
|||
static void invalidateNameTags();
|
||||
void addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font);
|
||||
void idleUpdateRenderCost();
|
||||
void doRenderCostNagging(U32 max_render_cost);
|
||||
void calculateUpdateRenderCost();
|
||||
void updateVisualComplexity() { mVisualComplexityStale = TRUE; }
|
||||
|
||||
S32 getVisualComplexity() { return mVisualComplexity; };
|
||||
S32 getUpdatePeriod() { return mUpdatePeriod; };
|
||||
const LLColor4 & getMutedAVColor() { return mMutedAVColor; };
|
||||
|
||||
void idleUpdateBelowWater();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
|
@ -304,11 +311,14 @@ public:
|
|||
return mPhases;
|
||||
}
|
||||
|
||||
static LLColor4 calcMutedAVColor(F32 value, S32 range_low, S32 range_high);
|
||||
|
||||
protected:
|
||||
BOOL updateIsFullyLoaded();
|
||||
BOOL processFullyLoadedChange(bool loading);
|
||||
void updateRuthTimer(bool loading);
|
||||
F32 calcMorphAmount();
|
||||
|
||||
private:
|
||||
BOOL mFirstFullyVisible;
|
||||
BOOL mFullyLoaded;
|
||||
|
|
@ -317,6 +327,7 @@ private:
|
|||
S32 mFullyLoadedFrameCounter;
|
||||
S32 mVisualComplexity;
|
||||
BOOL mVisualComplexityStale;
|
||||
LLColor4 mMutedAVColor;
|
||||
LLFrameTimer mFullyLoadedTimer;
|
||||
LLFrameTimer mRuthTimer;
|
||||
|
||||
|
|
@ -437,7 +448,16 @@ private:
|
|||
|
||||
public:
|
||||
U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0);
|
||||
bool isVisuallyMuted() const;
|
||||
bool isVisuallyMuted();
|
||||
|
||||
enum VisualMuteSettings
|
||||
{
|
||||
VISUAL_MUTE_NOT_SET = 0,
|
||||
ALWAYS_VISUAL_MUTE = 1,
|
||||
NEVER_VISUAL_MUTE = 2
|
||||
};
|
||||
void setVisualMuteSettings(VisualMuteSettings set) { mVisuallyMuteSetting = set; };
|
||||
VisualMuteSettings getVisualMuteSettings() { return mVisuallyMuteSetting; };
|
||||
|
||||
U32 renderRigid();
|
||||
U32 renderSkinned(EAvatarRenderPass pass);
|
||||
|
|
@ -461,6 +481,11 @@ private:
|
|||
S32 mUpdatePeriod;
|
||||
S32 mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer.
|
||||
|
||||
bool mCachedVisualMute; // cached return value for isVisuallyMuted()
|
||||
F64 mCachedVisualMuteUpdateTime; // Time to update mCachedVisualMute
|
||||
|
||||
VisualMuteSettings mVisuallyMuteSetting; // Always or never visually mute this AV
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Morph masks
|
||||
//--------------------------------------------------------------------
|
||||
|
|
@ -493,7 +518,7 @@ private:
|
|||
// Impostors
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
BOOL isImpostor() const;
|
||||
BOOL isImpostor();
|
||||
BOOL needsImpostorUpdate() const;
|
||||
const LLVector3& getImpostorOffset() const;
|
||||
const LLVector2& getImpostorDim() const;
|
||||
|
|
|
|||
|
|
@ -2862,7 +2862,7 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
|
|||
llassert(vobj); // trying to catch a bad assumption
|
||||
if (vobj) // this test may not be needed, see above
|
||||
{
|
||||
const LLVOAvatar* av = vobj->asAvatar();
|
||||
LLVOAvatar* av = vobj->asAvatar();
|
||||
if (av && av->isImpostor())
|
||||
{
|
||||
return;
|
||||
|
|
@ -10103,11 +10103,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
|||
|
||||
assertInitialized();
|
||||
|
||||
bool muted = avatar->isVisuallyMuted();
|
||||
bool visually_muted = avatar->isVisuallyMuted();
|
||||
|
||||
pushRenderTypeMask();
|
||||
|
||||
if (muted)
|
||||
if (visually_muted)
|
||||
{
|
||||
andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
|
||||
}
|
||||
|
|
@ -10251,7 +10251,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
|||
|
||||
F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha;
|
||||
|
||||
if (muted)
|
||||
if (visually_muted)
|
||||
{ //disable alpha masking for muted avatars (get whole skin silhouette)
|
||||
LLDrawPoolAvatar::sMinimumAlpha = 0.f;
|
||||
}
|
||||
|
|
@ -10282,7 +10282,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
|||
|
||||
LLGLDisable blend(GL_BLEND);
|
||||
|
||||
if (muted)
|
||||
if (visually_muted)
|
||||
{
|
||||
gGL.setColorMask(true, true);
|
||||
|
||||
|
|
@ -10317,8 +10317,8 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
|||
gGL.diffuseColor4ub(64,64,64,255);
|
||||
}
|
||||
else
|
||||
{ //blue visually muted avatar
|
||||
gGL.diffuseColor4ub(72,61,139,255);
|
||||
{ // Visually muted avatar
|
||||
gGL.diffuseColor4fv( avatar->getMutedAVColor().mV );
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -104,8 +104,43 @@
|
|||
<menu_item_call.on_enable
|
||||
function="Object.EnableInspect" />
|
||||
</menu_item_call>
|
||||
|
||||
<menu_item_separator />
|
||||
|
||||
<menu_item_check
|
||||
name="Normal"
|
||||
label="Normal">
|
||||
<menu_item_check.on_check
|
||||
function="Avatar.CheckImposterMode"
|
||||
parameter="0" />
|
||||
<menu_item_check.on_click
|
||||
function="Avatar.SetImposterMode"
|
||||
parameter="0" />
|
||||
</menu_item_check>
|
||||
<menu_item_check
|
||||
name="Always use imposter"
|
||||
label="Always use imposter">
|
||||
<menu_item_check.on_check
|
||||
function="Avatar.CheckImposterMode"
|
||||
parameter="1" />
|
||||
<menu_item_check.on_click
|
||||
function="Avatar.SetImposterMode"
|
||||
parameter="1" />
|
||||
</menu_item_check>
|
||||
<menu_item_check
|
||||
name="Never use imposter"
|
||||
label="Never use imposter">
|
||||
<menu_item_check.on_check
|
||||
function="Avatar.CheckImposterMode"
|
||||
parameter="2" />
|
||||
<menu_item_check.on_click
|
||||
function="Avatar.SetImposterMode"
|
||||
parameter="2" />
|
||||
</menu_item_check>
|
||||
|
||||
<menu_item_separator
|
||||
layout="topleft" />
|
||||
|
||||
<menu_item_call
|
||||
enabled="false"
|
||||
label="Mute Particle Owner"
|
||||
|
|
|
|||
|
|
@ -39,8 +39,10 @@
|
|||
<menu_item_call.on_click
|
||||
function="Avatar.InviteToGroup" />
|
||||
</menu_item_call>
|
||||
|
||||
<menu_item_separator />
|
||||
<menu_item_call
|
||||
|
||||
<menu_item_call
|
||||
enabled="false"
|
||||
label="Block"
|
||||
name="Avatar Mute">
|
||||
|
|
@ -95,8 +97,43 @@
|
|||
<menu_item_call.on_enable
|
||||
function="EnablePayAvatar" />
|
||||
</menu_item_call>
|
||||
|
||||
<menu_item_separator />
|
||||
|
||||
<menu_item_check
|
||||
name="Normal"
|
||||
label="Normal">
|
||||
<menu_item_check.on_check
|
||||
function="Avatar.CheckImposterMode"
|
||||
parameter="0" />
|
||||
<menu_item_check.on_click
|
||||
function="Avatar.SetImposterMode"
|
||||
parameter="0" />
|
||||
</menu_item_check>
|
||||
<menu_item_check
|
||||
name="Always use imposter"
|
||||
label="Always use imposter">
|
||||
<menu_item_check.on_check
|
||||
function="Avatar.CheckImposterMode"
|
||||
parameter="1" />
|
||||
<menu_item_check.on_click
|
||||
function="Avatar.SetImposterMode"
|
||||
parameter="1" />
|
||||
</menu_item_check>
|
||||
<menu_item_check
|
||||
name="Never use imposter"
|
||||
label="Never use imposter">
|
||||
<menu_item_check.on_check
|
||||
function="Avatar.CheckImposterMode"
|
||||
parameter="2" />
|
||||
<menu_item_check.on_click
|
||||
function="Avatar.SetImposterMode"
|
||||
parameter="2" />
|
||||
</menu_item_check>
|
||||
|
||||
<menu_item_separator
|
||||
layout="topleft" />
|
||||
|
||||
<menu_item_call
|
||||
enabled="false"
|
||||
label="Mute Particle Owner"
|
||||
|
|
|
|||
|
|
@ -543,6 +543,15 @@
|
|||
<menu_item_check.on_check
|
||||
control="NavBarShowParcelProperties" />
|
||||
</menu_item_check>
|
||||
<menu_item_check
|
||||
label="Simple Imposters"
|
||||
name="RenderAutoMuteEnabled">
|
||||
<menu_item_check.on_check
|
||||
control="RenderAutoMuteEnabled" />
|
||||
<menu_item_check.on_click
|
||||
function="ToggleControl"
|
||||
parameter="RenderAutoMuteEnabled" />
|
||||
</menu_item_check>
|
||||
<menu_item_separator />
|
||||
<menu_item_check
|
||||
label="Advanced Menu"
|
||||
|
|
|
|||
Loading…
Reference in New Issue