OpenGL ES 1.1和OpengGL ES2.0的规范中,都定义了每种实现必须支持的最低标准。但是,在OpenGL ES规范中,对这些应该支持的性能的实现没有限制的那么死板。在OpenGL ES的规范中,有很多种方法可以扩展这些能力范围。在之后的章节“平台注意事项”,会详细讲解IOS中每个OpenGL ES的实现所具备的特定能力。一个实现的准确能力范围根OpengGL ES特定的实现版本,硬件平台以及运行在设备中的IOS版本有关系。
无论你选择构建OpenGL ES1.1还是OpengGL ES2.0的应用程序,你的应用程序应该做的第一件事,就是确定在目前的实现下所具备的准确的能力。为了做这些,你的应用程序需要设定当前上下文,然后调用一个或者更多的OpenGL ES的函数来取回实现的某些特定能力。在创建之后,上下文所具备的能力不能够被改变。一旦你的应用程序具备了这些能力,那么就可以根据这些能力适当的修剪绘制的代码。例如,根据执行提供的纹理单元数量,你可能会单次执行计算,执行多遍,或选择一个简单的算法。一个常用的方式,就是在你的应用程序中,为每一个渲染方式都设计一个类,并且这些类都拥有一个通用的父类。你运行时,你会根据上下文的能力实例化不同的类。
读取实现依赖的值
在OpenGL ES规范中定义了实现依赖值,这些值来定义OpenGL ES实现所具有的能力极限范围。例如,纹理的最大尺寸和纹理单元的个数是经常用到的实现依赖值,一个应用程序经常会确认这些值的。IOS设备支持PowerBR MBX图像硬件,最大的纹理尺寸是1024x1024,而PowerVR SGX软件支持的最大纹理尺寸是2048x2048。这两个尺寸都超过了64x64,这个是OpenGL ES规范中的最小尺寸要求。如果你的应用程序要超过这个最小尺寸的要求,那么就应该查询硬件设备是否支持你需要的尺寸。否则,你就需要导入一个更小的纹理或者使用一个不同的渲染策略。
规范提供了这些限制的很完善的清单,但是在OpenGL ES应用程序中只有一部分会用到。表 3-1 列出了OpenGL ES1.1和OpenGL ES2.0应用程序应该检测的值。
纹理的最大尺寸 |
GL_MAX_TEXTURE_SIZE |
深度缓存面的数量 |
GL_DEPTH_BITS |
模版缓存面的数量 |
GL_STENCIL_BITS |
表 3-1
在OpenGL ES2.0的应用程序中,你的应用程序首先要读取放置在着色器上面的各种限制。所有的硬件设备都支持一个有限的属性值,传递给顶点和片段着色器。当你的应用程序实现时,超过了这些极限值,一个OpenGL ES 2.0的实现不会给你提供一个软件回退。所以你的应用程序要么就在规定的最小值上实现,要么就需要核对表3-2中的极限值,从而选择何时的值来使用着色器。
OpenGL ES2.0着色器
顶点属性的最大数量 |
GL_MAX_VERTEX_ATTRIBS |
统一顶点向量的最大数量 |
GL_MAX_VERTEX_UNIFORM_VECTORS |
统一片段向量的最大数量 |
GL_MAX_FRAGMENT_UNIFORM_VECTORS |
可变向量的最大数量 |
GL_MAX_VARYING_VECTORS |
在一个顶点着色器上纹理单元的最大数量 |
GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS |
在一个片段着色器上纹理单元的最大数量 |
GL_MAX_TEXTURE_IMAGE_UNITS |
表 3-2 openGL ES 2.0的着色器的值
对于所有的向量类型,查询将返回四分量的浮点向量的数量
OpenGL ES 1.1的应用程序需要检查纹理单元的数量,和可用的裁剪平面的数量,如表3-3.
OpenGL ES1.1
到固定功能管道中可用的纹理单元的最大数量 |
GL_MAX_TEXTURE_UNITS |
裁剪平面的最大数量 |
GL_MAX_CLIP_PLANES |
表 3-3 openGL ES 1.1的值
在使用他们之前核对扩展性
一个OpenGL ES的实现可以通过实现OpenGL ES的扩展来为OpenGL ES API增加一些函数的功能。在你打算用OpenGL ES的某个扩展特性时,你的应用程序必须检查这个扩展特性是否能用。唯一的例外是OES_framebuffer_object扩展,这个扩展性能在所有的OpenGL ES 1.1中都提供。在应用程序中,IOS使用framebuffer对象作为唯一一种绘制的帧缓冲。
清单 3-1 提供了如何检查扩展存在的代码
- BOOL CheckForExtension(NSString *searchName)
- {
- // For performance, the array can be created once and cached.
- NSString *extensionsString = [NSString
- stringWithCString:glGetString(GL_EXTENSIONS) encoding: NSASCIIStringEncoding];
- NSArray *extensionsNames = [extensionsString componentsSeparatedByString:@"
- "];
- return [extensionsNames containsObject: searchName];
- }
清单 3-1 检查OpenGL ES的扩展
调用glGetError来测试错误
你的应用程序的调试版本,应该通过定期的调用glGetError功能函数的返回值,来找出错误。如果有一个错误从glGetError函数中返回,这就意味着没有正确的使用OpenGL ES的API,或者底层的实现不能执行所请求的操作。
要注意的是重复多次的调用glGetError函数会降低你应用程序的性能。在你程序的release版本时要慎重调用。