源码

iOS图形处理概论

前言

对于刚接触iOS图形相关框架的小白,有一些图形框架在字面上和功能上非常容易混淆。这里旨在总结一下各种框架,区分它们的概念和功能,以作日后进一步细分学习的指引。因而,本文并不会针对具体框架作详解,只作区分引导,读者可自行选择方向继续深造。为此,笔者总结了一张各种框架关系图,如下所示:

iOS图形处理相关概念集合

1. 基本图形框架 -- UIKit

UIKit是一组Objective-C API,为线条图形、Quartz图像和颜色操作提供Objective-C 封装,并提供2D绘制、图像处理及用户接口级别的动画。

UIKit包括UIBezierPath(绘制线、角度、椭圆及其它图形)、UIImage(显示图像)、UIColor(颜色操作)、UIFont和UIScreen(提供字体和屏幕信息)等类以及在位图图形环境、PDF图形环境上进行绘制和 操作的功能等, 也提供对标准视图的支持,也提供对打印功能的支持。

在UIKit中UIView类本身在绘制时自动创建一个图形环境(对应Core Graphics层的CGContext类型)作为当前的图形绘制环境。在绘制时可以调用UIGraphicsGetCurrentContext 函数获得当前的图形环境。

2. 核心动画框架 -- Core Animation

Core Animation是一套Objective-C API,实现了一个高性能的复合引擎,并提供一个简单易用的编程接口,给用户UI添加平滑运动和动态反馈能力。

Core Animation 是 UIKit实现动画和变换的基础,也负责视图的复合功能。使用Core Animation可以实现定制动画和细粒度的动画控制,创建复杂的、支持动画和变换的layered 2D视图。

Core Animation不属于绘制系统,但它是以硬件复合和操作显示内容的基础设施。这个基础设施的核心是layer对象,用来管理和操作显示内容。在ios 中每一个视图都对应Core Animation的一个层对象,与视图一样,层之间也组织为层关系树。一个层捕获视图内容为一个被图像硬件容易操作的位图。在多数应用中层作为管理视图的方式使用,但也可以创建独立的层到一个层关系树中来显示视图不够支持的显示内容。

OpenGL ES的内容也可以与Core Animation内容进行集成。

为了使用Core Animation实现动画,可以修改层的属性值来触发一个action对象的执行,不同的action对象实现不同的动画。

Core Animation 提供了一下一组应用可以采用的类来提供对不同动画类型的支持:

  • CAAnimation是一个抽象公共基类,CAAnimation采用CAMediaTiming 和CAAction协议为动画提供时间(如周期、速度、重复次数等)和action行为(启动、停止等)。

  • CAPropertyAnimation是  CAAnimation的抽象子类,为动画提供一个由一个key路径规定的层属性的支持;

  • CABasicAnimation 是CAPropertyAnimation的具体子类,为一个层属性提供简单插入能力。

  • CAKeyframeAnimation也是CAPropertyAnimation的具体子类,提供key帧动画支持。

3. 苹果封装的图形框架 -- Core Graphics & Quartz 2D

context是个比较抽象的东西,它不仅仅是一个可以绘制的图层,还包含为当前图层设置的参数,如阴影,线条粗细,绘制模式等。可以类比成一个新建的Photoshop图层以及当前笔触,颜色等配置。对于移动平台,有三种常见的Context:

  • 位图上下文(A bitmap graphics context):一般用于绘制图片或者自定义控件。

  • View Graphics Context: 由UIView自动创建,你重写UIView drawRect方法时,你的内容会画在这个上下文上。

  • Bitmap Graphics Context: 绘制在该上下文的内容会以点阵形式存储在一块内存中。简单说,就是为图片开辟一块内存,然后在里面画东西,上下文帮你把图片内存抽象成一个Context(图层)了。

  • PDF上下文(A PDF graphics context):用于生成pdf文件。

  • 图层上下文(A layer context):用于离屏绘制( offscreen drawing)。

4. 传统跨平台图形框架 -- OpenGL ES

OpenGL ES是一套多功能开放标准的用于嵌入系统的C-based的图形库,用于2D和3D数据的可视化。OpenGL被设计用来转换一组图形调用功能到底层图形硬件(GPU),由GPU执行图形命令,用来实现复杂的图形操作和运算,从而能够高性能、高帧率利用GPU提供的2D和3D绘制能力。

OpenGL ES规范本身不定义绘制表面和绘制窗口,因此ios为了使用它必须提供和创建一个OpenGL ES 的呈现环境,创建和配置存储绘制命令结果的framebuffer 及创建和配置一个或多个呈现目标。

