diff options
author | Dave Parks <davep@lindenlab.com> | 2022-06-06 19:57:03 -0500 |
---|---|---|
committer | Dave Parks <davep@lindenlab.com> | 2022-06-06 19:57:03 -0500 |
commit | 616f2b639bc6907e810664522304305337646292 (patch) | |
tree | 29c98de959f080d07784687a838e01b5280cd17a | |
parent | 0fe8493b5a531bb0fbc431f54ee25f8e2923b5bf (diff) |
SL-17532 Potential fix for some rigged mesh draw order issues.
-rw-r--r-- | indra/newview/app_settings/shaders/class1/deferred/materialF.glsl | 13 | ||||
-rw-r--r-- | indra/newview/lldrawable.h | 1 | ||||
-rw-r--r-- | indra/newview/lldrawpoolalpha.cpp | 43 | ||||
-rw-r--r-- | indra/newview/llspatialpartition.cpp | 59 | ||||
-rw-r--r-- | indra/newview/llspatialpartition.h | 2 | ||||
-rw-r--r-- | indra/newview/llviewershadermgr.cpp | 12 | ||||
-rw-r--r-- | indra/newview/llvovolume.cpp | 51 |
7 files changed, 161 insertions, 20 deletions
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl index 02d83925ea..b26194f278 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl @@ -202,7 +202,7 @@ VARYING vec2 vary_texcoord2; uniform float env_intensity; uniform vec4 specular_color; // specular color RGB and specular exponent (glossiness) in alpha -#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK) +#ifdef HAS_ALPHA_MASK uniform float minimum_alpha; #endif @@ -227,11 +227,12 @@ void main() vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy); diffcol.rgb *= vertex_color.rgb; -#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK) - - // Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points - float bias = 0.001953125; // 1/512, or half an 8-bit quantization - if (diffcol.a < minimum_alpha-bias) +#ifdef HAS_ALPHA_MASK +#if DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND + if (diffcol.a*vertex_color.a < minimum_alpha) +#else + if (diffcol.a < minimum_alpha) +#endif { discard; } diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 2372ea01a6..2a0f4c93ac 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -133,6 +133,7 @@ public: inline LLFace* getFace(const S32 i) const; inline S32 getNumFaces() const; face_list_t& getFaces() { return mFaces; } + const face_list_t& getFaces() const { return mFaces; } //void removeFace(const S32 i); // SJB: Avoid using this, it's slow LLFace* addFace(LLFacePool *poolp, LLViewerTexture *texturep); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index e674707c01..70ffd85608 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -50,6 +50,8 @@ #include "llglcommonfunc.h" #include "llvoavatar.h" +#pragma optimize("", off) + BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE; #define current_shader (LLGLSLShader::sCurBoundShaderPtr) @@ -58,8 +60,11 @@ static BOOL deferred_render = FALSE; // minimum alpha before discarding a fragment static const F32 MINIMUM_ALPHA = 0.004f; // ~ 1/255 +static const F32 MINIMUM_RIGGED_ALPHA = MINIMUM_ALPHA; + // minimum alpha before discarding a fragment when rendering impostors static const F32 MINIMUM_IMPOSTOR_ALPHA = 0.1f; +static const F32 MINIMUM_IMPOSTOR_RIGGED_ALPHA = 0.1f; LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) : LLRenderPass(type), target_shader(NULL), @@ -111,11 +116,25 @@ static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma, bool d if (LLPipeline::sImpostorRender) { - shader->setMinimumAlpha(MINIMUM_IMPOSTOR_ALPHA); + if (shader->mRiggedVariant == shader) + { + shader->setMinimumAlpha(MINIMUM_IMPOSTOR_RIGGED_ALPHA); + } + else + { + shader->setMinimumAlpha(MINIMUM_IMPOSTOR_ALPHA); + } } else { - shader->setMinimumAlpha(MINIMUM_ALPHA); + if (shader->mRiggedVariant == shader) + { + shader->setMinimumAlpha(MINIMUM_RIGGED_ALPHA); + } + else + { + shader->setMinimumAlpha(MINIMUM_ALPHA); + } } if (textureGamma) { @@ -147,6 +166,10 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass) (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram; prepare_alpha_shader(simple_shader, false, true); //prime simple shader (loads shadow relevant uniforms) + for (int i = 0; i < LLMaterial::SHADER_COUNT; ++i) + { + prepare_alpha_shader(LLPipeline::sUnderWaterRender ? &gDeferredMaterialWaterProgram[i] : &gDeferredMaterialProgram[i], false, false); // note: bindDeferredShader will get called during render loop for materials + } // first pass, render rigged objects only and render to depth buffer forwardRender(true); @@ -184,7 +207,7 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass) } //set some generic parameters for forward (non-deferred) rendering -static void prepare_forward_shader(LLGLSLShader* shader, F32 minimum_alpha) +static void prepare_forward_shader(LLGLSLShader* shader, F32 minimum_alpha, F32 minimum_rigged_alpha) { shader->bind(); shader->setMinimumAlpha(minimum_alpha); @@ -193,7 +216,7 @@ static void prepare_forward_shader(LLGLSLShader* shader, F32 minimum_alpha) //also prepare rigged variant if (shader->mRiggedVariant && shader->mRiggedVariant != shader) { - prepare_forward_shader(shader->mRiggedVariant, minimum_alpha); + prepare_forward_shader(shader->mRiggedVariant, minimum_rigged_alpha, minimum_rigged_alpha); } } @@ -211,12 +234,20 @@ void LLDrawPoolAlpha::render(S32 pass) (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; F32 minimum_alpha = MINIMUM_ALPHA; + F32 minimum_rigged_alpha = MINIMUM_RIGGED_ALPHA; if (LLPipeline::sImpostorRender) { minimum_alpha = MINIMUM_IMPOSTOR_ALPHA; + minimum_rigged_alpha = MINIMUM_IMPOSTOR_RIGGED_ALPHA; + } + + prepare_forward_shader(fullbright_shader, minimum_alpha, minimum_rigged_alpha); + prepare_forward_shader(simple_shader, minimum_alpha, minimum_rigged_alpha); + + for (int i = 0; i < LLMaterial::SHADER_COUNT; ++i) + { + prepare_forward_shader(LLPipeline::sUnderWaterRender ? &gDeferredMaterialWaterProgram[i] : &gDeferredMaterialProgram[i], minimum_alpha, minimum_rigged_alpha); } - 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); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 0d53950889..c16a1854be 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1567,6 +1567,62 @@ void pushVertsColorCoded(LLSpatialGroup* group, U32 mask) } } +// return false if drawable is rigged and: +// - a linked rigged drawable has a different spatial group +// - a linked rigged drawable face has the wrong draw order index +bool check_rigged_group(LLDrawable* drawable) +{ + if (drawable->isState(LLDrawable::RIGGED)) + { + LLSpatialGroup* group = drawable->getSpatialGroup(); + LLDrawable* root = drawable->getRoot(); + + if (root->isState(LLDrawable::RIGGED) && root->getSpatialGroup() != group) + { + llassert(false); + return false; + } + + S32 last_draw_index = -1; + if (root->isState(LLDrawable::RIGGED)) + { + for (auto& face : root->getFaces()) + { + if ((S32) face->getDrawOrderIndex() <= last_draw_index) + { + llassert(false); + return false; + } + last_draw_index = face->getDrawOrderIndex(); + } + } + + for (auto& child : root->getVObj()->getChildren()) + { + if (child->mDrawable->isState(LLDrawable::RIGGED)) + { + for (auto& face : child->mDrawable->getFaces()) + { + if ((S32) face->getDrawOrderIndex() <= last_draw_index) + { + llassert(false); + return false; + } + last_draw_index = face->getDrawOrderIndex(); + } + } + + if (child->mDrawable->getSpatialGroup() != group) + { + llassert(false); + return false; + } + } + } + + return true; +} + void renderOctree(LLSpatialGroup* group) { //render solid object bounding box, color @@ -1611,6 +1667,9 @@ void renderOctree(LLSpatialGroup* group) { continue; } + + llassert(check_rigged_group(drawable)); + if (!group->getSpatialPartition()->isBridge()) { gGL.pushMatrix(); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 6d3ef33801..f7bc9fb644 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -264,7 +264,7 @@ public: return lhs->mAvatarp < rhs->mAvatarp; } - return lhs->mRenderOrder > rhs->mRenderOrder; + return lhs->mRenderOrder < rhs->mRenderOrder; } }; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 086b433c72..e926c5c3ba 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -1484,6 +1484,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredMaterialProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode)); + if (alpha_mode != 0) + { + gDeferredMaterialProgram[i].mFeatures.hasAlphaMask = true; + gDeferredMaterialProgram[i].addPermutation("HAS_ALPHA_MASK", "1"); + } + if (use_sun_shadow) { gDeferredMaterialProgram[i].addPermutation("HAS_SUN_SHADOW", "1"); @@ -1542,6 +1548,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() } gDeferredMaterialWaterProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode)); + if (alpha_mode != 0) + { + gDeferredMaterialWaterProgram[i].mFeatures.hasAlphaMask = true; + gDeferredMaterialWaterProgram[i].addPermutation("HAS_ALPHA_MASK", "1"); + } + if (use_sun_shadow) { gDeferredMaterialWaterProgram[i].addPermutation("HAS_SUN_SHADOW", "1"); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 126a25115d..eb1e2cbd80 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5480,7 +5480,7 @@ static inline void add_face(T*** list, U32* count, T* face) { if (count[1] < MAX_FACE_COUNT) { - face->setDrawOrderIndex(count[1]); + //face->setDrawOrderIndex(count[1]); list[1][count[1]++] = face; } } @@ -5488,15 +5488,40 @@ static inline void add_face(T*** list, U32* count, T* face) { if (count[0] < MAX_FACE_COUNT) { - face->setDrawOrderIndex(count[0]); + //face->setDrawOrderIndex(count[0]); list[0][count[0]++] = face; } } } +// return index into linkset for given object (0 for root prim) +U32 get_linkset_index(LLVOVolume* vobj) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE; + if (vobj->isRootEdit()) + { + return 0; + } + + LLViewerObject* root = vobj->getRootEdit(); + U32 idx = 1; + for (auto& child : root->getChildren()) + { + if (child == vobj) + { + return idx; + } + ++idx; + } + + llassert(false); + return idx; //should never get here +} + void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; + if (group->changeLOD()) { group->mLastUpdateDistance = group->mDistance; @@ -5655,6 +5680,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) avatar->addAttachmentOverridesForObject(vobj, NULL, false); } + U32 linkset_index = get_linkset_index(vobj); + // Standard rigged mesh attachments: bool rigged = !vobj->isAnimatedObject() && skinInfo && vobj->isAttachment(); // Animated objects. Have to check for isRiggedMesh() to @@ -5674,6 +5701,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) continue; } + // order by linkset index first and face index second + facep->setDrawOrderIndex(linkset_index * 100 + i); + //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render // batch, it will recover its vertex buffer reference from the spatial group facep->setVertexBuffer(NULL); @@ -5698,11 +5728,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (facep->isState(LLFace::RIGGED)) { //face is not rigged but used to be, remove from rigged face pool - LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); - if (pool) - { - pool->removeFace(facep); - } facep->clearState(LLFace::RIGGED); facep->mAvatar = NULL; facep->mSkinInfo = NULL; @@ -6158,6 +6183,13 @@ struct CompareBatchBreakerRigged } }; +struct CompareDrawOrder +{ + bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) + { + return lhs->getDrawOrderIndex() < rhs->getDrawOrderIndex(); + } +}; U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL rigged) { @@ -6202,6 +6234,11 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace //sort faces by things that break batches, including avatar and mesh id std::sort(faces, faces + face_count, CompareBatchBreakerRigged()); } + else + { + // preserve legacy draw order for rigged faces + std::sort(faces, faces + face_count, CompareDrawOrder()); + } } else if (!distance_sort) { |