views:

758

answers:

2

What's the minimum boilerplate code required to setup an OpenGL view (with the necessary projections,camera angles etc) for drawing a 2D game?

For example, the minimum required to do Quartz 2D drawing in a custom view (and, say, load a background image) is the following:

#import <Cocoa/Cocoa.h>

@interface MyView : NSView {
}

@end

= = =

#import "MyView.h"

@implementation MyView

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    return self;
}

- (void)drawRect:(NSRect)rect {
    CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort];
    CGRect frame = CGRectMake(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
    CFBundleRef mainBundle = CFBundleGetMainBundle();
    CFURLRef url = CFBundleCopyResourceURL(mainBundle, CFSTR("background"), CFSTR("png"), NULL);
    CGDataProviderRef provider = CGDataProviderCreateWithURL (url);
    CGImageRef image = CGImageCreateWithPNGDataProvider (provider, NULL, true, kCGRenderingIntentDefault);
    CGDataProviderRelease (provider);
    CGContextDrawImage (myContext, frame, image);
    CGImageRelease (image);

    //rest of drawing code here...
}

@end

Would anything in the boilerplate code be different for Open GS ES on the iPhone as opposed to using Open GL on a Mac?

A: 

Would anything in the boilerplate code be different for [OpenGL] ES on the iPhone as opposed to using Open GL on a Mac?

Yes. On a Mac, you'd use NSOpenGLView, which is part of Application Kit. The iPhone doesn't have AppKit.

I can't say more for sure because I'm not an iPhone developer, but I would guess that you'll use EAGL on the iPhone.

Peter Hosey
+1  A: 

The easiest way to setup an OpenGL application on the iPhone is to create a "OpenGL ES Application" through Xcode. It generates the boilerplate source code you'll need to get started.

Here is the boilerplate source I am using for an OpenGL iPhone game:

@implementation EAGLView

@synthesize context;

// You must implement this method
+ (Class)layerClass {
   return [CAEAGLLayer class];
}

//The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
- (id)initWithCoder:(NSCoder*)coder {

   if ((self = [super initWithCoder:coder])) {
      // Get the layer
      CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

      eaglLayer.opaque = YES;
      eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                      [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];

      context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];

      if (!context || ![EAGLContext setCurrentContext:context]) {
         [self release];
         return nil;
      }
   }
   return self;
}

- (void)drawView 
{
   [EAGLContext setCurrentContext:context];

   glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
   glViewport(0, 0, ScreenWidth, ScreenHeight);

   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();

   // Setup the coordinate system to use 0,0 as the lower left corner
   // and 320,480 as the upper right corner of the screen (in portrait mode).
   glOrthof(0.0f, ScreenWidth, 0.0f, ScreenHeight, -1.0f, 1.0f);

   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();

   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   // Here is where you draw everything in your world.
   DrawWorld();

   glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
   [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}


- (void)layoutSubviews {
   [EAGLContext setCurrentContext:context];
   [self destroyFramebuffer];
   [self createFramebuffer];
   [self drawView];
}


- (BOOL)createFramebuffer {

   glGenFramebuffersOES(1, &viewFramebuffer);
   glGenRenderbuffersOES(1, &viewRenderbuffer);

   glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
   glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
   [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
   glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

   glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &ScreenWidth);
   glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &ScreenHeight);

   if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
      NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
      return NO;
   }

   return YES;
}


- (void)destroyFramebuffer {

   glDeleteFramebuffersOES(1, &viewFramebuffer);
   viewFramebuffer = 0;
   glDeleteRenderbuffersOES(1, &viewRenderbuffer);
   viewRenderbuffer = 0;
}

- (void)dealloc {

   if ([EAGLContext currentContext] == context) {
      [EAGLContext setCurrentContext:nil];
   }

   [context release];  
   [super dealloc];
}

@end

As an alternative, this article provides a nice walkthrough in creating an OpenGL ES application on the iPhone.

Andrew Garrison