OpenGL ES GLKit 常用API

一、GLKit框架概述

GLKit 框架的设计目标是为了简化并加快基于OpenGL / OpenGL ES 的应⽤开发。 此框架封装了数学库、背景纹理加载、预先创建的着⾊器效果,以及标准视图和视图控制器,来帮助开发者实现渲染循环。
GLKit框架提供了功能和类,可以减少创建新的基于着⾊器的应⽤程序所需的工作量,或者支持依赖早期版本的OpenGL ES或OpenGL提供的固定函数顶点或片段处理的现有应用程序。
GLKView 提供绘制场所(View),继承于UIView
GLKViewController(扩展于标准的UIKit 设计模式. ⽤于绘制视图内容的管理与呈现.)
苹果弃用OpenGL ES ,但iOS开发者可以继续使⽤.

二、GLKit 苹果文档介绍

The GLKView class provides an OpenGL ES–based equivalent of the standard UIView drawing cycle.
A UIView instance automatically configures its graphics context so that your drawRect: implementation need only perform Quartz 2D drawing commands, and a GLKView instance automatically configures itself so that your drawing method need only perform OpenGL ES drawing commands. The GLKView class provides this functionality by maintaining a framebuffer object that holds the results of your OpenGL ES drawing commands, and then automatically presents them to Core Animation once your drawing method returns.
Like a standard UIKit view, a GLKit view renders its content on demand. When your view is first displayed, it calls your drawing method—Core Animation caches the rendered output and displays it whenever your view is shown. When you want to change the contents of your view, call its setNeedsDisplaymethod and the view again calls your drawing method, caches the resulting image, and presents it on screen. This approach is useful when the data used to render an image changes infrequently or only in response to user action. By rendering new view contents only when you need to, you conserve battery power on the device and leave more time for the device to perform other actions.

三、使⽤GLKit视图呈现OpenGL ES内容
使⽤GLKit视图呈现OpenGL ES内容
  1. FrameBuffer帧缓冲区,存储了深度缓冲区和颜色缓冲区,GLKit已经实现了创建帧缓冲区,不需要开发者创建
  2. 将开发者写的代码如glClear清除背景颜色、设置uniform、绑定纹理、绘制图形等写入到帧缓冲区
  3. GLKit从帧缓冲区中取出结果显示到屏幕上
四、配置GLKit视图
- (void)viewDidLoad{ 
[super viewDidLoad];

//创建OpenGL ES上下文并将其分配给从故事板加载的视图
GLKView * view =(GLKView *)self.view;
//context中存储OpenGL ES的相关状态,初始化时指定API,2.0与3.0没有太大的区别
view.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

//配置视图创建的渲染缓冲区
    view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888; //指定颜色缓冲区的格式,RGBA各占8位
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24; //指定深度缓冲区,一般使用Format24
    view.drawableStencilFormat = GLKViewDrawableStencilFormat8;

//启⽤多重采样
view.drawableMultisample = GLKViewDrawableMultisample4X;
}

-(void)drawRect:(CGRect)rect
{
//清除帧缓冲区
glClearColor(0.0f,0.0f,0.1f,1.0f); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

//使⽤先前配置的纹理,着⾊器和顶点数组绘制 
glBindTexture(GL_TEXTURE_2D, _planetTexture); 
glUseProgram(_diffuseShading); 
glUniformMatrix4fv(_uniformModelViewProjectionMatrix, 1, 0, 
_modelViewProjectionMatrix.m); 
glBindVertexArrayOES(_planetMesh); 
glDrawElements(GL_TRIANGLE_STRIP, 256, GL_UNSIGNED_SHORT);
}
五、GLKit功能

加载纹理;
提供高性能的数学运算,比如3D数学的计算;
提供常见的着色器;
提供视图以及视图控制器。

六、GLKit 常用API
  1. GLKit纹理加载
  • GLKTextureInfo 创建OpenGL 纹理信息
/* 
name:OpenGL 上下文中纹理名称
target:纹理绑定的目标
height:加载的纹理高度
width:加载的纹理宽度
textureOrigin:加载纹理中的原点位置
alphaState:加载纹理中alpha分量状态
containsMipmaps:布尔值,加载的纹理是否包含mip贴图
*/
  • GLTextureLoader 简化从各种资源文件中加载纹理
