OpenGL ES for iOS - 9

2017-05-24  本文已影响245人  孙健会员

使用纹理数据的最佳做法

纹理数据通常是您的应用程序用于渲染框架的数据的最大部分;纹理提供向用户呈现优质图像所需的细节。要从应用程序中获得最佳性能,请仔细管理应用程序的纹理。总结指导方针:

初始化期间加载纹理

创建和加载纹理是一项昂贵的操作。为了获得最佳效果,请避免在应用运行时创建新纹理。而是在初始化期间创建并加载纹理数据。

创建纹理后,避免更改它,除非在帧的开头或结尾。目前,所有iOS设备都使用基于瓦片的延迟渲染器,调用glTexSubImage和glCopyTexSubImage功能特别昂贵。有关详细信息,请参阅基于平铺的延迟渲染。

使用GLKit框架加载纹理数据

加载纹理数据是一个重要的基本操作。使用GLKit框架,GLKTextureLoader类可以轻松创建和加载新纹理。 GLKTextureLoader类可以从各种来源加载纹理数据,包括文件,URL,内存中的表示和CGImages。不管输入源如何,GLKTextureLoader类从数据创建并加载新的纹理,并将纹理信息作为GLKTextureInfo对象返回。可以访问GLKTextureInfo对象的属性来执行各种任务,包括将纹理绑定到上下文并使其可以进行绘制。

注意:GLKTextureInfo对象不拥有它描述的OpenGL ES纹理对象。完成使用后,您必须调用glDeleteTextures函数来处理纹理对象

清单9-1显示了从文件加载新纹理并绑定并启用纹理以供将来使用的典型策略

GLKTextureInfo *spriteTexture;
NSError *theError;
 
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Sprite" ofType:@"png"]; // 1
 
spriteTexture = [GLKTextureLoader textureWithContentsOfFile:filePath options:nil error:&theError]; // 2
glBindTexture(spriteTexture.target, spriteTexture.name); // 3

这是代码所做的,对应于列表中的编号步骤:

  1. 创建包含纹理数据的图像路径。该路径作为参数传递给GLKTextureLoader类方法textureWithContentsOfFile:
  2. 从图像文件加载新的纹理,并将纹理信息存储在GLKTextureInfo对象中。有各种纹理加载选项可用。有关更多信息,请参阅GLKTextureLoader类参考。
  3. 将纹理绑定到上下文,使用GLKTextureInfo对象的相应属性作为参数

GLKTextureLoader类也可以以最常见的图像格式加载cubemap纹理。而且,如果您的应用程序在运行时需要加载和创建新的纹理,GLKTextureLoader类还提供异步纹理加载的方法。有关更多信息,请参阅GLKTextureLoader类参考。

减少纹理内存使用

降低iOS应用程序使用的内存量始终是调整应用程序的重要部分。也就是说,OpenGL ES应用程序也受到可用于加载纹理的内存总量的限制。在可能的情况下,您的应用程序应始终尝试减少用于保存纹理数据的内存量。降低纹理使用的内存几乎总是以图像质量为代价,因此您必须将应用程序对其纹理的任何更改与最终渲染帧的质量水平进行平衡。为了获得最佳效果,请尝试下面描述的技术,并选择在可接受的质量水平下提供最佳内存节省的技术。

压缩纹理

纹理压缩通常提供最佳的内存节省和质量平衡。适用于iOS的OpenGL ES支持多种压缩纹理格式。

所有iOS设备都通过实现GL_IMG_texture_compression_pvrtc扩展来支持PowerVR纹理压缩(PVRTC)格式。 PVRTC压缩有两个级别,每像素4位,每像素2位,分别比未压缩的32位纹理格式提供8:1和16:1压缩率。压缩的PVRTC纹理仍然提供了一个体面的质量水平,特别是在4位级别。有关将纹理压缩为PVRTC格式的更多信息,请参阅使用纹理工具压缩纹理。

