cocos2d zooming sprite without distortion? - iphone

I want to implement zooming of sprites with a pinch gesture in Cocos2d.
How do I achieve it without the image getting pixelated?
I tried with vectors but with no success, I'm doomed using raster bitmap images.
Do I need the largest possible image with the highest resolution to make it look
nice?
What is the size limit for pngs in cocos2d?
What other pitfalls do I need to consider?

Yes. For example if the sprite should cover an area of 1024x1024 pixels when zoomed in to maximum, you need to create the image as 1024x1024 and set the scale property to below 1 in order to create a smaller version. If you use scale greater than 1.0 the image will always lose detail and become ever more blurred as scale increases.
There is no size limit in cocos2d, it's the devices that impose the limit. Most devices can handle 2048x2048 except 1st and 2nd generation which support only 1024x1024. You wouldn't normally support these older devices though, so 2048x2048 should be the default. Several newer devices (iPad 2+, iPhone 4S+) can use up to 4096x4096 textures.
Memory consumption. Not sure what you're trying to do, but often developers have little understanding about how much memory textures consume and what amount of memory is available. For instance, 2048x2048 as PNG with 32-Bit color consumes 16 MB of memory. Don't plan on using more than 4-5 of these, unless you're able to reduce color bit depth and use TexturePacker to be able to use the compressed .pvr.ccz format. Read my article about optimizing memory usage for more info.

Related

What are the limits on GMSGroundOverlay?

What are the limits on GMSGroundOverlay? This would be things like file size, resolution, etc..
I'm using Google Maps SDK 1.5. I created a ground overlay from an image that was 4836x5557 72 dpi 6.6 MB. That image did not show up. When I reduced the image to 3481x4000 72 dpi 4.5 MB, that overlay image did show up.
I did try some permutations of resolutions and file sizes but couldn't nail down the pattern. I did not see any documentation of limits in the docs nor headers.
This is important to me as we have customers who use want map overlays, and to be able to provide them up front with the constraints for the overlay graphics is useful and saves much time for all involved.
Thank you.
Overlay is rendered using OpenGL as a single texture, so the limitation on its size is probably the same as limitation on OpenGL texture size.
On the latest devices maximum texture size is 4096×4096:
https://apptyrant.com/2014/04/19/max-opengl-texture-sizes-for-various-ios-devices/
The solution is either to limit the overlay size or to use Tiles API.

Cocos2d and iPhone: Parallax Background with multiple texture atlases gives many memory warnings

The problem I am trying to solve is:
I have 6 stripes which I need to move at different speed. A texture sheet of 2048*2048 is not enough and to deal with this I splitted the image in two (top and bottom half), so each stripe is exactly 960*640pixels. The general algorithm is to allocate a top and bottom half for each stripe and move them at each frame making sure to reposition them at the top of the screen when they exit the user's view. My class implementation, a direct modification of ParallaxBackground in the ShootEmUp example from this book, is giving too many memory warnings when run and analyzed using Instruments. See analysis below:
OpenGL analysis:
Activity monitor:
What concerns me is the high number of memory warnings in both analysis (24 and 5 respectively).
EDIT: Below you can find a comment which explains the solution
2048x2048 is maximum possible size of texture for new devices. you can read about it in Apple OpenGL ES Programming Guide
Remember that Cocos2D always saves images with a width/height being a power of 2. So if your image is 960x640 pixels it'll use memory as if the image is 1024x1024 pixels.
Also remove textures you no longer need (and when outofmemory gets called).
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
You can also use images in a lower quality to save memory.
[CCTexture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGBA4444];
Whenever you need to load higher quality images or gradients you can put it back.
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];
Following the comment-suggestion to my question by LearnCocos2d the correct answer-solution was to simply reboot the device.. (see his comment above).
Thanks!

iPhone image resource - 1024 maximum, 2048 pixels #2x?

The restriction of 1024x1024 as the largest image for an iPhone is a problem with iPhone 4. However if an #2x image is used with maximum dimensions of 2048x2048 everything looks equally good on the 4 as it does on a 3 - tried and tested in simulator and device. Question is, does the image dimension restriction relate to the UIImage or the resource that it contains? I can't imagine resources of more than 1024 pixels are discouraged with the 960 pixel height of the screen.
The right answer is really to use tiles so that things look even better, but the deadline for for this deliverable is too close - it's a future thing.
From UIImage class reference:
You should avoid creating UIImage
objects that are greater than 1024 x
1024 in size. Besides the large amount
of memory such an image would consume,
you may run into problems when using
the image as a texture in OpenGL ES or
when drawing the image to a view or
layer. This size restriction does not
apply if you are performing code-based
manipulations, such as resizing an
image larger than 1024 x 1024 pixels
by drawing it to a bitmap-backed
graphics context. In fact, you may
need to resize an image in this manner
(or break it into several smaller
images) in order to draw it to one of
your views.
That is, views are rendered and composited with the iPhone's GPU. If your view, for example, overrides drawRect and tries to render a very big UIImage you might run into problems. Newer generation iDevices, such as iPad and iPhone 4 support bigger textures than 1024x1024 (2048x2048 I think).
I didn't realise there was a restriction, I'm using an image 15198 × 252 as the scrolling landscape in Scramble... works really well, though I must say I did have reservations before I tried it out!

Optimizing OpenGL ES on the iPhone and interpreting Instruments