/*
初始化
- initWithShareGroup: 初始化一个新的纹理加载到对象中
- initWithShareContext: 初始化一个新的纹理加载对象

从文件中加载纹理(加载纹理中实际已经执行了解压缩,Core Graphic将JPEG、png图片解压成了位图)
+ textureWithContentsOfFile:options:error: 从文件加载2D纹理图像并从数据中创建新的纹理
- textureWithContentsOfFile:options:queue:completionHandler: 从文件中异步加载2D纹理图像,并根据数据创建新纹理

从URL加载纹理
- textureWithContentsOfURL:options:error: 从URL加载2D纹理图像并从数据创建新纹理
- textureWithContentsOfURL:options:queue:completionHandler: 从URL异步加载2D纹理图像,并根据数据创建新纹理

从内存中加载纹理
- textureWithContentsOfData:options:error: 从内存空间加载2D纹理图像并根据数据创建新纹理
- textureWithContentsOfData:options:queue:completionHandler: 从内存空间异步加载2D纹理图像,并根据数据创建新纹理

从CGImage创建纹理
- textureWithCGImage:options:error: 从Quartz图像加载2D纹理图像并从数据创建新纹理
- textureWithCGImage:options:queue:completionHandler: 从Quartz图像异步加载2D纹理图像,并根据数据创建新纹理

从URL创建多维纹理
+ cubeMapWithContentsOfURL:options:error: 从单个URL加载立方体贴图纹理图像,并从数据创建新纹理
- cubeMapWithContentsOfURL:options:queue:completionHandler: 从单个URL异步加载立方体贴图纹理图像,并根据数据创建新纹理

从文件加载多维纹理创建纹理
+ cubeMapWithContentsOfFile:options:error: 从单个文件加载立方体贴图纹理图像,并从数据中创建新纹理
- cubeMapWithContentsOfFile:options:queue:completionHandler: 从单个文件异步加载立方体贴图纹理图像,并从数据中创建新纹理
+ cubeMapWithContentsOfFiles:options:error: 从一系列文件中加载立方体贴图纹理图像,并从数据中创建新纹理
- cubeMapWithContentsOfFiles:options:queue:completionHandler: 从一系列文件异步加载立方体贴图纹理图像,并从数据中创建新纹理

*/
  1. GLKit OpenGL ES视图渲染
  • GLKView 使用OpenGL ES绘制内容的视图默认实现
/*
初始化视图
- initWithFrame:context: 初始化新视图
*/
- (instancetype)initWithFrame:(CGRect)frame context:(EAGLContext *)context;
/*
代理
delegate 视图的代理
*/
@property (nullable, nonatomic, assign) IBOutlet id <GLKViewDelegate> delegate;
/*
配置帧缓冲区对象
drawableColorFormat 颜色渲染缓存区格式
drawableDepthFormat 深度渲染缓存区格式
drawableStencilFormat 模板渲染缓存区格式
drawableMultisample 多重采样缓存区的格式
*/
@property (nonatomic) GLKViewDrawableColorFormat drawableColorFormat; // 颜色缓冲区格式
@property (nonatomic) GLKViewDrawableDepthFormat drawableDepthFormat; // 深度缓冲区格式
@property (nonatomic) GLKViewDrawableStencilFormat drawableStencilFormat; // 模板缓冲区格式
@property (nonatomic) GLKViewDrawableMultisample drawableMultisample; // 多重采样
/*
帧缓存区属性,只读状态
drawableHeight 底层缓存区对象的高度,以像素为单位
drawableWidth 底层缓存区对象的宽度,以像素为单位
*/
@property (nonatomic, readonly) NSInteger drawableWidth;
@property (nonatomic, readonly) NSInteger drawableHeight;
/*
绘制视图的内容
context 绘制视图内容时使用的OpenGL ES 上下文
bindDrawable 将底层FrameBuffer对象绑定到OpenGL ES
enableSetNeedsDisplay 布尔值,指定视图是否响应使得视图内容无效的消息,设置是否显示
display 立即重绘视图内容
snapshot 绘制视图内容并将其作为新图像对象返回
*/
@property (nonatomic, retain) EAGLContext *context;
- (void)bindDrawable;
@property (nonatomic) BOOL enableSetNeedsDisplay;
- (void)display;
@property (readonly, strong) UIImage *snapshot;

