zoukankan      html  css  js  c++  java
  • 图集整理策略(转)

    转自:【内存优化】图集整理策略 - 知乎 (zhihu.com)

    前言

    游戏开发,肯定会有一堆的图片,游戏运行时,unity会把小图整合到1张大图上,方便渲染合批,降低渲染消耗。
    但是,随着游戏开发的进行,图片越来越多,我们总不能所有的图片都塞进这张大图里,那加载的时候,更新的时候,这张大图的加载速度就会超级慢,严重影响游戏体验。这就涉及到图集的整理问题。
    优化的本质就是不渲染或少渲染或用更省的方法渲染。

    1. Sprite Packer介绍

    Sprite Packer会把相同Packing Tag以及相同压缩格式的资源打到相同的图集里面。

    所以影响图集大小主要集中在2个方面:

    1. Packing Tag:图集名称
    2. 资源的压缩格式(format):安卓使用ETC1压缩,IOS默认使用PVRTC,选用不用压缩模式的2张图,即使是同一个Packing Tag,也会被打到2张不同的图集里面。

    修改Packing Tag就会使小图打到不同的图集里

    2. 图集整理策略

    知道了Sprite Packer怎么打包图集的,我们就要根据项目实际情况,去合理安排和整理图片资源,图集太大不行,太空也不行,然后又要关心业务,很多注意事项。

    所以整理以下几个我们平时整理图集时候会关注的几个点:

    1. 尽量紧凑,没有太多空白。比如一个图集512x512刚好塞满,现在额外加一张小图进去,就被迫变成512x1024,浪费的空间就很多了,而且在有的平台,该图集会被强制变成1024*1024,内存消耗从1M变成4M。
    2. Draw Call尽量少,同一个界面的小图尽量在一个图集里。
    3. 内存管理方便,加载性能好,打开一个界面时只加载必要的图集,关闭时可以方便地释放图集。
    4. AssetBundle打包热更粒度合理,不能出现“热更一个新界面,大量图集都需要热更”的情况。
    5. 维护方便,当界面变化时,调整方便,包括生成图集、调整引用、新图集尺寸变化的影响、新图集AssetBundle变化的影响等等。
    6. 图集间隙尽量少,主要靠图集工具,常见的比如更紧凑的多边形Mesh替代Rect Mesh、旋转、切割等等。【TP比Unity的 Spirte Packer算法更好,这里我们不讨论】

    3. 我们现在项目的图集整理策略:

    1. 【脚本】按业务功能的预制,寻找依赖,收集所有预制引用的图片,
    2. 【脚本】将依赖的图片分别移动到对应业务命名的文件夹下【没有就创建】,如果有多个预制使用了同一张图片,我们就把它扔到common文件夹;
    3. 【人工】打开Spirte Packer,查看图集情况是否合理,合并零碎文件夹,让图集尽量紧凑,没有太多空白,尽量让图集处于2的n次方大小。【这个有大神能提供思路写个脚本吗?】
    4. 细碎图片扔进common。
    5. 程序来管理图集,就导致出包前,老是要要求美术缩小图片啊,调整目录啊,美术也不高兴,我觉得应该将这件事交给美术去做,拉美术一个人负责这件事,这样,他们上传的时候就会注意图片的通道RGBA啊,然后图集分配是否合理这些事,这样我们检查后的反馈就会少很多,大家合作也更舒服。

     

    4. Unity上手动查看这些打包的大图方式:

    1. 打开 Sprite Packer界面【Window-Sprite Packer(2018版本:Window-2D-Sprite Packer)】
    2. 点击pack按钮【前提是已经设置了图片的Tag】
    3. 但是由于unity内置的查看图集很不友好,大哥写了个工具Altas Looker,可以按上下键看图集,挺方便的。
    4. 需要的可以到我的工具工程自取,用得舒服了如果还能想起来请赞赏一下。
    5. AtlasLooker

    5. 资源优化

    5.1 纹理优化

    纹理优化的目的是让它们占用的内存尽量的小,那么纹理加载进内存后,大小计算公式如下:

    纹理内存大小(字节) = 纹理宽度 x 纹理高度 x 像素字节
    像素字节 = 像素通道数(R/G/B/A) x 通道大小(1字节/半字节)

    5.1.1 纹理尺寸

    根据项目实际情况将贴图都缩小至合适的大小。这里的合适大小是指渲染对象在画面中大多数情况下不可能达到的最大尺寸,这个尺寸最好保持2的N次方。

    5.1.2 纹理通道

    通道优化的目的是降低像素所占的大小,可以通过以下方法达到目的:

    • 去除Alpha通道。可以减少通道数量,适用于不需要Alpha混合或Alpha Test的角色和物件
    • 应用单通道图。也可以减少通道数量,比如灰度图、地形高度图,掩码图,Shader掩码图等
    • 使用16位代替32位图。例如RGB444/RGBA4444就可以减少像素通道大小。

    5.1.3 提高纹理复用率

    • 建立共享图库。将通用的元素放至共享库,例如按钮/进度条/背景/UI通用元素等。
    • 用九宫格图代替大块背景图。九宫格在游戏开发中是比较常见的UI组件。
    • 纹理元素通过变换可组合成复合纹理。例下图,上下左右对称的背景图可以用4张相同贴图实例通过旋转/翻转后获得。【mirror】

    5.1.4 UI图集

    界面A引用界面A图集和共享图集是允许的,但尽量不要引用界面B等其它图集。

    但实际在游戏开发过程中,很难保证美术做到这一点,通常存在以下问题:

    1. 如果界面A确实要用到界面B图集的某个元素,怎么办?

    参考解决方法:要看被引用元素的通用度,如果只是界面A和B在用,可以将被引用元素拷贝到界面A图集下;如果其它界面也会引用到,就可以将它移到共享图库。

    2. 有些UI纹理很大且很多界面都有用到,如果放在共享图库会导致共享图库急剧膨胀,怎么办?

    参考解决方法:大尺寸纹理建议用九宫格+细节图,或通过组合的方式来代替。

    3. 如何保证美术制作的UI只引用到自身图集和共享图集?

    参考解决方法:实现批处理检查工具,找出每个UI界面引用到的图集列表,引用的图集超过2个便是不合格。

     

    拓展

    1. 几种主流贴图压缩算法的实现原理详解

    1.1 ETC

    ETC压缩算法采用将图像中的chromatic和luminance分开存储的方式,
    而在解码时使用luminance对chromatic进行调制进而重现原始图像信息。
    ETC也主要有两种方法:ETC1和改进后的ETC2。

    ETC1:

    采用4x2的block进行分割(原始为4*2*24=192,压缩后为32,压缩率为6):

    ETC2:

    根据ETC1的实现方式,如果其块内的颜色分布不均匀的话,则其存储的两个basecolor会较远的分布于插值趋线的较远的两侧,进行解压后会得到较低的压缩质量,因而ETC2就是解决如何针对这些较为特殊的颜色分布来选择更加优化的压缩策略。

    1. 2. PVRTC

    PVRTC的不是基于block的方式生成的,但是却也可以理解为以block方式组织的。

    1.3 ASTC

    ASTC中ARM研发的一种较新的贴图压缩格式,相对于上述几种方法具有较多的优势,其应该会慢慢成为之后移动设备上贴图压缩的主要标准和主流。其主要具有如下的特性:

    1. 较高的灵活性;
    2. 可变的压缩率;
    3. 支持2d/3d贴图;
    4. 适用于移动平台;
    5. 支持LDR/HDR贴图内容;

    ASTC同样是基于block的压缩方式,但块的大小却较支持多种尺寸,比如从基本的4x4到12x12,而且块的宽高也不限于pot,比如6x5;每个块内的内容用128bits来进行存储,因而不同的块就对应着不同的压缩率。

  • 相关阅读:
    vue-element-admin实战 | 第二篇: 最小改动接入后台实现根据权限动态加载菜单
    设置git同时推送github和gitee远程仓库
    Spring Cloud实战 | 第一篇:Windows搭建Nacos服务
    winfrom 打开文件夹并定位到指定的文件
    winfrom 关于textbox回车事件有换行的问题
    winfrom切换账号功能
    解决winfrom最大化 窗体被任务栏挡住的问题
    winfrom解决控件闪烁
    winfrom防止程序多开
    c# 对象,IntPtr互转
  • 原文地址:https://www.cnblogs.com/mcyushao/p/14978097.html
Copyright © 2011-2022 走看看