Textures and Images

In the previous section, you might have noticed that we displayed an image using the SPImage object, but used an SPTexture object to set the button's image. So what is the difference between an image and a texture?

Textures

A texture is just the data that describes an image — like the file that is saved on your digital camera. You can't show anybody that file alone. It's all zeros and ones, after all. You need some device that can display the image, like your iPad.

In Sparrow, that device is called “SPImage”.

What exactly is an Image in Sparrow?

In order to make full use of GPU acceleration, Sparrow 'paints' the texture onto a quad (a geometric figure that looks like a flat rectangle). In other words, an Image is nothing else than a quad with a texture mapped onto it.

To create a texture, you initialize an object of type “SPTexture”.

// create the texture object
SPTexture *texture = [SPTexture textureWithContentsOfFile:@"mushroom.png"];
 
// display the texture through an image
SPImage *image = [SPImage imageWithTexture:texture];
 
// or do the same in one line:
SPImage *image = [SPImage imageWithContentsOfFile:@"mushroom.png"];

Every texture you create takes up precious memory. So, if you need to display something multiple times simultaneously, load the texture only once, and use different SPImage objects to display them.

File Formats

In the samples above, we've always used PNG files for our textures. Sparrow supports more file formats, though, and each has specific advantages and disadvantages.

For now, you know enough about textures to use them in Sparrow. We will revisit the topic a little later, though. If you want to peek ahead, you'll find more information here: Texture Formats.

Texture Atlases

A texture atlas from Penguflip

Even if all the previous samples created textures directly from PNG files, a real application should not do that. Here's why.

  • Sparrow batches the rendered Quads/Images to draw as many as possible with only one GPU call. Batch processing has to be stopped whenever the texture changes.
  • Some texture types have certain limitations, e.g. requiring that height and width are each a power of 2. Sparrow hides this limitation from you, but you will nevertheless use more memory.

By using a texture atlas, you avoid both the texture switches and the power-of-two limitation. All textures are within one big “super-texture”, and Sparrow takes care that the correct part of this texture is displayed. (Some other frameworks call this feature “Sprite Sheets”.)

The trick is to have OpenGL use this big texture instead of the small ones, and to map only a part of it to the quad you are drawing. If the images are arranged in a smart way (more on that later), this will lead to a very efficient memory usage, wasting as little space as possible.

Now lean back and enjoy a comical introduction to sprite sheets, brought to you by the “Texture Packer” team: What is a Sprite Sheet?

Creating the Atlas

The positions of each sub-texture are defined in an XML file like this one:

<TextureAtlas imagePath="atlas.png">
 <SubTexture name="moon" x="0" y="0" width="30" height="30"/>;
 <SubTexture name="jupiter" x="30" y="0" width="65" height="78"/>;
 ...
</TextureAtlas>;

You don't have to create a texture atlas manually. You can use the following tools to create a texture atlas:

  • Sparrow has its own atlas generator. Find it in the folder sparrow/util/atlas_generator. The README file in the same folder shows you how to install and use it.
  • Another great tool is TexturePacker. It has a GUI that is very simple to use (available in a free and commercial version).

Andreas Löw supports us by sharing some of his revenue with us when Sparrow users purchase one of his tools. If you choose to buy Texture Packer, it would be great if you could use the following link: Purchase TexturePacker – thanks in advance!

Using the Atlas

So, now you have a texture atlas. But how do you use it?

Create a new “SPTextureAtlas” instance and access all subtextures through the “textureByName:” method. Create the atlas object once when the game is initialized and reference it throughout the lifetime of your game.

// load the atlas
SPTextureAtlas *atlas = [SPTextureAtlas atlasWithContentsOfFile:@"atlas.xml"];
 
// display a sub-texture
SPTexture *jupiterTexture = [atlas textureByName:@"jupiter"];
SPImage *jupiterImage = [SPImage imageWithTexture:jupiterTexture];

It's as simple as that!


Next Section: Displaying Text

  manual/textures_and_images.txt · Last modified: 2013/05/30 12:39 by daniel
 
Powered by DokuWiki