• ‎Cocos2d-x 学习笔记(26) 从源码学习 DrawCall 的降低方法


    【Cocos2d-x】学习笔记目录

    本文链接:https://www.cnblogs.com/deepcho/p/cocos2dx-drawcall-glcalls.html

    1. 屏幕左下角

    我们通常在Cocos2d-x项目运行前,在AppDelegate::applicationDidFinishLaunching()方法中,执行

    director->setDisplayStats(true);

    用于开启屏幕左下角的数据显示,数据一共三行,分别是:

    第一行GL verts表示此时绘制的顶点数。

    第二行GL calls表示此时DrawCall数量。

    第三行表示此时的FPS。

    我们研究第二行的GL calls,也就是DrawCall的相关知识。

    2. bool _displayStats

    左下角数据通过Director的setDisplayStats方法控制显示与否。该方法仅改变了Director的_displayStats变量,我们可以猜测是该变量控制了数据显示。该变量默认为false,所以要开启数据显示的话,需要手动修改该变量。

    另外,Director::setDefaultValues(void)方法也会修改_displayStats。下面看setDefaultValues方法的被调用过程。

    在程序入口Application::run()方法调用的AppDelegate::applicationDidFinishLaunching()方法的第一行,执行了:

    Configuration::getInstance()->loadConfigFile("configs/config-example.plist");

    可以猜测该行是加载了一个plist配置文件,因为其执行的位置很靠前,应该是设置了Cocos2d-x项目的一些重要变量。

    打开该plist发现刚才的预测正确。该plist文件如下:

     loadConfigFile方法仅设置了Configuration单例对象的几个变量。在该方法最后,执行了:

    Director::getInstance()->getEventDispatcher()->dispatchEvent(_loadedEvent);

    该行表面看是分发了一个我们自定义的事件,实际上重要的是,这是Director在程序内的初始化位置。

    因为此时不存在Director单例对象,所以执行Director::init()方法。在init方法第一行,执行了:

    setDefaultValues();

    该方法是对刚才的Configuration单例对象plist文件内与Director和图像纹理相关的内容进行设置,包括这几个内容:

    _oldAnimationInterval  _animationInterval(1.0/fps)

    _displayStats

    _projection (3d、2d、CUSTOM)

    Texture2D::setDefaultAlphaPixelFormat(Texture2D::PixelFormat::RGBA8888)

    Image::setPVRImagesHavePremultipliedAlpha(pvr_alpha_premultiplied)

    所以,这是在我们手动调用setDisplayStats方法之前对_displayStats的一次设置,这次设置是通过在setDefaultValues方法中加载plist配置文件进行的。

    3. ssize_t _drawnBatches

    在帧循环内的Director::drawScene()方法中,会对_displayStats进行判断,为true时分别执行showStats()方法和calculateMPF()方法。

    showStats()方法是直接输出三行数据到屏幕左下角。其中DrawCall的值是Renderer成员变量_drawnBatches。

    DrawCall的值就是_drawnBatches的值,_drawnBatches的增加仅在Renderer::drawBatchedTriangles()方法中进行,如下:

        /************** 3: Draw *************/
        for (int i=0; i<batchesTotal; ++i)
        {
            CC_ASSERT(_triBatchesToDraw[i].cmd && "Invalid batch");
            _triBatchesToDraw[i].cmd->useMaterial();
            glDrawElements(GL_TRIANGLES, (GLsizei) _triBatchesToDraw[i].indicesToDraw, GL_UNSIGNED_SHORT, (GLvoid*) (_triBatchesToDraw[i].offset*sizeof(_indices[0])) );
            _drawnBatches++;
            _drawnVertices += _triBatchesToDraw[i].indicesToDraw;
        }

    所以,表面上看想办法降低batchesTotal的值就能降低DrawCall的值。

    上篇文章对Renderer渲染的学习中可以总结出降低DrawCall的大致思路:

    同GlobalZOrder的元素中,元素被添加到节点的顺序就是渲染命令的添加顺序。当两个命令相邻且同材质ID的情况下,这两个命令的索引是被添加到同一个_triBatchesToDraw的索引中,而_triBatchesToDraw的索引是在被GL一次绘制,_triBatchesToDraw的数量决定了batchesTotal的值,也就是DrawCall的值。所以,我们要想实现一次DrawCall中绘制多个元素,就要尽可能让不同元素添加到节点的顺序是相邻的且不被打断,并且它们的材质ID一致,从而这些元素顶点索引被整合到一起,在一次glDrawElements方法中被绘制。


    本文链接:https://www.cnblogs.com/deepcho/p/cocos2dx-drawcall-glcalls.html

     
  • 相关阅读:
    自控力和专注力是执行力的保证
    今宵又除夕
    买了小米盒子三代
    电容相位滞后?电感超前
    lcr电桥浅谈
    ad 线束和网络
    浅谈 R_S触发器
    NTSC PAL 介绍
    verilog 之流水灯
    io 口方向调整 stm32
  • 原文地址:https://www.cnblogs.com/deepcho/p/cocos2dx-drawcall-glcalls.html
Copyright © 2020-2023  润新知