cocos2d flicker - ios

I have a pool of CCSprites numbering 1200 in each of two arrays, displayGrid1 and displayGrid2. I turn them visible or invisible when showing walls or floors. Floors have a number of different textures and are not z-order dependent. Walls also have several textures and are z-order dependent.
I am getting about 6-7 frames when moving which is okay because its a turn based isometric rogue-like. However, I am also getting a small amount of flicker, which I think is performance related, because there is no flicker on the simulator.
I would like to improve performance. I am considering using an array CCSpriteBatchNodes for the floor which is not z-order dependent but am concerned with the cost of adding and removing sprites frequently between the elements of this array, which would be necessary I think.
Can anyone please advise as to how I can improve performance?

As mentioned in the comments, you're using multiple small sprite files loaded individually which can cause performance issues as there is wasted memory being used to store excess pixel data around each of the individual sprites. Each row of pixel data in an OpenGL texture must have a number of bytes totaling a power of 2 for performance reasons. Although I believe OpenGL ES under iOS does this automatically, it can come with a big performance hit. Grouping sprites together into a single texture that is correctly sized can be a tremendous boon to rendering performance.
You can use an App like Zwoptex to group all these smaller sprite files into a larger, more manageable sprite sheets/texture atlas and utilize one CCSpriteBatchNode for each sprite sheet/texture atlas.
Cocos2D has pretty good support for utilizing sprite sheets with texture atlases and converting your code to using these instead of individual files can be done with little effort. Creating individual sprites from a texture atlas is easy, you just call the sprite by name instead of from the file.
CCSpriteBatchNodes group OpenGL calls for their sprites together, a process known as batching, which causes the operating system and OpenGL to have to make less round trips to the GPU which greatly improves performance. Unfortunately, CCSpriteBatchNodes are limited to only being able to draw sprites for the texture that backs them (enter sprite sheets/texture atlases).

Related

What are the benefits of using texture atlas in Sprite Kit?

I'm new to ios game development field.
I have been going through the following apple tutorial multiple times but not getting the points
https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Sprites/Sprites.html
thanks
Directly from the SKTextureAtlas class reference :
Texture atlases can improve memory usage and rendering performance. For example, if you have a scene with sprites drawn with different textures, Sprite Kit performs one drawing pass for each texture. However, if all of the textures were loaded from the same texture atlas, then Sprite Kit can render the sprites in a single drawing pass—and use less memory to do so. Whenever you have textures that are always used together, you should store them in an atlas.
SKTextureAtlas Class Reference
animation can be hundred of files. atlas puts them in one large file.
reading one file (large with lots of images) is much more efficient then reading hundreds of files (with one image each)
rendering of one large image and then showing only part of it is much more efficient then rendering each file separately.

Cocos2d: GPU having to process the non visible CCSprite quads

Given one texture sheet is it better to have one or multiple CCSpriteBatchNodes? Or does this not affect at all the GPU computational cost in processing the non visible CCSprite quads?
I am thinking about performance and referring to this question and answer I got. Basically it suggests that I should use more than one CCSpriteBatchNode even if I have only one file. I don't understand if the sentence "Too many batched sprites still affects performance negatively even if they are not visible or outside the screen" is applicable also having two CCSpriteBatchNode instead of one. In other words, does the sentence refer to this "The GPU is responsible for cancelling draws of quads that are not visible due to being entirely outside the screen. It still needs to process those quads."? And if so it should meant that it doesn't really matter how may CCSpriteBatchNode instances I have using the same texture sheet, right?
How can I optimize this? I mean, how can I avoid the GPU having to process the non visible quads?
Would you be able to answer to at least the questions in bold?
First case: Too many nodes (or sprites) in the scene and many of them are out of screen/visible area. In this case for each sprite, GPU has to check if its outside the visible area or not. Too many sprite-nodes means too much load on GPU.
Adding more CCSpriteBatchNode should not effect the performance. Because the sprite-sheet bitmap is loaded to the GPU memory, and an array of coordinates is kept by the application for drawing individual sprites. So if you put 2 images in 2 different CCSpriteBatchNodes or 2 images in 1, it will be same for both CPU and GPU.
How to optimize?
The best way would be to remove the invisible nodes/sprites from the parent. But it depends on your application.
FPS drops certainly because of two reasons:
fillrate - when a lot of sprites overlap each others (and additionally if we render high-res texture into small sprite)
redundant state changes - in this case the heaviest are shader and texture switches
You can render sprites outside of screen in single batch and this doesn't drop performance singnificantly. Pay attention that rendering sprite with zero opacity (or transparent texture) takes the same time as non-transparent sprite.
First of all, this really sounds like a case of premature optimization. Do a test with the number of sprites you expect to be on screen, and some added, others removed. Do you get 60 fps on the oldest supported device? If yes, good, no need to optimize. If no, tweak the code design to see what actually makes a difference.
I mean, how can I avoid the GPU having to process the non visible quads?
You can't, unless you're going to rewrite how cocos2d handles drawing of sprites/batched sprites.
it doesn't really matter how may CCSpriteBatchNode instances I have using the same texture sheet, right?
Each additional sprite batch node adds a draw call. Given how many sprites they can batch into a single draw call, the benefit far outweighs the drawbacks. Whether you have one, two or three sprite batch nodes makes absolutely no difference.

