关于 OpenGL ES

重要OpenGL ES 在 iOS 12 中已弃用。要在 GPU 上创建高功用代码,请改用 Metal 结构。见Metal。

打开图形库 (OpenGL) 用于可视化 2D 和 3D 数据。它是一个多用途的打开规范图形库,支撑 2D 和 3D 数字内容创建、机械和修建规划、虚拟原型、飞翔模仿、视频游戏等运用程序。您运用 OpenGL 配备 3D 图形管道并向其提交数据。极点被转换和照亮,组装成图元,然后光栅化以创建 2D 图画。OpenGL 旨在将函数调用转换为可以发送到底层图形硬件的图形指令。因为这个底层硬件专门用于处理图形指令,所以 OpenGL 绘图一般非常快。

用于嵌入式系统的 OpenGL (OpenGL ES) 是 OpenGL 的简化版别,它消除了冗余功用,供应了一个更易于学习且更易于在移动图形硬件中结束的库。

OpenGL ES 编程攻略(上)

乍看上去

OpenGL ES 答应运用程序运用底层图形处理器的功用。iOS 设备上的 GPU 可以实行凌乱的 2D 和 3D 绘图,以及对最终图画中的每个像素进行凌乱的上色核算。假设您的运用程序的规划要求要求对 GPU 硬件进行最直接和全面的访问,您应该运用 OpenGL ES。OpenGL ES 的典型客户端包含出现 3D 图形的视频游戏和模仿。

OpenGL ES 是一个初级的、以硬件为中心的 API。虽然它供应了最强大和最灵敏的图形处理东西,但它也有一个峻峭的学习曲线,而且对你的运用程序的全体规划有严重影响。关于需求高功用图形以结束更专业用途的运用程序,iOS 供应了几个更高等级的结构:

  • Sprite Kit 结构供应了一个硬件加速动画系统,针对创建 2D 游戏进行了优化。(请参看*SpriteKit 编程攻略*。)
  • Core Image 结构为静态和视频图画供应实时过滤和分析。(请参看*中心映像编程攻略*。)
  • Core Animation 为全部 iOS 运用程序供应了硬件加速的图形烘托和动画基础设施,以及一个简略的声明式编程模型,使结束凌乱的用户界面动画变得简略。(请参看*中心动画编程攻略*。)
  • 您可以运用 UIKit 结构中的功用将动画、依据物理的动力学和其他特殊效果添加到 Cocoa Touch 用户界面。

OpenGL ES 是在 iOS 中结束的渠道中立 API

因为 OpenGL ES 是一个依据 C 的 API,它具有极强的可移植性和广泛的支撑。作为一个 C API,它与 Objective-C Cocoa Touch 运用程序无缝集成。OpenGL ES 规范没有定义窗口层;相反,宿主操作系统有必要供应函数来创建一个 OpenGL ES烘托上下文,它承受指令,以及一个帧缓冲区,任何绘图指令的效果都被写入其间。在 iOS 上运用 OpenGL ES 需求运用 iOS 类来设置和出现绘图表面,并运用渠道中立的 API 来出现其内容。

GLKit 供应绘图表面和动画支撑

由 UIKit 结构定义的视图和视图控制器控制 iOS 上视觉内容的出现。GLKit 结构供应了这些类的 OpenGL ES 感知版别。当您开发 OpenGL ES 运用程序时,您运用一个GLKView政策来烘托您的 OpenGL ES 内容。您还可以运用GLKViewController政策来处理视图并支撑对其内容进行动画处理。

iOS 支撑替代烘托政策

除了制造内容以填充整个屏幕或视图层次结构的一部分之外,您还可以将 OpenGL ES 帧缓冲区政策用于其他烘托策略。iOS 结束了规范的 OpenGL ES 帧缓冲区政策,您可以运用这些政策烘托到屏幕外缓冲区或纹理,以便在 OpenGL ES 场景的其他地方运用。此外,iOS 上的 OpenGL ES 支撑烘托到 Core Animation 层(CAEAGLLayer类),然后您可以将其与其他层组合以构建运用程序的用户界面或其他视觉闪现。

运用程序需求额外的功用调整

图形处理器是针对图形操作优化的并行设备。为了在您的运用程序中获得超卓的功用,您有必要仔细规划您的运用程序以向 OpenGL ES 供应数据和指令,以便图形硬件与您的运用程序并行工作。调整不佳的运用程序会强制 CPU 或 GPU 等候对方结束处理指令。

