• cocos2dx-3.0(14)------SpriteBatchNode与SpriteFrameCache加快渲染


    ~~~~我的生活,我的点点滴滴!


               大家都知道一个游戏里面会有大量的图片。每一个图片渲染是须要时间的,以下分析两个类来加快渲染速度。加快游戏执行速度

    一、SpriteBatchNode

    1、先说下渲染批次:这是游戏引擎中一个比較重要的优化指标,指的是一次渲染凋用。也就是说。渲染的次数越少,游戏的执行效率越高。怎么看这个次数了?GL calls的值,以下会讲到。

    2、SpriteBatchNode就是cocos2d-x为了减少渲染批次而建立的一个专门管理精灵的类。

    有人会问,怎么高速知道究竟渲染了多少次了,告诉你吧,游戏左下角有三行数据:

    GL verts 表示给显卡绘制的顶点数

    GL calls 表示代表每一帧中OpenGL指令的调用次数

    FPS 这个是帧率不多说

    主要看第二个“GL calls”代表每一帧中OpenGL指令的调用次数。这个数字越小,程序的绘制性能就越好。我们有没有法子让他小点了,答案当然是yes

    首先我们使用sprite创建100个精灵。看看这个值是多少

    code:

    for(int i = 0; i < 100; ++ i)
    {
    	char name[15];
    	memset(name, 0, sizeof(name));
    	sprintf(name, "%d.png", i % 10);
    	auto sp = Sprite::create(name);
    	sp->setPosition(Point(i*5,i*5));
    	node->addChild(sp);
    }
    this->addChild(node);

    这个循环创建了100个精灵,显示出来,看效果


    看左下角红色圈圈。有101次绘制,当中100个元素每一个元素绘制一次。多出来的一次是绘制这个左下角信息自己。

    在来看看使用SpriteBatchNode

    code:

    auto spBatchNode = SpriteBatchNode::create("0.png");
    	spBatchNode->setPosition(Point::ZERO);
    	this->addChild(spBatchNode);
    	for(int i = 0; i < 100; ++ i)
    	{
    		count++;
    		//float x = CCRANDOM_0_1() * visibleSize.width;
    		//float y = CCRANDOM_0_1() * visibleSize.height;
    		//log("x=%lf, y=%lf",x, y);
    		char name[15];
    		memset(name, 0, sizeof(name));
    		sprintf(name, "%d.png", i % 10);
    		auto sp = Sprite::createWithTexture(spBatchNode->getTexture());
    		sp->setPosition(Point(i*5,i*5));
    		spBatchNode->addChild(sp);
    	}
    看效果图


    看到没,立刻减到2了,这快了太多了。

    这是一个提速。在3.x版本号里面已经自己主动实现了批渲染处理了。所以非常多时候SpriteBatchNode用不上了

    在来看看SpriteFrameCache

    二、SpriteFrameCache

          首先我们使用合图软件,将这10张图合成张大图和一个plist文件。

    在使用CocoStudio导出时。选择“使用大图”就可以将小图合成一张大图。当然我们也能够选择TexturePacker这样的专业的合图软件。合成的图片分为“test.png”和“test.plist”两部分,然后使用SpriteFrameCache。

    code:

    SpriteFrameCache::getInstance()->addSpriteFramesWithFile("test.plist","test.png"); 
    Node* node = Node::create(); 
    char name[32]; 
    for(int i = 0;i<100;++i) 
    { 
    char name[15];
    memset(name, 0, sizeof(name));
    //auto sprite = Sprite::create(name); 
    auto sprite = Sprite::createWithSpriteFrameName(name); 
    sprite->setPosition(Point(i*5,i*5)); 
    node->addChild(sprite, 0); 
    } 
    this->addChild(node);
    这段代码中,我们调用addSpriteFramesWithFile函数,将大图加载到内存中,创建对象时,调用createWithSpriteFrameName从缓存纹理中加载图片。

    如此做我们全部的绘制调用都能够合并到一次OpenGL指令中。这些绘制指令的计算与合并都由Cocos2d-x引擎完毕。编译执行例如以下图所看到的:


    我们能够很明显的看到,优化后的程序“GL calls”依旧变成了2次。

    另一种优化。就是当精灵超出屏幕后就剔除掉,这样也能降低OpenGL指令。


    三、绘制剔除

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

    code:

    Node* node = Node::create();
    
    for(int i  = 0;i<100;++i)
    {
    	char name[15];
    	memset(name, 0, sizeof(name));
    	sprintf(name, "%d.png",i%10);
    	auto sprite = Sprite::create(name);
    	//auto sprite = Sprite::createWithSpriteFrameName(name);
    	sprite->setPosition(Point(i*5,i*5));
    	node->addChild(sprite, 0);
    }
    this->addChild(node);
    
    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = [=](Touch *pTouch, Event *pEvent)
    {
    	return true;
    };
    listener->onTouchMoved = [=](Touch *pTouch, Event *pEvent)
    {
    	node->setPosition(node->getPosition()+pTouch->getDelta());
    };
    Director::getInstance()->getEventDispatcher()->
    	addEventListenerWithSceneGraphPriority(listener, this);
    
    return true;}
    
    效果图例如以下:


    我们发现GL calls也变小了。这也是一种不错的方法


    四、小结

        总的来说,这两点优化能够说是对程序性能有了极大提升。

    同一时候在开发的过程中,也使程序猿不必过多的纠结于渲染效率的优化。

  • 相关阅读:
    CSS3实现10种Loading效果(转)
    Editorial Board 、co-editor、ediitor、editor-in-chief的区别
    Android必知必会-使用okhttp的PUT方式上传文件
    Android项目开发填坑记-so文件引发的攻坚战
    Android开发学习之路--RxAndroid之操作符
    Libgdx教程目录
    Android开发学习之路--RxAndroid之lambda
    Android开发学习之路--RxAndroid之初体验
    Android必知必会-获取视频文件的截图、缩略图
    Android开发学习之路--Annotation注解简化view控件之初体验
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/7250314.html
Copyright © 2020-2023  润新知