博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
实习小白::(转) Cocos2d-x 3.x 开发(十八)10行代码看自动Batch,10行代码看自动剔除 --------其实就是渲染图片机制...
阅读量:5815 次
发布时间:2019-06-18

本文共 3116 字,大约阅读时间需要 10 分钟。

1、概述

 

    在游戏的运行过程中,图形的绘制是非常大的开销。对于良莠不齐的Android手机市场,绘制优化较好的游戏,可以在更多的手机上运行,因此也是优化的重 中之重。图形方面的优化主要体现在减少GPU的绘制次数上。这里我们分别从自动优化渲染批次和绘制剔除两个方面来看新版本在绘制上的优化。

2、自动batch

 

    在Cocos2d-x 3.x中,抛弃了先前手动编写BatchNode,采用自动管理的方式。说起BatchNode,就难免涉及到显卡底层的绘制原理。简单的说,每提交一条 绘制指令到显卡都会产生消耗,因此尽量少的提交指令就可以优化性能。更具体的说,当整个场景绘制都放在同一条指令中时,是最佳的状态。

    只介绍理论很难说明问题,我们动手写个Demo做测试。

    创建一个新工程。更改init函数如下。
 
[cpp]
  1. bool HelloWorld::init()  
  2. {  
  3.     //  
  4.     // 1. super init first  
  5.     if ( !Layer::init() )  
  6.     {  
  7.         return false;  
  8.     }  
  9.     Node* node = Node::create();  
  10.     char name[32];  
  11.     for(int i  = 0;i<100;++i)  
  12.     {  
  13.         memset(name, 0, sizeof(name));  
  14.         sprintf(name, "%d.png",i%10);  
  15.         auto sprite = Sprite::create(name);  
  16.         sprite->setPosition(Point(i*5,i*5));  
  17.         node->addChild(sprite, 0);  
  18.     }  
  19.     this->addChild(node);  
  20.     return true;  
  21. }  
 
   
这段代码创建了100个图片。我将示例工程中的按钮复制了9个,并将第三个按钮稍作了修改。这样程序会循环创建这10张图片。图片资源如下图所示。
 
 

    编译运行程序,我们可以看到下面的运行画面。

 

 

    我们关注的是左下角信息的第二行。“GL calls”代表每一帧中OpenGL指令的调用次数。这个数字越小,程序的绘制性能就越好。现在每有101次绘制,其中100个元素每个元素绘制一次,多出来的一次是绘制这个左下角信息自己。

    接下来,我们使用合图软件,将这10张图合成一张大图和一个plist文件。在使用CocoStudio导出时,选择“使用大图”即可将小图合成一张大 图。当然我们也可以选择TexturePacker这种专业的合图软件。合成的图片分为“test.png”和“test.plist”两部分,如上面的 资源文件图片所示。

    更改init代码如下。

[cpp]
  1. bool HelloWorld::init()  
  2. {  
  3.     //  
  4.     // 1. super init first  
  5.     if ( !Layer::init() )  
  6.     {  
  7.         return false;  
  8.     }  
  9.     CCSpriteFrameCache::getInstance()->addSpriteFramesWithFile("test.plist","test.png");  
  10.     Node* node = Node::create();  
  11.     char name[32];  
  12.     for(int i  = 0;i<100;++i)  
  13.     {  
  14.         memset(name, 0, sizeof(name));  
  15.         sprintf(name, "%d.png",i%10);  
  16.         //auto sprite = Sprite::create(name);  
  17.         auto sprite = Sprite::createWithSpriteFrameName(name);  
  18.         sprite->setPosition(Point(i*5,i*5));  
  19.         node->addChild(sprite, 0);  
  20.     }  
  21.     this->addChild(node);  
  22.     return true;  
  23. }  

    这 段代码中,我们调用addSpriteFramesWithFile函数,将大图载入到内存中,创建对象时,调用 createWithSpriteFrameName从缓存纹理中载入图片。如此做我们所有的绘制调用都可以合并到一次OpenGL指令中,这些绘制指令 的计算与合并都由Cocos2d-x引擎完成。编译运行如下图所示。

 

 

    我们可以非常明显的看到,优化后的程序“GL calls”变成了2次。

