读书频道 > 移动开发 > ios开发 > OpenGL ES应用开发实践指南:iOS卷
2.4 深入探讨GLKView是怎么工作的
2013-07-02 15:46:37     我来说两句 
收藏    我要投稿   
这是一本系统的具备实战性的OpenGL ES 3D图形开发指南。由资深iOS开发专家根据OpenGL ES最新版本撰写,不仅详细讲解了OpenGL ES与GLKit的结合使用,而且还系统讲解OpenGL ES的核心概念、技术,以及iOS的图形...  立即去当当网订购

在介绍iOS 5的GLKit之前,对于每个开发者来说创建一个类似于GLKView 的UIView 的子类是必要的。苹果没有提供GLKit类的源代码,但是根据OpenGL ES可以推断出类似GLKView这样的类的主要功能可能的实现方式。本节剩下的部分和OpenGLES_Ch2_2这个例子会介绍AGLKView类以及它对于GLKView的部分重新实现。AGLKView类不应该用在产品代码中,它仅仅是为了消除对于GLKView、Core Animation和OpenGL ES之间的交互的神秘感。不管从哪个方面来说,苹果优化的、测试的、面向未来的对于GLKit的实现都是最好的。如果你对于深入了解GLKView没有兴趣,可以跳到下一节。

注意如果你不想在你的应用中使用苹果的GLKit类,你就需要使用AGLKView示例或者自己再创建一个相似的类。本书剩下的例子都假设使用了GLKit。因此AGLKView不会出现在本书其他的任何例子中。

在OpenGLES_Ch2_2例子中的AGLKView类继承自Cocoa Touch的UIView类,下面是这个类的接口声明,与苹果的GLKView类接口相似。

 

AGLKViewDelegate协议指定了一个任何AGLKView的委托都必须实现的方法。如果AGLKView实例的委托属性不等于nil,每个AGLKView实例都会向它的委托发送“-glkView:drawInRect:”消息。

AGLKView的实现比较简单易懂,但重写了来自UIView的多个方法并添加了一些用于支持OpenGL ES绘图的方法。


 

每一个UIView实例都有一个相关联的被Cocoa Touch按需自动创建的Core Animation层。Cocoa Touch会调用“+layerClass”方法来确定要创建什么类型的层。在这个例子中,AGLKView类重写了继承自UIView的实现。当Cocoa Touch调用AGLKView实现的“+layerClass”方法时,它被告知要使用一个CAEAGLLayer类的实例,而不是原先的CALayer。CAEAGLLayer是Core Animation提供的标准层类之一。CAEAGLLayer会与一个OpenGL ES的帧缓存共享它的像素颜色仓库。

接下来的代码块实现了“-initWithFrame:context:”方法并重写了继承来的“-init WithCoder:”方法。“-initWithFrame:context:”方法初始化了通过代码手动分配的实例。“-initWithCoder:”方法是Cocoa Touch用于初始化对象的标准方法之一。Cocoa Touch会自动调用“-initWithCoder:”方法,这是反归档先前归档入一个文件的对象的过程的一部分。归档和反归档在其他流行的面向对象的框架中(比如Java和微软的.NET)叫做串行化和反串行化。当OpenGLES_Ch2_2应用启动时,在这个例子中使用的AGLKView实例会自动地从应用的storyboard文件中加载(又叫做反归档)。

之后的两个方法的代码几乎是相同的。每个实例初始化的时候只有一个方法会被调用。两个方法首先都会给超类UIView一个执行其初始化的机会,然后再执行这个例子需要的Core Animation和OpenGL ES 上下文的一次性初始化。第一步是初始化视图的Core Animation层的本地指针,具体代码如下:

 

需要C语言的类型转换(CAEAGLLayer *),这是因为UIView的“-layer”方法返回的是一个CALayer实例的指针。在AGLKView类的实现中,真正使用的是CAEAGLLayer类型,因此强制编译器接受CAEAGLLayer类型的这个转换是安全的。


 

每个AGLKView的初始化方法会使用一个临时的NSDictionary实例来设置eaglLayer的drawableProperties属性。Dictionary会保存键值对的集合。每个值都可以用对应的键快速获取。NSDictionary是一个Cocoa Touch类,在这里被CAEAGLLayer类实例使用是为了保存层中用到的OpenGL ES的帧缓存类型的信息。

 

