OpenGL ES显示白色或黑色屏幕

时间:2018-02-27 15:37:14

标签: ios objective-c opengl-es

我试图将我的桌面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;
}

1 个答案:

答案 0 :(得分:0)

@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。