diff options
author | Andrey Lihatskiy <alihatskiy@productengine.com> | 2022-05-27 02:53:34 +0300 |
---|---|---|
committer | Andrey Lihatskiy <alihatskiy@productengine.com> | 2022-05-27 02:53:34 +0300 |
commit | b2ef95522f07301cfddbdace1042e60d52fde436 (patch) | |
tree | c51119f79b734a7d503bb3adeac1759b819c8f92 /indra/newview/lldrawpoolalpha.cpp | |
parent | 43a338c6270f9a000052465d09d4ad999524af0b (diff) | |
parent | 3da7a50b71d4ef5919c2d4d5b9547b3ef0abab7d (diff) |
Merge branch 'DRTVWR-543-maint' into DRTVWR-543-maint_cmake
Diffstat (limited to 'indra/newview/lldrawpoolalpha.cpp')
-rw-r--r-- | indra/newview/lldrawpoolalpha.cpp | 892 |
1 files changed, 433 insertions, 459 deletions
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 91b0e40aa9..e674707c01 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -48,34 +48,25 @@ #include "lldrawpoolwater.h" #include "llspatialpartition.h" #include "llglcommonfunc.h" +#include "llvoavatar.h" BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE; +#define current_shader (LLGLSLShader::sCurBoundShaderPtr) + static BOOL deferred_render = FALSE; -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SETUP("Alpha Setup"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_PUSH("Alpha Push Verts"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED("Alpha Deferred"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SETBUFFER("Alpha SetBuffer"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DRAW("Alpha Draw"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_TEX_BINDS("Alpha Tex Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MATS("Alpha Mat Tex Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GLOW("Alpha Glow Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SHADER_BINDS("Alpha Shader Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS("Alpha Def Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS("Alpha Def Tex Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MESH_REBUILD("Alpha Mesh Rebuild"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_EMISSIVE("Alpha Emissive"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_LIGHT_SETUP("Alpha Light Setup"); +// minimum alpha before discarding a fragment +static const F32 MINIMUM_ALPHA = 0.004f; // ~ 1/255 +// minimum alpha before discarding a fragment when rendering impostors +static const F32 MINIMUM_IMPOSTOR_ALPHA = 0.1f; LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) : - LLRenderPass(type), current_shader(NULL), target_shader(NULL), - simple_shader(NULL), fullbright_shader(NULL), emissive_shader(NULL), + LLRenderPass(type), target_shader(NULL), mColorSFactor(LLRender::BF_UNDEF), mColorDFactor(LLRender::BF_UNDEF), mAlphaSFactor(LLRender::BF_UNDEF), mAlphaDFactor(LLRender::BF_UNDEF) { - + } LLDrawPoolAlpha::~LLDrawPoolAlpha() @@ -86,232 +77,203 @@ LLDrawPoolAlpha::~LLDrawPoolAlpha() void LLDrawPoolAlpha::prerender() { mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + + // TODO: is this even necessay? These are probably set to never discard + LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(1024.f*1024.f); + LLViewerFetchedTexture::sWhiteImagep->addTextureStats(1024.f * 1024.f); } S32 LLDrawPoolAlpha::getNumPostDeferredPasses() { - if (LLPipeline::sImpostorRender) - { //skip depth buffer filling pass when rendering impostors - return 1; - } - else if (gSavedSettings.getBOOL("RenderDepthOfField")) - { - return 2; - } - else - { - return 1; - } + return 1; } -void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED); +// set some common parameters on the given shader to prepare for alpha rendering +static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma, bool deferredEnvironment) +{ + static LLCachedControl<F32> displayGamma(gSavedSettings, "RenderDeferredDisplayGamma"); + F32 gamma = displayGamma; + + // Does this deferred shader need environment uniforms set such as sun_dir, etc. ? + // NOTE: We don't actually need a gbuffer since we are doing forward rendering (for transparency) post deferred rendering + // TODO: bindDeferredShader() probably should have the updating of the environment uniforms factored out into updateShaderEnvironmentUniforms() + // i.e. shaders\class1\deferred\alphaF.glsl + if (deferredEnvironment) + { + gPipeline.bindDeferredShader( *shader ); + } + else + { + shader->bind(); + } + shader->uniform1i(LLShaderMgr::NO_ATMO, (LLPipeline::sRenderingHUDs) ? 1 : 0); + shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f)); + + if (LLPipeline::sImpostorRender) + { + shader->setMinimumAlpha(MINIMUM_IMPOSTOR_ALPHA); + } + else + { + shader->setMinimumAlpha(MINIMUM_ALPHA); + } + if (textureGamma) + { + shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); + } - F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); + //also prepare rigged variant + if (shader->mRiggedVariant && shader->mRiggedVariant != shader) + { + prepare_alpha_shader(shader->mRiggedVariant, textureGamma, deferredEnvironment); + } +} + +void LLDrawPoolAlpha::renderPostDeferred(S32 pass) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; + deferred_render = TRUE; + // prepare shaders emissive_shader = (LLPipeline::sRenderDeferred) ? &gDeferredEmissiveProgram : (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; + prepare_alpha_shader(emissive_shader, true, false); - emissive_shader->bind(); - emissive_shader->uniform1i(LLShaderMgr::NO_ATMO, (LLPipeline::sRenderingHUDs) ? 1 : 0); - emissive_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); - emissive_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); + fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightAlphaMaskProgram : + (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightAlphaMaskProgram; + prepare_alpha_shader(fullbright_shader, true, false); - if (pass == 0) - { - fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightProgram : - (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightProgram; + simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram : + (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram; + prepare_alpha_shader(simple_shader, false, true); //prime simple shader (loads shadow relevant uniforms) - fullbright_shader->bind(); - fullbright_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); - fullbright_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); - fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); - fullbright_shader->unbind(); - simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram : - (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram; + // first pass, render rigged objects only and render to depth buffer + forwardRender(true); - //prime simple shader (loads shadow relevant uniforms) - gPipeline.bindDeferredShader(*simple_shader); + // second pass, regular forward alpha rendering + forwardRender(); - simple_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); - } - else if (!LLPipeline::sImpostorRender) - { - //update depth buffer sampler - gPipeline.mScreen.flush(); - gPipeline.mDeferredDepth.copyContents(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), - 0, 0, gPipeline.mDeferredDepth.getWidth(), gPipeline.mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); - gPipeline.mDeferredDepth.bindTarget(); - simple_shader = fullbright_shader = &gObjectFullbrightAlphaMaskProgram; - gObjectFullbrightAlphaMaskProgram.bind(); - gObjectFullbrightAlphaMaskProgram.setMinimumAlpha(0.33f); - } + // final pass, render to depth for depth of field effects + if (!LLPipeline::sImpostorRender && gSavedSettings.getBOOL("RenderDepthOfField")) + { + //update depth buffer sampler + gPipeline.mScreen.flush(); + gPipeline.mDeferredDepth.copyContents(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), + 0, 0, gPipeline.mDeferredDepth.getWidth(), gPipeline.mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); + gPipeline.mDeferredDepth.bindTarget(); + simple_shader = fullbright_shader = &gObjectFullbrightAlphaMaskProgram; - deferred_render = TRUE; - if (mShaderLevel > 0) - { - // Start out with no shaders. - current_shader = target_shader = NULL; - } - gPipeline.enableLightsDynamic(); -} + simple_shader->bind(); + simple_shader->setMinimumAlpha(0.33f); -void LLDrawPoolAlpha::endPostDeferredPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED); + // mask off color buffer writes as we're only writing to depth buffer + gGL.setColorMask(false, false); - if (pass == 1 && !LLPipeline::sImpostorRender) - { - gPipeline.mDeferredDepth.flush(); - gPipeline.mScreen.bindTarget(); - gObjectFullbrightAlphaMaskProgram.unbind(); - } + // 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, + true); // <--- discard mostly transparent faces + + gPipeline.mDeferredDepth.flush(); + gPipeline.mScreen.bindTarget(); + gGL.setColorMask(true, false); + } - deferred_render = FALSE; - endRenderPass(pass); + deferred_render = FALSE; } -void LLDrawPoolAlpha::renderPostDeferred(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED); - render(pass); +//set some generic parameters for forward (non-deferred) rendering +static void prepare_forward_shader(LLGLSLShader* shader, F32 minimum_alpha) +{ + shader->bind(); + shader->setMinimumAlpha(minimum_alpha); + shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); + + //also prepare rigged variant + if (shader->mRiggedVariant && shader->mRiggedVariant != shader) + { + prepare_forward_shader(shader->mRiggedVariant, minimum_alpha); + } } -void LLDrawPoolAlpha::beginRenderPass(S32 pass) +void LLDrawPoolAlpha::render(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SETUP); - - simple_shader = (LLPipeline::sImpostorRender) ? &gObjectSimpleImpostorProgram : - (LLPipeline::sUnderWaterRender) ? &gObjectSimpleWaterProgram : &gObjectSimpleProgram; + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; + + simple_shader = (LLPipeline::sImpostorRender) ? &gObjectSimpleImpostorProgram : + (LLPipeline::sUnderWaterRender) ? &gObjectSimpleWaterProgram : &gObjectSimpleAlphaMaskProgram; - fullbright_shader = (LLPipeline::sImpostorRender) ? &gObjectFullbrightProgram : - (LLPipeline::sUnderWaterRender) ? &gObjectFullbrightWaterProgram : &gObjectFullbrightProgram; + fullbright_shader = (LLPipeline::sImpostorRender) ? &gObjectFullbrightAlphaMaskProgram : + (LLPipeline::sUnderWaterRender) ? &gObjectFullbrightWaterProgram : &gObjectFullbrightAlphaMaskProgram; - emissive_shader = (LLPipeline::sImpostorRender) ? &gObjectEmissiveProgram : - (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; + emissive_shader = (LLPipeline::sImpostorRender) ? &gObjectEmissiveProgram : + (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; + F32 minimum_alpha = MINIMUM_ALPHA; if (LLPipeline::sImpostorRender) - { - if (mShaderLevel > 0) - { - fullbright_shader->bind(); - fullbright_shader->setMinimumAlpha(0.5f); - fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); - simple_shader->bind(); - simple_shader->setMinimumAlpha(0.5f); - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); - } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); //OK - } - } - else - { - if (mShaderLevel > 0) - { - fullbright_shader->bind(); - fullbright_shader->setMinimumAlpha(0.f); - fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); - simple_shader->bind(); - simple_shader->setMinimumAlpha(0.f); - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); - } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK - } + { + minimum_alpha = MINIMUM_IMPOSTOR_ALPHA; } - gPipeline.enableLightsDynamic(); - - LLGLSLShader::bindNoShader(); - current_shader = NULL; -} + prepare_forward_shader(fullbright_shader, minimum_alpha); + prepare_forward_shader(simple_shader, minimum_alpha); -void LLDrawPoolAlpha::endRenderPass( S32 pass ) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SETUP); - LLRenderPass::endRenderPass(pass); + //first pass -- rigged only and drawn to depth buffer + forwardRender(true); - if(gPipeline.canUseWindLightShaders()) - { - LLGLSLShader::bindNoShader(); - } + //second pass -- non-rigged, no depth buffer writes + forwardRender(); } -void LLDrawPoolAlpha::render(S32 pass) +void LLDrawPoolAlpha::forwardRender(bool rigged) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA); + gPipeline.enableLightsDynamic(); - LLGLSPipelineAlpha gls_pipeline_alpha; + LLGLSPipelineAlpha gls_pipeline_alpha; - if (deferred_render && pass == 1) - { //depth only - gGL.setColorMask(false, false); - } - else - { - gGL.setColorMask(true, true); - } - - bool write_depth = LLDrawPoolWater::sSkipScreenCopy - || (deferred_render && pass == 1) - // we want depth written so that rendered alpha will - // contribute to the alpha mask used for impostors - || LLPipeline::sImpostorRenderAlphaDepthPass; + //enable writing to alpha for emissive effects + gGL.setColorMask(true, true); - LLGLDepthTest depth(GL_TRUE, write_depth ? GL_TRUE : GL_FALSE); + 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; - if (deferred_render && pass == 1) - { - gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - } - else - { - mColorSFactor = LLRender::BF_SOURCE_ALPHA; // } regular alpha blend - mColorDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } - mAlphaSFactor = LLRender::BF_ZERO; // } glow suppression - mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } - gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - } + LLGLDepthTest depth(GL_TRUE, write_depth ? GL_TRUE : GL_FALSE); - if (mShaderLevel > 0) - { - renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, pass); - } - else - { - renderAlpha(getVertexDataMask(), pass); - } + mColorSFactor = LLRender::BF_SOURCE_ALPHA; // } regular alpha blend + mColorDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } + mAlphaSFactor = LLRender::BF_ZERO; // } glow suppression + mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } + gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - gGL.setColorMask(true, false); + // 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, false, rigged); - if (deferred_render && pass == 1) - { - gGL.setSceneBlendType(LLRender::BT_ALPHA); - } + gGL.setColorMask(true, false); + 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() +{ if (sShowDebugAlpha) { - BOOL shaders = gPipeline.canUseVertexShaders(); - if(shaders) - { - gHighlightProgram.bind(); - } - else - { - gPipeline.enableLightsFullbright(); - } + gHighlightProgram.bind(); + gGL.diffuseColor4f(1, 0, 0, 1); + LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f * 1024.f); + gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::sSmokeImagep); - gGL.diffuseColor4f(1,0,0,1); - - LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f*1024.f); - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep, TRUE) ; - renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD0); + renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0); pushBatches(LLRenderPass::PASS_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); pushBatches(LLRenderPass::PASS_ALPHA_INVISIBLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); @@ -327,43 +289,85 @@ void LLDrawPoolAlpha::render(S32 pass) gGL.diffuseColor4f(0, 1, 0, 1); pushBatches(LLRenderPass::PASS_INVISIBLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); - if(shaders) - { - gHighlightProgram.unbind(); - } + gHighlightProgram.mRiggedVariant->bind(); + gGL.diffuseColor4f(1, 0, 0, 1); + + pushRiggedBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + pushRiggedBatches(LLRenderPass::PASS_ALPHA_INVISIBLE_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + + // Material alpha mask + gGL.diffuseColor4f(0, 0, 1, 1); + pushRiggedBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + pushRiggedBatches(LLRenderPass::PASS_NORMMAP_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + pushRiggedBatches(LLRenderPass::PASS_SPECMAP_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + + gGL.diffuseColor4f(0, 1, 0, 1); + pushRiggedBatches(LLRenderPass::PASS_INVISIBLE_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + LLGLSLShader::sCurBoundShaderPtr->unbind(); } } void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) { - 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]; + for (int pass = 0; pass < 2; ++pass) + { //two passes, one rigged and one not + LLVOAvatar* lastAvatar = nullptr; + U64 lastMeshId = 0; - for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) - { - LLDrawInfo& params = **k; - - if (params.mParticle) - { - continue; - } + LLCullResult::sg_iterator begin = pass == 0 ? gPipeline.beginAlphaGroups() : gPipeline.beginRiggedAlphaGroups(); + LLCullResult::sg_iterator end = pass == 0 ? gPipeline.endAlphaGroups() : gPipeline.endRiggedAlphaGroups(); - LLRenderPass::applyModelMatrix(params); - if (params.mGroup) - { - params.mGroup->rebuildMesh(); - } - params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); - } - } - } + 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 + + for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) + { + LLDrawInfo& params = **k; + + 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(); } inline bool IsFullbright(LLDrawInfo& params) @@ -383,47 +387,41 @@ inline bool IsEmissive(LLDrawInfo& params) inline void Draw(LLDrawInfo* draw, U32 mask) { - draw->mVertexBuffer->setBuffer(mask); + draw->mVertexBuffer->setBufferFast(mask); LLRenderPass::applyModelMatrix(*draw); - draw->mVertexBuffer->drawRange(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); - gPipeline.addTrianglesDrawn(draw->mCount, draw->mDrawMode); + draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); } -bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_material, LLGLSLShader* current_shader) +bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_material) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_TEX_BINDS); - bool tex_setup = false; if (deferred_render && use_material && current_shader) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS); if (draw->mNormalMap) - { + { draw->mNormalMap->addTextureStats(draw->mVSize); current_shader->bindTexture(LLShaderMgr::BUMP_MAP, draw->mNormalMap); } - + if (draw->mSpecularMap) { draw->mSpecularMap->addTextureStats(draw->mVSize); current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, draw->mSpecularMap); } } - else if (current_shader == simple_shader) + else if (current_shader == simple_shader || current_shader == simple_shader->mRiggedVariant) { - LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(draw->mVSize); - LLViewerFetchedTexture::sWhiteImagep->addTextureStats(draw->mVSize); - current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep); + current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep); current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep); } - if (use_shaders && draw->mTextureList.size() > 1) + if (draw->mTextureList.size() > 1) { for (U32 i = 0; i < draw->mTextureList.size(); ++i) { if (draw->mTextureList[i].notNull()) { - gGL.getTexUnit(i)->bind(draw->mTextureList[i], TRUE); + gGL.getTexUnit(i)->bindFast(draw->mTextureList[i]); } } } @@ -431,16 +429,15 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_mate { //not batching textures or batch has only 1 texture -- might need a texture matrix if (draw->mTexture.notNull()) { - draw->mTexture->addTextureStats(draw->mVSize); - if (use_shaders && use_material) + if (use_material) { current_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, draw->mTexture); } else { - gGL.getTexUnit(0)->bind(draw->mTexture, TRUE) ; + gGL.getTexUnit(0)->bindFast(draw->mTexture); } - + if (draw->mTextureMatrix) { tex_setup = true; @@ -452,7 +449,7 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_mate } else { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->unbindFast(LLTexUnit::TT_TEXTURE); } } @@ -470,160 +467,83 @@ void LLDrawPoolAlpha::RestoreTexSetup(bool tex_setup) } } -void LLDrawPoolAlpha::renderSimples(U32 mask, std::vector<LLDrawInfo*>& simples) +void LLDrawPoolAlpha::drawEmissive(U32 mask, LLDrawInfo* draw) { - gPipeline.enableLightsDynamic(); - simple_shader->bind(); - simple_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep); - simple_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep); - simple_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, 1.0f, 1.0f, 1.0f, 1.0f); - simple_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, 0.0f); - simple_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 0.0f); - bool use_shaders = gPipeline.canUseVertexShaders(); - for (LLDrawInfo* draw : simples) - { - bool tex_setup = TexSetup(draw, use_shaders, false, simple_shader); - LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test); - gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); - - Draw(draw, mask); - RestoreTexSetup(tex_setup); - } - simple_shader->unbind(); + LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f); + draw->mVertexBuffer->setBufferFast((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE); + draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); } -void LLDrawPoolAlpha::renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& fullbrights) -{ - gPipeline.enableLightsFullbright(); - fullbright_shader->bind(); - fullbright_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.0f); - bool use_shaders = gPipeline.canUseVertexShaders(); - for (LLDrawInfo* draw : fullbrights) - { - bool tex_setup = TexSetup(draw, use_shaders, false, fullbright_shader); - LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test); - gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); +void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives) +{ + emissive_shader->bind(); + emissive_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f); - Draw(draw, mask & ~(LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2)); + for (LLDrawInfo* draw : emissives) + { + bool tex_setup = TexSetup(draw, false); + drawEmissive(mask, draw); RestoreTexSetup(tex_setup); } - fullbright_shader->unbind(); } -void LLDrawPoolAlpha::renderMaterials(U32 mask, std::vector<LLDrawInfo*>& materials) +void LLDrawPoolAlpha::renderRiggedEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives) { - LLGLSLShader::bindNoShader(); - current_shader = NULL; + LLGLDepthTest depth(GL_TRUE, GL_FALSE); //disable depth writes since "emissive" is additive so sorting doesn't matter + LLGLSLShader* shader = emissive_shader->mRiggedVariant; + shader->bind(); + shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f); - gPipeline.enableLightsDynamic(); - bool use_shaders = gPipeline.canUseVertexShaders(); - for (LLDrawInfo* draw : materials) - { - U32 mask = draw->mShaderMask; + LLVOAvatar* lastAvatar = nullptr; + U64 lastMeshId = 0; - llassert(mask < LLMaterial::SHADER_COUNT); - target_shader = (LLPipeline::sUnderWaterRender) ? &(gDeferredMaterialWaterProgram[mask]) : &(gDeferredMaterialProgram[mask]); - - if (current_shader != target_shader) - { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS); - if (current_shader) - { - gPipeline.unbindDeferredShader(*current_shader); - } - gPipeline.bindDeferredShader(*target_shader); - current_shader = target_shader; - } - - bool tex_setup = TexSetup(draw, use_shaders, true, current_shader); - - current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, draw->mSpecColor.mV[0], draw->mSpecColor.mV[1], draw->mSpecColor.mV[2], draw->mSpecColor.mV[3]); - current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, draw->mEnvIntensity); - current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, draw->mFullbright ? 1.f : 0.f); + mask |= LLVertexBuffer::MAP_WEIGHT4; + for (LLDrawInfo* draw : emissives) + { + bool tex_setup = TexSetup(draw, false); + if (lastAvatar != draw->mAvatar || lastMeshId != draw->mSkinInfo->mHash) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS); - if (draw->mNormalMap) - { - draw->mNormalMap->addTextureStats(draw->mVSize); - current_shader->bindTexture(LLShaderMgr::BUMP_MAP, draw->mNormalMap); - } - - if (draw->mSpecularMap) - { - draw->mSpecularMap->addTextureStats(draw->mVSize); - current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, draw->mSpecularMap); - } + if (!uploadMatrixPalette(*draw)) + { // failed to upload matrix palette, skip rendering + continue; + } + lastAvatar = draw->mAvatar; + lastMeshId = draw->mSkinInfo->mHash; } - - LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test); - gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); - - Draw(draw, mask); + drawEmissive(mask, draw); RestoreTexSetup(tex_setup); } } -void LLDrawPoolAlpha::drawEmissive(U32 mask, LLDrawInfo* draw) -{ - draw->mVertexBuffer->setBuffer((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE); - draw->mVertexBuffer->drawRange(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); - gPipeline.addTrianglesDrawn(draw->mCount, draw->mDrawMode); -} - -void LLDrawPoolAlpha::drawEmissiveInline(U32 mask, LLDrawInfo* draw) +void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) { - // install glow-accumulating blend mode - gGL.blendFunc( - LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color - LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow) + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; + BOOL initialized_lighting = FALSE; + BOOL light_enabled = TRUE; - emissive_shader->bind(); - - drawEmissive(mask, draw); - - // restore our alpha blend mode - gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - - current_shader->bind(); -} - -void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives) -{ - emissive_shader->bind(); - emissive_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f); + LLVOAvatar* lastAvatar = nullptr; + U64 lastMeshId = 0; + LLGLSLShader* lastAvatarShader = nullptr; - gPipeline.enableLightsDynamic(); + LLCullResult::sg_iterator begin; + LLCullResult::sg_iterator end; - // install glow-accumulating blend mode - // don't touch color, add to alpha (glow) - gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE); - bool use_shaders = gPipeline.canUseVertexShaders(); - for (LLDrawInfo* draw : emissives) + if (rigged) { - bool tex_setup = TexSetup(draw, use_shaders, false, emissive_shader); - drawEmissive(mask, draw); - RestoreTexSetup(tex_setup); + begin = gPipeline.beginRiggedAlphaGroups(); + end = gPipeline.endRiggedAlphaGroups(); + } + else + { + begin = gPipeline.beginAlphaGroups(); + end = gPipeline.endAlphaGroups(); } - // restore our alpha blend mode - gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - - emissive_shader->unbind(); -} - -void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) -{ - static LLCachedControl<bool> batch_fullbrights(gSavedSettings, "RenderAlphaBatchFullbrights"); - static LLCachedControl<bool> batch_emissives(gSavedSettings, "RenderAlphaBatchEmissives"); - bool initialized_lighting = FALSE; - bool light_enabled = TRUE; - - bool use_shaders = gPipeline.canUseVertexShaders(); - - for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) + for (LLCullResult::sg_iterator i = begin; i != end; ++i) { + LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("renderAlpha - group"); LLSpatialGroup* group = *i; llassert(group); llassert(group->getSpatialPartition()); @@ -631,25 +551,31 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) if (group->getSpatialPartition()->mRenderByGroup && !group->isDead()) { - std::vector<LLDrawInfo*> emissives; - std::vector<LLDrawInfo*> fullbrights; + static std::vector<LLDrawInfo*> emissives; + static std::vector<LLDrawInfo*> rigged_emissives; + emissives.resize(0); + rigged_emissives.resize(0); bool is_particle_or_hud_particle = group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_PARTICLE || group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE; bool draw_glow_for_this_partition = mShaderLevel > 0; // no shaders = no glow. - - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_GROUP_LOOP); - 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]; for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { 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! @@ -659,29 +585,21 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) continue; } - // Fix for bug - NORSPEC-271 - // 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 - if(pass == 1 && !LLPipeline::sImpostorRender) + if(depth_only) { + // when updating depth buffer, discard faces that are more than 90% transparent LLFace* face = params.mFace; if(face) { const LLTextureEntry* tep = face->getTextureEntry(); if(tep) - { - if(tep->getColor().mV[3] < 0.1f) + { // don't render faces that are more than 90% transparent + if(tep->getColor().mV[3] < MINIMUM_IMPOSTOR_ALPHA) continue; } } } - if (params.mFullbright && batch_fullbrights) - { - fullbrights.push_back(¶ms); - continue; - } - LLRenderPass::applyModelMatrix(params); LLMaterial* mat = NULL; @@ -696,34 +614,17 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) // Turn off lighting if it hasn't already been so. if (light_enabled || !initialized_lighting) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_LIGHT_SETUP); - initialized_lighting = TRUE; - if (use_shaders) - { - target_shader = fullbright_shader; - } - else - { - gPipeline.enableLightsFullbright(); - } + target_shader = fullbright_shader; + light_enabled = FALSE; } } // Turn on lighting if it isn't already. else if (!light_enabled || !initialized_lighting) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_LIGHT_SETUP); - initialized_lighting = TRUE; - if (use_shaders) - { - target_shader = simple_shader; - } - else - { - gPipeline.enableLightsDynamic(); - } + target_shader = simple_shader; light_enabled = TRUE; } @@ -739,11 +640,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) target_shader = &(gDeferredMaterialWaterProgram[mask]); } + if (params.mAvatar != nullptr) + { + llassert(target_shader->mRiggedVariant != nullptr); + target_shader = target_shader->mRiggedVariant; + } + if (current_shader != target_shader) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS); gPipeline.bindDeferredShader(*target_shader); - current_shader = target_shader; } } else if (!params.mFullbright) @@ -755,25 +660,23 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) target_shader = fullbright_shader; } - if(use_shaders && (current_shader != target_shader)) - {// If we need shaders, and we're not ALREADY using the proper shader, then bind it - // (this way we won't rebind shaders unnecessarily). - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SHADER_BINDS); - current_shader = target_shader; - current_shader->bind(); - } - else if (!use_shaders && current_shader != NULL) - { - LLGLSLShader::bindNoShader(); - current_shader = NULL; - } + if (params.mAvatar != nullptr) + { + target_shader = target_shader->mRiggedVariant; + } + + if (current_shader != target_shader) + {// If we need shaders, and we're not ALREADY using the proper shader, then bind it + // (this way we won't rebind shaders unnecessarily). + target_shader->bind(); + } LLVector4 spec_color(1, 1, 1, 1); F32 env_intensity = 0.0f; F32 brightness = 1.0f; // We have a material. Supply the appropriate data here. - if (use_shaders && mat && deferred_render) + if (mat && deferred_render) { spec_color = params.mSpecColor; env_intensity = params.mEnvIntensity; @@ -782,7 +685,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) if (current_shader) { - current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, spec_color.mV[0], spec_color.mV[1], spec_color.mV[2], spec_color.mV[3]); + current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, spec_color.mV[0], spec_color.mV[1], spec_color.mV[2], spec_color.mV[3]); current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env_intensity); current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, brightness); } @@ -792,38 +695,69 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) params.mGroup->rebuildMesh(); } - bool tex_setup = TexSetup(¶ms, use_shaders, use_shaders && (mat != nullptr), current_shader); + if (params.mAvatar != nullptr) + { + if (lastAvatar != params.mAvatar || + lastMeshId != params.mSkinInfo->mHash || + lastAvatarShader != LLGLSLShader::sCurBoundShaderPtr) + { + if (!uploadMatrixPalette(params)) + { + continue; + } + lastAvatar = params.mAvatar; + lastMeshId = params.mSkinInfo->mHash; + lastAvatarShader = LLGLSLShader::sCurBoundShaderPtr; + } + } - { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_PUSH); + bool tex_setup = TexSetup(¶ms, (mat != nullptr)); + { LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test); gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); - params.mVertexBuffer->setBuffer(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0)); + bool reset_minimum_alpha = false; + if (!LLPipeline::sImpostorRender && + params.mBlendFuncDst != LLRender::BF_SOURCE_ALPHA && + params.mBlendFuncSrc != LLRender::BF_SOURCE_ALPHA) + { // this draw call has a custom blend function that may require rendering of "invisible" fragments + current_shader->setMinimumAlpha(0.f); + reset_minimum_alpha = true; + } + + U32 drawMask = mask; + if (params.mFullbright) + { + drawMask &= ~(LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2); + } + if (params.mAvatar != nullptr) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DRAW); - params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + drawMask |= LLVertexBuffer::MAP_WEIGHT4; + } + + params.mVertexBuffer->setBufferFast(drawMask); + params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + + if (reset_minimum_alpha) + { + current_shader->setMinimumAlpha(MINIMUM_ALPHA); } } // If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow). Interleaving these state-changing calls is expensive, but glow must be drawn Z-sorted with alpha. - if (current_shader && - draw_glow_for_this_partition && + if (draw_glow_for_this_partition && params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE)) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_EMISSIVE); - - if (batch_emissives) + if (params.mAvatar != nullptr) { - emissives.push_back(¶ms); + rigged_emissives.push_back(¶ms); } else { - drawEmissiveInline(mask, ¶ms); - } + emissives.push_back(¶ms); + } } if (tex_setup) @@ -835,31 +769,71 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) } } - if (batch_fullbrights) + // render emissive faces into alpha channel for bloom effects + if (!depth_only) { - light_enabled = false; - renderFullbrights(mask, fullbrights); - } + gPipeline.enableLightsDynamic(); - if (batch_emissives) - { - light_enabled = true; - renderEmissives(mask, emissives); - } + // install glow-accumulating blend mode + // don't touch color, add to alpha (glow) + gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE); - if (current_shader) - { - current_shader->bind(); + bool rebind = false; + LLGLSLShader* lastShader = current_shader; + if (!emissives.empty()) + { + light_enabled = true; + renderEmissives(mask, emissives); + rebind = true; + } + + if (!rigged_emissives.empty()) + { + light_enabled = true; + renderRiggedEmissives(mask, rigged_emissives); + rebind = true; + } + + // restore our alpha blend mode + gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); + + if (lastShader && rebind) + { + lastShader->bind(); + } } - } + } } gGL.setSceneBlendType(LLRender::BT_ALPHA); - LLVertexBuffer::unbind(); - + LLVertexBuffer::unbind(); + if (!light_enabled) { gPipeline.enableLightsDynamic(); } } + +bool LLDrawPoolAlpha::uploadMatrixPalette(const LLDrawInfo& params) +{ + if (params.mAvatar.isNull()) + { + return false; + } + const LLVOAvatar::MatrixPaletteCache& mpc = params.mAvatar.get()->updateSkinInfoMatrixPalette(params.mSkinInfo); + U32 count = mpc.mMatrixPalette.size(); + + if (count == 0) + { + //skin info not loaded yet, don't render + return false; + } + + LLGLSLShader::sCurBoundShaderPtr->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, + count, + FALSE, + (GLfloat*)&(mpc.mGLMp[0])); + + return true; +} |