如何在ios使用opengl

       在MAC OS 和 IOS 中使用opengl有两种方式:一种是直接继承OpenGL View,需要用到GLKit;另一种是自定义UIView,这需要用到CAEAGLLayer,其实每个UIView可以拥有多个Layer。下面的例子是使用自定义UIView。

OpenGLView.h文件:

#ifndef OpenGL_View_h
#define OpenGL_View_h

@interface OpenGLView : UIView


- (void)swapBuffer;

@end


#endif /* OpenGLView.h */

OpenGLView.m文件:

#import <UIKit/UIKit.h>
#import "OpenGLView.h"
#import <OpenGLES/ES3/gl.h>
#import <OpenGLES/ES3/glext.h>

@interface OpenGLView ()

@property (nonatomic, strong) EAGLContext *context;
@property (nonatomic, strong) CAEAGLLayer *eagLayer;

@property (nonatomic, assign) GLuint renderBuffer;
@property (nonatomic, assign) GLuint frameBuffer;

@end

@implementation OpenGLView 

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if(self) {
        [self setupLayer];
        [self setupBuffer];

    }
    return self;
}

+ (Class) layerClass
{
    return [CAEAGLLayer class];
}

- (void)dealloc{
    glDeleteRenderbuffers(1, &_renderBuffer);
    glDeleteFramebuffers(1, &_frameBuffer);
}

- (void)setupLayer
{
    EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
    if(![EAGLContext setCurrentContext:context])
    {
        NSLog(@"Fail to set current context");
        return;
    }
    self.context = context;
    self.eagLayer = (CAEAGLLayer*) self.layer;
    [self setContentScaleFactor:[[UIScreen mainScreen] scale]];
    self.eagLayer.opaque = true;
    self.eagLayer.drawableProperties = @{kEAGLDrawablePropertyRetainedBacking   : [NSNumber numberWithBool:NO],
                                         kEAGLDrawablePropertyColorFormat       : kEAGLColorFormatRGBA8};
}

- (BOOL)setupBuffer
{
    glGenRenderbuffers(1, &_renderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, self.renderBuffer);
    [self.context renderbufferStorage:GL_RENDERBUFFER fromDrawable:self.eagLayer];

    glGenFramebuffers(1, &_frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, self.frameBuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, self.renderBuffer);

    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if(status != GL_FRAMEBUFFER_COMPLETE)
        return NO;
    
    return YES;
}

- (void)swapBuffer
{
    if([EAGLContext currentContext] != self.context)
    {
        [EAGLContext setCurrentContext:self.context];
    }
       
    [self.context presentRenderbuffer:GL_RENDERBUFFER];
}

- (void)layoutSublayers
{
    glDeleteRenderbuffers(1, &_renderBuffer);
    glDeleteFramebuffers(1, &_frameBuffer);
    
    EAGLContext *prevContext = [EAGLContext currentContext];
    if(prevContext != self.context)
    {
        [EAGLContext setCurrentContext:self.context];
    }
    
    [self setupBuffer];
    
    if(prevContext != self.context)
    {
        [EAGLContext setCurrentContext:prevContext];
    }
}

@end