在 iOS中使用EAGL提供的EAGLContext类 来实现和提供一个呈现环境,用来保持OpenGL ES使用到的硬件状态。   EAGL是一个Objective-C API,提供使OpenGL ES与Core Animation和UIKIT集成的接口。

在调用任何OpenGL ES 功能之前必须首先初始化一个EAGLContext 对象。

每一个IOS应用的每一个线程都有一个当前context,在调用OpenGL ES函数时,使用或改变此context中的状态。

EAGLContext 的类方法setCurrentContext: 用来设置当前线程的当前context。EAGLContext 的类方法currentContext 返回当前线程的当前context。在切换相同线程的两个上下文之前,必须调用glFlush函数来确保先前已提交的命令被提交到图形硬件中。

可以采用不同的方式使用OpenGL ES以便呈现OpenGL ES内容到不同的目标:GLKit和CAEAGLLayer。

为了创建全屏幕的视图或使OpenGL ES内容与UIKit视图集成,可以使用GLKit。在使用GLKit时,GLKit提供的类GLKView类本身实现呈现目标及创建和维护一个framebuffer。

为了使OpenGL ES内容作为一个Core Animation层的部分内容时,可以使用CAEAGLLayer 作为呈现目标,并需要另外创建framebuffer以及自己实现和控制整个绘制流程。

GLKit是一组Objective-C 类,为使用OpenGL ES 提供一个面向对象接口,用来简化OpenGL ES应用的开发。

GLKit支持四个3D应用开发的关键领域:

1) GLKView 和GLKViewController类提供一个标准的OpenGL ES视图和相关联的呈现循环。GLKView可以作为OpenGL ES内容的呈现目标,GLKViewController提供内容呈现的控制和动画。视图管理和维护一个framebuffer,应用只需在framebuffer进行绘画即可。

2)GLKTextureLoader 为应用提供从IOS支持的各种图像格式的源自动加载纹理图像到OpenGL ES 图像环境的方式,并能够进行适当的转换,并支持同步和异步加载方式。

3)数学运算库,提供向量、矩阵、四元数的实现和矩阵堆栈操作等OpenGL ES 1.1功能。

4)Effect效果类提供标准的公共着色效果的实现。能够配置效果和相关的顶点数据,然后创建和加载适当的着色器。GLKit 包括三个可配置着色效果类:GLKBaseEffect实现OpenGL ES 1.1规范中的关键的灯光和材料模式, GLKSkyboxEffect提供一个skybox效果的实现, GLKReflectionMapEffect 在GLKBaseEffect基础上包括反射映射支持。

使用GLKView和OpenGL ES进行绘制过程:

1)创建一个GLKView 对象

GLKView 对象可以编程或使用Interface Builder来创建和配置。

在采用编程方式时,首先创建一个context然后调用initWithFrame:context: 方法。

使用Interface Builder方式时,在从storyboard加载一个GLKView后,创建一个context和设置它作为视图的context属性.

在iOS中GLKit的使用需要创建OpenGL ES 2.0以上的图形环境context。

GLKit视图自动创建和配置它所有的OpenGL ES framebuffer对象和renderbuffers,可以通过修改视图的drawable属性来控制这些对象的属性。

2)绘制OpenGL内容(发布绘制命令)

使用GLKit视图绘制OpenGL内容需要三个子步骤:准备OpenGL ES基础;发布绘制命令;呈现显示内容到Core Animation。             GLKit类本身已经实现了第一个和第三个步骤,用户只需实现第二个步骤,在视图的方法drawRect或视图的代理对象的glkView:drawInRect:中调用适当的OpenGL ES绘制命令进行内容绘制。

GLKViewController类维护一个animation 呈现循环(包含两个方法update和display),用来实现连续的动画复杂的场景。

animation 呈现循环的交替速率由GLKViewController的属性framesPerSecond 指示,并使用preferredFramesPerSecond 属性来修改它。

5. 苹果最新力推的图形框架 -- Metal

Metal框架支持GPU硬件加速、高级3D图形渲染以及大数据并行运算。且提供了先进而精简的API来确保框架的细粒度(fine-grain),并且在组织架构、程序处理、图形呈现、运算指令以及指令相关数据资源的管理上都支持底层控制。其核心目的是尽可能的减少CPU开销,而将运行时产生的大部分负载交由GPU承担

编写基于底层图形 API 的渲染引擎时,除了 Metal 以外的其他选择还有 OpenGL 和 OpenGL ES。OpenGL 不仅支持包括 OSX,Windows,Linux 和 Android 在内的几乎所有平台,还有大量的教程,书籍和最佳实践指南等资料。目前,Metal 的资源非常有限,并且仅限于搭载了 64 位处理器的 iPhone 和 iPad。但另外一方面,因为 OpenGL 的限制,其性能与 Metal 相比并不占优势,毕竟后者是专门用来解决这些问题的。

