在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