3、绘制剔除

    另一方面优化是绘制剔除。相对于上一种优化,这个要更容易理解。它是指当一个元素移动到屏幕之外,就不进行绘制。

    接着刚才的例子,我们测试一下这个特性。更改init函数如下。

[cpp]
  1. bool HelloWorld::init()  
  2. {  
  3.     //  
  4.     // 1. super init first  
  5.     if ( !Layer::init() )  
  6.     {  
  7.         return false;  
  8.     }  
  9.     //CCSpriteFrameCache::getInstance()->addSpriteFramesWithFile("test.plist","test.png");  
  10.     Node* node = Node::create();  
  11.     char name[32];  
  12.     for(int i  = 0;i<100;++i)  
  13.     {  
  14.         memset(name, 0, sizeof(name));  
  15.         sprintf(name, "%d.png",i%10);  
  16.         auto sprite = Sprite::create(name);  
  17.         //auto sprite = Sprite::createWithSpriteFrameName(name);  
  18.         sprite->setPosition(Point(i*5,i*5));  
  19.         node->addChild(sprite, 0);  
  20.     }  
  21.     this->addChild(node);  
  22.     
  23.     auto listener = EventListenerTouchOneByOne::create();  
  24.     listener->onTouchBegan = [=](Touch *pTouch, Event *pEvent)  
  25.     {  
  26.         return true;  
  27.     };  
  28.     listener->onTouchMoved = [=](Touch *pTouch, Event *pEvent)  
  29.     {  
  30.         node->setPosition(node->getPosition()+pTouch->getDelta());  
  31.     };  
  32.     Director::getInstance()->getEventDispatcher()->  
  33.         addEventListenerWithSceneGraphPriority(listener, this);  
  34.       
  35.     return true;  
  36. }  

    首先,我们将自动Batch的优化更改回来,否则无法进行测试。接下来,我们在场景中加入一个点击事件,点击拖动屏幕时,移动这100个元素。编译运行,运行效果如下图。

 

 
 

    可以看到,当部分图片被移出屏幕时,“GL calls”的数量会下降。

4、小结

   
总的来说,这两点优化可以说是对程序性能有了极大提升。同时在开发的过程中,也使程序员不必过多的纠结于渲染效率的优化。
 
相关代码下载:http://download.csdn.net/detail/fansongy/7398941
 
 
PS:最近工作比较忙,博客更新的比较少了。忙过了这段,尽量多写些文章补上,以飨读者。
 

   本篇博客出自,转载请注明出处,禁止用于商业用途:

转载于:https://www.cnblogs.com/dudu580231/p/4983831.html

你可能感兴趣的文章
【译】UNIVERSAL IMAGE LOADER.PART 2---ImageLoaderConfiguration详解
查看>>
工作笔记00
查看>>
javascript call()
查看>>
sql 内联,左联,右联,全联
查看>>
C++关于字符串的处理
查看>>
6、Web Service-拦截器
查看>>
面试题: 数据库 oracle数据库 已看1 意义不大 有用
查看>>
Flask 源码流程,上下文管理
查看>>
drf序列化组件
查看>>
qt 出现traceback -----relloc pointer
查看>>
Python 好用得让人发指的函数参数语法糖
查看>>
AWS设置允许root登陆
查看>>
真集群与伪集群的区别
查看>>
Note 387206.1 ORA-15041: ASM diskgroup with unlike disks sizes
查看>>
成都国税打造全能“电子税务局”
查看>>
[转载] 孙子兵法——01 始计第一
查看>>
python实现float/double的0x转化
查看>>
搭建Git服务器
查看>>
C#使用Xamarin开发可移植移动应用(5.进阶篇显示弹出窗口与通讯中心)附源码
查看>>
修改cmd路径方法 成功
查看>>