您应该规划您的运用程序以有效地运用 OpenGL ES API。结束构建运用程序后,运用 Instruments 微调运用程序的功用。假设您的运用程序在 OpenGL ES 中遇到瓶颈,请运用本攻略中供应的信息来优化您的运用程序的功用。

Xcode 供应了一些东西来协助您进步 OpenGL ES 运用程序的功用。

OpenGL ES 或许无法在后台运用程序中运用

在后台工作的运用程序或许不会调用 OpenGL ES 函数。假设您的运用程序在后台访问图形处理器,它会被 iOS 自动终止。为防止这种情况,您的运用应在移入后台之前改写之前提交给 OpenGL ES 的全部待处理指令,并防止调用 OpenGL ES,直到将其移回前台。

OpenGL ES 对多线程运用程序施加了额外的约束

规划运用程序以运用并发性有助于进步运用程序的功用。假设您打算向 OpenGL ES 运用程序添加并发性,您有必要保证它不会一同从两个不同的线程访问相同的上下文。

为 iOS 构建 OpenGL ES 运用程序的清单

OpenGL ES 规范定义了一个渠道中立的 API,用于运用 GPU 硬件来烘托图形。结束 OpenGL ES 的渠道供应了用于实行 OpenGL ES 指令的烘托上下文、用于保存烘托效果的帧缓冲区以及一个或多个出现帧缓冲区内容以供闪现的烘托政策。在 iOS 中,EAGLContext该类结束了一个烘托上下文。iOS 仅供应一种类型的帧缓冲区,即 OpenGL ES 帧缓冲区政策,而且GLKViewCAEAGLLayer类结束烘托政策。

在 iOS 中构建 OpenGL ES 运用程序需求考虑几个要素,其间一些是 OpenGL ES 编程通用的,而一些是特定于 iOS 的。请按照此清单和以下详细部分开始:

  1. 承认哪些 OpenGL ES 版别具有适宜您的运用程序的功用集,并创建 OpenGL ES 上下文。
  2. 在工作时验证设备是否支撑您要运用的 OpenGL ES 功用。
  3. 选择烘托 OpenGL ES 内容的方位。
  4. 保证您的运用在 iOS 中正确工作。
  5. 结束你的烘托引擎。
  6. 运用 Xcode 和 Instruments 调试您的 OpenGL ES 运用程序并调整它以获得最佳功用。

选择要支撑的 OpenGL ES 版别

承认您的运用程序是否应支撑 OpenGL ES 3.0、OpenGL ES 2.0、OpenGL ES 1.1 或多个版别。

  • OpenGL ES 3.0 是 iOS 7 中的新功用。它添加了许多新功用,可结束更高的功用、通用 GPU 核算技能以及更凌乱的视觉效果,而这些视觉效果早年只能在桌面级硬件和游戏控制台上结束。
  • OpenGL ES 2.0 是 iOS 设备的基准配备文件,具有依据可编程上色器的可配备图形管道。
  • OpenGL ES 1.1 仅供应基本的固定功用图形管道,而且在 iOS 中可用首要是为了向后兼容。

您应该针对支撑与您的运用程序最相关的功用和设备的一个或多个 OpenGL ES 版别。要了解有关 iOS 设备的 OpenGL ES 功用的更多信息,请阅读*iOS 设备兼容性参看*。

验证 OpenGL ES 功用

*iOS 设备兼容性参看*总结了发货 iOS 设备上可用的功用和扩展。但是,为了让您的运用程序可以在尽或许多的设备和 iOS 版别上工作,您的运用程序应始终在工作时查询 OpenGL ES 结束的功用。

要承认结束特定的约束,例如最大纹理大小或最大极点特色数,请运用其数据类型的恰当函数查找相应符号的值(例如,MAX_TEXTURE_SIZEMAX_VERTEX_ATTRIBS在标头中找到)。gl.h``glGet

要检查 OpenGL ES 3.0 扩展,请运用glGetIntegervglGetStringi函数,如以下代码示例所示:

BOOL CheckForExtension(NSString *searchName)
{
    // Create a set containing all extension names.
    // (For better performance, create the set only once and cache it for future use.)
    int max = 0;
    glGetIntegerv(GL_NUM_EXTENSIONS, &max);
    NSMutableSet *extensions = [NSMutableSet set];
    for (int i = 0; i < max; i++) {
        [extensions addObject: @( (char *)glGetStringi(GL_EXTENSIONS, i) )];
    }
    return [extensions containsObject: searchName];
}

