diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index c74d531398..b324ed65c7 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2112,6 +2112,8 @@ set(viewer_APPSETTINGS_FILES ${CMAKE_SOURCE_DIR}/../etc/message.xml ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg packages-info.txt + featuretable.txt + featuretable_mac.txt ) if (WINDOWS) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f876a7828e..e751445ba8 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12852,7 +12852,7 @@ Change of this parameter will affect the layout of buttons in notification toast Value 2.2 - RenderGLCoreProfile + RenderGLContextCoreProfile Comment Don't use a compatibility profile OpenGL context. Requires restart. diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 5977908ea9..f7ae1aa9d3 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -70,7 +70,7 @@ RenderShadowDetail 1 2 RenderUseStreamVBO 1 1 RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 -RenderGLCoreProfile 1 1 +RenderGLContextCoreProfile 1 1 RenderGLMultiThreaded 1 1 @@ -314,12 +314,12 @@ list Intel RenderAnisotropic 1 0 RenderFSAASamples 1 0 RenderGLMultiThreaded 1 0 -RenderGLCoreProfile 1 0 +RenderGLContextCoreProfile 1 0 // AMD cards generally perform better when not using VBOs for streaming data // AMD cards also prefer an OpenGL Compatibility Profile Context list AMD RenderUseStreamVBO 1 0 -RenderGLCoreProfile 1 0 +RenderGLContextCoreProfile 1 0 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 422a84f4de..601cb6e5e7 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -70,7 +70,7 @@ RenderShadowDetail 1 2 RenderUseStreamVBO 1 1 RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 -RenderGLCoreProfile 1 0 +RenderGLContextCoreProfile 1 0 RenderGLMultiThreaded 1 0 // diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9203663a2b..2b0fae1bc9 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -607,7 +607,7 @@ static void settings_to_globals() LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize")); - LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLCoreProfile"); + LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLContextCoreProfile"); LLRender::sNsightDebugSupport = gSavedSettings.getBOOL("RenderNsightDebugSupport"); // Vertex Array Objects are required in OpenGL core profile LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO"); diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index d4f30fc51a..fd1b022e5b 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -183,6 +183,7 @@ public: PASS_GLOW, PASS_GLOW_RIGGED, PASS_ALPHA, + PASS_ALPHA_RIGGED, PASS_ALPHA_MASK, PASS_ALPHA_MASK_RIGGED, PASS_FULLBRIGHT_ALPHA_MASK, // Diffuse texture used as alpha mask and fullbright diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 29ee729e1a..28d4a1bcaf 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -130,23 +130,26 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass) LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; deferred_render = TRUE; - // first pass, regular forward alpha rendering - { - emissive_shader = (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; - prepare_alpha_shader(emissive_shader, true, false); + // prepare shaders + emissive_shader = (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; + prepare_alpha_shader(emissive_shader, true, false); - fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightProgram : - (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightProgram; - prepare_alpha_shader(fullbright_shader, true, false); + fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightProgram : + (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightProgram; + prepare_alpha_shader(fullbright_shader, true, false); - simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram : - (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram; - prepare_alpha_shader(simple_shader, false, true); //prime simple shader (loads shadow relevant uniforms) - - forwardRender(); - } + simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram : + (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram; + prepare_alpha_shader(simple_shader, false, true); //prime simple shader (loads shadow relevant uniforms) - // second pass, render to depth for depth of field effects + + // first pass, render rigged objects only and render to depth buffer + forwardRender(true); + + // second pass, regular forward alpha rendering + forwardRender(); + + // final pass, render to depth for depth of field effects if (!LLPipeline::sImpostorRender && gSavedSettings.getBOOL("RenderDepthOfField")) { //update depth buffer sampler @@ -210,10 +213,14 @@ void LLDrawPoolAlpha::render(S32 pass) prepare_forward_shader(fullbright_shader, minimum_alpha); prepare_forward_shader(simple_shader, minimum_alpha); + //first pass -- rigged only and drawn to depth buffer + forwardRender(true); + + //second pass -- non-rigged, no depth buffer writes forwardRender(); } -void LLDrawPoolAlpha::forwardRender() +void LLDrawPoolAlpha::forwardRender(bool rigged) { gPipeline.enableLightsDynamic(); @@ -222,7 +229,8 @@ void LLDrawPoolAlpha::forwardRender() //enable writing to alpha for emissive effects gGL.setColorMask(true, true); - bool write_depth = LLDrawPoolWater::sSkipScreenCopy + bool write_depth = rigged + || LLDrawPoolWater::sSkipScreenCopy // we want depth written so that rendered alpha will // contribute to the alpha mask used for impostors || LLPipeline::sImpostorRenderAlphaDepthPass; @@ -237,11 +245,17 @@ void LLDrawPoolAlpha::forwardRender() // If the face is more than 90% transparent, then don't update the Depth buffer for Dof // We don't want the nearly invisible objects to cause of DoF effects - renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2); + renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, false, rigged); gGL.setColorMask(true, false); - renderDebugAlpha(); + if (!rigged) + { //render "highlight alpha" on final non-rigged pass + // NOTE -- hacky call here protected by !rigged instead of alongside "forwardRender" + // so renderDebugAlpha is executed while gls_pipeline_alpha and depth GL state + // variables above are still in scope + renderDebugAlpha(); + } } void LLDrawPoolAlpha::renderDebugAlpha() @@ -293,65 +307,71 @@ void LLDrawPoolAlpha::renderDebugAlpha() void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) { LL_PROFILE_ZONE_SCOPED; - LLVOAvatar* lastAvatar = nullptr; - U64 lastMeshId = 0; + for (int pass = 0; pass < 2; ++pass) + { //two passes, one rigged and one not + LLVOAvatar* lastAvatar = nullptr; + U64 lastMeshId = 0; - for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) - { - LLSpatialGroup* group = *i; - if (group->getSpatialPartition()->mRenderByGroup && - !group->isDead()) - { - LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; + LLCullResult::sg_iterator begin = pass == 0 ? gPipeline.beginAlphaGroups() : gPipeline.beginRiggedAlphaGroups(); + LLCullResult::sg_iterator end = pass == 0 ? gPipeline.endAlphaGroups() : gPipeline.endRiggedAlphaGroups(); - std::unique_ptr ratPtr{}; // Render time Stats collection - for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) - { - LLDrawInfo& params = **k; - // Capture render times - if(params.mFace) - { - LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject(); - if(vobj->isAttachment()) - { - trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr ); - } - } - // - - if (params.mParticle) - { - continue; - } + for (LLCullResult::sg_iterator i = begin; i != end; ++i) + { + LLSpatialGroup* group = *i; + if (group->getSpatialPartition()->mRenderByGroup && + !group->isDead()) + { + LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA+pass]; // <-- hacky + pass to use PASS_ALPHA_RIGGED on second pass - bool rigged = (params.mAvatar != nullptr); - gHighlightProgram.bind(rigged); - gGL.diffuseColor4f(1, 0, 0, 1); - - if (rigged) + std::unique_ptr ratPtr{}; // Render time Stats collection + for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { - if (lastAvatar != params.mAvatar || - lastMeshId != params.mSkinInfo->mHash) + LLDrawInfo& params = **k; + // Capture render times + if(params.mFace) { - if (!uploadMatrixPalette(params)) + LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject(); + if(vobj->isAttachment()) { - continue; + trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr ); } - lastAvatar = params.mAvatar; - lastMeshId = params.mSkinInfo->mHash; } - } + // - LLRenderPass::applyModelMatrix(params); - if (params.mGroup) - { - params.mGroup->rebuildMesh(); - } - params.mVertexBuffer->setBufferFast(rigged ? mask | LLVertexBuffer::MAP_WEIGHT4 : mask); - params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - } - } - } + if (params.mParticle) + { + continue; + } + + bool rigged = (params.mAvatar != nullptr); + gHighlightProgram.bind(rigged); + gGL.diffuseColor4f(1, 0, 0, 1); + + if (rigged) + { + if (lastAvatar != params.mAvatar || + lastMeshId != params.mSkinInfo->mHash) + { + if (!uploadMatrixPalette(params)) + { + continue; + } + lastAvatar = params.mAvatar; + lastMeshId = params.mSkinInfo->mHash; + } + } + + LLRenderPass::applyModelMatrix(params); + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } + params.mVertexBuffer->setBufferFast(rigged ? mask | LLVertexBuffer::MAP_WEIGHT4 : mask); + params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + } + } + } + } // make sure static version of highlight shader is bound before returning gHighlightProgram.bind(); @@ -484,6 +504,8 @@ void LLDrawPoolAlpha::renderRiggedEmissives(U32 mask, std::vector& LLVOAvatar* lastAvatar = nullptr; U64 lastMeshId = 0; + mask |= LLVertexBuffer::MAP_WEIGHT4; + std::unique_ptr ratPtr{}; // Render time Stats collection for (LLDrawInfo* draw : emissives) { @@ -511,7 +533,7 @@ void LLDrawPoolAlpha::renderRiggedEmissives(U32 mask, std::vector& } } -void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only) +void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; BOOL initialized_lighting = FALSE; @@ -521,7 +543,21 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only) U64 lastMeshId = 0; LLGLSLShader* lastAvatarShader = nullptr; - for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) + LLCullResult::sg_iterator begin; + LLCullResult::sg_iterator end; + + if (rigged) + { + begin = gPipeline.beginRiggedAlphaGroups(); + end = gPipeline.endRiggedAlphaGroups(); + } + else + { + begin = gPipeline.beginAlphaGroups(); + end = gPipeline.endAlphaGroups(); + } + + for (LLCullResult::sg_iterator i = begin; i != end; ++i) { LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("renderAlpha - group"); LLSpatialGroup* group = *i; @@ -553,13 +589,19 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only) bool disable_cull = is_particle_or_hud_particle; LLGLDisable cull(disable_cull ? GL_CULL_FACE : 0); - LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; + LLSpatialGroup::drawmap_elem_t& draw_info = rigged ? group->mDrawMap[LLRenderPass::PASS_ALPHA_RIGGED] : group->mDrawMap[LLRenderPass::PASS_ALPHA]; std::unique_ptr ratPtr{}; // Render time Stats collection for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { - LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("ra - push batch") LLDrawInfo& params = **k; + if ((bool)params.mAvatar != rigged) + { + continue; + } + + LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("ra - push batch") + U32 have_mask = params.mVertexBuffer->getTypeMask() & mask; if (have_mask != mask) { //FIXME! diff --git a/indra/newview/lldrawpoolalpha.h b/indra/newview/lldrawpoolalpha.h index 1f6909e282..fa8ef0f227 100644 --- a/indra/newview/lldrawpoolalpha.h +++ b/indra/newview/lldrawpoolalpha.h @@ -55,13 +55,13 @@ public: /*virtual*/ S32 getNumPasses() { return 1; } virtual void render(S32 pass = 0); - void forwardRender(); + void forwardRender(bool write_depth = false); /*virtual*/ void prerender(); void renderDebugAlpha(); void renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE); - void renderAlpha(U32 mask, bool depth_only = false); + void renderAlpha(U32 mask, bool depth_only = false, bool rigged = false); void renderAlphaHighlight(U32 mask); bool uploadMatrixPalette(const LLDrawInfo& params); diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 6153942fa0..3767836355 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -526,9 +526,10 @@ void LLDrawPoolWater::renderWater() LLColor4 specular(sun_up ? psky->getSunlightColor() : psky->getMoonlightColor()); F32 phase_time = (F32) LLFrameTimer::getElapsedSeconds() * 0.5f; - bool edge = false; LLGLSLShader *shader = nullptr; - do // twice through, once with normal shader bound & once with edge shader bound + + // two passes, first with standard water shader bound, second with edge water shader bound + for( int edge = 0 ; edge < 2; edge++ ) { // select shader if (underwater && LLPipeline::sWaterReflections) @@ -681,7 +682,7 @@ void LLDrawPoolWater::renderWater() gGL.getTexUnit(diffTex)->bind(face->getTexture()); - if (edge == (bool) water->getIsEdgePatch()) + if ((bool)edge == (bool) water->getIsEdgePatch()) { face->renderIndexed(); @@ -705,9 +706,7 @@ void LLDrawPoolWater::renderWater() shader->unbind(); gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); - - edge = !edge; - } while (!edge); + } gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 6f7c8b4331..aa884d73c9 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -4222,6 +4222,7 @@ LLCullResult::LLCullResult() { mVisibleGroupsAllocated = 0; mAlphaGroupsAllocated = 0; + mRiggedAlphaGroupsAllocated = 0; mOcclusionGroupsAllocated = 0; mDrawableGroupsAllocated = 0; mVisibleListAllocated = 0; @@ -4233,6 +4234,9 @@ LLCullResult::LLCullResult() mAlphaGroups.clear(); mAlphaGroups.push_back(NULL); mAlphaGroupsEnd = &mAlphaGroups[0]; + mRiggedAlphaGroups.clear(); + mRiggedAlphaGroups.push_back(NULL); + mRiggedAlphaGroupsEnd = &mRiggedAlphaGroups[0]; mOcclusionGroups.clear(); mOcclusionGroups.push_back(NULL); mOcclusionGroupsEnd = &mOcclusionGroups[0]; @@ -4275,6 +4279,9 @@ void LLCullResult::clear() mAlphaGroupsSize = 0; mAlphaGroupsEnd = &mAlphaGroups[0]; + mRiggedAlphaGroupsSize = 0; + mRiggedAlphaGroupsEnd = &mRiggedAlphaGroups[0]; + mOcclusionGroupsSize = 0; mOcclusionGroupsEnd = &mOcclusionGroups[0]; @@ -4319,6 +4326,16 @@ LLCullResult::sg_iterator LLCullResult::endAlphaGroups() return mAlphaGroupsEnd; } +LLCullResult::sg_iterator LLCullResult::beginRiggedAlphaGroups() +{ + return &mRiggedAlphaGroups[0]; +} + +LLCullResult::sg_iterator LLCullResult::endRiggedAlphaGroups() +{ + return mRiggedAlphaGroupsEnd; +} + LLCullResult::sg_iterator LLCullResult::beginOcclusionGroups() { return &mOcclusionGroups[0]; @@ -4397,6 +4414,20 @@ void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) mAlphaGroupsEnd = &mAlphaGroups[mAlphaGroupsSize]; } +void LLCullResult::pushRiggedAlphaGroup(LLSpatialGroup* group) +{ + if (mRiggedAlphaGroupsSize < mRiggedAlphaGroupsAllocated) + { + mRiggedAlphaGroups[mRiggedAlphaGroupsSize] = group; + } + else + { + pushBack(mRiggedAlphaGroups, mRiggedAlphaGroupsAllocated, group); + } + ++mRiggedAlphaGroupsSize; + mRiggedAlphaGroupsEnd = &mRiggedAlphaGroups[mRiggedAlphaGroupsSize]; +} + void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) { if (mOcclusionGroupsSize < mOcclusionGroupsAllocated) diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 093f50abf9..b191a32b6d 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -481,6 +481,9 @@ public: sg_iterator beginAlphaGroups(); sg_iterator endAlphaGroups(); + sg_iterator beginRiggedAlphaGroups(); + sg_iterator endRiggedAlphaGroups(); + bool hasOcclusionGroups() { return mOcclusionGroupsSize > 0; } sg_iterator beginOcclusionGroups(); sg_iterator endOcclusionGroups(); @@ -499,6 +502,7 @@ public: void pushVisibleGroup(LLSpatialGroup* group); void pushAlphaGroup(LLSpatialGroup* group); + void pushRiggedAlphaGroup(LLSpatialGroup* group); void pushOcclusionGroup(LLSpatialGroup* group); void pushDrawableGroup(LLSpatialGroup* group); void pushDrawable(LLDrawable* drawable); @@ -507,6 +511,7 @@ public: U32 getVisibleGroupsSize() { return mVisibleGroupsSize; } U32 getAlphaGroupsSize() { return mAlphaGroupsSize; } + U32 getRiggedAlphaGroupsSize() { return mRiggedAlphaGroupsSize; } U32 getDrawableGroupsSize() { return mDrawableGroupsSize; } U32 getVisibleListSize() { return mVisibleListSize; } U32 getVisibleBridgeSize() { return mVisibleBridgeSize; } @@ -520,6 +525,7 @@ private: U32 mVisibleGroupsSize; U32 mAlphaGroupsSize; + U32 mRiggedAlphaGroupsSize; U32 mOcclusionGroupsSize; U32 mDrawableGroupsSize; U32 mVisibleListSize; @@ -527,6 +533,7 @@ private: U32 mVisibleGroupsAllocated; U32 mAlphaGroupsAllocated; + U32 mRiggedAlphaGroupsAllocated; U32 mOcclusionGroupsAllocated; U32 mDrawableGroupsAllocated; U32 mVisibleListAllocated; @@ -538,6 +545,8 @@ private: sg_iterator mVisibleGroupsEnd; sg_list_t mAlphaGroups; sg_iterator mAlphaGroupsEnd; + sg_list_t mRiggedAlphaGroups; + sg_iterator mRiggedAlphaGroupsEnd; sg_list_t mOcclusionGroups; sg_iterator mOcclusionGroupsEnd; sg_list_t mDrawableGroups; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index f0052767dd..a750ab8230 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -348,9 +348,8 @@ static bool handleAnisotropicChanged(const LLSD& newvalue) static bool handleVSyncChanged(const LLSD& newvalue) { -#if LL_WINDOWS gViewerWindow->getWindow()->toggleVSync(newvalue.asBoolean()); -#endif + return true; } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index cccde57f55..5cc9608d10 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -148,6 +148,9 @@ const F32 MIN_HOVER_Z = -2.0f; const F32 MIN_ATTACHMENT_COMPLEXITY = 0.f; const F32 DEFAULT_MAX_ATTACHMENT_COMPLEXITY = 1.0e6f; +// Unlike with 'self' avatar, server doesn't inform viewer about +// expected attachments so viewer has to wait to see if anything +// else will arrive const F32 FIRST_APPEARANCE_CLOUD_MIN_DELAY = 3.f; // seconds const F32 FIRST_APPEARANCE_CLOUD_MAX_DELAY = 45.f; @@ -779,7 +782,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mCurrentGesticulationLevel = 0; - mFirstSeenTimer.reset(); + mFirstAppearanceMessageTimer.reset(); mRuthTimer.reset(); mRuthDebugTimer.reset(); mDebugExistenceTimer.reset(); @@ -3037,7 +3040,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) //override rigged attachments' octree spatial extents with this avatar's bounding box LLSpatialBridge* bridge = attached_object->mDrawable->getSpatialBridge(); bool rigged = false; - if (bridge) + if (bridge && !bridge->isDead()) { //transform avatar bounding box into attachment's coordinate frame LLVector4a extents[2]; @@ -3054,13 +3057,21 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) attached_object->mDrawable->makeActive(); attached_object->mDrawable->updateXform(TRUE); - if (!rigged) + if (bridge && !bridge->isDead()) { - if (bridge) + if (!rigged) { gPipeline.updateMoveNormalAsync(bridge); } + else + { + //specialized impl of updateMoveNormalAsync just for rigged attachment SpatialBridge + bridge->setState(LLDrawable::MOVE_UNDAMPED); + bridge->updateMove(); + bridge->setState(LLDrawable::EARLY_MOVE); + } } + attached_object->updateText(); } } @@ -7248,6 +7259,16 @@ void LLVOAvatar::updateAttachmentOverrides() #endif } +void LLVOAvatar::notifyAttachmentMeshLoaded() +{ + if (!isFullyLoaded()) + { + // We just received mesh or skin info + // Reset timer to wait for more potential meshes or changes + mFullyLoadedTimer.reset(); + } +} + //----------------------------------------------------------------------------- // addAttachmentOverridesForObject //----------------------------------------------------------------------------- @@ -9096,7 +9117,7 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading) // Note that textures can causes 60s delay on thier own // so this delay might end up on top of textures' delay mFirstUseDelaySeconds = llclamp( - mFirstSeenTimer.getElapsedTimeF32(), + mFirstAppearanceMessageTimer.getElapsedTimeF32(), FIRST_APPEARANCE_CLOUD_MIN_DELAY, FIRST_APPEARANCE_CLOUD_MAX_DELAY); @@ -9987,6 +10008,9 @@ void LLVOAvatar::onFirstTEMessageReceived() mMeshTexturesDirty = TRUE; gPipeline.markGLRebuild(this); + + mFirstAppearanceMessageTimer.reset(); + mFullyLoadedTimer.reset(); } } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 5397b60608..99207bc6df 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -211,7 +211,7 @@ public: inline LLJoint* getSkeletonJoint(S32 joint_num) { return mSkeleton[joint_num]; } inline size_t getSkeletonJointCount() const { return mSkeleton.size(); } - + void notifyAttachmentMeshLoaded(); void addAttachmentOverridesForObject(LLViewerObject *vo, std::set* meshes_seen = NULL, bool recursive = true); void removeAttachmentOverridesForObject(const LLUUID& mesh_id); void removeAttachmentOverridesForObject(LLViewerObject *vo); @@ -411,7 +411,7 @@ protected: private: BOOL mFirstFullyVisible; F32 mFirstUseDelaySeconds; - LLFrameTimer mFirstSeenTimer; + LLFrameTimer mFirstAppearanceMessageTimer; BOOL mFullyLoaded; BOOL mPreviousFullyLoaded; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index d73028b13b..ab2c431a1f 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1320,13 +1320,17 @@ void LLVOVolume::notifyMeshLoaded() mSculptChanged = TRUE; gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); - if (getAvatar() && !isAnimatedObject()) + LLVOAvatar *av = getAvatar(); + if (av && !isAnimatedObject()) { - getAvatar()->addAttachmentOverridesForObject(this); + av->addAttachmentOverridesForObject(this); + av->notifyAttachmentMeshLoaded(); } - if (getControlAvatar() && isAnimatedObject()) + LLControlAvatar *cav = getControlAvatar(); + if (cav && isAnimatedObject()) { - getControlAvatar()->addAttachmentOverridesForObject(this); + cav->addAttachmentOverridesForObject(this); + cav->notifyAttachmentMeshLoaded(); } updateVisualComplexity(); } @@ -5404,7 +5408,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, bool rigged = facep->isState(LLFace::RIGGED); - if (rigged && type != LLRenderPass::PASS_ALPHA) + if (rigged) { // hacky, should probably clean up -- if this face is rigged, put it in "type + 1" // See LLRenderPass PASS_foo enum diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 15e37d4957..264dc6bcfe 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -4019,6 +4019,16 @@ void LLPipeline::postSort(LLCamera& camera) sCull->pushAlphaGroup(group); } } + + LLSpatialGroup::draw_map_t::iterator rigged_alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA_RIGGED); + + if (rigged_alpha != group->mDrawMap.end()) + { //store rigged alpha groups for LLDrawPoolAlpha prepass (skip distance update, rigged attachments use depth buffer) + if (hasRenderType(LLDrawPool::POOL_ALPHA)) + { + sCull->pushRiggedAlphaGroup(group); + } + } } } } @@ -9675,7 +9685,11 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLColor3 col = LLEnvironment::instance().getCurrentWater()->getWaterFogColor(); glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f); - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1; + // HACK FIX -- pretend underwater camera is the world camera to fix weird visibility artifacts + // during distortion render (doesn't break main render because the camera is the same perspective + // as world camera and occlusion culling is disabled for this pass) + //LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1; + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; mWaterDis.bindTarget(); mWaterDis.getViewport(gGLViewport); @@ -11514,6 +11528,16 @@ LLCullResult::sg_iterator LLPipeline::endAlphaGroups() return sCull->endAlphaGroups(); } +LLCullResult::sg_iterator LLPipeline::beginRiggedAlphaGroups() +{ + return sCull->beginRiggedAlphaGroups(); +} + +LLCullResult::sg_iterator LLPipeline::endRiggedAlphaGroups() +{ + return sCull->endRiggedAlphaGroups(); +} + bool LLPipeline::hasRenderType(const U32 type) const { // STORM-365 : LLViewerJointAttachment::setAttachmentVisibility() is setting type to 0 to actually mean "do not render" diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index c47f4584c5..09da2f2189 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -338,6 +338,8 @@ public: LLCullResult::drawinfo_iterator endRenderMap(U32 type); LLCullResult::sg_iterator beginAlphaGroups(); LLCullResult::sg_iterator endAlphaGroups(); + LLCullResult::sg_iterator beginRiggedAlphaGroups(); + LLCullResult::sg_iterator endRiggedAlphaGroups(); void addTrianglesDrawn(S32 index_count, U32 render_type = LLRender::TRIANGLES);