craft or crap

Is this site blocked by GFW?

Implement OpenGL ES color picking in iOS 5 with GLKView and GLKViewController

leave a comment »

iOS 5 introduces GLKView and GLKViewController classes, allowing us to implement OpenGL ES programs with less effort. Searching “GLKView iOS tutorial” will gives you some of the examples of how to use them, such as this one that I found quite helpful. However, most of those tutorials only cover the most basic topics of how to construct a OpenGL ES program. When I developed my own iOS5 games, I spent a lot of time searching one the Internet for the proper implementation of color picking techniques in GLKView.

For those who don’t know the color picking technique, you can refer here for a detailed description. Before iOS5, the only way to implement color picking is drawing the content into the framebuffer, then use glPickPixel(…) to read the color value at a specific location.

With GLKView and GLKViewController, there is no need to read from the framebuffer directly, which is also not encouraged by Apple. The GLKView class provides a quite handy API to draw the content into a UIImage object, rather than display in the current UI. It is called snapshot. Let’s say we have a UIViewController (inheriting GLKViewController) has the following methods:


- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect

- (void)touchesBegin(NSSet *)touches withEvent:(UIEvent *)event

What we want to achieve is when the user touches an object in the view, we will take a snapshot of the view, and then use the touch coordinate to pickup the pixel’s color value. The trick is: In order to detect which object the user touched, we need to draw the scene without any lighting or texture, and we also need to draw each identifiable object with a single unique color value. So, in the glkView:drawInRect: function, we should check whether the controller is snapshotting, then draw content with different routines. Here is the implementation of those functions:


- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {

  if (isSnapshotting) {

    self.effect.light0.enabled = GL_FALSE; // disable lighting

    self.effect.texture2d0.enabled = GL_FALSE; // disable texture

    // clear scene

    [self.effect prepareToDraw];

    // here goes to drawing for object picking

  } else {

    self.effect.light0.enabled = GL_TRUE; // disable lighting

    self.effect.texture2d0.enabled = GL_TRUE; // disable texture

    // clear scene

    [self.effect prepareToDraw];

    // here goes regular drawing

  }

  isSnapshotting = GL_FALSE; // switch back to normal drawing

}

- (void)touchesBegin(NSSet *)touches withEvent:(UIEvent *)event {

  isSnapshotting = GL_TRUE;

  UIImage *image = [((GLKView *) self.view) snapshot];

  // pickup pixel's color value by touch location and identify the object

}

For the pixel pickup implementation, you can refer to this link.

Written by wentao

November 29, 2011 at 4:23 am

Posted in iOS, programming

Leave a comment