无论你选择构建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
顶点属性的最大数量 | 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 |
对于所有的向量类型,查询将返回四分量的浮点向量的数量
OpenGL ES 1.1的应用程序需要检查纹理单元的数量,和可用的裁剪平面的数量,如表3-3.
到固定功能管道中可用的纹理单元的最大数量 | GL_MAX_TEXTURE_UNITS |
裁剪平面的最大数量 | GL_MAX_CLIP_PLANES |
在使用他们之前核对扩展性
一个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版本时要慎重调用。