这个示例设置kEAGLDrawablePropertyRetainedBacking键的值为NO并设置kEAGL-DrawablePropertyColorFormat键的值为kEAGLColorFormatRGBA8。不使用“保留背景”的意思是告诉Core Animation在层的任何部分需要在屏幕上显示的时候都要绘制整个层的内容。换句话说,这段代码是告诉Core Animation不要试图保留任何以前绘制的图像留作以后重用。RGBA8颜色格式是告诉Core Animation用8 位来保存层内的每个像素的每个颜色元素的值。

两个手动实现的访问器方法用于设置和返回视图的特定于平台的OpenGL ES 上下文。因为AGLKView实例需要创建和配置一个帧缓存和一个像素颜色渲染缓存来与视图的Core Animation层一起使用,所以设置上下文会引起一些副作用。由于上下文保存缓存,因此修改视图的上下文会导致先前创建的所有缓存全部失效,并需要创建和配置新的缓存。

会受缓存操作影响的上下文是在调用OpenGL ES函数之前设定为当前上下文的。请注意在下面的代码中,创建帧缓存和渲染缓存会遵循一些适用于其他类型的缓存的相同的步骤,包括在OpenGLES_Ch2_1例子中的顶点数组缓存。一个新的步骤会调用glFramebufferRenderbuffer()函数来配置当前绑定的帧缓存以便在colorRenderBuffer中保存渲染的像素颜色。



 

下面的“-display”方法设置视图的上下文为当前上下文,告诉OpenGL ES让渲染填满整个帧缓存,调用视图的“-drawRect:”方法来实现用OpenGL ES函数进行真正的绘图,然后让上下文调整外观并使用Core Animation 合成器把帧缓存的像素颜色渲染缓存与其他相关层混合起来。

 

glViewport()函数可以用来控制渲染至帧缓存的子集,但是在这个例子中使用的是整个帧缓存。

如果视图的委托属性不是nil,“-drawRect:”方法会调用委托的“-glkView: drawInRect:”方法。没有委托,AGLKView什么都不会绘制。AGLKView的子类可以通过重写继承的“-drawRect:”实现来绘图,即使是没有指定委托。“-glkView: drawInRect:”的参数是一个要被绘制的视图和一个覆盖整个视图范围的矩形。

 

任何在接收到视图重新调整大小的消息时,Cocoa Touch都会调用下面的-layout- Subviews方法。视图附属的帧缓存和像素颜色渲染缓存取决于视图的尺寸。视图会自动地调整相关层的尺寸。上下文的“-renderbufferStorage:fromDrawable:”方法会调整视图的缓存的尺寸以匹配层的新尺寸。

 

“-drawableWidth”和“-drawableHeight”方法是它们各自的属性的访问器。它们被实现用来通过OpenGL ES的glGetRenderbufferParameteriv()方法获取和返回当前上下文的帧缓存的像素颜色渲染缓存的尺寸。


 

最后,在一个对象可以被回收时Cocoa Touch会自动地调用“-dealloc”方法,然后它的资源就会返回给操作系统。AGLKView实现“-dealloc”方法是为了确保视图的上下文不再是当前上下文,其次是为了设置上下文属性为nil。如果在属性变成nil之后,视图的上下文不再被使用了,那这个上下文也会被自动回收。

 

关于AGLKView类就介绍这些内容。例子OpenGLES_Ch2_2还包含一个与GLKit的GLKViewController类相似的AGLKViewController类。除了在显示GLKit类的运行机制时使用了AGLKView和AGLKViewController类而不是GLKit类之外,OpenGLES_Ch2_2和OpenGLES_Ch2_1是相同的。

与GLKit的GLKViewController类相似,AGLKViewController使用一个Core Animation CADisplayLink对象来调度和执行与控制器相关联的视图的周期性的重绘。CADisplayLink本质上是一个用于显示更新的同步计时器,它能够被设置用来在每个显示更新或者其他更新时发送一个消息。CADisplayLink计时器的周期是以显示更新来计量的。

显示更新率通常是由嵌入设备的硬件决定的,它代表一个帧缓存的内容每秒最多能够被在屏幕上通过的像素显示出来的次数。因此来自CADisplayLink的消息为重新渲染一个场景提供了理想的触发器。渲染速度如果快于显示刷新率就是一种浪费,因为用户永远看不到两次显示刷新之间的额外的帧缓存的更新。

点击复制链接 与好友分享!回本站首页
分享到: 更多
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:2.3.5 支持文件
下一篇:2.5 对于GLKit的推断
相关文章
图文推荐
1.3.5 有限的屏幕尺
1.2 必备条件
精通iOS开发 : 第7版
3.5 iFunBox
排行
热门
文章
下载
读书

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做最好的IT技术学习网站