版本记录
版本号 | 时间 |
---|---|
V1.0 | 2017.10.01 |
前言
OpenGL ES是一个强大的图形库,是跨平台的图形API,属于OpenGL的一个简化版本。iOS系统可以利用OpenGL ES将图像数据直接送入到GPU进行渲染,这样避免了从CPU进行计算再送到显卡渲染带来的性能的高消耗,能带来来更好的视频效果和用户体验。接下来几篇就介绍下iOS 系统的 OpenGL ES框架。感兴趣的可以看上面几篇。
1. OpenGL ES 框架详细解析(一) —— 基本概览
2. OpenGL ES 框架详细解析(二) —— 关于OpenGL ES
3. OpenGL ES 框架详细解析(三) —— 构建用于iOS的OpenGL ES应用程序的清单
4. OpenGL ES 框架详细解析(四) —— 配置OpenGL ES的上下文
5. OpenGL ES 框架详细解析(五) —— 使用OpenGL ES和GLKit进行绘制
6. OpenGL ES 框架详细解析(六) —— 绘制到其他渲染目的地
Multitasking, High Resolution, and Other iOS Features - 多任务,高分辨率和其他iOS功能
使用OpenGL ES的许多方面是平台中立的,但是在iOS上使用OpenGL ES的一些细节需要特别考虑。 特别是,使用OpenGL ES的iOS应用程序必须正确处理多任务,或者在移动到后台时可能会被终止。 在为iOS设备开发OpenGL ES内容时,还应考虑显示分辨率和其他设备功能。
Implementing a Multitasking-Aware OpenGL ES App - 实现多任务感知OpenGL ES应用程序
当用户切换到其他应用程序时,您的应用程序可以继续运行。 有关iOS上多任务的全面讨论,请参阅App States and Multitasking。
当OpenGL ES应用程序移动到后台时,它必须执行其他工作。 如果应用程序处理这些任务不正确,则可能会由iOS终止。 此外,一个应用程序可能想要释放OpenGL ES资源,以便这些资源可用于前台应用程序。
1. Background Apps May Not Execute Commands on the Graphics Hardware - 后台应用程序可能无法在图形硬件上执行命令
如果OpenGL ES应用程序尝试在图形硬件上执行OpenGL ES命令,则会终止该应用程序。 iOS防止后台应用程序访问图形处理器,以便最前沿的应用程序始终能够向用户呈现出极好的体验。 您的应用程序不仅可以在后台进行OpenGL ES调用时被终止,还可以在后台将先前提交的命令刷新到GPU。 您的应用程序必须确保所有以前提交的命令在移动到后台之前已完成执行。
如果您使用GLKit
视图并查看控制器,并且仅在绘图方法中提交OpenGL ES命令,则当应用程序移动到后台时,您的应用程序会自动正常运行。 默认情况下,GLKViewController
类在您的应用程序处于非活动状态时暂停其动画定时器,确保您的绘图方法不被调用。
如果您不使用GLKit视图或视图控制器,或者如果您在GLKView绘图方法之外提交OpenGL ES命令,则必须执行以下步骤以确保您的应用程序未在后台终止:
- 在应用程序委托的applicationWillResignActive:方法中,您的应用程序应该停止其动画定时器(如果有的话),将其置于已知的良好状态,然后调用glFinish函数。
- 在您的应用程序委托的applicationDidEnterBackground:方法中,您的应用程序可能需要删除其一些OpenGL ES对象,以使内存和资源可用于前台应用程序。 调用
glFinish
函数以确保资源立即被删除。 - 在您的应用程序退出其applicationDidEnterBackground:方法之后,它不能进行任何新的OpenGL ES调用。 如果是OpenGL ES调用,则由iOS终止。
- 在您的应用程序的应用程序applicationWillEnterForeground:方法中,重新创建任何对象并重新启动动画定时器。
总而言之,您的应用程序需要调用glFinish
函数,以确保所有以前提交的命令都从命令缓冲区中排出并由OpenGL ES执行。 移动到后台后,您必须避免使用OpenGL ES,直到它移回到前台。
2. Delete Easily Re-Created Resources Before Moving to the Background - 在移动到后台之前删除容易重新创建的资源
您的应用程序从来不需要在OpenGL ES对象移动到后台时释放。 通常,您的应用程序应避免处理其内容。 考虑两种情况:
- 用户正在玩游戏,并短暂退出以检查他们的日历。 当玩家返回游戏时,游戏资源仍然在内存中,游戏可以立即恢复。
- 当用户启动另一个OpenGL ES应用程序时,您的OpenGL ES应用程序处于后台。 如果该应用程序需要比设备上可用的内存更多的内存,系统将自动终止您的应用程序,而不需要执行任何其他工作。
您的目标应该是将您的应用程序设计为一个好的产品:这意味着保持移动到前台的时间尽可能短,同时在后台减少其内存占用。
以下是处理这两种情况的方法:
- 您的应用程序应将纹理,模型和其他资产保留在内存中; 在您的应用程序移动到后台时,不应该处理需要很长时间重新创建的资源。
- 您的应用程序应该处理可以快速,轻松地重新创建的对象。 寻找消耗大量内存的对象。
简单的目标是您的应用程序分配用于保存呈现结果的帧缓冲区。 当你的应用程序在后台时,用户看不到它,可能不会使用OpenGL ES
渲染任何新的内容。 这意味着应用程序的帧缓冲区消耗的内存是分配的,但没有用。 此外,帧缓冲区的内容是暂时的; 大多数应用程序在每次呈现新帧时重新创建帧缓冲区的内容。 这使得renderbuffers成为可以轻松重新创建的内存密集型资源,成为当移动到后台时可以处理的对象的良好候选。
如果您使用GLKit
视图和视图控制器,则当应用程序移动到后台时,GLKViewController
类会自动处理其关联视图的帧缓冲区。 如果您手动创建用于其他用途的帧缓冲区,则在应用程序移动到后台时应该处理它们。 在这两种情况下,您还应该考虑当时应用程序可以处理的其他暂时资源。
Supporting High-Resolution Displays - 支持高分辨率显示
默认情况下,GLKit视图的 contentScaleFactor属性的值与包含它的屏幕的比例匹配,因此其关联的帧缓冲区配置为以显示的全分辨率进行渲染。 有关UIKit中支持高分辨率显示的详细信息,请参阅 Supporting High-Resolution Screens In Views。
如果您使用Core Animation
层提供OpenGL ES内容,则其缩放因子默认设置为1.0。 为了绘制Retina显示屏的完整分辨率,您应该更改CAEAGLLayer
对象的比例因子以匹配屏幕的比例因子。
当支持具有高分辨率显示器的设备时,您应该相应地调整应用程序的模型和纹理资产。 在高分辨率设备上运行时,您可能需要选择更详细的模型和纹理来渲染更好的图像。 相反,在标准分辨率设备上,您可以使用较小的模型和纹理。
重要:许多OpenGL ES API调用以屏幕像素表示维度。 如果使用大于1.0的比例因子,则应在使用glScissor,glBlitFramebuffer,glLineWidth
或glPointSize
函数或gl_PointSize
着色器变量时相应调整维度。
确定如何支持高分辨率显示器的一个重要因素是性能。 Retina显示屏上的比例因子倍增了像素数量的四倍,导致GPU处理的片断数量是四倍。 如果您的应用程序执行许多每个片段的计算,像素的增加可能会降低帧速率。 如果您发现您的应用程序在较高比例因子下运行速度显着较慢,请考虑以下选项之一:
- 使用本文档中的性能调整指南优化片段着色器的性能。
- 在片段着色器中实现更简单的算法。 通过这样做,您可以降低单个像素的质量,以更高的分辨率渲染整体图像。
- 使用1.0之间的分数比例因子和屏幕的比例因子。 比例因子1.5提供比1.0的比例因子更好的质量,但是需要填充比缩放到2.0的图像更少的像素。
- 对您的GLKView对象的drawableColorFormat和drawableDepthFormat属性使用较低精度的格式。 通过这样做,可以减少对底层渲染缓冲区进行操作所需的内存带宽。
- 使用较小的比例因子并启用多重采样。 另外一个优点是,多采样在不支持高分辨率显示器的设备上也提供了更高的质量。
要为GLKView
对象启用多重采样,请更改其drawableMultisample
属性的值。 如果没有渲染到GLKit视图,则必须手动设置多采样缓冲区并在呈现最终图像之前对其进行解析(请参阅使用多重采样来提高图像质量)。
多次采样不是免费的; 需要额外的内存来存储附加样本,并将样本解析为解析帧缓冲区需要时间。 如果您向应用程序添加多重采样,请始终测试应用程序的性能,以确保其仍然可以接受。
Supporting Multiple Interface Orientations - 支持多种界面方向
像任何应用程序一样,OpenGL ES应用程序应该支持适合其内容的用户界面方向。 您可以在其信息属性列表中声明支持的应用程序接口方向,或者使用supportedInterfaceOrientations方法来托管OpenGL ES内容的视图控制器。 (有关详细信息,请参阅View Controller Programming Guide for iOS)。
默认情况下,GLKViewController
和GLKView
类自动处理方向更改:当用户将设备旋转到受支持的方向时,系统会动态定向更改并更改视图控制器视图的大小。 当其大小更改时,GLKView对象会相应地调整其帧缓冲区和视口的大小。 如果您需要响应此更改,请在GLKViewController子类中实现viewWillLayoutSubviews
或viewDidLayoutSubviews
方法,如果使用自定义GLKView子类,则实现layoutSubviews
方法。
如果您使用Core Animation层绘制OpenGL ES内容,则应用程序仍应包含一个视图控制器来管理用户界面方向。
Presenting OpenGL ES Content on External Displays - 在外部显示器上呈现OpenGL ES内容
iOS设备可以连接到外部显示器。 外部显示器的分辨率及其内容比例因子可能与主屏幕的分辨率和比例因子不同, 您渲染帧的代码应该进行调整和匹配。
在外部显示器上绘制的程序与在主屏幕上运行的程序几乎相同。
按照Multiple Display Programming Guide for iOS中的步骤,在外部显示器上创建一个窗口。
-
将适当的视图或视图控制器添加到窗口对象的渲染策略。
- 如果使用GLKit渲染,请设置GLKViewController和GLKView(或您的自定义子类)的实例,并使用其
rootViewController
属性将其添加到窗口。 - 如果渲染到Core Animation图层,请将包含图层的视图添加为window的子视图。 要使用动画循环进行渲染,请通过检索窗口的屏幕属性并调用其displayLinkWithTarget:selector:方法来创建为外部显示优化的显示链接对象。
- 如果使用GLKit渲染,请设置GLKViewController和GLKView(或您的自定义子类)的实例,并使用其
后记
未完,待续~~~