要检查 OpenGL ES 1.1 和 2.0 扩展,请调用glGetString(GL_EXTENSIONS)以获取全部扩展称号的空格分隔列表。

选择烘托政策

在 iOS 中,帧缓冲区政策存储绘图指令的效果。(iOS 不结束窗口系统供应的帧缓冲区。)您可以通过多种方法运用帧缓冲区政策的内容:

  • GLKit 结构供应了一个制造 OpenGL ES 内容并处理其自己的帧缓冲区政策的视图,以及一个支撑动画 OpenGL ES 内容的视图控制器。运用这些类来创建全屏视图或将 OpenGL ES 内容适宜 UIKit 视图层次结构。
  • 该类CAEAGLLayer供应了一种将 OpenGL ES 内容作为中心动画层组合的一部分进行制造的方法。运用此类时,您有必要创建自己的帧缓冲区政策。
  • 与任何 OpenGL ES 结束一样,您还可以运用帧缓冲区进行离屏图形处理或烘托到纹理以在图形管道的其他地方运用。运用 OpenGL ES 3.0,屏幕外缓冲区可用于运用多个烘托政策的烘托算法。

与 iOS 集成

iOS 运用程序默许支撑多任务处理,但在 OpenGL ES 运用程序中正确处理此功用需求额外考虑。OpenGL ES 运用不当或许会导致您的运用在后台被系统杀死。

许多 iOS 设备都包含高分辨率闪现器,因此您的运用应支撑多种闪现器尺度和分辨率。

结束烘托引擎

规划您的 OpenGL ES 绘图代码有许多或许的策略,其悉数细节超出了本文档的范围。烘托引擎规划的许多方面关于 OpenGL 和 OpenGL ES 的全部结束都是通用的。

调试和分析

Xcode 和 Instruments 供应了许多东西来跟踪烘托问题和分析运用程序中的 OpenGL ES 功用。

配备 OpenGL ES 上下文

OpenGL ES 的每个结束都供应了一种创建烘托上下文的方法,以处理 OpenGL ES 规范所需的情况。通过将此情况置于上下文中,多个运用程序可以轻松同享图形硬件,而不会烦扰对方的情况。

本章详细介绍了怎样在 iOS 上创建和配备上下文。

EAGL 是 OpenGL ES 烘托上下文的 iOS 结束

在您的运用程序可以调用任何 OpenGL ES 函数之前,它有必要初始化一个EAGLContext政策。该类EAGLContext还供应了用于将 OpenGL ES 内容与 Core Animation 集成的方法。

其时上下文是 OpenGL ES 函数调用的政策

iOS 运用程序中的每个线程都有一个其时上下文;当您调用 OpenGL ES 函数时,这是调用更改其情况的上下文。

要设置线程的其时上下文,请在该线程上实行时调用EAGLContext类方法。setCurrentContext:

[EAGLContext setCurrentContext: myContext];

调用EAGLContext类方法currentContext来检索线程的其时上下文。

留意:假设您的运用在同一线程上的两个或多个上下文之间自动切换,请glFlush在将新上下文设置为其时上下文之前调用该函数。这可保证将早年提交的指令及时传送到图形硬件。

OpenGL ES 持有EAGLContext与其时上下文对应的政策的强引用。(假设您运用手动引用计数,OpenGL ES 会保存此政策。)当您调用该setCurrentContext:方法更改其时上下文时,OpenGL ES 不再引用早年的上下文。(假设您运用手动引用计数,OpenGL ES 会开释该EAGLContext政策。)为了防止EAGLContext政策在不是其时上下文时被开释,您的运用程序有必要坚持对(或保存)这些政策的强引用。

每个上下文都针对特定版其他 OpenGL ES

一个EAGLContext政策只支撑一个版其他 OpenGL ES。例如,为 OpenGL ES 1.1 编写的代码与 OpenGL ES 2.0 或 3.0 上下文不兼容。运用中心 OpenGL ES 2.0 功用的代码与 OpenGL ES 3.0 上下文兼容,为 OpenGL ES 2.0 扩展规划的代码一般可以在 OpenGL ES 3.0 上下文中运用,只需稍作更改。许多新的 OpenGL ES 3.0 特性和增强的硬件功用都需求 OpenGL ES 3.0 上下文。

您的运用在创建和初始化EAGLContext政策时抉择支撑哪个版其他 OpenGL ES 。假设设备不支撑请求的 OpenGL ES 版别,则该initWithAPI:方法回来nil.您的运用程序有必要进行测验以保证上下文在运用之前已成功初始化。

