How to texturize objects with GLKit (Part 2)

This is the sixth post in my 2D Game Engine Tutorial. This post relies on code created in earlier posts, so if you jumped in on this post I recommend you at least skim the previous posts in the series. You can also grab the tagged code so that you don’t have to start from scratch if you don’t want to.

In this post we’ll learn how to create a sprite class to encapsulate our texture information, and turn on transparency for nicer graphics.

Iteration 11: Sprites and other transparent textures

Let’s go ahead and start a sprite class that will encapsulate the rectangular texture code we’ve handled above. Since a sprite is a rectangle, we’ll descend from EERectangle.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// EESprite.h
@interface EESprite : EERectangle
-(id)initWithImage:(UIImage*)image pointRatio:(float)ratio;
@end
 
 
// EESprite.m
-(id)initWithImage:(UIImage*)image pointRatio:(float)ratio {
  self = [super init];
  if (self) {
    self.width = image.size.width/ratio;
    self.height = image.size.height/ratio;
 
    [self setTextureImage:image];
    self.textureCoordinates[0] = GLKVector2Make(1,0);
    self.textureCoordinates[1] = GLKVector2Make(1,1);
    self.textureCoordinates[2] = GLKVector2Make(0,1);
    self.textureCoordinates[3] = GLKVector2Make(0,0);
  }
  return self;
}

This lets us initialize a sprite with just an image file. The width and height are calculated based on the image’s size and scaled by a ratio parameter (i.e. N pixels represent 1 unit in our world coordinates).

To test, we’ll use a free sprite by Danc at LostGarden (I’ve trimmed it of the extra whitespace).

Now we’ll create a test scene that uses our sprite class.

// SpriteScene.m
-(id)init {
  self = [super init];
  if (self) {
    sprite = [[EESprite alloc] initWithImage:[UIImage imageNamed:@"boy-sprite.png"] pointRatio:100];
  }
  return self;
}

Uh oh! The transparent parts are showing up as blackā€”not as transparent.

By default, OpenGL doesn’t turn on transparency. We’ll need to set it ourselves using a blend function in our rendering code. It’s just a few lines of code.

// EEShape.m in renderInScene:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
...  
glDrawArrays(GL_TRIANGLE_FAN, 0, self.numVertices);
...
glDisable(GL_BLEND);

The blend function tells OpenGL to use our alpha values to create transparent effects. It’s actually more complicated than that, and there’s a whole slew of ways that OpenGL can blend your colors. To give you a bit of flavor for what’s going on under the curtains (feel free to skip), the OpenGL FAQ on transparency says about this blend function:

[glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)] modifies the incoming color by its associated alpha value and modifies the destination color by one minus the incoming alpha value. The sum of these two colors is then written back into the framebuffer.

The pragmatist in me says that it’s not necessary to have anything but the vaguest of grasps on that to use it: it turns on transparency in the default case.

As a nice side effect, partially transparent colored objects without textures work now, too.

iteration-11

Hey! Our EEScene‘s renderInScene: has gotten kind of big, so iteration 11 includes comments to make sure you understand what each part is doing!

Continue on to the next article in the tutorial to learn how to move, scale, and rotate your shapes and sprites.

This entry was posted in 2D Game Engine Tutorial, GLKit, Lessons, OpenGL. Bookmark the permalink.