如果想要一个 iOS 上高性能的并行计算库,答案非常简单。Metal 是唯一的选择。OpenGL 在 iOS 上是私有框架,而 Core Image (使用了 OpenGL) 对这样的任务来说既不够强大又不够灵活。

6. 适合图片的苹果滤镜框架 -- Core Image

Core Image 是 iOS5 新加入到 iOS 平台的一个图像处理框架,提供了强大高效的图像处理功能, 用来对基于像素的图像进行操作与分析, 内置了很多强大的滤镜(Filter) (目前数量超过了180种), 这些Filter 提供了各种各样的效果, 并且还可以通过 滤镜链 将各种效果的 Filter叠加 起来形成强大的自定义效果。

一个 滤镜 是一个对象,有很多输入和输出,并执行一些变换。例如,模糊滤镜可能需要输入图像和一个模糊半径来产生适当的模糊后的输出图像。

一个 滤镜链 是一个链接在一起的滤镜网络,使得一个滤镜的输出可以是另一个滤镜的输入。以这种方式,可以实现精心制作的效果。

iOS8 之后更是支持自定义 CIFilter,可以定制满足业务需求的复杂效果。

Core Image 的 API 主要就是三类:

  • CIImage 保存图像数据的类,可以通过UIImage,图像文件或者像素数据来创建,包括未处理的像素数据。

  • CIFilter 表示应用的滤镜,这个框架中对图片属性进行细节处理的类。它对所有的像素进行操作,用一些键-值设置来决定具体操作的程度。

  • CIContext 表示上下文,如 Core Graphics 以及 Core Data 中的上下文用于处理绘制渲染以及处理托管对象一样,Core Image 的上下文也是实现对图像处理的具体对象。可以从其中取得图片的信息。

Core Image 的另外一个优势,就是可以根据需求选择 CPU 或者 GPU 来处理。

// 创建基于 CPU 的 CIContext 对象 (默认是基于 GPU,CPU 需要额外设置参数)
context = [CIContext contextWithOptions: [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:kCIContextUseSoftwareRenderer]];

// 创建基于 GPU 的 CIContext 对象
context = [CIContext contextWithOptions: nil];

// 创建基于 GPU 的 CIContext 对象
EAGLContext *eaglctx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
context = [CIContext contextWithEAGLContext:eaglctx];

7. 适合视频的第三方滤镜方案 -- GPUImage

GPUImage 优势:
最低支持 iOS 4.0,iOS 5.0 之后就支持自定义滤镜。
在低端机型上,GPUImage 有更好的表现。(这个我没用真正的设备对比过,GPUImage 的主页上是这么说的)
GPUImage 在视频处理上有更好的表现。
GPUImage 的代码完成公开,实现透明。
可以根据自己的业务需求,定制更加复杂的管线操作。可定制程度高。

8. 游戏引擎 -- Scene Kit (3D) 和 Sprite Kit (2D)

对于寻找游戏引擎的开发者来说,Metal 不是最佳选择。苹果官方的 Scene Kit (3D) 和 Sprite Kit (2D) 是更好的选择。这些 API 提供了包括物理模拟在内的更高级别的游戏引擎。

另外还有功能更全面的 3D 引擎,例如 Epic 的 Unreal EngineUnity,二者都是跨平台的。使用这些引擎,你无需直接使用 Metal 的 API,就可以从 Metal 中获益。

SpriteKit

SpriteKit 让开发者可以开发高性能、省电节能的 2D 游戏。在 iOS 8 中,我们新添了多项增强功能,这将使 2D 游戏体验更加精彩。这些新技术有助于使游戏角色的动作更加自然,并让开发者可以更轻松地在游戏中加入力场、检测碰撞和生成新的灯光效果。

SceneKit

SceneKit 专为休闲 3D 游戏而设计,可让开发者渲染 3D 游戏场景。SceneKit 内置了物理引擎、粒子发生器和各种易用工具,可以轻松快捷地为 3D 物体编写动作。不仅如此,它还与 SpriteKit 完全集成,所以开发者可以直接在 3D 游戏中加入 SpriteKit 的素材。

9. 参考文献

作者:陈满iOS
链接:https://www.jianshu.com/p/24d691ae0720

(0)

本文由 投稿者 创作,文章地址:https://blog.isoyu.com/archives/iostuxingchuligailun.html
采用知识共享署名4.0 国际许可协议进行许可。除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。最后编辑时间为:7月 17, 2018 at 11:41 下午

热评文章

发表回复

[必填]

我是人?

提交后请等待三秒以免造成未提交成功和重复