Non Power of Two Textures in iOS

Non power of two textures in iOS

As mentioned in my edit, I found the solution. NPOT on ES 2.0 requires that you use linear filtering and clamp to edge. Also, no mipmaps.

iphone opengl es 2.0 non power of two

OpenGL ES for iOS requires Power-of-Two images, unfortunately, as it is a rather strict implementation (case in point, look at all of the stuff that is not available in OpenGL ES).

If your image is non-power-of-two there are a few solutions.

First, the most obvious, you must add some padding to the image to make it so. This can be done either in an image editor, or programatically when you load the texture data.

Second, if you have multiple textures, you can instead compile your images into one larger image using a texture packing tool. This is a more targeted approach depending on your intended use, and requires some more work if you are intending to use the texture for more than one 3D mesh or model as your UV/texture coordinates will be different from their originals.

Edit

Since not everyone reads the comments, I'll quote my comment to give it higher visibility. Under very specific circumstances, NPOT textures are valid, as is follows.

After a bit of digging, NPOT textures are technically enabled in the newer iOS hardware running 2.0 ES, but with extremely limited use. Specifically, you must use linear filtering with clamp-to-edge, and no mipmapping. This limits your use, and in most cases a power-of-two image would still be more efficient/have higher framerates.

Do I have to worry about non-power-of-two textures on API 16+?

Firstly, you didn't mention whether you are targeting OpenGLES 1 or 2. From the information you've posted, all the devices you target support OpenGLES 2, but it's up to you which version you actually chose to use.

Assuming your code uses OpenGLES 2, then all devices should work with non-POT textures. However, you should be aware that texture wrapping (GL_REPEAT) and mipmapping are only supported on non-POT textures via extensions. Also, a lot of devices will allocate memory as if your texture was POT anyway.

Because of these reasons, it's almost always a good idea to author POT textures for 3D assets. For 2D assets it's a good idea to think about using texture atlasses to combine multiple non-POT textures into a larger POT atlas.

Implementing non-power-of-2 textures in iSGL3d

simply by disabling mipmapping, even valid textures fail to draw

Did you set the minification sampling for these textures to not use the mipmaps? It defaults to mipmap option, so you have to set it to something else if you don't use mipmaps.

e.g.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Hardware support for non-power-of-two textures

Arbitrary texture sizes have been specified as core part of OpenGL ever since OpenGL-2, which was a long time ago (2004). All GPUs designed every since do support NP2 textures just fine. The only question is how good the performance is.

However ever since GPUs got programmable any optimization based on the predictable patterns of fixed function texture gather access became sort of obsolete and GPUs now have caches optimized for general data locality and performance is not much of an issue now either. In fact, with P2 textures you may need to upscale the data to match the format, which increases the required memory bandwidth. However memory bandwidth is the #1 bottleneck of modern GPUs. So using a slightly smaller NP2 texture may actually improve performance.

In short: You can use NP2 textures safely and performance is not much of a big issue either.

Loading non-power-of-two images in OpenGL ES iPhone

For performance reasons, it's best to putt all your sprites into an atlas. An atlas is a large texture, that contains all your sprites. There are tools to automate this process. For example TexturePacker: http://www.texturepacker.com/

Depending on which technology you're using, you might have to parse the output from texture packer to get the UV-Offsets.

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

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.



Related Topics



Leave a reply



Submit