1. Overview
During the running of the game, drawing images is very costly. For the mixed Android mobile phone market, creating well-optimized games can run on more mobile phones, which is also the top priority of optimization. Graphics optimization is mainly reflected in reducing the number of GUP draws. Here we will look at the optimization of the new version in terms of Automatic Optimization of rendering batches and rendering removal.
2. Automatic batch
In Cocos2d-x 3. x, the previous manual Writing of BatchNode was abandoned, using an automatic management approach. When talking about BatchNode, it will inevitably involve the Rendering Principle of the underlying layer of the video card. Simply put, each time you submit a drawing command to the video card, it will consume, so you can optimize the performance by submitting as few instructions as possible. More specifically, when the entire scenario is drawn in the same command, it is the best state.
It is difficult to explain the problem only by introducing the theory. Let's write a Demo for testing.
Create a new project. The init function is changed as follows.
bool HelloWorld::init(){ ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } Node* node = Node::create(); char name[32]; for(int i = 0;i<100;++i) { memset(name, 0, sizeof(name)); sprintf(name, "%d.png",i%10);auto sprite = Sprite::create(name); sprite->setPosition(Point(i*5,i*5)); node->addChild(sprite, 0); } this->addChild(node); return true;}
This Code creates 100 images. I copied nine buttons in the sample project and slightly modified the third button. In this way, the program will create these 10 images cyclically. Shows the image resources.
Compile and run the program. We can see the following running screen.
We focus on the second row of information in the lower left corner. "Gl cils" indicates the number of OpenGL instruction calls in each frame. The smaller the number, the better the rendering performance of the program. Currently, every 101 times of painting, 100 of which each element is drawn once, and once more, the information in the lower left corner is drawn.
Next, we use the graph software to combine the 10 images into a large image and a plist file. When using CocoStudio to export data, select "use big image" to merge the small image into a large image. Of course, we can also choose professional graph software such as TexturePacker. The synthesized image is divided into two parts: test.png and test. plist, as shown in the preceding resource file image.
Modify the init Code as follows.
bool HelloWorld::init(){ ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } CCSpriteFrameCache::getInstance()->addSpriteFramesWithFile("test.plist","test.png"); Node* node = Node::create(); char name[32]; for(int i = 0;i<100;++i) { 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); return true;}
In this Code, we call the addSpriteFramesWithFile function to load the large image to the memory. When creating an object, we call createWithSpriteFrameName to load the image from the cached texture. In this way, all our drawing calls can be merged into an OpenGL command, and the calculation and merging of these drawing commands are done by the Cocos2d-x engine. Shows how to compile and run the program.
We can see that the optimized program "gl cils" is changed twice.
3. Draw and remove
Optimization is to remove the rendering. Compared with the previous optimization, this is easier to understand. It means that when an element is moved out of the screen, it is not drawn.
Next, let's test this feature. The init function is changed as follows.
bool HelloWorld::init(){ ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } //CCSpriteFrameCache::getInstance()->addSpriteFramesWithFile("test.plist","test.png"); Node* node = Node::create(); char name[32]; for(int i = 0;i<100;++i) { 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;}
First, we will change the optimization of the automatic Batch back, otherwise the test will not be available. Next, we add a click event to the scene. When we click and drag the screen, the 100 elements are moved. Compile and run the program. The running result is as follows.
As you can see, when some images are removed from the screen, the number of gl cils decreases.
4. In summary, these two optimizations can be said to have greatly improved the procedural performance. At the same time, in the development process, programmers do not have to worry too much about rendering efficiency optimization.
Download related code: http://download.csdn.net/detail/fansongy/7398941
PS: Recently, my work has been busy, and my blog has been updated less. When you are busy with this section, try to write more articles to help readers.
This blog from a shura Road, reproduced please indicate the source, prohibited for commercial purposes: http://blog.csdn.net/fansongy/article/details/26968473