iOS Reference Library Apple Developer
Search

Best Practices for Working with Texture Data

In the previous chapter, you saw how a few simple rules could improve your application’s ability to process vertex data. This chapter provides similar guidelines for textures.

Reduce Texture Memory Usage

The amount of memory your iOS application uses is critical. However, texture memory in OpenGL ES is even more constrained. iPhone or iPod touch devices that use the PowerVR MBX hardware have a limit on the total amount of memory they can use for textures and renderbuffers (described in “PowerVR MBX”). Where possible, your application should minimize the amount of memory it uses for textures.

Broadly, your application must balance the size of your texture data with the quality of the final image.

Compress Textures

Texture compression is often the single largest source of memory savings. OpenGL ES for iOS supports the PowerVR Texture Compression (PVRTC) format by implementing the GL_IMG_texture_compression_pvrtc extension. There are two levels of PVRTC compression, 4 bits per channel and 2 bits per channel, which offer a 8:1 and 16:1 compression ratio over the uncompressed 32-bit texture format respectively. A compressed PVRTC texture still provides a decent level of quality, particularly at the 4-bit level.

Important: Future Apple hardware may not support the PVRTC texture format. You must test for the existence of the GL_IMG_texture_compression_pvrtc extension before loading a PVRTC compressed texture. For more information on how to check for extensions, see ‚ÄúCheck for Extensions Before Using Them.‚Äù For maximum compatibility, your application may want to include uncompressed textures to use when this extension is not available.

For more information on compressing textures into PVRTC format, see “Using texturetool to Compress Textures.”

Use Lower-Precision Color Formats

If your application cannot use compressed textures, you should consider using a smaller pixel format. A texture in RGB565, RGBA5551, or RGBA4444 format uses half the memory of a texture in RGBA8888 format. Use RGBA8888 only when your application needs that level of quality.

Use Properly Sized Textures

The images that an iOS-based device displays are very small. Your application does not need to provide large textures to present acceptable images to the screen. Halving both dimensions of a texture reduces the amount of memory needed for that texture to one-quarter that of the original texture.

Before shrinking your textures, you should first attempt to compress the texture or use a lower-precision color format. A texture compressed with the PVRTC format usually provides higher-quality output than shrinking the texture—and it uses less memory too!

Load Textures During Initialization

Creating and loading textures is an expensive operation. For best results, avoid creating new textures while your application is running. Instead, create and load your texture data during initialization. Be sure to dispose of your original images once you’ve finished creating the texture.

Once your application creates a texture, avoid changing it except at the beginning or end of a frame. Currently, all iPhone and iPod touch devices uses a tile-based deferred renderer that makes calls to glTexSubImage and glCopyTexSubImage particularly expensive. See “Tile-Based Deferred Rendering” for more information.

Combine Textures into Texture Atlases

Binding to a texture changes OpenGL ES state, which takes CPU time to process. Applications that reduce the number of changes they make to OpenGL ES state perform better. Reducing the number of state changes is discussed in detail in “Avoid Changing OpenGL ES State Unnecessarily.”

One way to avoid changing the texture is to combine multiple smaller textures into a single large texture, known as a texture atlas. Each model uses modified texture coordinates to select the desired texture from within the atlas. A texture atlas allows multiple models to be drawn without changing the bound texture and may also allow you to collapse multiple glDrawElements calls into a single call.

Texture atlases have a few restrictions:

Use Mipmapping to Reduce Memory Bandwidth

Your application should provide mipmaps for all textures except those being used to draw 2D unscaled images. Although mipmaps use additional memory, they prevent texturing artifacts and improve image quality. More importantly, when smaller mipmaps are sampled, fewer texels are fetched from texture memory, which reduces the memory bandwidth used by the hardware and significantly improves performance.

The GL_LINEAR_MIPMAP_LINEAR filter mode provides the best quality when texturing but requires additional texels to be fetched from memory. Your application can trade some image quality for better performance by specifying the GL_LINEAR_MIPMAP_NEAREST filter mode instead.

Use Multitexturing Instead of Multiple Passes

Many applications perform multiple passes on their geometry, altering the configuration of OpenGL as they need to in order to generate the final result. This is not only expensive due to the number of state changes required, but it also requires vertex information to be reprocessed for every pass, and pixel data to be read back from the framebuffer on later passes.

All OpenGL ES implementations support at least two texture units and your application can use these texture units to perform multiple steps of your algorithm in each pass. You can retrieve the number of texture units available to your application by calling glGetIntegerv with GL_MAX_TEXTURE_UNITS as the parameter.

If your application requires multiple passes to render a single object:




Last updated: 2010-07-09

Did this document help you? Yes It's good, but... Not helpful...