I'm trying to push my FPS up on iPhone 3Gs from 30 as high as possible... and I'm running into a couple of issues and thought it would be better to ask for advice.
1) What exactly do the Renderer Utilization and Tiler Utilization columns on the OpenGL ES Instrument signify? My Tiler Utiliation percentage is extremely low, and my Renderer Utilization tends to drop during user interaction and when the app is flipped to landscape mode. I noticed that my FPS tends to drop whenever the Renderer Utilization value drops as well. My FPS dropping during landscape mode is particularly odd for me, because portrait mode and landscape mode use the exact same game logic, and textures... and landscape mode actually renders fewer vertices/triangles to boot (some parts of the UI aren't drawn at all in landscape mode).
2) I've already done most of the recommended optimizations in the ngmoco/Stanford videos, and the only things I think I can do left are changing GLfloats to GLshorts and interleaving my vertices with my texture coordinates into one array. Are any of these likely to have large effects on my FPS? It's a 2D sprite game with lots of large, detailed textures...
3) Which is a faster way to hide a polygon: setting all of its vertices to the same coordinates (essentially, reducing it to a point), or setting its alpha value to 0? I'm guessing its the former, since blending is slower in general and particularly expensive on the iPhone.
4) Currently, I'm using a 2 512x512 textures, a 1024x512 texture, and a 256x256 texture. I've sought advice on how to best manage this, and I was told not to combine them into 1 1024x1024 texture because of memory problems on the iPhone 3G. I'd like to confirm that here, because if I put everything into 1 texture, I can eradicate having to call glBindTexture repeatedly...
To #4: (a) yes, the iPhone is documented not to deal with images larger than 1024 on a side. 1024x1024 is the maximum theoretical limit, although you may run into problems if you try to push right up against the limit.
(b) all your textures don't fit into a 1024x1024; after the 1024x512 and 2 512x512s fill that space, you'll still have the 256x256 left over.

Why do images for textures on the iPhone need to have power-of-two dimensions?

I'm trying to solve this flickering problem on the iphone (open gl es game). I have a few images that don't have pow-of-2 dimensions. I'm going to replace them with images with appropriate dimensions... but why do the dimensions need to be powers of two?
The reason that most systems (even many modern graphics cards) demand power-of-2 textures is mipmapping.
What is mipmapping?
Smaller versions of the image will be created in order to make the thing look correctly at a very small size. The image is divided by 2 over and over to make new images.
So, imagine a 256x128 image. This would have smaller versions created of dimensions 128x64, 64x32, 32x16, 16x8, 8x4, 4x2, 2x1, and 1x1.
If this image was 256x192, it would work fine until you got down to a size of 4x3. The next smaller image would be 2x1.5 which is obviously not a valid size. Some graphics hardware can deal with this, but many types cannot.
Some hardware also requires a square image but this isn't very common anymore.
Why do you need mipmapping?
Imagine that you have a picture that is VERY far away, so far away as to be only the size of 4 pixels. Now, when each pixel is drawn, a position on the image will be selected as the color for that pixel. So you end up with 4 pixels that may not be at all representative of the image as a whole.
Now, imagine that the picture is moving. Every time a new frame is drawn, a new pixel is selected. Because the image is SO far away, you are very likely to see very different colors for small changes in movement. This leads to very ugly flashing.
Lack of mipmapping causes problems for any size that is smaller than the texture size, but it is most pronounced when the image is drawn down to a very small number of pixels.
With mipmaps, the hardware will have access to 2x2 version of the texture, so each pixel on it will be the average color of that quadrant of the image. This eliminates the odd color flashing.
http://en.wikipedia.org/wiki/Mipmap
Edit to people who say this isn't true anymore:
It's true that many modern GPUs can support non-power-of-two textures but it's also true that many cannot.
In fact, just last week I had a 1024x768 texture in an XNA app I was working on, and it caused a crash upon game load on a laptop that was only about a year old. It worked fine on most machines though. It's a safe bet that the iPhone's gpu is considerably more simple than a full PC gpu.
Typically, graphics hardware works natively with textures in power-of-2 dimensions. I'm not sure of the implementation/construction details that cause this to be the case, but it's generally how it is everywhere.
EDIT: With a little research, it turns out my knowledge is a little out of date -- a lot of modern graphics cards can handle arbitrary texture sizes now. I would imagine that with the space limitations of a phone's graphics processor though, they'd probably need to omit anything that would require extra silicon like that.
You can find OpenGL ES support info about Apple Ipod/Iphone devices here:
Apple OpenES support
OpenGL ES 2.0 is defined as equal to OpenGL 2.0
The constraint about texture size's has been disappear only from version 2.0
So if you use OpenGL ES with version less then 2.0 - it is normal situation.
I imagine it's a pretty decent optimization in the graphics hardware to assume power-of-2 textures. I bought a new laptop, with latest laptop graphics hardware, and if textures aren't power-of-2 in Maya, the rendering is all messed up.
Are you using PVRTC compression? That requires powers of 2 and square images.
Try implementing wrapping texture-mapping in software and you will quickly discover why power-of-2 sized are desirable.
In short, you will find that if you can assume power-of-2 dimensions then a lot of integer multiplications and divisions turn into bit-shifts.
I would hazard a guess that the recent trend in relaxing this restriction is due to GPUs moving to floating-point maths.
Edit: The "because of mipmapping" answer is incorrect. Mipmapped, non-power-of-two textures are a common feature of modern GPUs.