How to leverage CCSpriteBatchNode when frames are distributed into multiple textures

In my game, there're plenty of enemies(subclass of CCNode) which animation frames are distributed into multiple texture files(enemy01.png, enemy02.png...) and enemies from different textures may be generated in the same scene.
I'd like to have a unified way to dynamically add a randomly generated enemy to the correct CCSpriteBatchNode, but a lookup table seems not so elegant. Is there any better way to handle it?
Thanks
Since each enemy uses its own texture, you can use one sprite batch node per enemy. So when you create enemy "X" it shouldn't be hard to get the corresponding sprite batch node from wherever you store it (perhaps an NSDictionary).
Keep in mind that one sprite batch node per enemy kind of defies the purpose, especially if the texture atlas for each enemy is rather small and not even close to the maximum allowed size (1024x1024 for old devices, 2048x2048 or more for iPhone 3GS and newer). If possible, cram as many images into one texture atlas and use one sprite batch node for it.

Why using triangulation for flat terrain?

I've seen many terrains in wire mode and all of them used triangles. I get it if you use it for different heights BUT why do people use so many triangles for flat areas in their terrain? If there is a large flat area wouldn't it be wise to create one big square or at least one big triangle (as big as possible) instead of using so many small ones?
So my question is, is there a reason to do this (maybe for textures)? I know tesselation does something like this but still leaves too many triangles from my point of view.
Possible reasons:
They don't have terrain optimization routines.
They use vertex lighting. Unless terrain is densely triangulated, it'll look horrible.
Shader does not work well with huge triangles. Interpolating huge values (like light dir etc) across a triangle might cause precision problems.
Physics engine does not work with huge triangles.
Huge triangles cause artifacts (I think there's a hardware-dependent limit on number of texture repeats).
Multiple materials (more than 8) across terrain. That'll go above multitexturing limits on certain cards, so it'll be necessary to split terrain.
Multiple different materials or regions across terrain, streamed zones. Different materials might require different texture coordinates, etc, and if there's some kind of 2nd set of coordinates on top of the terrain (optimized unwrapped lightmap), you won't be able to use one big flat triangle.
Per-pixel lighting with multiple sources. If you have several light sources, and want to use them all at once, you might have to use additive alpha-blending. With triangulated terrain you can pick out a small region that is affected by this particular resource, and redraw it with added specular from that lightsource. If you simply cut big triangle with clip-planes, you'll see z-fighting. If you don't select small region of terrain light affects, you'll have to redraw entire terrain, which is very likely to cause performance drop (fillrate/shader performance because many pixels are redrawn).

How does memory usage increase as you load textures in Cocos2d (using sprite sheets)?

I am building an app that uses Cocos2d to create a map of content (technically a big Tree in the graph theory sense). Each node is represented by a sprite with it's own texture, with the leaf nodes all having a second "button pressed" texture. In addition, some of the nodes are PNG animations. I have one sprite sheet containing the 130 or so node textures, and 3 other sprite sheets for the animations. All in all those 4 files add up to only about 18.4 MB.
If I run the app and DON'T run the cocos2d part (i.e. Never launch the framework at all and therefore never load the textures) the app runs at around 10 MB. When I load Cocos2d and those sprite sheets, the memory shoots up past 90 MB.
All my research seems to say I am doing things in the most efficient way possible, but with the memory usage already so high I get a lot of memory related crashes on iPad 1.
Is this normal for cocos2d? Since the images themselves aren't so large, is it using so much memory because of the number of sprites? Are there ways to bring the memory footprint down? I am at a loss, and very much under the gun...
It turns out that the efficiency you achieve by packing the sprites together into big sprite sheets is measured in rendering time, not in memory saved. No matter in a UIImage or into an OpenGL framework like Cocos2d, when you load an image the amount of memory it takes up is width x height x bytes per pixel. So a 2048x2048 png image takes up 2048x2048x4 bytes in memory (12 MB).
To keep memory down in this case I simply have to load things as needed, and unload them as soon as they are not needed. Now the trick is finding out where and when to load, so the user never sees a stutter. FUN!

Resources