我正在尝试将我的桌面OpenGL程序移植到iOS上的OpenGL ES 1.1,但我没有运气。所有代码都相同,例如drawArrays和glOrthof,除了iOS方面的framebuffer逻辑显然是不同的,因为它取代了iOS上不存在的GLUT。有人能告诉我这段代码有什么问题吗?它往往显示白色或黑色屏幕。
gllayer = (CAEAGLLayer *)self.layer;
gllayer.opaque = TRUE;
gllayer.drawableProperties = @{
kEAGLDrawablePropertyRetainedBacking: @YES,
kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8
};
context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
return nil;
}
glGenFramebuffersOES (1, &framebuffer);
glGenRenderbuffersOES (1, &renderbuffer);
glBindFramebufferOES (GL_FRAMEBUFFER_OES, framebuffer);
glBindRenderbufferOES (GL_RENDERBUFFER_OES, renderbuffer);
[context renderbufferStorage: GL_RENDERBUFFER_OES fromDrawable: gllayer];
glFramebufferRenderbufferOES (GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, renderbuffer);
glGetRenderbufferParameterivOES (GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES (GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
glGenRenderbuffersOES (1, &depthbuffer);
glBindRenderbufferOES (GL_RENDERBUFFER_OES, depthbuffer);
glRenderbufferStorageOES (GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
glFramebufferRenderbufferOES (GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthbuffer);
if (glCheckFramebufferStatusOES (GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
return nil;
它看起来像我基本上在iOS上我们正在绘制缓冲区。如果可以直接在屏幕上绘制,我只会这样做。
- (void) startAnimation
{
displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self
selector:@selector(drawGLContent)
];
[displayLink setFrameInterval: animationFrameInterval];
[displayLink addToRunLoop: [NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
animating = TRUE;
}
@Frank,我可以看到你在使用OpenGL初始化时遇到了麻烦。在这里,我创建了一个MyGLView视图,它是一个包含所有OpenGL设置代码的UIView。正确创建和销毁EAGLContext,renderbuffer和framebuffer。我添加了一些评论,以便您可以看到发生了什么。
此外,方法drawGLContent
是您需要在“TODO”注释下专门放置绘制调用的地方。
#import <GLKit/GLKit.h>
#import <Foundation/Foundation.h>
@interface MyGLView : UIView{
EAGLContext *context;
GLuint viewRenderbuffer, viewFramebuffer;
}
- (void)drawGLContent;
@end
@implementation MyGLView
// Implement this to override the default layer class (which is [CALayer class]).
// We do this so that our view will be backed by a layer that is capable of OpenGL ES rendering.
+ (Class)layerClass
{
return [CAEAGLLayer class];
}
- (id)init{
if ((self = [super init])) {
[self initView];
}
return self;
}
- (id)initWithFrame:(CGRect)frame{
if ((self = [super initWithFrame:frame])) {
[self initView];
}
return self;
}
- (id)initWithCoder:(NSCoder*)coder {
if ((self = [super initWithCoder:coder])) {
[self initView];
}
return self;
}
- (void)initView{
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
eaglLayer.opaque = YES;
// In this application, we want to retain the EAGLDrawable contents after a call to presentRenderbuffer.
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!context || ![EAGLContext setCurrentContext:context]) {
NSLog(@"failed to init HeatmapView");
}
// Set the view's scale factor as you wish
self.contentScaleFactor = [[UIScreen mainScreen] scale];
[EAGLContext setCurrentContext:context];
[self createBuffers];
}
- (void)createBuffers{
// The pixel dimensions
GLint backingWidth;
GLint backingHeight;
// Generate IDs for a framebuffer object and a color renderbuffer
glGenFramebuffers(1, &viewFramebuffer);
glGenRenderbuffers(1, &viewRenderbuffer);
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
// This call associates the storage for the current render buffer with the EAGLDrawable (our CAEAGLLayer)
// allowing us to draw into a buffer that will later be rendered to screen wherever the layer is (which corresponds with our view).
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(id<EAGLDrawable>)self.layer];
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, viewRenderbuffer);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
// Setup the view port in Pixels
glViewport(0, 0, backingWidth ,backingHeight);
}
- (void)destroyBuffers{
// Destroy framebuffers and renderbuffers
if (viewFramebuffer) {
glDeleteFramebuffers(1, &viewFramebuffer);
viewFramebuffer = 0;
}
if (viewRenderbuffer) {
glDeleteRenderbuffers(1, &viewRenderbuffer);
viewRenderbuffer = 0;
}
}
#pragma mark - Public methods
- (void)drawGLContent{
[EAGLContext setCurrentContext:context];
if(viewRenderbuffer == 0 || viewFramebuffer == 0){
[self createBuffers];
}
//Clear the framebuffer
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
///////////////////////////////////////////
//TODO:MAKE Draw Calls!!
///////////////////////////////////////////
// Display the buffer
[context presentRenderbuffer:GL_RENDERBUFFER];
}
#pragma mark -
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
return NO;
}
-(void)layoutSubviews
{
[EAGLContext setCurrentContext:context];
[self destroyBuffers];
[self createBuffers];
//Clear the framebuffer
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
[context presentRenderbuffer:GL_RENDERBUFFER];
}
- (void)dealloc
{
[self destroyBuffers];
// tear down context
if ([EAGLContext currentContext] == context)
[EAGLContext setCurrentContext:nil];
}
@end
本课程基于Ray Wenderlich OpenGL ES 2.0教程,但稍微适应了OpenGL ES 1.0。