要在您的运用程序中支撑多个版其他 OpenGL ES 作为烘托选项,您应该首要尝试初始化您想要定位的最新版其他烘托上下文。假设回来的政策是nil,则改为初始化旧版其他上下文。清单 2-1演示了怎样做到这一点。

清单 2-1在同一个运用程序中支撑多个版其他 OpenGL ES

EAGLContext* CreateBestEAGLContext()
{
   EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
   if (context == nil) {
      context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
   }
   return context;
}

上下文的API特色说清楚上下文支撑的 OpenGL ES 版别。您的运用应该测验上下文的API特色并运用它来选择正确的烘托途径。结束此行为的常见方式是为每个烘托途径创建一个类。您的运用程序会在初始化时测验上下文并创建一次烘托器。

EAGL 同享组处理上下文的 OpenGL ES 政策

虽然上下文持有 OpenGL ES 情况,但它并不直接处理 OpenGL ES 政策。相反,OpenGL ES 政策由政策创建和维护EAGLSharegroup。每个上下文都包含一个EAGLSharegroup将政策创建委托给的政策。

当两个或多个上下文引用同一个同享组时,同享组的优势就变得很明显,如图 2-1所示。当多个上下文连接到一个公共同享组时,任何上下文创建的 OpenGL ES 政策在全部上下文上都可用;假设您在创建它的上下文之外的另一个上下文中绑定到相同的政策标识符,则您引用了相同的OpenGL ES 政策。移动设备上的资源一般很稀缺;在多个上下文中创建相同内容的多个副本是一种浪费。同享公共资源可以更好地运用设备上的可用图形资源。

同享组是一个不透明的政策;它没有您的运用可以调用的方法或特色。运用 sharegroup 政策的上下文坚持对它的强引用。

图 2-1同享 OpenGL ES 政策的两个上下文

OpenGL ES 编程攻略(上)

同享组在两种特定情况下最有用:

  • 当上下文之间同享的大部分资源不变时。
  • 当您期望您的运用程序可以在烘托器的主线程以外的线程上创建新的 OpenGL ES 政策时。在这种情况下,第二个上下文在单独的线程上工作,专门用于获取数据和创建资源。加载资源后,第一个上下文可以绑定到政策并立即运用它。该类GLKTextureLoader运用此方式来供应异步纹理加载。

要创建引用同一同享组的多个上下文,第一个上下文通过调用初始化initWithAPI:;为上下文自动创建一个同享组。第二个和以后的上下文通过调用该initWithAPI:sharegroup:方法来初始化以运用第一个上下文的同享组。清单 2-2展现了它是怎样工作的。第一个上下文是运用清单 2-1中定义的便当函数创建的。第二个上下文是通过从第一个上下文中提取 API 版别和同享组来创建的。

重要提示:与同一同享组相关的全部上下文有必要运用相同版其他 OpenGL ES API 作为初始上下文。

清单 2-2运用公共同享组创建两个上下文

EAGLContext* firstContext = CreateBestEAGLContext();
EAGLContext* secondContext = [[EAGLContext alloc] initWithAPI:[firstContext API] sharegroup: [firstContext sharegroup]];

当同享组由多个上下文同享时,处理 OpenGL ES 政策的情况更改是您的运用程序的职责。以下是规则:

  • 假设政策未被批改,您的运用程序可以一同跨多个上下文访问该政策。
  • 当政策被发送到上下文的指令批改时,不得在任何其他上下文中读取或批改该政策。
  • 批改政策后,全部上下文都有必要从头绑定政策才能看到更改。假设上下文在绑定它之前引用它,则政策的内容是未定义的。

以下是您的运用程序更新 OpenGL ES 政策应遵照的步骤:

  1. 调用glFlush或许正在运用该政策的每个上下文。
  2. 在要批改政策的上下文中,调用一个或多个 OpenGL ES 函数来更改政策。
  3. 调用glFlush接收到情况批改指令的上下文。
  4. 在全部其他上下文中,从头绑定政策标识符。

留意:同享政策的另一种方法是运用单个烘托上下文,但运用多个政策帧缓冲区。在烘托时,您的运用会绑定恰当的帧缓冲区并依据需求烘托其帧。因为全部 OpenGL ES 政策都是从单个上下文中引用的,所以它们会看到相同的 OpenGL ES 数据。此方式运用的资源较少,但仅对您可以仔细控制上下文情况的单线程运用程序有用。