MAINT-2370 Add debug setting "RenderAutoMuteRenderCostLimit" that automatically visually mutes avatars above a certain threshold (adjusted by Avatar Mesh Detail Slider)
parent
cc260a6356
commit
f67087b872
|
|
@ -2282,6 +2282,22 @@ void LLRender::diffuseColor4ubv(const U8* c)
|
|||
}
|
||||
}
|
||||
|
||||
void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a)
|
||||
{
|
||||
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
|
||||
llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL);
|
||||
|
||||
if (shader)
|
||||
{
|
||||
shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r/255.f, g/255.f, b/255.f, a/255.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
glColor4ub(r,g,b,a);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLRender::debugTexUnits(void)
|
||||
{
|
||||
LL_INFOS("TextureUnit") << "Active TexUnit: " << mCurrTextureUnitIndex << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -388,6 +388,7 @@ public:
|
|||
void diffuseColor4f(F32 r, F32 g, F32 b, F32 a);
|
||||
void diffuseColor4fv(const F32* c);
|
||||
void diffuseColor4ubv(const U8* c);
|
||||
void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a);
|
||||
|
||||
void vertexBatchPreTransformed(LLVector3* verts, S32 vert_count);
|
||||
void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count);
|
||||
|
|
|
|||
|
|
@ -458,6 +458,12 @@ U32 LLRenderTarget::getTexture(U32 attachment) const
|
|||
return mTex[attachment];
|
||||
}
|
||||
|
||||
U32 LLRenderTarget::getNumTextures() const
|
||||
{
|
||||
return mTex.size();
|
||||
}
|
||||
|
||||
|
||||
void LLRenderTarget::bindTexture(U32 index, S32 channel)
|
||||
{
|
||||
gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index));
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ public:
|
|||
LLTexUnit::eTextureType getUsage(void) const { return mUsage; }
|
||||
|
||||
U32 getTexture(U32 attachment = 0) const;
|
||||
U32 getNumTextures() const;
|
||||
|
||||
U32 getDepth(void) const { return mDepth; }
|
||||
bool hasStencil() const { return mStencil; }
|
||||
|
|
|
|||
|
|
@ -9169,6 +9169,17 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderAutoMuteRenderCostLimit</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Maximum render cost before an avatar is automatically visually muted (0 for no limit).</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderAutoMuteSurfaceAreaLimit</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ out vec4 frag_data[3];
|
|||
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
uniform float minimum_alpha;
|
||||
|
||||
VARYING vec3 vary_normal;
|
||||
VARYING vec2 vary_texcoord0;
|
||||
|
||||
|
|
@ -38,7 +40,7 @@ void main()
|
|||
{
|
||||
vec4 diff = texture2D(diffuseMap, vary_texcoord0.xy);
|
||||
|
||||
if (diff.a < 0.2)
|
||||
if (diff.a < minimum_alpha)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL;
|
|||
BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE;
|
||||
BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE;
|
||||
S32 LLDrawPoolAvatar::sDiffuseChannel = 0;
|
||||
F32 LLDrawPoolAvatar::sMinimumAlpha = 0.2f;
|
||||
|
||||
|
||||
static bool is_deferred_render = false;
|
||||
|
|
@ -272,7 +273,7 @@ void LLDrawPoolAvatar::beginPostDeferredAlpha()
|
|||
|
||||
gPipeline.bindDeferredShader(*sVertexProgram);
|
||||
|
||||
sVertexProgram->setMinimumAlpha(0.2f);
|
||||
sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);
|
||||
|
||||
sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
|
||||
}
|
||||
|
|
@ -620,7 +621,7 @@ void LLDrawPoolAvatar::beginRigid()
|
|||
if (sVertexProgram != NULL)
|
||||
{ //eyeballs render with the specular shader
|
||||
sVertexProgram->bind();
|
||||
sVertexProgram->setMinimumAlpha(0.2f);
|
||||
sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -671,7 +672,7 @@ void LLDrawPoolAvatar::beginDeferredRigid()
|
|||
sVertexProgram = &gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram;
|
||||
sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
|
||||
sVertexProgram->bind();
|
||||
sVertexProgram->setMinimumAlpha(0.2f);
|
||||
sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);
|
||||
}
|
||||
|
||||
void LLDrawPoolAvatar::endDeferredRigid()
|
||||
|
|
@ -729,7 +730,7 @@ void LLDrawPoolAvatar::beginSkinned()
|
|||
|
||||
if (LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
sVertexProgram->setMinimumAlpha(0.2f);
|
||||
sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1027,7 +1028,7 @@ void LLDrawPoolAvatar::beginDeferredSkinned()
|
|||
sRenderingSkinned = TRUE;
|
||||
|
||||
sVertexProgram->bind();
|
||||
sVertexProgram->setMinimumAlpha(0.2f);
|
||||
sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);
|
||||
|
||||
sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
|
||||
gGL.getTexUnit(0)->activate();
|
||||
|
|
@ -1138,7 +1139,10 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
|
|||
|
||||
if (impostor)
|
||||
{
|
||||
if (LLPipeline::sRenderDeferred && !LLPipeline::sReflectionRender && avatarp->mImpostor.isComplete())
|
||||
if (LLPipeline::sRenderDeferred && //rendering a deferred impostor
|
||||
!LLPipeline::sReflectionRender &&
|
||||
avatarp->mImpostor.isComplete() && //impostor has required data channels
|
||||
avatarp->mImpostor.getNumTextures() >= 3)
|
||||
{
|
||||
if (normal_channel > -1)
|
||||
{
|
||||
|
|
@ -1151,112 +1155,94 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
|
|||
}
|
||||
avatarp->renderImpostor(LLColor4U(255,255,255,255), sDiffuseChannel);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
llassert(LLPipeline::sImpostorRender || !avatarp->isVisuallyMuted());
|
||||
|
||||
/*if (single_avatar && avatarp->mSpecialRenderMode >= 1) // 1=anim preview, 2=image preview, 3=morph view
|
||||
{
|
||||
gPipeline.enableLightsAvatarEdit(LLColor4(.5f, .5f, .5f, 1.f));
|
||||
}*/
|
||||
|
||||
if (pass == 1)
|
||||
else if (pass == 1)
|
||||
{
|
||||
// render rigid meshes (eyeballs) first
|
||||
avatarp->renderRigid();
|
||||
return;
|
||||
}
|
||||
|
||||
if (pass == 3)
|
||||
{
|
||||
if (is_deferred_render)
|
||||
else if (pass >= 3 && pass <= 9)
|
||||
{ //render rigged attachments
|
||||
if (!avatarp->isVisuallyMuted())
|
||||
{
|
||||
renderDeferredRiggedSimple(avatarp);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderRiggedSimple(avatarp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (pass == 4)
|
||||
{
|
||||
if (is_deferred_render)
|
||||
{
|
||||
renderDeferredRiggedBump(avatarp);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderRiggedFullbright(avatarp);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (pass == 5)
|
||||
{
|
||||
renderRiggedShinySimple(avatarp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pass == 6)
|
||||
{
|
||||
renderRiggedFullbrightShiny(avatarp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pass >= 7 && pass < 9)
|
||||
{
|
||||
if (pass == 7)
|
||||
{
|
||||
renderRiggedAlpha(avatarp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pass == 8)
|
||||
{
|
||||
renderRiggedFullbrightAlpha(avatarp);
|
||||
return;
|
||||
if (pass == 3)
|
||||
{
|
||||
if (is_deferred_render)
|
||||
{
|
||||
renderDeferredRiggedSimple(avatarp);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderRiggedSimple(avatarp);
|
||||
}
|
||||
}
|
||||
else if (pass == 4)
|
||||
{
|
||||
if (is_deferred_render)
|
||||
{
|
||||
renderDeferredRiggedBump(avatarp);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderRiggedFullbright(avatarp);
|
||||
}
|
||||
}
|
||||
else if (pass == 5)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
else if (pass == 9)
|
||||
{
|
||||
renderRiggedGlow(avatarp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pass == 9)
|
||||
else
|
||||
{
|
||||
renderRiggedGlow(avatarp);
|
||||
if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
|
||||
{
|
||||
LLMatrix4 rot_mat;
|
||||
LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat);
|
||||
LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
|
||||
rot_mat *= cfr;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ public:
|
|||
static BOOL sSkipOpaque;
|
||||
static BOOL sSkipTransparent;
|
||||
static S32 sDiffuseChannel;
|
||||
static F32 sMinimumAlpha;
|
||||
|
||||
static LLGLSLShader* sVertexProgram;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
#include "llviewerregion.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llviewershadermgr.h"
|
||||
#include "llvoavatar.h"
|
||||
|
||||
|
||||
#define LL_MAX_INDICES_COUNT 1000000
|
||||
|
|
@ -325,6 +326,12 @@ void LLFace::dirtyTexture()
|
|||
if (vobj)
|
||||
{
|
||||
vobj->mLODChanged = TRUE;
|
||||
|
||||
LLVOAvatar* avatar = vobj->getAvatar();
|
||||
if (avatar)
|
||||
{ //avatar render cost may have changed
|
||||
avatar->updateVisualComplexity();
|
||||
}
|
||||
}
|
||||
gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, FALSE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1200,8 +1200,7 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
|
|||
LLMutexLock lock(mHeaderMutex);
|
||||
mMeshHeaderSize[mesh_id] = header_size;
|
||||
mMeshHeader[mesh_id] = header;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LLMutexLock lock(mMutex); // make sure only one thread access mPendingLOD at the same time.
|
||||
|
||||
|
|
|
|||
|
|
@ -688,6 +688,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
|||
mFullyLoaded(FALSE),
|
||||
mPreviousFullyLoaded(FALSE),
|
||||
mFullyLoadedInitialized(FALSE),
|
||||
mVisualComplexity(0),
|
||||
mVisualComplexityStale(TRUE),
|
||||
mSupportsAlphaLayers(FALSE),
|
||||
mLoadedCallbacksPaused(FALSE),
|
||||
mHasPelvisOffset( FALSE ),
|
||||
|
|
@ -3434,12 +3436,23 @@ void LLVOAvatar::slamPosition()
|
|||
|
||||
bool LLVOAvatar::isVisuallyMuted() const
|
||||
{
|
||||
static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit");
|
||||
static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit");
|
||||
bool ret = false;
|
||||
|
||||
if (!isSelf())
|
||||
{
|
||||
static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit");
|
||||
static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit");
|
||||
static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit");
|
||||
|
||||
return LLMuteList::getInstance()->isMuted(getID()) ||
|
||||
U32 max_cost = (U32) (max_render_cost*(LLVOAvatar::sLODFactor+0.5));
|
||||
|
||||
ret = LLMuteList::getInstance()->isMuted(getID()) ||
|
||||
(mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) ||
|
||||
(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f);
|
||||
(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) ||
|
||||
(mVisualComplexity > max_cost && max_render_cost > 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
|
@ -4139,46 +4152,6 @@ bool LLVOAvatar::shouldAlphaMask()
|
|||
|
||||
}
|
||||
|
||||
U32 LLVOAvatar::renderSkinnedAttachments()
|
||||
{
|
||||
/*U32 num_indices = 0;
|
||||
|
||||
const U32 data_mask = LLVertexBuffer::MAP_VERTEX |
|
||||
LLVertexBuffer::MAP_NORMAL |
|
||||
LLVertexBuffer::MAP_TEXCOORD0 |
|
||||
LLVertexBuffer::MAP_COLOR |
|
||||
LLVertexBuffer::MAP_WEIGHT4;
|
||||
|
||||
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
const LLViewerObject* attached_object = (*attachment_iter);
|
||||
if (attached_object && !attached_object->isHUDAttachment())
|
||||
{
|
||||
const LLDrawable* drawable = attached_object->mDrawable;
|
||||
if (drawable)
|
||||
{
|
||||
for (S32 i = 0; i < drawable->getNumFaces(); ++i)
|
||||
{
|
||||
LLFace* face = drawable->getFace(i);
|
||||
if (face->isState(LLFace::RIGGED))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return num_indices;*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// renderSkinned()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -4336,21 +4309,23 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
|
|||
BOOL first_pass = TRUE;
|
||||
if (!LLDrawPoolAvatar::sSkipOpaque)
|
||||
{
|
||||
bool muted = isVisuallyMuted();
|
||||
|
||||
if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
|
||||
{
|
||||
if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy)
|
||||
if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy || muted)
|
||||
{
|
||||
num_indices += mMeshLOD[MESH_ID_HEAD]->render(mAdjustedPixelArea, TRUE, mIsDummy);
|
||||
first_pass = FALSE;
|
||||
}
|
||||
}
|
||||
if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy)
|
||||
if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy || muted)
|
||||
{
|
||||
num_indices += mMeshLOD[MESH_ID_UPPER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy);
|
||||
first_pass = FALSE;
|
||||
}
|
||||
|
||||
if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy)
|
||||
if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy || muted)
|
||||
{
|
||||
num_indices += mMeshLOD[MESH_ID_LOWER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy);
|
||||
first_pass = FALSE;
|
||||
|
|
@ -6090,6 +6065,8 @@ const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_o
|
|||
return 0;
|
||||
}
|
||||
|
||||
mVisualComplexityStale = TRUE;
|
||||
|
||||
if (viewer_object->isSelected())
|
||||
{
|
||||
LLSelectMgr::getInstance()->updateSelectionCenter();
|
||||
|
|
@ -6244,6 +6221,7 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
|
|||
|
||||
if (attachment->isObjectAttached(viewer_object))
|
||||
{
|
||||
mVisualComplexityStale = TRUE;
|
||||
cleanupAttachedMesh( viewer_object );
|
||||
attachment->removeObject(viewer_object);
|
||||
lldebugs << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << llendl;
|
||||
|
|
@ -8456,7 +8434,7 @@ void LLVOAvatar::updateImpostors()
|
|||
|
||||
BOOL LLVOAvatar::isImpostor() const
|
||||
{
|
||||
return (isVisuallyMuted() || (sUseImpostors && mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE;
|
||||
return sUseImpostors && (isVisuallyMuted() || (mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -8501,6 +8479,8 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d
|
|||
|
||||
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;
|
||||
|
||||
|
|
@ -8511,123 +8491,147 @@ void LLVOAvatar::idleUpdateRenderCost()
|
|||
setDebugText(llformat("%.1f KB, %.2f m^2", mAttachmentGeometryBytes/1024.f, mAttachmentSurfaceArea));
|
||||
}
|
||||
|
||||
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
|
||||
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME) && max_render_cost == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
U32 cost = 0;
|
||||
LLVOVolume::texture_cost_t textures;
|
||||
|
||||
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
|
||||
if (mVisualComplexityStale)
|
||||
{
|
||||
const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
|
||||
ETextureIndex tex_index = baked_dict->mTextureIndex;
|
||||
if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT)))
|
||||
{
|
||||
if (isTextureVisible(tex_index))
|
||||
{
|
||||
cost +=ARC_BODY_PART_COST;
|
||||
}
|
||||
}
|
||||
}
|
||||
mVisualComplexityStale = FALSE;
|
||||
U32 cost = 0;
|
||||
LLVOVolume::texture_cost_t textures;
|
||||
|
||||
|
||||
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
|
||||
{
|
||||
const LLViewerObject* attached_object = (*attachment_iter);
|
||||
if (attached_object && !attached_object->isHUDAttachment())
|
||||
const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
|
||||
ETextureIndex tex_index = baked_dict->mTextureIndex;
|
||||
if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT)))
|
||||
{
|
||||
textures.clear();
|
||||
const LLDrawable* drawable = attached_object->mDrawable;
|
||||
if (drawable)
|
||||
if (isTextureVisible(tex_index))
|
||||
{
|
||||
const LLVOVolume* volume = drawable->getVOVolume();
|
||||
if (volume)
|
||||
{
|
||||
cost += volume->getRenderCost(textures);
|
||||
|
||||
const_child_list_t children = volume->getChildren();
|
||||
for (const_child_list_t::const_iterator child_iter = children.begin();
|
||||
child_iter != children.end();
|
||||
++child_iter)
|
||||
{
|
||||
LLViewerObject* child_obj = *child_iter;
|
||||
LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj );
|
||||
if (child)
|
||||
{
|
||||
cost += child->getRenderCost(textures);
|
||||
}
|
||||
}
|
||||
|
||||
for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
|
||||
{
|
||||
// add the cost of each individual texture in the linkset
|
||||
cost += iter->second;
|
||||
}
|
||||
}
|
||||
cost +=ARC_BODY_PART_COST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 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.
|
||||
if (isSelf())
|
||||
{
|
||||
// print any attachment textures we didn't already know about.
|
||||
for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it)
|
||||
{
|
||||
LLUUID image_id = it->first;
|
||||
if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
|
||||
continue;
|
||||
if (all_textures.find(image_id) == all_textures.end())
|
||||
{
|
||||
// attachment texture not previously seen.
|
||||
llinfos << "attachment_texture: " << image_id.asString() << llendl;
|
||||
all_textures.insert(image_id);
|
||||
}
|
||||
}
|
||||
|
||||
// print any avatar textures we didn't already know about
|
||||
for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
|
||||
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
|
||||
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end();
|
||||
++iter)
|
||||
{
|
||||
const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
|
||||
// TODO: MULTI-WEARABLE: handle multiple textures for self
|
||||
const LLViewerTexture* te_image = getImage(iter->first,0);
|
||||
if (!te_image)
|
||||
continue;
|
||||
LLUUID image_id = te_image->getID();
|
||||
if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
|
||||
continue;
|
||||
if (all_textures.find(image_id) == all_textures.end())
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
llinfos << "local_texture: " << texture_dict->mName << ": " << image_id << llendl;
|
||||
all_textures.insert(image_id);
|
||||
const LLViewerObject* attached_object = (*attachment_iter);
|
||||
if (attached_object && !attached_object->isHUDAttachment())
|
||||
{
|
||||
textures.clear();
|
||||
const LLDrawable* drawable = attached_object->mDrawable;
|
||||
if (drawable)
|
||||
{
|
||||
const LLVOVolume* volume = drawable->getVOVolume();
|
||||
if (volume)
|
||||
{
|
||||
cost += volume->getRenderCost(textures);
|
||||
|
||||
const_child_list_t children = volume->getChildren();
|
||||
for (const_child_list_t::const_iterator child_iter = children.begin();
|
||||
child_iter != children.end();
|
||||
++child_iter)
|
||||
{
|
||||
LLViewerObject* child_obj = *child_iter;
|
||||
LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj );
|
||||
if (child)
|
||||
{
|
||||
cost += child->getRenderCost(textures);
|
||||
}
|
||||
}
|
||||
|
||||
for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
|
||||
{
|
||||
// add the cost of each individual texture in the linkset
|
||||
cost += iter->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 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.
|
||||
if (isSelf())
|
||||
{
|
||||
// print any attachment textures we didn't already know about.
|
||||
for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it)
|
||||
{
|
||||
LLUUID image_id = it->first;
|
||||
if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
|
||||
continue;
|
||||
if (all_textures.find(image_id) == all_textures.end())
|
||||
{
|
||||
// attachment texture not previously seen.
|
||||
llinfos << "attachment_texture: " << image_id.asString() << llendl;
|
||||
all_textures.insert(image_id);
|
||||
}
|
||||
}
|
||||
|
||||
// print any avatar textures we didn't already know about
|
||||
for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
|
||||
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
|
||||
++iter)
|
||||
{
|
||||
const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
|
||||
// TODO: MULTI-WEARABLE: handle multiple textures for self
|
||||
const LLViewerTexture* te_image = getImage(iter->first,0);
|
||||
if (!te_image)
|
||||
continue;
|
||||
LLUUID image_id = te_image->getID();
|
||||
if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
|
||||
continue;
|
||||
if (all_textures.find(image_id) == all_textures.end())
|
||||
{
|
||||
llinfos << "local_texture: " << texture_dict->mName << ": " << image_id << llendl;
|
||||
all_textures.insert(image_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus());
|
||||
setDebugText(llformat("%s %d", viz_string.c_str(), cost));
|
||||
mVisualComplexity = cost;
|
||||
F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f);
|
||||
F32 red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f);
|
||||
mText->setColor(LLColor4(red,green,0,1));
|
||||
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
|
||||
|
|
|
|||
|
|
@ -252,6 +252,7 @@ public:
|
|||
static void invalidateNameTags();
|
||||
void addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font);
|
||||
void idleUpdateRenderCost();
|
||||
void updateVisualComplexity() { mVisualComplexityStale = TRUE; }
|
||||
void idleUpdateBelowWater();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
|
@ -314,6 +315,7 @@ private:
|
|||
BOOL mFullyLoadedInitialized;
|
||||
S32 mFullyLoadedFrameCounter;
|
||||
S32 mVisualComplexity;
|
||||
BOOL mVisualComplexityStale;
|
||||
LLFrameTimer mFullyLoadedTimer;
|
||||
LLFrameTimer mRuthTimer;
|
||||
|
||||
|
|
@ -437,7 +439,6 @@ public:
|
|||
U32 renderRigid();
|
||||
U32 renderSkinned(EAvatarRenderPass pass);
|
||||
F32 getLastSkinTime() { return mLastSkinTime; }
|
||||
U32 renderSkinnedAttachments();
|
||||
U32 renderTransparent(BOOL first_pass);
|
||||
void renderCollisionVolumes();
|
||||
static void deleteCachedImages(bool clearAll=true);
|
||||
|
|
|
|||
|
|
@ -1116,6 +1116,12 @@ void LLVOVolume::notifyMeshLoaded()
|
|||
{
|
||||
mSculptChanged = TRUE;
|
||||
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
|
||||
|
||||
LLVOAvatar* avatar = getAvatar();
|
||||
if (avatar)
|
||||
{
|
||||
avatar->updateVisualComplexity();
|
||||
}
|
||||
}
|
||||
|
||||
// sculpt replaces generate() for sculpted surfaces
|
||||
|
|
|
|||
|
|
@ -10247,6 +10247,13 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
|||
avatar->mImpostor.bindTarget();
|
||||
}
|
||||
|
||||
F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha;
|
||||
|
||||
if (muted)
|
||||
{ //disable alpha masking for muted avatars (get whole skin silhouette)
|
||||
LLDrawPoolAvatar::sMinimumAlpha = 0.f;
|
||||
}
|
||||
|
||||
if (LLPipeline::sRenderDeferred)
|
||||
{
|
||||
avatar->mImpostor.clear();
|
||||
|
|
@ -10260,7 +10267,9 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
|||
avatar->mImpostor.clear();
|
||||
renderGeom(camera);
|
||||
}
|
||||
|
||||
|
||||
LLDrawPoolAvatar::sMinimumAlpha = old_alpha;
|
||||
|
||||
{ //create alpha mask based on depth buffer (grey out if muted)
|
||||
LLFastTimer t(FTM_IMPOSTOR_BACKGROUND);
|
||||
if (LLPipeline::sRenderDeferred)
|
||||
|
|
@ -10274,6 +10283,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
|||
if (muted)
|
||||
{
|
||||
gGL.setColorMask(true, true);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -10292,25 +10302,36 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
|||
gGL.pushMatrix();
|
||||
gGL.loadIdentity();
|
||||
|
||||
static const F32 clip_plane = 0.99999f;
|
||||
static const F32 clip_plane = 0.999f;
|
||||
|
||||
if (LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
gUIProgram.bind();
|
||||
gDebugProgram.bind();
|
||||
}
|
||||
|
||||
gGL.color4ub(64,64,64,255);
|
||||
gGL.begin(LLRender::QUADS);
|
||||
gGL.vertex3f(-1, -1, clip_plane);
|
||||
gGL.vertex3f(1, -1, clip_plane);
|
||||
gGL.vertex3f(1, 1, clip_plane);
|
||||
gGL.vertex3f(-1, 1, clip_plane);
|
||||
gGL.end();
|
||||
gGL.flush();
|
||||
|
||||
if (LLMuteList::getInstance()->isMuted(avatar->getID()))
|
||||
{ //grey muted avatar
|
||||
gGL.diffuseColor4ub(64,64,64,255);
|
||||
}
|
||||
else
|
||||
{ //blue visually muted avatar
|
||||
gGL.diffuseColor4ub(72,61,139,255);
|
||||
}
|
||||
|
||||
{
|
||||
gGL.begin(LLRender::QUADS);
|
||||
gGL.vertex3f(-1, -1, clip_plane);
|
||||
gGL.vertex3f(1, -1, clip_plane);
|
||||
gGL.vertex3f(1, 1, clip_plane);
|
||||
gGL.vertex3f(-1, 1, clip_plane);
|
||||
gGL.end();
|
||||
gGL.flush();
|
||||
}
|
||||
|
||||
if (LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
gUIProgram.unbind();
|
||||
gDebugProgram.unbind();
|
||||
}
|
||||
|
||||
gGL.popMatrix();
|
||||
|
|
|
|||
|
|
@ -202,6 +202,45 @@ Message Template [PATH] not found.
|
|||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="notify.tga"
|
||||
name="ExceededHighDetailRenderCost"
|
||||
persist="false"
|
||||
type="alertmodal">
|
||||
Your avatar has become too complex to be rendered by even high performance computers. Almost all Residents will see a low detail stand in instead of your actual avatar.
|
||||
<unique/>
|
||||
<usetemplate
|
||||
ignoretext="Avatar exceeded high detail complexity."
|
||||
name="okignore"
|
||||
yestext="Close"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="notify.tga"
|
||||
name="ExceededMidDetailRenderCost"
|
||||
persist="false"
|
||||
type="alertmodal">
|
||||
Your avatar has become too complex to be rendered by most computers. Many Residents will see a low detail stand in instead of your actual avatar.
|
||||
<unique/>
|
||||
<usetemplate
|
||||
ignoretext="Avatar exceeded mid detail complexity."
|
||||
name="okignore"
|
||||
yestext="Close"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="notify.tga"
|
||||
name="ExceededLowDetailRenderCost"
|
||||
persist="false"
|
||||
type="alertmodal">
|
||||
Your avatar has become too complex to be rendered by some computers. Some Residents will see a low detail stand in instead of your actual avatar.
|
||||
<unique/>
|
||||
<usetemplate
|
||||
ignoretext="Avatar exceeded low detail complexity."
|
||||
name="okignore"
|
||||
yestext="Close"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="WearableSave"
|
||||
|
|
@ -9935,5 +9974,5 @@ An internal error prevented us from properly updating your viewer. The L$ balan
|
|||
<tag>fail</tag>
|
||||
Cannot create large prims that intersect other players. Please re-try when other players have moved.
|
||||
</notification>
|
||||
|
||||
|
||||
</notifications>
|
||||
|
|
|
|||
Loading…
Reference in New Issue