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也變小了。這也是一種不錯的方法


四、小結

    總的來說,這兩點優化能夠說是對程序性能有了極大提升。

同一時候在開發的過程中,也使程序猿不必過多的糾結於渲染效率的優化。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM