Xcode 4 OpenGL ES 1.1 template
I start a new opengles project from xcode 4 and i delete all ES2 references and calls (i want to use ES1 draw code). My example project work fine on iphone 4 but doesn't work on iphone 3g and ipod 2nd generation. Hre is my modified code :
EAGLView.m
#import <QuartzCore/QuartzCore.h>
#import "EAGLView.h"
@interface EAGLView (PrivateMethods)
- (void)createFramebuffer;
- (void)deleteFramebuffer;
@end
@implementation EAGLView
@synthesize context;
// You must implement this method
+ (Class)layerClass
{
return [CAEAGLLayer class];
}
//The EAGL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:.
- (id)initWithCoder:(NSCoder*)coder
{
self = [super initWithCoder:coder];
if (self) {
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
eaglLayer.opaque = TRUE;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:FALSE], kEAGLDrawable开发者_Python百科PropertyRetainedBacking,
kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
nil];
}
return self;
}
- (void)dealloc
{
[self deleteFramebuffer];
[context release];
[super dealloc];
}
- (void)setContext:(EAGLContext *)newContext
{
if (context != newContext) {
[self deleteFramebuffer];
[context release];
context = [newContext retain];
[EAGLContext setCurrentContext:nil];
}
}
- (void)createFramebuffer
{
if (context && !defaultFramebuffer) {
[EAGLContext setCurrentContext:context];
// Create default framebuffer object.
glGenFramebuffersOES(1, &defaultFramebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
// Create color render buffer and allocate backing store.
glGenRenderbuffersOES(1, &colorRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer *)self.layer];
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &framebufferWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &framebufferHeight);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);
if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
}
}
- (void)deleteFramebuffer
{
if (context) {
[EAGLContext setCurrentContext:context];
if (defaultFramebuffer) {
glDeleteFramebuffersOES(1, &defaultFramebuffer);
defaultFramebuffer = 0;
}
if (colorRenderbuffer) {
glDeleteRenderbuffersOES(1, &colorRenderbuffer);
colorRenderbuffer = 0;
}
}
}
- (void)setFramebuffer
{
if (context) {
[EAGLContext setCurrentContext:context];
if (!defaultFramebuffer)
[self createFramebuffer];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
glViewport(0, 0, framebufferWidth, framebufferHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0, framebufferWidth, framebufferHeight, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
}
- (BOOL)presentFramebuffer
{
BOOL success = FALSE;
if (context) {
[EAGLContext setCurrentContext:context];
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
success = [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
return success;
}
- (void)layoutSubviews
{
// The framebuffer will be re-created at the beginning of the next setFramebuffer method call.
[self deleteFramebuffer];
}
@end
testViewController.m
#import "testAppDelegate.h"
#import "testViewController.h"
#import "EAGLView.h"
// Uniform index.
enum {
UNIFORM_TRANSLATE,
NUM_UNIFORMS
};
GLint uniforms[NUM_UNIFORMS];
// Attribute index.
enum {
ATTRIB_VERTEX,
ATTRIB_COLOR,
NUM_ATTRIBUTES
};
@interface testViewController ()
@property (nonatomic, retain) EAGLContext *context;
@property (nonatomic, assign) CADisplayLink *displayLink;
@end
@implementation PyrotexniViewController
@synthesize animating, context, displayLink;
- (void)awakeFromNib
{
EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!aContext)
NSLog(@"Failed to create ES context");
else if (![EAGLContext setCurrentContext:aContext])
NSLog(@"Failed to set ES context current");
self.context = aContext;
[aContext release];
[(EAGLView *)self.view setContext:context];
[(EAGLView *)self.view setFramebuffer];
animating = FALSE;
animationFrameInterval = 1;
self.displayLink = nil;
- (void)dealloc
{
// Tear down context.
if ([EAGLContext currentContext] == context)
[EAGLContext setCurrentContext:nil];
[context release];
[EAGLView dealloc];
[self stopAnimation];
[super dealloc];
}
- (NSInteger)animationFrameInterval
{
return animationFrameInterval;
}
- (void)setAnimationFrameInterval:(NSInteger)frameInterval
{
if (frameInterval >= 1) {
animationFrameInterval = frameInterval;
if (animating) {
[self stopAnimation];
[self startAnimation];
}
}
}
- (void)startAnimation
{
if (!animating) {
CADisplayLink *aDisplayLink = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selector(drawFrame)];
[aDisplayLink setFrameInterval:animationFrameInterval];
[aDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
self.displayLink = aDisplayLink;
animating = TRUE;
}
}
- (void)stopAnimation
{
if (animating) {
[self.displayLink invalidate];
self.displayLink = nil;
animating = FALSE;
}
}
- (void)drawFrame
{
[(EAGLView *)self.view setFramebuffer];
......draw code here.....
[(EAGLView *)self.view presentFramebuffer];
}
based on this project scheme supposed to work on opengles 1.1 devices ,but doesn't (this code work only on iphone4) ! what goes wrong here ? please help me. Thanks.
One problem is that CADisplayLink doesn't exist in IOS versions earlier than 3.1. You can detect that in awakeFromNib like this:
NSString *reqSysVer = @"3.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
mDisplayLinkSupported = TRUE;
and then in startAnimation you can do this
if (mDisplayLinkSupported)
{
// CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
// if the system version runtime check for CADisplayLink exists in -initWithCoder:. The runtime check ensures this code will
// not be called in system versions earlier than 3.1.
mDisplayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(drawView:)];
[mDisplayLink setFrameInterval:1];
[mDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
else
mAnimationTimer = [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval)(1.0 / 60.0) target:self selector:@selector(drawView:) userInfo:nil repeats:TRUE];
and in stopAnimation do something like this:
if (mAnimating)
{
if (mDisplayLinkSupported)
{
[mDisplayLink invalidate];
mDisplayLink = nil;
}
else
{
[mAnimationTimer invalidate];
mAnimationTimer = nil;
}
mAnimating = FALSE;
}
You also need to make drawFrame's signature look like this so it can handle the AnimationTimer messages.
- (void) drawFrame:(id)sender
Anyway, this code isn't using all the same variable names as you had since I just copied it from my code, but you get the gist. Incidentally, this code was derived from an older XCode template that took into account older IOS versions that didn't support display links.
The problem probably lies in the view files. you have to set it to GLES 1 as default instead of GLES 2 which is default in most cases. it will probably have something like
if ((self = [super initWithCoder:coder]))
{
// Get the layer
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
eaglLayer.opaque = TRUE;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
renderer = [[ES2Renderer alloc] init];
if (!renderer)
{
renderer = [[ES1Renderer alloc] init];
if (!renderer)
{
[self release];
return nil;
}
}
Just change the ES2Renderer and ES1Renderer. It is saying that all of that stuff works to create the EALayer and then set ES2 as its default and if ES2 can not be loaded, then you use ES1
精彩评论