OpenGL ES 3.0还支持ETC2和EAC压缩纹理格式;但是,建议在iOS设备上使用PVRTC纹理。

使用较低精度的颜色格式

如果您的应用程序无法使用压缩纹理,请考虑使用较低精度的像素格式。 RGB565,RGBA5551或RGBA4444格式的纹理使用RGBA8888格式纹理的一半存储器。只有当您的应用程序需要该级别的质量时,才能使用RGBA8888。

使用适当尺寸的纹理

基于iOS的设备显示的图像非常小。您的应用程序不需要提供大的纹理来将可接受的图像呈现给屏幕。将纹理的两个维度减半将该纹理所需的内存量减少到原始纹理的四分之一。

缩小纹理之前,先尝试压缩纹理或使用较低精度的颜色格式。使用PVRTC格式压缩的纹理通常提供比缩小纹理更高的图像质量,并且它也使用较少的内存!

将纹理组合到纹理图集中

绑定到纹理需要时间才能处理OpenGL ES。减少对OpenGL ES状态所做更改次数的应用程序性能更好。对于纹理,避免绑定到新纹理的一种方法是将多个较小的纹理组合成单个大的纹理,称为纹理图集。当您使用纹理图集时,您可以绑定单个纹理,然后使用该纹理进行多个绘图调用,甚至将多个绘图调用合并到单个绘图调用中。修改顶点数据中提供的纹理坐标以从图集中选择较小部分的纹理。


multiple.png

纹理图集有一些限制:

Xcode可以从图像集合自动为您构建纹理地图集。有关创建纹理图集的详细信息,请参阅Xcode帮助。此功能主要面向使用Sprite Kit框架的开发人员,但任何应用程序都可以使用它生成的纹理图集文件。对于项目中的每个.atlas文件夹,Xcode在应用程序包中创建一个.atlasc文件夹,其中包含一个或多个已编译的图集和属性列表(.plist)文件。属性列表文件描述构成图集的各个图像及其在图集图像中的位置 - 您可以使用此信息来计算在OpenGL ES绘图中使用的适当纹理坐标

使用Mipmap来减少内存带宽使用

您的应用程序应该为所有纹理提供mipmap,除了用于绘制2D未缩放图像的纹理。虽然mipmap可以使用额外的内存,但它们可以防止纹理伪影,并提高图像质量。更重要的是,当较小的mipmap被采样时,从纹理存储器中取出较少的纹素,这降低了图形硬件所需的存储器带宽,从而提高了性能。

GL_LINEAR_MIPMAP_LINEAR过滤器模式在纹理化时提供最佳质量,但需要从内存中提取额外的纹素。通过指定GL_LINEAR_MIPMAP_NEAREST过滤器模式,您的应用程序可以交换一些图像质量以获得更好的性能。

将mip地图与纹理图集相结合时,请使用OpenGL ES 3.0中的TEXTURE_MAX_LEVEL参数来控制纹理的过滤方式。 (此功能也可通过APPLE_texture_max_level扩展名在OpenGL ES 1.1和2.0中使用。)

使用多重扩展而不是多次通过

许多应用程序执行多次通过以绘制模型,改变每次通过图形管道的配置。这不仅需要额外的时间来重新配置图形流水线,而且还需要为每次通过重新处理顶点信息,并在稍后的传递中从帧缓冲区读回像素数据。

iOS上的所有OpenGL ES实现至少支持两个纹理单元,大多数设备至少支持八个。您的应用程序应该使用这些纹理单元在每次通过中在算法中执行尽可能多的步骤。您可以通过调用glGetIntegerv函数,将GL_MAX_TEXTURE_UNITS作为参数传回应用程序的纹理单元数。

如果您的应用需要多次传递来渲染单个对象:

确保每个通行证的位置数据保持不变。
在第二和后期阶段,通过使用GL_EQUAL作为参数调用glDepthFunc函数来测试模型表面上的像素

上一篇下一篇

猜你喜欢

热点阅读