views:

825

answers:

1

Hi,

Anyone know how to create an OpenGL ES app that doesn't use the full iPhone screen dimensions as its drawing surface?

Everything I've seen so far has the EAGLView (or whatever) drawing to 0, 0, 320, 480.

I'd like to have my EAGLView at 100, 100, 100, 100. Is this possible? It seems all I'd need to do is change the glViewport() call, but not sure... does glViewport simply set up a clipping rectangle for a fullscreen OpenGL ES view? Or does it actually define where the origin (0, 0) is?

It's very confusing, especially when you're trying to think about it in terms of UIViews, which I am. I'd like to pass a CGRect into my initialize function so that it sets up glViewport and everything else to be in that rectangle.

Thanks!

+5  A: 

All you need to do is call [super initWithFrame:frame] with the frame you want from your EAGLView class when you initiate it. This example will create a transparent OpenGL view in the upper left corner and add it to you controllers view.

I've got the following code in my EAGLView class:

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        // get the layer
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
        eaglLayer.opaque = NO;
        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;
        }
     [EAGLContext setCurrentContext:context];
     [self destroyFramebuffer];
     [self createFramebuffer];      
    }
    return self;
}

And then I create the EAGLView from my controller like this:

theEAGLView = [[EAGLView alloc] initWithFrame:CGRectMake(30.0f, 30.0f, 
               90.0f, 70.0f)];
theEAGLView.opaque = NO;
[self.view addSubview:theEAGLView];

The code that does the actual drawing in my EAGLView class is called from the controller and goes something like this:

- (void)render {
    glViewport(0, 0, backingWidth, backingHeight);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrthof(0.0f, backingWidth, 0.0f, backingHeight, 1000.0f, -1000.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    // this is where we draw our stuff
    // ...
    // ...

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
Jens Utbult
This is great -- thanks. I'm still confused though on why you would do this:glViewport(0, 0, backingWidth, backingHeight);glOrthof(0.0f, backingWidth, 0.0f, backingHeight, 1000.0f, -1000.0f);When backingWidth and height are set to 320x480, and your drawing surface (the EAGLView) is now not fullscreen anymore.What's the relationship between glViewport() and the CGRect of the EAGLView? Or is it completely arbitrary?Also in the glOrtho() call, wouldn't you want to just go from 0 to your max width in the EAGLView, rather than 0 to 320?Thanks for the help!
monkey32
The backingWidth and backingHeight of the EAGLView will be set from the size of the CGRect used when initializing the EAGLView. So in this example they will both be 30.
Jens Utbult