OpenGL ES提供程序接口原函数以透过图形加速硬件管线绘制。OpenGL消耗图形命令产生影像用以显示给用户,或进一步处理OpenGL ES以外的检索。
OpenGL ES规范明确声明了每个函数的行为。参考下面步骤以理解大部份OpenGL ES命令:
·参考25页“Determining OpenGL ESCapabilities” 获得各类别的详细实践信息。
·读写状态变量声明于规范中。OpenGL ES的状态通常表示当前配置的图形管线。例如,OpenGL ES的1.1使用状态变量,广泛地配置灯光,材料和固定功能管线进行计算。
·建立,修改及推毁OpenGL ES对象。OpenGL ES对象不是Objective-C对象;它们是透过OpenGL ES程序接口操作的资源。参考17页See “OpenGL ES Objects Encapsulate Resources on Behalf ofYour Application” 获得更多讯息。
·顶点需透过绘图原函数提交至管线加工,组合,或著作为祯缓存影格。
当你设计OpenGL ES应用程序时,必须回答一个关键问题:你的应用要支持OpenGL ES2.0或OpenGL ES 1.1或是两者兼有。
·OpenGL ES 2.0比OpenGL ES1.1更强大灵活,是新应用的最佳选择。可更清晰,简洁的自定义顶点及著色器,以及有更好的效能。在OpenGL ES1.1执行相同的计算,往往需要多个渲染通道或更复杂的状态配置,容易掩盖算法目的。如果算法变复杂,OpenGL ES2.0的著色器更能清晰及简洁的表达运算,以及更高的效能。建制OpenGL ES2.0应用程序需要较多工作,默认情况下,需重新为OpenGL ES1.1创建一些基础配置。
·OpenGL ES1.1提供了一些固定功能管线,包括一些不错的基础3D应用功能,转换和光照,及混合至祯缓存。如果应用需求简单,用OpenGL ES1.1可较少编码。若需要支持所有iOS装置,就只能选择OpenGL ES1.1。
如果你为了就设备相容性选择实践OpenGL ES1.1为主,可以考虑增加一个OpenGL ES 2.0的渲染选项,OpenGL ES2.0有更大的能力及优势发挥新的iOS装置的图形处理器。
重要如果你的应用不支持OpenGL ES 1.1与2.0绘图路径,将会限制应用能选择的装置版本。参考 iOS App Programming Guild中的”Declaring the Required Device Capabilities”章节。 |
2.2.了解OpenGLES的架构
OpenGL ES运作在几个关键原则上。为了设计高效的OpenGL ES应用程序,需要了解底层架构。
2.2.1. 客户端-服务器模型
OpenGL ES使用客户端-服务器模型,如图1.1。当应用程序呼叫OpenGL ES函数时,它会与OpenGL ES客户端交谈。客户端程序到函数调用完毕,必要时转化为OpenGL服务器命令。客户端-服务器模型允许工作处理被分为客户端与服务器端的函数调用。客户端,服务器,及之间的沟通路径的本质,OpenGL ES各别具体实践;在iOS终至上,工作是介于CPU与专用的图形处理器之间。
图1.1 OpenGL ES 客户端-服务器模型
2.2.2. OpenGL ES 依赖于具体平台的关键功能库
OpenGL ES规范声明了OpenGL ES如何工作,但是没有声明管理OpenGL ES与主操作系统之间交互的功能。相反地,规范假设每个实践都提供配置渲染内文与系统祯缓存的配置功能。渲染内文储存OpenGL ES状态机的内部状态。渲染内文每个OpenGLES应用程序各自维护自己的状态数据副本,不用担心会影响其他程序。参考20页的“Configuring OpenGL ES Contexts”。也可以在单一应用中使用多个宣染内文。系统祯缓存是OpenGL ES绘制命令的终点,也与主操作系统的图形子系统有关。iOS不提供系统祯缓存。相反地,iOS扩展了OpenGLES的祯缓存对象,并允许与CoreAnimation共享数据。参考18页的“Framebuffer Objects are theOnly Rendering Target on iOS”获得更多有关祯缓存对象的信息,28页的“Drawing With OpenGL ES”详细讨论了在应用中创建与使用祯缓存。
2.2.3. 命令可以异步执行
OpenGL ES客户端-服务器模型的一个好处是OpenGL ES函数可以在请求操作完成前将控制权还给应用程序。假如OpenGL ES在将控制权还给应用前,需等每个函数执行完毕,CPU与GPU将会步调一致,应用会丧失很多并行机会。在iOS中,推迟执行绘图命令很常见。推迟几个绘图命令,并同时处理,图形硬件可以删除隐藏的表面于执行昂贵的片段计算之前。许多OpenGL ES函数或明或暗送刷新命令给图形装置。其他刷新图形处理器的OpenGL命令会等到某些或全部命令完成。尽可能避免设计出客户-服务端同步的应用。
2.2.4. 命令可以依序执行
若客户端应用程序照相同顺序执行函数,OpenGL ES保证函数调用的结果与宣染内文相同。当你的应用调用OpenGL ES函数,可以假设这些函数结果是有效的,即时命令尚未执行完毕。
2.2.5. 呼叫时参数会被复制
为了让命令异步处理,应用调用函数时需要的参数数据必须在控制权返回应用前被复制。若参数是个指向应用程序内存中的顶点数据数组指针,OpenGL ES必须在返回前复制顶点数据。这有一些重要意义。首先,应用可以自由改变自己的内存无论是否调用OpenGL ES,因为OpenGL ES绝不会和应用同时存取内存。再来,复制及格式化数据,以便图形装置可读取,并增加每个函数呼叫开销。为了最好的效能,应用需声明为了图形装置最佳化的数据格式,并且应该使用缓冲对象隐藏应用与OpenGL ES之间的内存管理及复制。
2.2.6. 定义在规范中具扩充功能实践方法
一個OpenGLES實現可以擴展OpenGLES規范的兩種方法之一。首先实现需满足规范规定的最低要求,如应用程序可存取的纹理大小,纹理单元数量。一个OpenGL ES实现是自由支持较大变量:如一个大型纹理或更多纹理单元。其次,OpenGL ES扩充允许一个实践提供新的OpenGL ES函数其常量。扩充允许实践添加全新特性。Apple实践许多扩充功能,允许应用程序利用硬件特性来改善应用程序的效能。不同的iOS装置与版本的实际硬件限制与提供的扩充功能清单会有所不同。应用需测试运行能力,以确保行为一致。
2.3.应用程序中常用OpenGL ES中具代表性封装对象资源
对象是不透明的容器,在应用中用来保存配置状态或是渲染器所需的数据。因为只有对象的访问是通过程序的API,在应用中配置对象时,可以选择不同策略的OpenGL ES实践。它可以存储在数据格式或是徒刑处理器最佳化的内存位置中。对象的另一个好处是重复使用,允许应用一次或多次配置对象。
OpenGL ES最重要的对象类型包括:
l纹理(texture)是个图像,可被绘图管线采样。通常纹理被用来映射到原语上的彩色图像,但也可映射到其他数据,如一般映射或是预计算的照明讯息。章节“Best Practices for Workingwith Texture Data”讨论在iOS上使用纹理(texture)这重要议题。
l缓存(buffer)对象在应用中是一个拥有OpenGL ES储存数据的区块内存。缓存被用来精确控制应用跟OpenGL ES之间复制数据的过程。举例来说,假设你提供顶点数组给,每次提交绘制呼叫都必需复制数据。相比之下,若你的应用将数据储存在顶点缓存对象(vertex buffer object),当应用提交命令修改顶点缓存对象的内文时,数据才被复制。使用缓存来管理顶点数据,可显著提高应用效能。
l顶点数组(vertex array)对象持有的是图型管线读取的顶点属性配置。许多应用渲染实体需要不同的管线配置。通过储存顶点数组配置,避免重新配置管线的成本,并可能允许执行特定的顶点配置优化处理。
l著色器程序(Shader programs),或著称作著色器(shaders),也是对象。OpenGL ES2.0应用可创建顶点与片段著色器分别进行顶点或片段的计算。
l渲染缓存(renderbuffer)是简单的2D图型影像的特殊格式。这种格式通常被定义为颜色,深度或模板数据。渲染缓存通常是不单独使用,而是与祯缓存(framebuffer)一起使用。
l祯缓存(Framebuffer)对象是图型管线的最终目的。祯缓存对象只是个容器,内含纹理(texture)与渲染缓存(renderbuffer),本身创建渲染器的完整配置。在之后的章节“Drawing With OpenGL ES”, 讨论在iOS应用中创建及使用祯缓存的策略。
虽然在OpenGL ES中的每个对象类型都有它自己的函数来操纵它,所有的对象共享一个类似的编程模型:
1. 产生对象身份
身份是个普通的整数,用来表示某个特定对象实例。每当你需要一个新对象,呼叫OpenGL ES创建一个新的身份。创建对象身份不代表实际创建对象,只是配置个参考。
2.绑定对象到OpenGLES内文
大部分OpenGL ES函数隐含作用于对象,而不是要求每次呼叫时明确指定对象身份。你设置对象并绑定配置到内文。每个不同类型的对象使用不同的绑定函数。在第一次绑定一个对象身分时,OpenGL ES会配置及初始化对象。
3.修改对象状态
你的应用程序使一或多个函数调用配置对象。举例来说,在绑定纹理对象后,通常会配置纹理过滤及读取图像数据。改变一个对象可能是昂贵的,因为他可能需要提交新的数据给图型硬件。这是合理的,创建及配置对象一次,并在应用程序中不要改变它。
4. 使用对象渲染
一但创建并配置了渲染场景所需全部对象,你要替管线绑定对象并执行一或多个绘图功能。OpenGL ES照原语将对象储存的数据渲染出来。结果会送到绑定的祯缓存对象。
5. 删除对象
当对象不用时,应用应该要将其删除。对象被删除后,内容会被摧毁,对象身分会被回收。
2.4.只宣染在iOS上的侦缓存对象(Framebuffer)
祯缓存(framebuffer)对象是渲染命令的目标。OpenGL ES2.0提供的祯缓存对象是核心规范中的一部分;在OpenGLES1.1中由OES_framebuffer_object拓展提供。因威祯缓存对象只在iOS上渲染,苹果保证OES_framebuffer_object拓展会被实践在所有
实践OpenGL ES1.1的iOS上。如图1-2,祯缓存对象提供颜色深度或模版数据存储将图像连结至祯缓存。最常见的图像连结对象是渲染缓存(renderbuffer)。然而,OpenGL ES纹理可以被连接到祯缓存的颜色附着点,而让图像直接渲染成纹理。
之后,纹理可以作为未来的渲染命令的输入。
图1-2,祯缓存与颜色及深度渲染缓存
建立祯缓存需依循下列步骤:
1. 产生及连结一个祯缓存对象。
2. 产生,连结,及配置图像。
3. 连结图像到祯缓存的附著点。
4. 若需更多图像则重复2-3。
5. 测试祯缓存完整性。完整性的规则声明在OpenGL ES规范中。这些规则确保了祯缓存及其附著点。