9.4、尽量减少状态变化

OpenGL ES上下文存储了大量的用于控制渲染运算的信息。其中一些信息缓存在CPU控制的内存中,另一些信息存储在GPU寄存器中。上下文状态的变化通常需要一些GPU计算,并且寄存器值变化时,可能也会拖慢GPU的速度。尤其要避免不必要 的对于glBindBuffer()和glVertexAttribPointer()以及glEnable()和glDisable()函数的调用,具体是指避免在它们的所有变体函数中的调用,比如glEnableVertexAttribArray()。在开启一个模式后就没有必要再重新开启了。模式不变的情况下多次调用glEnable()没有任何益处,而且会浪费CPU时间。例如,调用glEnable(GL_DEPTH_TEST)多次会浪费时间来更新上下文的状态,即使该值与当前值是相同的。

iOs 4.0和之后的OpenGL ES实现包含了一个新近的非标准OpenGL ES扩展,用来帮助合并上下文状态的变化。很多应用会在一个渲染帧中多次调用glBindBuffer()、glEnableVertexAttribArray()和glVertexAttribPointer() 函数。例如,应用可能会使用不同的顶点属性来渲染多个网格。新的顶点数组对象(VAO)扩展会记录当前上下文中与顶点属性相关的状态,并存储这些信息到一个小的缓存中。后面,整个状态可以通过单次调用glBindVertexArrayOES(函数来恢复,而不用单独地调用glBindBuffer()、glEnableVertexAttribArray()和glVertexAttribPointer() 函数。“OES" ;扩展是OpenGL ES标准的维护者(Khronos Group, Inc.) 提出的一个非标准扩展。

遵循其他类型缓存的使用方式,在多个步骤中生成、绑定、初始化顶点数组对象。

glGenVertexArraysOES(1, // STEP 1 &vertexArray0bjectID);

glBindVertexArray0ES (vertexArrayobjectID); // STEP 2

// STEP 3: initialize the bound VAO by calling
// glBindBuffer(), 
//glEnableVertexAttribArray(), and
// glVertexAttribPointer()to configure needed vertex
// attributes

想要恢复一个顶点数组对象所代表的整个顶点数组属性状态,只要重新绑定 VAO即可。OpenGLES函数使用这个恢复的状态,就好像已经单独地显式调用了 glBindBuffer()、glEnableVertexAttribArray() 和glVertexAttribPointer()函数。


glVertexAttribPointer() had been made.
glBindVertexArrayOES (vertexArray0bjectID);
glDrawElements(...

由于顶点数组对象是非标准的,因此也应该避免使用它,除非分析表明与顶点数,组属性缓存相关的上下文状态变化表现出一个显著的瓶颈。VAO可能会变成未来的OpenGL ES标准的正式组成部分,但是这并没有任何保证,使用VAO的应用编程接口(API)可能稍作修改就作为标准化进程的一部分。如果最终的标准与非标准的实现方式在很大程度上是不同的,那么使用非标准VAO扩展的iOs应用可能需要修改以使用最新的标准。

9.5 小结

iOs设备上的GPU可以以一个合理的帧速率来渲染复杂的场景,但这是有限制的。

你可以做的最有效的优化就是简单地减少绘图。使用基于视平截体的剔除可以避免在用户看不到的几何图形上浪费处理器周期。解析应用的性能以找出瓶颈,然后对瓶颈做集中优化。如果一个代码块很少执行,那就不用刻意地让这个代码块的执行快10倍。用户永远不会注意这个加速。别忘了iOS设备有相对小的屏幕。小的纹理和简单的几何图形通常就可以产生适当的视觉质量。不要让几何模型太复杂以至于组成它的三角形比一 个屏幕像素还小。用户永远看不到这些细节。

第10章会介绍更多的3D图形技巧,包括可以让用户与渲染对象交互的技术。如果用户感觉就好像他们正在与自己看到的对象接触并交互,那么触摸输人会变得引人入胜。

results matching ""

    No results matching ""