From d6614cc0da6688d58b8ff21a817cc34efbca229a Mon Sep 17 00:00:00 2001 From: Arnold <40414978+PatriceJiang@users.noreply.github.com> Date: Tue, 2 Apr 2019 14:56:29 +0800 Subject: [PATCH] [bugfix] fix label effects (#19554) --- cocos/2d/CCFontAtlas.cpp | 44 +++++-- cocos/2d/CCFontAtlas.h | 2 + cocos/2d/CCLabel.cpp | 275 ++++++++++++++++++++++++++------------- cocos/2d/CCLabel.h | 20 ++- 4 files changed, 230 insertions(+), 111 deletions(-) diff --git a/cocos/2d/CCFontAtlas.cpp b/cocos/2d/CCFontAtlas.cpp index 3b22d581ac..e4dea0cc30 100644 --- a/cocos/2d/CCFontAtlas.cpp +++ b/cocos/2d/CCFontAtlas.cpp @@ -112,18 +112,8 @@ void FontAtlas::reinit() _currentPageData = new (std::nothrow) unsigned char[_currentPageDataSize]; memset(_currentPageData, 0, _currentPageDataSize); - //metal do no support AI88 format - if(outlineSize > 0) - { - texture->initWithData(_currentPageDataRGBA, _currentPageDataSizeRGBA, - Texture2D::PixelFormat::RGBA8888, CacheTextureWidth, CacheTextureHeight, Size(CacheTextureWidth,CacheTextureHeight) ); - } - else - { - texture->initWithData(_currentPageData, _currentPageDataSize, - Texture2D::PixelFormat::A8, CacheTextureWidth, CacheTextureHeight, Size(CacheTextureWidth,CacheTextureHeight) ); - - } + initTextureWithZeros(texture); + addTexture(texture,0); texture->release(); } @@ -153,6 +143,29 @@ FontAtlas::~FontAtlas() #endif } +void FontAtlas::initTextureWithZeros(Texture2D *texture) +{ + char *zeros = nullptr; + Texture2D::PixelFormat pixelFormat; + float outlineSize = _fontFreeType->getOutlineSize(); + size_t zeroBytes = 0; + if (outlineSize > 0) + { + //metal do no support AI88 format + pixelFormat = Texture2D::PixelFormat::RGBA8888; + zeroBytes = CacheTextureWidth * CacheTextureWidth * 4; + } + else + { + pixelFormat = Texture2D::PixelFormat::A8; + zeroBytes = CacheTextureWidth * CacheTextureWidth; + } + zeros = new char[zeroBytes](); + //std::fill(zeros, zeros + cnt, 0); + texture->initWithData(zeros, zeroBytes, pixelFormat, CacheTextureWidth, CacheTextureHeight, Size(CacheTextureWidth, CacheTextureHeight)); + delete[] zeros; +} + void FontAtlas::reset() { releaseTextures(); @@ -405,6 +418,9 @@ bool FontAtlas::prepareLetterDefinitions(const std::u32string& utf32Text) memset(_currentPageData, 0, _currentPageDataSize); _currentPage++; auto tex = new (std::nothrow) Texture2D; + + initTextureWithZeros(tex); + if (_antialiasEnabled) { tex->setAntiAliasTexParameters(); @@ -413,9 +429,8 @@ bool FontAtlas::prepareLetterDefinitions(const std::u32string& utf32Text) { tex->setAliasTexParameters(); } - tex->initWithData(_currentPageData, _currentPageDataSize, - pixelFormat, CacheTextureWidth, CacheTextureHeight, Size(CacheTextureWidth, CacheTextureHeight)); addTexture(tex, _currentPage); + tex->release(); } } @@ -469,6 +484,7 @@ void FontAtlas::updateTextureContent(Texture2D::PixelFormat format, int startY) { int nLen = CacheTextureWidth * (_currentPageOrigY - startY + _currLineHeight); data = _currentPageData + CacheTextureWidth * (int)startY * 2; + memset(_currentPageDataRGBA, 0, 4 * nLen); for (auto i = 0; i < nLen; i++) { _currentPageDataRGBA[i*4] = data[i*2]; diff --git a/cocos/2d/CCFontAtlas.h b/cocos/2d/CCFontAtlas.h index 065a522fa2..959bb4d172 100644 --- a/cocos/2d/CCFontAtlas.h +++ b/cocos/2d/CCFontAtlas.h @@ -122,6 +122,8 @@ protected: void conversionU32TOGB2312(const std::u32string& u32Text, std::unordered_map& charCodeMap); + void initTextureWithZeros(Texture2D *texture); + /** * Scale each font letter by scaleFactor. * diff --git a/cocos/2d/CCLabel.cpp b/cocos/2d/CCLabel.cpp index 3dc4028930..d1086020b2 100644 --- a/cocos/2d/CCLabel.cpp +++ b/cocos/2d/CCLabel.cpp @@ -36,8 +36,10 @@ #include "2d/CCDrawNode.h" #include "2d/CCCamera.h" #include "base/ccUTF8.h" +#include "base/ccMacros.h" #include "platform/CCFileUtils.h" #include "renderer/CCRenderer.h" +#include "renderer/CCRenderCommand.h" #include "base/CCDirector.h" #include "base/CCEventListenerCustom.h" #include "base/CCEventDispatcher.h" @@ -48,6 +50,29 @@ #include "renderer/backend/ProgramState.h" NS_CC_BEGIN + + +namespace { + void updateBlend(backend::BlendDescriptor &blendDescriptor, BlendFunc blendFunc) + { + blendDescriptor.blendEnabled = true; + if (blendFunc == BlendFunc::ALPHA_NON_PREMULTIPLIED) + { + blendDescriptor.sourceRGBBlendFactor = backend::BlendFactor::SRC_ALPHA; + blendDescriptor.destinationRGBBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDescriptor.sourceAlphaBlendFactor = backend::BlendFactor::SRC_ALPHA; + blendDescriptor.destinationAlphaBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + } + else + { + blendDescriptor.sourceRGBBlendFactor = backend::BlendFactor::ONE; + blendDescriptor.destinationRGBBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDescriptor.sourceAlphaBlendFactor = backend::BlendFactor::ONE; + blendDescriptor.destinationAlphaBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + } + } +} + /** * LabelLetter used to update the quad in texture atlas without SpriteBatchNode. */ @@ -173,6 +198,28 @@ private: bool _letterVisible; }; +Label::BatchCommand::BatchCommand() +{ + textCommand.setDrawType(CustomCommand::DrawType::ELEMENT); + textCommand.setPrimitiveType(CustomCommand::PrimitiveType::TRIANGLE); + shadowCommand.setDrawType(CustomCommand::DrawType::ELEMENT); + shadowCommand.setPrimitiveType(CustomCommand::PrimitiveType::TRIANGLE); + outLineCommand.setDrawType(CustomCommand::DrawType::ELEMENT); + outLineCommand.setPrimitiveType(CustomCommand::PrimitiveType::TRIANGLE); +} + +Label::BatchCommand::~BatchCommand() +{ + CC_SAFE_RELEASE_NULL(textCommand.getPipelineDescriptor().programState); + CC_SAFE_RELEASE_NULL(shadowCommand.getPipelineDescriptor().programState); + CC_SAFE_RELEASE_NULL(outLineCommand.getPipelineDescriptor().programState); +} + +std::array Label::BatchCommand::getCommandArray() +{ + return std::array{&textCommand, &shadowCommand, &outLineCommand}; +} + Label* Label::create() { auto ret = new (std::nothrow) Label; @@ -398,6 +445,7 @@ Label::Label(TextHAlignment hAlignment /* = TextHAlignment::LEFT */, it.second->setTexture(nullptr); } _batchNodes.clear(); + _batchCommands.clear(); if (_fontAtlas) { @@ -437,6 +485,7 @@ Label::~Label() _batchNodes.clear(); FontAtlasCache::releaseFontAtlas(_fontAtlas); } + _batchCommands.clear(); _eventDispatcher->removeEventListener(_purgeTextureListener); _eventDispatcher->removeEventListener(_resetTextureListener); @@ -454,6 +503,7 @@ void Label::reset() CC_SAFE_RELEASE_NULL(_reusedLetter); _letters.clear(); _batchNodes.clear(); + _batchCommands.clear(); _lettersInfo.clear(); if (_fontAtlas) { @@ -563,9 +613,7 @@ void Label::setVertexLayout(PipelineDescriptor& pipelineDescriptor) layout.setAtrribute("a_color", iter->second.location, backend::VertexFormat::UBYTE4, offsetof(V3F_C4B_T2F, colors), true); } layout.setLayout(sizeof(V3F_C4B_T2F), backend::VertexStepMode::VERTEX); - - _customCommand.setDrawType(CustomCommand::DrawType::ELEMENT); - _customCommand.setPrimitiveType(CustomCommand::PrimitiveType::TRIANGLE); + } void Label::setProgramState(backend::ProgramState *programState) @@ -576,11 +624,15 @@ void Label::setProgramState(backend::ProgramState *programState) _programState = programState; CC_SAFE_RETAIN(programState); } - - auto &pipelineDescriptor = _customCommand.getPipelineDescriptor(); - pipelineDescriptor.programState = programState; updateUniformLocations(); - setVertexLayout(pipelineDescriptor); + for (auto &batch : _batchCommands) + { + updateBatchCommand(batch); + } + + auto &quadPipeline = _quadCommand.getPipelineDescriptor(); + setVertexLayout(quadPipeline); + quadPipeline.programState = _programState; } void Label::updateShaderProgram() @@ -649,23 +701,51 @@ void Label::updateShaderProgram() return; } } - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); + CC_SAFE_RELEASE(_programState); - _programState = new (std::nothrow) backend::ProgramState(vert, frag); - pipelineDescriptor.programState = _programState; + _programState = new backend::ProgramState(vert, frag); + updateUniformLocations(); + + for (auto &batch : _batchCommands) + { + updateBatchCommand(batch); + } + + auto &quadPipeline = _quadCommand.getPipelineDescriptor(); + setVertexLayout(quadPipeline); + quadPipeline.programState = _programState; +} + +void Label::updateBatchCommand(Label::BatchCommand &batch) +{ + CCASSERT(_programState, "programState should be set!"); + + auto& pipelineDescriptor = batch.textCommand.getPipelineDescriptor(); + CC_SAFE_RELEASE_NULL(pipelineDescriptor.programState); + pipelineDescriptor.programState = _programState->clone(); setVertexLayout(pipelineDescriptor); + + auto &pipelineShadow = batch.shadowCommand.getPipelineDescriptor(); + CC_SAFE_RELEASE_NULL(pipelineShadow.programState); + pipelineShadow.programState = _programState->clone();; + setVertexLayout(pipelineShadow); + + auto &pipelineOutline = batch.outLineCommand.getPipelineDescriptor(); + CC_SAFE_RELEASE_NULL(pipelineOutline.programState); + pipelineOutline.programState = _programState->clone(); + setVertexLayout(pipelineOutline); + } void Label::updateUniformLocations() { - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); - _mvpMatrixLocation = pipelineDescriptor.programState->getUniformLocation("u_MVPMatrix"); - _textureLocation = pipelineDescriptor.programState->getUniformLocation("u_texture"); - _alphaTextureLocation = pipelineDescriptor.programState->getUniformLocation("u_texture1"); - _textColorLocation = pipelineDescriptor.programState->getUniformLocation("u_textColor"); - _effectColorLocation = pipelineDescriptor.programState->getUniformLocation("u_effectColor"); - _effectTypeLocation = pipelineDescriptor.programState->getUniformLocation("u_effectType"); + _mvpMatrixLocation = _programState->getUniformLocation("u_MVPMatrix"); + _textureLocation = _programState->getUniformLocation("u_texture"); + _alphaTextureLocation = _programState->getUniformLocation("u_texture1"); + _textColorLocation = _programState->getUniformLocation("u_textColor"); + _effectColorLocation = _programState->getUniformLocation("u_effectColor"); + _effectTypeLocation = _programState->getUniformLocation("u_effectType"); } void Label::setFontAtlas(FontAtlas* atlas,bool distanceFieldEnabled /* = false */, bool useA8Shader /* = false */) @@ -1434,6 +1514,7 @@ void Label::updateContent() if (_fontAtlas) { _batchNodes.clear(); + _batchCommands.clear(); CC_SAFE_RELEASE_NULL(_reusedLetter); FontAtlasCache::releaseFontAtlas(_fontAtlas); _fontAtlas = nullptr; @@ -1539,27 +1620,25 @@ void Label::updateBuffer(TextureAtlas* textureAtlas, CustomCommand& customComman if (textureAtlas->getTotalQuads() > customCommand.getVertexCapacity()) { customCommand.createVertexBuffer((unsigned int)sizeof(V3F_C4B_T2F_Quad), (unsigned int)textureAtlas->getTotalQuads(), CustomCommand::BufferUsage::DYNAMIC); - customCommand.createIndexBuffer(CustomCommand::IndexFormat::U_SHORT, (unsigned int)textureAtlas->getTotalQuads()*6, CustomCommand::BufferUsage::DYNAMIC); + customCommand.createIndexBuffer(CustomCommand::IndexFormat::U_SHORT, (unsigned int)textureAtlas->getTotalQuads() * 6, CustomCommand::BufferUsage::DYNAMIC); } - customCommand.updateVertexBuffer(textureAtlas->getQuads(), (unsigned int)(textureAtlas->getTotalQuads() * sizeof(V3F_C4B_T2F_Quad)) ); - customCommand.updateIndexBuffer(textureAtlas->getIndices(), (unsigned int)(textureAtlas->getTotalQuads()*6*sizeof(unsigned short)) ); - customCommand.setIndexDrawInfo(0, (unsigned int)(textureAtlas->getTotalQuads()*6)); + customCommand.updateVertexBuffer(textureAtlas->getQuads(), (unsigned int)(textureAtlas->getTotalQuads() * sizeof(V3F_C4B_T2F_Quad))); + customCommand.updateIndexBuffer(textureAtlas->getIndices(), (unsigned int)(textureAtlas->getTotalQuads() * 6 * sizeof(unsigned short))); + customCommand.setIndexDrawInfo(0, (unsigned int)(textureAtlas->getTotalQuads() * 6)); } -void Label::updateEffectUniforms(TextureAtlas* textureAtlas, Renderer *renderer, const Mat4 &transform) +void Label::updateEffectUniforms(BatchCommand &batch, TextureAtlas* textureAtlas, Renderer *renderer, const Mat4 &transform) { - updateBuffer(textureAtlas, _customCommand); - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); + updateBuffer(textureAtlas, batch.textCommand); + + auto & matrixProjection = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); + if (_shadowEnabled) { - updateBuffer(textureAtlas, _customCommandShadow); - auto& pipelineShadow = _customCommandShadow.getPipelineDescriptor(); - pipelineShadow = pipelineDescriptor; - pipelineShadow.programState = pipelineDescriptor.programState; - const auto& matrixP = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); - Mat4 matrixMVP = matrixP * _shadowTransform; - pipelineShadow.programState->setUniform(_mvpMatrixLocation, matrixMVP.m, sizeof(matrixMVP.m)); + updateBuffer(textureAtlas, batch.shadowCommand); + auto shadowMatrix = matrixProjection * _shadowTransform; + batch.shadowCommand.getPipelineDescriptor().programState->setUniform(_mvpMatrixLocation, shadowMatrix.m, sizeof(shadowMatrix.m)); } - + if(_currentLabelType == LabelType::TTF) { switch (_currLabelEffect) { @@ -1572,43 +1651,43 @@ void Label::updateEffectUniforms(TextureAtlas* textureAtlas, Renderer *renderer, if(_shadowEnabled) { effectType = 2; - auto& pipelineShadow = _customCommandShadow.getPipelineDescriptor(); Vec4 shadowColor = Vec4(_shadowColor4F.r, _shadowColor4F.g, _shadowColor4F.b, _shadowColor4F.a); - pipelineShadow.programState->setUniform(_effectColorLocation, &shadowColor, sizeof(Vec4)); - pipelineShadow.programState->setUniform(_effectTypeLocation, &effectType, sizeof(effectType)); - _customCommandShadow.init(_globalZOrder); - renderer->addCommand(&_customCommandShadow); + auto *programStateShadow = batch.shadowCommand.getPipelineDescriptor().programState; + programStateShadow->setUniform(_effectColorLocation, &shadowColor, sizeof(Vec4)); + programStateShadow->setUniform(_effectTypeLocation, &effectType, sizeof(effectType)); + batch.shadowCommand.init(_globalZOrder); + renderer->addCommand(&batch.shadowCommand); } //draw outline { effectType = 1; - updateBuffer(textureAtlas, _customCommandOutLine); - auto& pipelineOutline = _customCommandOutLine.getPipelineDescriptor(); - pipelineOutline = pipelineDescriptor; - pipelineOutline.programState = pipelineDescriptor.programState; - pipelineOutline.programState->setUniform(_effectColorLocation, &effectColor, sizeof(Vec4)); - pipelineOutline.programState->setUniform(_effectTypeLocation, &effectType, sizeof(effectType)); - _customCommandOutLine.init(_globalZOrder); - renderer->addCommand(&_customCommandOutLine); + updateBuffer(textureAtlas, batch.outLineCommand); + auto *programStateOutline = batch.outLineCommand.getPipelineDescriptor().programState; + programStateOutline->setUniform(_effectColorLocation, &effectColor, sizeof(Vec4)); + programStateOutline->setUniform(_effectTypeLocation, &effectType, sizeof(effectType)); + batch.outLineCommand.init(_globalZOrder); + renderer->addCommand(&batch.outLineCommand); } //draw text { effectType = 0; - pipelineDescriptor.programState->setUniform(_effectColorLocation, &effectColor, sizeof(Vec4)); - pipelineDescriptor.programState->setUniform(_effectTypeLocation, &effectType, sizeof(effectType)); + auto *programStateText= batch.textCommand.getPipelineDescriptor().programState; + + programStateText->setUniform(_effectColorLocation, &effectColor, sizeof(effectColor)); + programStateText->setUniform(_effectTypeLocation, &effectType, sizeof(effectType)); } } break; case LabelEffect::NORMAL: { if (_shadowEnabled) { - auto& pipelineShadow = _customCommandShadow.getPipelineDescriptor(); Vec4 shadowColor = Vec4(_shadowColor4F.r, _shadowColor4F.g, _shadowColor4F.b, _shadowColor4F.a); - pipelineShadow.programState->setUniform(_textColorLocation, &shadowColor, sizeof(Vec4)); - _customCommandShadow.init(_globalZOrder); - renderer->addCommand(&_customCommandShadow); + auto *programStateShadow = batch.shadowCommand.getPipelineDescriptor().programState; + programStateShadow->setUniform(_textColorLocation, &shadowColor, sizeof(Vec4)); + batch.shadowCommand.init(_globalZOrder); + renderer->addCommand(&batch.shadowCommand); } } break; @@ -1617,16 +1696,16 @@ void Label::updateEffectUniforms(TextureAtlas* textureAtlas, Renderer *renderer, //draw shadow if(_shadowEnabled) { - auto& pipelineShadow = _customCommandShadow.getPipelineDescriptor(); Vec4 shadowColor = Vec4(_shadowColor4F.r, _shadowColor4F.g, _shadowColor4F.b, _shadowColor4F.a); - pipelineShadow.programState->setUniform(_textColorLocation, &shadowColor, sizeof(Vec4)); - pipelineShadow.programState->setUniform(_effectColorLocation, &shadowColor, sizeof(Vec4)); - _customCommandShadow.init(_globalZOrder); - renderer->addCommand(&_customCommandShadow); + auto *programStateShadow = batch.shadowCommand.getPipelineDescriptor().programState; + programStateShadow->setUniform(_textColorLocation, &shadowColor, sizeof(Vec4)); + programStateShadow->setUniform(_effectColorLocation, &shadowColor, sizeof(Vec4)); + batch.shadowCommand.init(_globalZOrder); + renderer->addCommand(&batch.shadowCommand); } Vec4 effectColor(_effectColorF.r, _effectColorF.g, _effectColorF.b, _effectColorF.a); - pipelineDescriptor.programState->setUniform(_effectColorLocation, &effectColor, sizeof(Vec4)); + batch.textCommand.getPipelineDescriptor().programState->setUniform(_effectColorLocation, &effectColor, sizeof(Vec4)); } break; default: @@ -1640,17 +1719,17 @@ void Label::updateEffectUniforms(TextureAtlas* textureAtlas, Renderer *renderer, GLubyte oldOPacity = _displayedOpacity; _displayedOpacity = _shadowColor4F.a * (oldOPacity / 255.0f) * 255; setColor(Color3B(_shadowColor4F)); - _customCommandShadow.updateVertexBuffer(textureAtlas->getQuads(), (unsigned int)(textureAtlas->getTotalQuads() * sizeof(V3F_C4B_T2F_Quad)) ); - _customCommandShadow.init(_globalZOrder); - renderer->addCommand(&_customCommandShadow); + batch.shadowCommand.updateVertexBuffer(textureAtlas->getQuads(), (unsigned int)(textureAtlas->getTotalQuads() * sizeof(V3F_C4B_T2F_Quad)) ); + batch.shadowCommand.init(_globalZOrder); + renderer->addCommand(&batch.shadowCommand); _displayedOpacity = oldOPacity; setColor(oldColor); } } - _customCommand.init(_globalZOrder); - renderer->addCommand(&_customCommand); + batch.textCommand.init(_globalZOrder); + renderer->addCommand(&batch.textCommand); } void Label::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) @@ -1675,11 +1754,10 @@ void Label::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) if (_insideBounds) #endif { - updateBlendState(); - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); cocos2d::Mat4 matrixProjection = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); if (!_shadowEnabled && (_currentLabelType == LabelType::BMFONT || _currentLabelType == LabelType::CHARMAP)) { + updateBlendState(); for (auto&& it : _letters) { it.second->updateTransform(); @@ -1691,8 +1769,6 @@ void Label::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) auto texture = textureAtlas->getTexture(); auto& pipelineQuad = _quadCommand.getPipelineDescriptor(); - pipelineQuad = pipelineDescriptor; - pipelineQuad.programState = pipelineDescriptor.programState; pipelineQuad.programState->setUniform(_mvpMatrixLocation, matrixProjection.m, sizeof(matrixProjection.m)); pipelineQuad.programState->setTexture(_textureLocation, 0, texture->getBackendTexture()); auto alphaTexture = textureAtlas->getTexture()->getAlphaTexture(); @@ -1705,23 +1781,45 @@ void Label::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) } else { + cocos2d::Mat4 matrixMVP = matrixProjection * transform; + + for (auto &&it : _letters) + { + it.second->updateTransform(); + } + int i = 0; + + if (_batchCommands.size() != _batchNodes.size()) + { + _batchCommands.resize(_batchNodes.size()); + updateShaderProgram(); + } + + updateBlendState(); + for (auto&& batchNode : _batchNodes) { auto textureAtlas = batchNode->getTextureAtlas(); - if(!textureAtlas->getTotalQuads()) + if (!textureAtlas->getTotalQuads()) return; - - cocos2d::Mat4 matrixMVP = matrixProjection * transform; - pipelineDescriptor.programState->setUniform(_mvpMatrixLocation, matrixMVP.m, sizeof(matrixMVP.m)); - Vec4 textColor(_textColorF.r, _textColorF.g, _textColorF.b, _textColorF.a); - pipelineDescriptor.programState->setUniform(_textColorLocation, &textColor, sizeof(Vec4)); - pipelineDescriptor.programState->setTexture(_textureLocation, 0, textureAtlas->getTexture()->getBackendTexture()); - auto alphaTexture = textureAtlas->getTexture()->getAlphaTexture(); - if(alphaTexture && alphaTexture->getBackendTexture()) + + auto &batch = _batchCommands[i++]; + auto &&commands = batch.getCommandArray(); + for (auto command : commands) { - pipelineDescriptor.programState->setTexture(_alphaTextureLocation, 1, alphaTexture->getBackendTexture()); + auto *programState = command->getPipelineDescriptor().programState; + Vec4 textColor(_textColorF.r, _textColorF.g, _textColorF.b, _textColorF.a); + programState->setUniform(_textColorLocation, &textColor, sizeof(Vec4)); + programState->setTexture(_textureLocation, 0, textureAtlas->getTexture()->getBackendTexture()); + auto alphaTexture = textureAtlas->getTexture()->getAlphaTexture(); + if (alphaTexture && alphaTexture->getBackendTexture()) + { + programState->setTexture(_alphaTextureLocation, 1, alphaTexture->getBackendTexture()); + } } - updateEffectUniforms(textureAtlas, renderer, transform); + batch.textCommand.getPipelineDescriptor().programState->setUniform(_mvpMatrixLocation, matrixMVP.m, sizeof(matrixMVP.m)); + batch.outLineCommand.getPipelineDescriptor().programState->setUniform(_mvpMatrixLocation, matrixMVP.m, sizeof(matrixMVP.m)); + updateEffectUniforms(batch, textureAtlas, renderer, transform); } } } @@ -1729,24 +1827,15 @@ void Label::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) void Label::updateBlendState() { - backend::BlendDescriptor& blendDescriptor = _customCommand.getPipelineDescriptor().blendDescriptor; - blendDescriptor.blendEnabled = true; - if (_blendFunc == BlendFunc::ALPHA_NON_PREMULTIPLIED) + setOpacityModifyRGB(_blendFunc != BlendFunc::ALPHA_NON_PREMULTIPLIED); + for(auto &batch: _batchCommands) { - blendDescriptor.sourceRGBBlendFactor = backend::BlendFactor::SRC_ALPHA; - blendDescriptor.destinationRGBBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; - blendDescriptor.sourceAlphaBlendFactor = backend::BlendFactor::SRC_ALPHA; - blendDescriptor.destinationAlphaBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; - setOpacityModifyRGB(false); - } - else - { - blendDescriptor.sourceRGBBlendFactor = backend::BlendFactor::ONE; - blendDescriptor.destinationRGBBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; - blendDescriptor.sourceAlphaBlendFactor = backend::BlendFactor::ONE; - blendDescriptor.destinationAlphaBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; - setOpacityModifyRGB(true); + for(auto *command : batch.getCommandArray()) { + auto & blendDescriptor = command->getPipelineDescriptor().blendDescriptor; + updateBlend(blendDescriptor, _blendFunc); + } } + updateBlend(_quadCommand.getPipelineDescriptor().blendDescriptor, _blendFunc); } void Label::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags) diff --git a/cocos/2d/CCLabel.h b/cocos/2d/CCLabel.h index 4638e90592..91be77009d 100644 --- a/cocos/2d/CCLabel.h +++ b/cocos/2d/CCLabel.h @@ -647,6 +647,17 @@ protected: int lineIndex; }; + struct BatchCommand { + BatchCommand(); + ~BatchCommand(); + + CustomCommand textCommand; + CustomCommand outLineCommand; + CustomCommand shadowCommand; + + std::array getCommandArray(); + }; + virtual void setFontAtlas(FontAtlas* atlas, bool distanceFieldEnabled = false, bool useA8Shader = false); bool getFontLetterDef(char32_t character, FontLetterDefinition& letterDef) const; @@ -695,9 +706,11 @@ protected: void updateUniformLocations(); void setVertexLayout(PipelineDescriptor& vertexLayout); void updateBlendState(); - void updateEffectUniforms(TextureAtlas* textureAtlas, Renderer *renderer, const Mat4 &transform); + void updateEffectUniforms(BatchCommand &batch, TextureAtlas* textureAtlas, Renderer *renderer, const Mat4 &transform); void updateBuffer(TextureAtlas* textureAtlas, CustomCommand& customCommand); + void updateBatchCommand(BatchCommand &batch); + LabelType _currentLabelType; bool _contentDirty; std::u32string _utf32Text; @@ -749,9 +762,8 @@ protected: Color4F _textColorF; QuadCommand _quadCommand; - CustomCommand _customCommand; - CustomCommand _customCommandOutLine; - CustomCommand _customCommandShadow; + + std::vector _batchCommands; Mat4 _shadowTransform; GLint _uniformEffectColor;