cocos2dx的label假如运用的ttf时,是无法合批的

原因剖析

能够看到label的draw函数

void Label::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags){
        if (!_shadowEnabled && (_currentLabelType == LabelType::BMFONT || _currentLabelType == LabelType::CHARMAP))
        {
            _quadCommand.init(_globalZOrder, texture, getGLProgramState(), 
                _blendFunc, textureAtlas->getQuads(), textureAtlas->getTotalQuads(), transform, flags);
            renderer->addCommand(&_quadCommand);
        }
        else
        {
            _customCommand.init(_globalZOrder, transform, flags);
            _customCommand.func = CC_CALLBACK_0(Label::onDraw, this, transform, transformUpdated);
            renderer->addCommand(&_customCommand);
        }
}

label的类型不同,会选用不同的renderCommand,而ttf类型运用的CustomCommand

QuadCommand _quadCommand;
CustomCommand _customCommand;

而当运用bmfont时,运用的QuadCommand是承继自TrianglesCommand

class CC_DLL QuadCommand : public TrianglesCommand

从烘托逻辑结构中,咱们看到只要TRIANGLES_COMMAND才干进行合批处理

[✔️] cocos2dx label合批探讨
所以,无论你怎样对label节点进行排序,都无法完结合批操作,由于烘托流程压根就不支撑。

怎样支撑合批

一种比较彻底的方法便是,调整render流程,就像TrianglesCommand那样,将CMD收集起来,然后再进行合批处理,但是这样的话,改动十分大,究竟烘托流程是整个engine正常运行的基础,假如没有富余的时刻,大概率重构出来的新烘托流程经不起项目考虑,何况这种级别的重构,十分考验个人的才智和架构才能,是一项十分充溢挑战性的作业。

另外一个方法相对来说改动不是那么大,主体思路便是在ttf形式下,咱们不运用CustomCommand,继续运用QuadCommand就能在原有烘托结构下完结合批,那么要处理的问题就变成了:

怎样在ttf形式下运用QuadCommand或者TrianglesCommand

现有的CustomCommand所做的事情大概如下:

  1. 先制作暗影作用
  2. 当有描边时,制作描边后的作用
  3. 再制作字体自身的作用

能够看到描边是一个十分特别的操作,会产生屡次draw

要运用TrianglesCommand形式完结以上的流程,其实还是挺麻烦的,由于label的作用不同,所运用的shader也不同,而TrianglesCommand是对应的固定shader,要完成合批,就不能像现在那样动态切换shader,所以咱们就不得不把带有文字作用的图片,集中放到一个RenderTexture里边。

其实这里边还牵扯到FontAtlas的问题,由于这里边存储的是从freetype制作的位图字体文件,假如放到RenderTexture后,这个fontAtlas便是一个中心的缓冲池,这个fontAtlas能够防止咱们重复生成位图字体文件,或许咱们也需求处理这个中心文件,由于有些状况下某些字体装备创建一次后就再也不会运用这种状况的字体装备了,当然这算是优化了。

顺着RenderTexture的逻辑往下走,其实问题就变成了如何得到带有effect的字体位图,由于描边、暗影等作用都是动态生成的,这里能够考虑运用frame buffer,不过我就fbo就不太了解了,后续再展开这个思路。