创建OpenGL ES 项目
2019-06-24 本文已影响0人
紫水依
-
创建iOS工程
创建iOS工程 -
更改Main.storyBoard中view为GLKView
更改Main.storyBoard中view为GLKView -
ViewController.h中导入GLKit框架,将ViewController的继承父类改为GLKViewController
#import <UIKit/UIKit.h>
#import <GLKit/GLKit.h>
@interface ViewController : GLKViewController
@end
- GLKViewController内部实现
// GLKViewController继承于UIViewController,可以使用UIViewController的所有属性和方法
@interface GLKViewController : UIViewController <NSCoding, GLKViewDelegate>
{
}
// 提供了更新Update和暂停Pause的代理方法
@property (nullable, nonatomic, assign) IBOutlet id <GLKViewControllerDelegate> delegate;
/*
For setting the desired frames per second at which the update and drawing will take place.
The default is 30.
帧之间切换的速率,默认30帧/秒
*/
@property (nonatomic) NSInteger preferredFramesPerSecond;
/*
The actual frames per second that was decided upon given the value for preferredFramesPerSecond
and the screen for which the GLKView resides. The value chosen will be as close to
preferredFramesPerSecond as possible, without exceeding the screen's refresh rate. This value
does not account for dropped frames, so it is not a measurement of your statistical frames per
second. It is the static value for which updates will take place.
*/
@property (nonatomic, readonly) NSInteger framesPerSecond;
/*
Used to pause and resume the controller.
*/
@property (nonatomic, getter=isPaused) BOOL paused;
/*
The total number of frames displayed since drawing began.
视图控制器自创建以来发送的帧更新数
*/
@property (nonatomic, readonly) NSInteger framesDisplayed;
/*
Time interval since properties.
timeSinceFirstResume 自视图控制器第一次恢复发送更新事件以来经过的时间量
timeSinceLastResume 自上次视图控制器恢复发送更新事件以来更新的时间量
timeSinceLaseUpdate 自上次视图控制器调用委托方法以及经过的时间量
timeSinceLastDraw 自上次视图控制器调用视图display方法以来经过的时间量
*/
@property (nonatomic, readonly) NSTimeInterval timeSinceFirstResume;
@property (nonatomic, readonly) NSTimeInterval timeSinceLastResume;
@property (nonatomic, readonly) NSTimeInterval timeSinceLastUpdate;
@property (nonatomic, readonly) NSTimeInterval timeSinceLastDraw;
/*
If true, the controller will pause when the application recevies a willResignActive notification.
If false, the controller will not pause and it is expected that some other mechanism will pause
the controller when necessary.
The default is true.
*/
@property (nonatomic) BOOL pauseOnWillResignActive;
/*
If true, the controller will resume when the application recevies a didBecomeActive notification.
If false, the controller will not resume and it is expected that some other mechanism will resume
the controller when necessary.
The default is true.
*/
@property (nonatomic) BOOL resumeOnDidBecomeActive;
@end
#pragma mark -
#pragma mark GLKViewControllerDelegate
#pragma mark -
@protocol GLKViewControllerDelegate <NSObject>
@required
/*
Required method for implementing GLKViewControllerDelegate. This update method variant should be used
when not subclassing GLKViewController. This method will not be called if the GLKViewController object
has been subclassed and implements -(void)update.
更新视图内容,在显示每个帧之前调用
*/
- (void)glkViewControllerUpdate:(GLKViewController *)controller;
@optional
/*
Delegate method that gets called when the pause state changes.
在渲染循环暂停或恢复之前调用
*/
- (void)glkViewController:(GLKViewController *)controller willPause:(BOOL)pause;
@end
- ViewController.m中导入OpenGLES,创建上下文并设置为当前上下文,获取GLKView设置背景颜色,代理里清除颜色缓冲区
#import "ViewController.h"
#import <OpenGLES/ES3/gl.h>
#import <OpenGLES/ES3/glext.h>
@interface ViewController ()
{
EAGLContext *context; //上下文,管理OpenGL ES 状态
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
//1. 初始化上下文
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
if (!context) {
NSLog(@"Create ES context failed.");
}
//2. 设置上下文
[EAGLContext setCurrentContext:context];
//3. 获取GLKView
GLKView *view = (GLKView *)self.view;
view.context = context;
//4. 设置背景颜色
glClearColor(0.5, 0, 0, 1);
}
#pragma mark - GLKViewDelegate
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
glClear(GL_COLOR_BUFFER_BIT);
}
@end
- EAGLContext内部实现
@interface EAGLContext : NSObject
{
@public
struct _EAGLContextPrivate *_private;
}
// 初始化
- (nullable instancetype) init NS_UNAVAILABLE;
- (nullable instancetype) initWithAPI:(EAGLRenderingAPI) api;
- (nullable instancetype) initWithAPI:(EAGLRenderingAPI) api sharegroup:(EAGLSharegroup*) sharegroup NS_DESIGNATED_INITIALIZER;
// 设置当前上下文
+ (BOOL) setCurrentContext:(nullable EAGLContext*) context;
// 获取当前上下文
+ (nullable EAGLContext*) currentContext;
@property (readonly) EAGLRenderingAPI API;
@property (nonnull, readonly) EAGLSharegroup* sharegroup;
@property (nullable, copy, nonatomic) NSString* debugLabel NS_AVAILABLE_IOS(6_0);
@property (getter=isMultiThreaded, nonatomic) BOOL multiThreaded NS_AVAILABLE_IOS(7_1);
@end
- GLKView内部实现
@interface GLKView : UIView <NSCoding>
{
}
// 初始化视图
- (instancetype)initWithFrame:(CGRect)frame context:(EAGLContext *)context;
@property (nullable, nonatomic, assign) IBOutlet id <GLKViewDelegate> delegate;
@property (nonatomic, retain) EAGLContext *context;
// 绘制对象的宽/高,只读状态
@property (nonatomic, readonly) NSInteger drawableWidth;
@property (nonatomic, readonly) NSInteger drawableHeight;
@property (nonatomic) GLKViewDrawableColorFormat drawableColorFormat; // 颜色缓冲区格式
@property (nonatomic) GLKViewDrawableDepthFormat drawableDepthFormat; // 深度缓冲区格式
@property (nonatomic) GLKViewDrawableStencilFormat drawableStencilFormat; // 模板缓冲区格式
@property (nonatomic) GLKViewDrawableMultisample drawableMultisample; // 多重采样
/*
Binds the context and drawable. This needs to be called when the currently bound framebuffer
has been changed during the draw method.
将底层FrameBuffer对象绑定到OpenGL ES
*/
- (void)bindDrawable;
/*
deleteDrawable is normally invoked by the GLKViewController when an application is backgrounded, etc.
It is the responsibility of the developer to call deleteDrawable when a GLKViewController isn't being used.
删除视图FrameBuffer对象
*/
- (void)deleteDrawable;
/*
Returns a UIImage of the resulting draw. Snapshot should never be called from within the draw method.
绘制视图内容并将其作为新图像对象返回
*/
@property (readonly, strong) UIImage *snapshot;
/*
Controls whether the view responds to setNeedsDisplay. If true, then the view behaves similarily to a UIView.
When the view has been marked for display, the draw method is called during the next drawing cycle. If false,
the view's draw method will never be called during the next drawing cycle. It is expected that -display will be
called directly in this case. enableSetNeedsDisplay is automatically set to false when used in conjunction with
the GLKViewController. This value is true by default.
设置是否显示
*/
@property (nonatomic) BOOL enableSetNeedsDisplay;
/*
-display should be called when the view has been set to ignore calls to setNeedsDisplay. This method is used by
the GLKViewController to invoke the draw method. It can also be used when not using a GLKViewController and custom
control of the display loop is needed.
立即重绘
*/
- (void)display;
@end
#pragma mark -
#pragma mark GLKViewDelegate
#pragma mark -
@protocol GLKViewDelegate <NSObject>
@required
/*
Required method for implementing GLKViewDelegate. This draw method variant should be used when not subclassing GLKView.
This method will not be called if the GLKView object has been subclassed and implements -(void)drawRect:(CGRect)rect.
绘制视图内容
*/
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect;
@end
- 运行查看效果,得到一个背景为暗红色的view