/*
删除视图FrameBuffer对象
deleteDrawable 删除与视图关联的可绘制对象
*/
- (void)deleteDrawable;
  • GLKViewDelegate 用于GLKView对象回调方法
/*
绘制视图的内容
- glkView:drawInRect: 绘制视图内容,关于绘图的实现都在这里操作(必须实现此代理)
*/
@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
  • GLKViewController 管理OpenGL ES 渲染循环的视图控制器
/*
更新
- (void)update 更新视图内容
- (void)glkViewControllerUpdate: 
*/
/*
 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;
/*
配置帧速率
preferredFramesPerSecond 视图控制器调用视图以及更新视图内容的速率,也就是帧之间切换的速率,默认30fps
framesPerSecond 视图控制器调用视图以及更新其内容的实际速率
*/
@property (nonatomic) NSInteger preferredFramesPerSecond;
@property (nonatomic, readonly) NSInteger framesPerSecond;
/*
配置GLKViewController 代理
delegate 视图控制器的代理
*/
@property (nullable, nonatomic, assign) IBOutlet id <GLKViewControllerDelegate> delegate;
/*
获取有关View更新信息
frameDisplayed 视图控制器自创建以来发送的帧更新数
timeSinceFirstResume 自视图控制器第一次恢复发送更新事件以来经过的时间量
timeSinceLastResume 自上次视图控制器恢复发送更新事件以来更新的时间量
timeSinceLaseUpdate 自上次视图控制器调用委托方法以及经过的时间量
timeSinceLastDraw 自上次视图控制器调用视图display方法以来经过的时间量
*/
@property (nonatomic, readonly) NSInteger framesDisplayed;
@property (nonatomic, readonly) NSTimeInterval timeSinceFirstResume;
@property (nonatomic, readonly) NSTimeInterval timeSinceLastResume;
@property (nonatomic, readonly) NSTimeInterval timeSinceLastUpdate;
@property (nonatomic, readonly) NSTimeInterval timeSinceLastDraw;
  • GLKViewControllerDelegate 渲染循环回调方法
/*
处理更新事件
- glkViewControllerUpdate: 在显示每个帧之前调用

暂停/回复通知
- glkViewController: willPause: 在渲染循环暂停或恢复之前调用
*/
@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
  • GLKBaseEffect 一种简单的光照/着色系统,用于基于着色器OpenGL渲染
/*
命名Effect
label 给Effect(效果)命名

配置模型视图转换,缩放旋转等
transform 绑定效果时应用于顶点数据的模型视图,投影和纹理变换

配置光照效果
lightingType 用于计算每个片段的光照策略,GLKLightingType

GLKLightingType
GLKLightingTypePerVertex 表示在三角形中每个顶点执行光照计算,然后在三角形进行插值
GLKLightingTypePerPixel 表示光照计算的输入在三角形内插入,并且在每个片段执行光照计算

配置光照
lightModelTwoSided 布尔值,表示为基元的两侧计算光照
material 计算渲染图元光照使用的材质属性
lightModelAmbientColor 环境颜色,应用效果渲染的所有图元
light0 场景中第一个光照属性
light1 场景中第二个光照属性
light2 场景中第三个光照属性

GLKBaseEffect 提供了三个光照两个纹理可供使用,当场景中超过这个数量时需要自定义着色器

配置纹理
texture2d0 第一个纹理属性
texture2d1 第二个纹理属性
textureOrder 纹理应用于渲染图元的顺序

配置雾化
fog 应用于场景的雾属性

配置颜色信息
colorMaterialEnable 布尔值,表示计算光照与材质交互时是否使用颜色顶点属性
useConstantColor 布尔值,表示是否使用常量颜色,常量颜色默认黑色
constantColor 不提供每个顶点颜色数据时使用常量颜色

准备绘制效果
- prepareToDraw 准备渲染
*/
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容