zoukankan      html  css  js  c++  java
  • 手机游戏开发中如何选择适合的纹理格式

    为毛要写这个


    本来觉得像这样的问题,是无法归类的,因为不同的项目有不同的需求,但今天因为quick论坛中的一个技术疑问贴,钩起了我整理这篇文章的兴趣 http://www.cocoachina.com/bbs/read.php?tid=214811

    于是,我决定尽力描述一下纹理格式选择方面的问题,一是起到一个科普的作用,因为目前没有发现十分完整的讲这方面的文章。二是整理一下自己的思路。

    当然,这些东西肯定不是我自己凭空YY出来的,我也是参考了不少文章,也从项目中总结了一些问题。在此先列出一些链接,先睹为快

    移动平台GPU压缩文理大全

    使用Mali官方工具进行ETC1纹理压缩

    Ericsson Texture Compression

    iOS和android游戏纹理优化和内存优化(cocos2d-x)

    优化你的手机游戏(没有延迟,才是健康的)

    Cocos2d-x纹理优化方案的一些总结

    手机游戏开发纹理图片优化心得

    手机游戏开发,如何选择和优化图片素材

    嗯 ,我觉得已经足够多了,并且,可能你也没有耐心把所有链接看完。 至少我没有……。

    GPU纹理与非GPU纹理


    很多小伙伴其实一直不明白GPU纹理与非GPU纹理的区别,以致于我打了将近1000字,他也没有懂为什么JPG不能省内存。

    常见的JPG格式,是一种文件压缩格式,即它能够把图片像素值,使用一种有损压缩的方式来存储,这样图片的体积会变得非常小。

    而我们经常提到的GPU纹理格式,如pvrtc,etc等,是一种GPU压缩格式,这种压缩格式,文件大小会比JPG大,但是它读入到内存后,不会被解压,而是直接送到显卡。 显卡也不会对齐解压,而是在执行如tex2D纹理采样指令的时候,取访问并索取对应像素值的内容。 这样才能够节省显存和内存。 pvrtc、etc等,既能够进行压缩,同时又提供随机访问(即在不全部解压的情况下,访问指定UV坐标的像素值)能力,因此会比jpg大许多

    图片格式简介


    ->pvrtc

    pvrtc有两种格式,一种是pvrtc 2bp,一种是pvrtc4bp。 二者没有本质区别,最主要的区别就是2bp表示每个像素使用2 bit来存储,4bp使用4bit来存储。当然这是一种理论值,由于pvrtc还需要储存额外的信息以保证能够恢复像素值,以及提供随机访问能力。 所以,实际的pvrtc格式的文件,不会是1/8和1/16这么小。pvrtc格式读入内存后,不会进行解压,而是直接送给GPU。 GPU也不会进行解压,从而保证了内存和显存的节约。 而tex2D能够对这种格式的纹理直接采样。

    另外,pvrtc目前有两个大版本,pvrtc1和pvrtc2,pvrtc2对压缩算法做了明显的改进。 但需要新款的GPU才支持,所以,如果要使用pvrtc2版本的PVRTC纹理,记得检查OPENGL ES的扩展标记。

    pvrtc建议只对IOS平台使用,因为这是power vr显卡专用的纹理格式。

    ->etc

    etc目前有两种格式,etc1/etc2。 etc1是opengl es 1.x和opengl es 2.0提供的必须支持的硬件格式,其唯一的缺点就是不支持ALPHA通道。 而etc2是opengl es 3.0才支持的,且增加了ALPHA通道能力。

    由于目前opengles 3.0设备的普及率还不高,目前(写这文章的时候是2014年7月18日)建议使用etc1格式

    建议etc1格式使用在ANDROID平台上。

    ->png24/32

    png24和32其实是一样的,24表示ALPHA通道不使用,因此,这是一种RGBA8888的纹理格式,这种格式不进行任何压缩,完全保持原始像素值。可以提供较高的质量,但这种纹理占用的磁盘空间较大。(与其内存占用等同),可以简单地通过 长x宽x4来计算大小。 比如1024x1024的PNG24/32纹理,占用磁盘空间和内存为 4MB。

    ->png8

    png8十分复杂,因为png8的意义比较多。

    仅包含ALPHA通道的8位PNG:这种通常拿来提供单独的ALPHA通道能力,opengl d3d等均支持这种8位ALPHA纹理。

    256色调色板的PNG:这种通常见于网站图标等,它只有一位表示ALPHA,即镂空效果。且不适合用在需要表现丰富和高饱和度的场合。

    通过一些压缩方式得到的压缩PNG:如grunt-png8,tinypng等, 这些工具,使用了较高的压缩技巧,使PNG24/32的RGBA可以保存在8位通道中。 且能够提供较高的还原度。 这种和PNG一样,读入内存后,每个像素依然占4BYTES。

    ->jpg

    jpg是一种通过有损压缩算法,使原始图片可以以很小的文件来存储的格式。 这种和上面提到的png8十分类似,但JPG不支持ALPHA通道。 虽然不支持ALPHA通道,但它读进内存后,内存占用依然是每个像素4BYTES。

    另外还有一些dds,tga等,由于我个人在手机游戏开发方面涉及这方面较少(端游使用tga和dds较多),在此不作论述。

    如何选择纹理格式


    人生之所以纠结,在于许多事情你可以选择

                                                 ---纠结帝·麒麟子·Alex

    上面的纹理格式,同一种情况下,可能多种都适合,那如何选择呢。 我们还是根据具体情况而定。

    1、场景、背景、全屏图片

    2D手机游戏中,多半都有这样的图片,以作为背景,特别在一些SLG,横版过关游戏中。这种图片对ALPHA没有要求,并且,在同一时间,只会出现一张(如果是多张拼接,也不会超过屏幕尺寸太多),内存不会成为关键点。所以,在这种情况下,我们大胆选择JPG就可以了。

    2、场景的前景,装饰物,可移动对象

    这种要看规模,如果规模较小,类型不多。 或者类型虽然多,但同一时间出现在场景中的类型不多,那我们可以选择压缩PNG8的方式,它支持ALPHA通道,文件又小。

    如果同屏可能出现多种这种,则需要考虑在IOS上使用PVRTC,在ANDROID上使用ETC1+ALPHA_MASK

    3、UI

    UI的背景图,可以优先考虑使用压缩PNG8,如果达不到精度要求,则使用PNG32。而对于UI的小元素,可以考虑使用压缩PNG8.

    对于UI的图标,一般是不带ALPHA的PVRTC/ETC + 一张公共的ALPHA掩码图,通过双层混合来实现圆边效果。 因为图标同屏出现可能较大。 如果图标能够控制在一定范围内,由于图标是48X48等大小,一张1024x1024的大图,可以放400个图标。 换用JPG,也有4MB的开销,如果这个是可以接受的,也可以使用JPG+ALPHA_MASK的方式。

    写到这里才发现,其实只需要下面一句话就可以搞定。

    这类图片会不会同时出现多个,同时出现时,内存开销是否无法接受, 如果确实无法接受,则使用GPU纹理,否则,优先考虑JPG,JPG+ALPHA,或者PNG8

    就是说,首先要减小安装包大小,如果内存有无法接受的情况,才需要用GPU纹理进行优化。而我们在优化的时候,最好是对某一类图片进行统一处理。 比如场景图片,如果决定了使用JPG,那就清一色的JPG。

    纹理的出图和处理


    这么多格式,如果让美术来出图,不是要折腾死么。

    因此,只需要规定,美术出图只给PNG(有些可能会是TGA)即可,剩下的事情,程序自己写脚本进行解决。 这样可以保证美术出图的规范性,同时也避免了程序在优化过程中,切换纹理格式带来的重新出图问题。

    PS:pvrtc和etc都可以使用pvrtex tool进行转换, etc的转换也可以使用mali的工具,看各人爱好了。 pvr的工具不管是下载,还是查看文档,都需要注册,就不给链接了……。

    结束


    或许你会说,JJYY半天,没有带点实际的。

    这句话真的挺嘲讽的,但我真的打算结束了,一是我想要说的,就是这些,二是,我没有打算写一个如何在移动平台上使用各种纹理的文章。

    希望这篇文章能够给迷茫的兄弟带来灵感。

  • 相关阅读:
    html自定义加载动画
    数据结构与算法:贪心算法简介
    WEB 前端常用字体和色值你知道多少?
    为什么浮点精度运算会有问题
    Java 字符串格式示例
    使用 Java 和 Maven (JBake) 生成静态网站
    硅谷钢铁侠
    Flink中的5种窗口使用场景
    prometheus-operator监控k8s资源
    fluentd收集k8s集群pod日志
  • 原文地址:https://www.cnblogs.com/qilinzi/p/3854410.html
Copyright © 2011-2022 走看看