OpenGL ES for iOS - 9

使用纹理数据的最佳做法

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

  • 在您的应用程序初始化时创建纹理,并且不要在渲染循环中更改它们。
  • 减少纹理使用的内存量。
  • 将较小的纹理组合成更大的纹理图集。
  • 使用mipmap可以减少获取纹理数据所需的带宽。
  • 在单次传递中使用multitexturing来执行纹理化操作。

初始化期间加载纹理

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

创建纹理后,避免更改它,除非在帧的开头或结尾。目前,所有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

纹理图集有一些限制:

  • 如果您使用GL_REPEAT纹理包装参数,则不能使用纹理图集。
  • 过滤可能有时将纹素移除到预期范围之外。要在纹理图集中使用这些纹理,您必须在构成纹理图集的纹理之间放置填充。
  • 由于纹理图集仍然是纹理,它受到OpenGL ES实现的最大纹理大小以及其他纹理属性的约束。

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函数来测试模型表面上的像素

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容