unity图像压缩算法原理

10 篇文章 3 订阅

概述

在计算机图形学中,存在许多纹理压缩方案。压缩既减少了纹理内存占用,又降低了使用纹理的带宽要求。本文中,“纹理压缩”与“图像压缩”不同,因为纹理压缩方案的设计允许作为纹理采样的一部分进行有效的随机访问。“图像压缩”可以通过将图像视为一个整体来进一步减少图像冗余,但这样做对于有效的纹理访问操作是不切实际的。本文主要介绍几种unity当前主流的图像压缩算法,并给出推荐理由。


目的

纹理在移动和桌面图形中无处不在。它们为广泛的应用程序(如游戏或导航应用程序)添加了一定程度的真实感,其中图像质量和加载时间等因素的组合对智能手机、平板电脑和便携式控制台用户至关重要。通常,此类内容越来越多地要求更高分辨率的更高质量,以提高整体质量标准。这意味着计算系统需要获得功能、原始图形和计算性能以及软件工具的正确组合,以有效利用所有可用资源。

尽管艺术家和开发人员在纹理设计和贴图方面所做的努力很少受到赞赏,但游戏玩家可以快速识别与纹理压缩相关的问题,如低分辨率、压缩瑕疵或锯齿。因此,在开始任何应用程序的开发工作时,采用和维护正确的压缩标准对于取得成功至关重要。

现代应用已变得图形密集;某些类型的软件,如游戏或导航辅助工具,通常需要大量纹理才能以令人满意的质量表示场景。纹理压缩可以节省或允许更好地利用带宽、电源和内存,而不会明显损失图形质量。

  • Performance Improvement:较小的纹理数据大小意味着从内存到GPU的传输更小。内存带宽非常宝贵,尤其是在共享内存架构盛行的移动平台上。在内存带宽是应用程序性能限制因素的情况下,纹理压缩可以提供显著的改善。
  • Storage Footprint vs. Memory Footprint:纹理压缩减少了给定纹理的内存占用;这允许应用程序在有限的纹理内存中匹配其所有所需的纹理,或者使用更大(或更多)的纹理来获得相同的内存预算,从而产生潜在的额外质量。此外,在整个SoC(片上系统)中共享内存的移动和平板设备中,内存需求的任何节省都非常有用。
  • Power Consumption:在电池寿命最为重要的移动设备上,内存访问的功耗非常昂贵。运行时纹理压缩带来的带宽节约和更好的缓存使用率都有助于减少内存访问的数量和幅度;这反过来又降低了应用程序的功耗。

术语

bpp : Bits per pixel,每像素占用位数,是单个纹理像素所需的存储量。bpp值较低的纹理在磁盘和内存中的大小较小。较低的bpp值还意味着GPU可以在其缓存中存储更多像素,从而加快纹理访问速度。
lossy:有损压缩在GPU等渲染系统中是可以容忍的,因此大多数纹理压缩算法都涉及固定大小像素块的某种形式的量化。但随着便携式设备的高分辨率显示器开始成为一种常见功能,在图像质量和压缩因子之间取得正确的平衡是编写针对移动世界优化的应用程序的必要步骤。
Channels:R(红)G(绿)B(蓝)A(透明度),一般都包含这四条通道的某几条
Compression ratio:压缩比,RGB原生纹理的像素指24位,4bpp表示每像素占4位,所以也可以认为4bpp表示压缩比为6:1
LDR: (Low Dynamic Range) 指颜色概念上介于0.0(黑色)和1.0(白色)之间的大多数典型图像。大多数图像文件(如PNG和JPG)的动态范围较低。
HDR: (High Dynamic Range)指特殊的图像和纹理格式,其中颜色的范围可以大于0到1。像.exr或.hdr这样的图像文件格式通常用于hdr图像数据。在运行时和GPU上,有几种HDR格式,在精度、范围和内存使用方面进行权衡。


算法

以下是本篇文章主要内容,介绍现在比较主流的图像压缩算法。

S3TC

S3TC也叫 DXTC(或BC)为微软为DX而推出的基于block的贴图压缩格式,其主要采用调色板的原理来进行压缩。

1. BC1 with no alpha

基于4x4 block来进行,共64位,不含有alpha通道,图像被视为完全不透明。
每个block内记录两个16bits的颜色做为基准颜色,然后解压时再使用两个基准色调制出另外两个颜色做为块内4个压缩颜色。其计算方式为:

basecolor2 = 2/3 *basecolor0 + 1/3 * basecolor1
basecolro3 = 1/3 *basecolor0 + 2/3 * basecolor1

对于每个块内的texel,存储2bits的索引,用来指向到4个基准颜色中的一个。所以对于BC1的压缩状态为64bits:
32bits:两个RGB565格式的基准颜色basecolor0 与 basecolor1
32bits:16个2bits的索引

2. BC1 with alpha

每个4×4 texel块由64位RGB图像数据和最小alpha信息组成。texel的RGB分量以与BC1 没有alpha时相同的方式提取。
在一个纹理block的x,y位置,alpha的值定义为:

ConditionAlpha value
color0 ≤ color1 and code(x, y) = 30.0
otherwise1.0

最终alpha为0的任何texel的红色、绿色和蓝色分量应编码为零(黑色)。如果格式为带alpha的BC1,则code(x,y)= 3是透明的(alpha=0)。如果格式为BC1,没有alpha,则代码(x,y)=3表示不透明黑色。

3. BC2

BC2在BC1的基础上支持了a值。它将4x4共16个像素存储为128位数据,其中包括64位a通道(每像素4位)和64位颜色通道,RGB和DXT1一致,即两个16位RGB值和16个2位索引表。它的透明度只有4位共16种数值.

4. BC3

BC3在BC1的基础上支持alpha通道。首先,RGB的存储方式与BC1相同,需要64bits;对于alpha部分,使用与RGB部分相同的策略来处理。在block存储两个基准的alpha值,然后在其基础上插值得到其它6个共计8个alpha值,来做为alpha的调色板;然后对于每个texel存储一个3bits的索引,用来指向到这8个alpha中的一个。所以其对应的存储状态为:

  1. 32bits:两个RGB565格式的基准颜色;
  2. 32bits:16个2bits的颜色索引;
  3. 48bits:16个3bits的alpha索引;
  4. 16bits:2个8bits的基准alpha;

BPTC

BC6H

未完待续

BC7

未完待续

ETC1

纹理被描述为若干4×4像素块。如果纹理(或特定mipmap级别)在任何维度上小于4个像素(例如2×2或8×1纹理),则纹理位于块的左上部分,其余像素不使用。例如,大小为4×2的纹理将放置在4×4块的上半部分,而块中像素的下半部分将不被访问。
ETC1中有两种模式:“单独”individual和“differential”模式。对于特定的4×4块,哪个模式是活动的由位33控制,我们称之为diff位。如果diff=0,则选择“individual”模式,使用2种baseColor;如果diff=1,则选择“differential”模式,使用baseColor + colorDelta。两种模式的位布局不同:单独模式的位布局如表60 a部分和c部分所示,差分模式的位布局如表60 b部分和c部分所示。
ETC1 texture bit

  • 其中包含2个12位的color: 24bit
  • 2个3位的Table codeword: 6bit
  • diff bit, flip bit: 2bit
  • a0 a1 - p0 p1共16个纹素,每个纹素2bit:32bit
    因此,ETC1是使用64位编码4*4 block的纹素的

在这两种模式中,4×4的block被分为两个子块,大小为2×4或4×2。这是由位32控制的,我们称之为flip bit。如果flip bit=0,则块被并排分成两个2×4子块,如图7所示。如果flip bit=1,则该块被划分为两个相互重叠的4×2子块,如图8所示。
在这里插入图片描述
在这里插入图片描述
接下来,我们使用两个“像素索引”位,也就是a0 a1 两位组成一个0-3的索引值,从修改器表中确定要使用的修改器值。像素索引位对于每个像素都是唯一的。请注意,特定texel的像素索引始终存储在相同的位位置,而不考虑位diff bit和flip bit。使用表62对像素索引位进行解码。例如,如果像素索引位为01b=1,并且使用修改器表[-29,-9,9,29],则为该像素选择的修改器值为29(参见表62)。此修改器值现在用于添加修改基础颜色。例如,如果我们有基色(231,8,16),我们应该将修改器值29添加到所有三个组件中:(231+29,8+29,16+29),从而得到(260,37,45)。然后将这些值钳制为[0…255],得到颜色(255,37,45),我们就完成了对texel的解码。
在这里插入图片描述
在这里插入图片描述

ETC2 (不带alpha)

根据ETC1的实现方式,如果其块内的颜色分布不均匀的话,则其存储的两个basecolor会较远的分布于插值趋线的较远的两侧,进行解压后会得到较低的压缩质量。因而ETC2就是解决如何针对这些较为特殊的颜色分布来选择更加优化的压缩策略。改进主要针对ETC1中的diff为1的情况下展开.
在这里插入图片描述

对于RGB ETC2,每个64包含关于三通道4×4像素块的信息,如图10所示。
在这里插入图片描述
在这里插入图片描述

使用五种不同的“”之一对块进行压缩。表63的a部分显示了用于确定给定块中使用的模式的位。
首先,如果标记为D的“differential bit”设置为0,则使用“individual”模式。否则,检查三个5位值R、G和B以及三个3位值Rd、Gd和Bd。R、 G和B被视为介于0和31之间的整数,Rd、Gd和Bd被视为介于-4和+3之间的两个s-补码整数。
首先,R和Rd相加,如果总和不在区间[0…31]内,则选择T模式。
否则,如果GGd之和在区间[0…31]之外,则选择H模式。
否则,如果BBd之和在间隔[0…31]之外,则选择planar模式。
最后,如果D位设置为1,且上述所有总和均在0和31之间,则选择differential模式。

b)与ETC1一样的 diff = 0, 使用“individual”模式。如果R=14=1110二进制(简称1110b),G=3=0011b,B=8=1000b,则子块1的基色的红色分量变为11101110b=238,绿色和蓝色分量变为00110011b=51和10001000b=136。子块2的基色解码方式相同,但使用4位码字R2(位59…56)、G2(位51…48)和B2(位43…40)。

c) 与ETC1一样的 diff = 1, 使用“differential”模式,子块1的基色源自五位码字R、G和B。通过将前三个最高阶位复制到三个最低阶位,将这五位码字扩展到八位。例如,如果R=28=11100b,则得到的八位红色分量变为11100111b=231。同样,如果G=4=00100b和B=3=00011b,则绿色和蓝色分量分别变为00100001b=33和0001100B=24。因此,在此示例中,子块1的基色为(231、33、24)。子块2的基色的五位表示是通过用码字Rd、Gd和Bd修改五位码字R、G和B来获得的。Rd、Gd和Bd中的每一个都是一个三位二补数,可以保持-4和+3之间的值。例如,如果如上所述R=28,并且Rd=100b=y-4,则红色分量的五位表示为28+(-4)=24=11000b,然后将其扩展到八位,以11000110b=198。同样,如果G=4、Gd=2、B=3和Bd=0,则子块2的基色将是RGB=(198、49、24)。

d) T字型分布,一部分颜色沿插值趋线分布,另外的颜色分布于距离较远的位置上,如蓝色点所示
在这里插入图片描述
在“T”模式下,绘制paint color 0只是第一个基色,paint color 2是第二个基色。要获得其他绘制颜色,首先确定“距离”,该距离将用于修改其中一种基色的亮度。这是通过将表63第d节中所示的值da和db与da | db相结合,然后将该值作为索引放入表66中所示的小查找表中来实现的。例如,如果da为10二进制,db为1二进制,则距离索引为101二进制,选择的“距离”d为32。然后,Paint color 1等于第二个基色 加 “距离 d 到每个通道,而Paint color 3等于第二个基色,并将“距离”d减去。在这里插入图片描述
e)H字型分布,两部分的颜色均有不同的分布趋向
在这里插入图片描述

“H”模式也会计算“d”值,但这样做稍微复杂一些。为了将三位索引构建到表66中所示的距离表中,表63 e部分中所示的da和db分别用作最高有效位和中间位,但最低有效位计算为(base color 1 value + base color 2 value),用于比较的颜色的“值”等于(R l 16)+(G l 8)+ B。确定“H”块的“距离”d
在本例中,第一个基色定义为4位RGB值(13、1、8),如上面的“T模式”情况所示。这将扩展4到8位,达到(221、17136)。第二种基色定义为4位RGB值(4、12、13),其扩展为(68,204,221)。块编码的距离索引为5(这意味着基色1必须大于基色2),对应于32的距离d。这将得到以下颜色:
在这里插入图片描述
最后,在“T”和“H”模式下,每个像素都被指定为四种绘画颜色中的一种,这与四个修改器值在“单个”或“差异”块中分布的方式相同。例如,要为像素d选择绘制颜色,使用位19作为最高有效位,位3作为最低有效位来构造索引。然后,例如,如果像素具有索引2,则将为其指定“paint color 2.”。

g) ‘planar’ mode“,提供并使用三种基色来形成用于确定块中各个像素的颜色的颜色平面。平面分布型,其主要针对block块内的颜色分布于4个角落上的情形,如下所示:
在这里插入图片描述
所有三种基色均以RGB:676格式存储,并以表63第g节所示的方式存储。这两种二级颜色的后缀为“h”和“v”,因此这三种颜色的红色成分分别为R、Rh和Rv。一些颜色通道被分割成非连续的位范围;例如,使用B5作为最高有效位,B4…3作为随后的两个位,以及B2…0作为三个最低有效位来重构B。一旦基色的位被提取出来,它们必须以类似于在其他模式中用于基色的方法的方式扩展到每个通道8位。例如,通过将六位中的两个最高有效位复制到最后八位中的两个最低有效位来扩展六位蓝色和红色通道。
最后通过三角形绘制与插值,得到每一个纹素的颜色。

ETC2 (带alpha)

RGBA:8888信息的每个4×4块被压缩为128位。要解码一个块,按照上节中的说明计算两个64位整数64bit Alpha64bit Color。然后,**64bit Color*以与RGB ETC2相同的方式对RGB分量进行解码(参见ETC1 no alpha)。
在这里插入图片描述
用于解压缩alpha通道的64bit Alpha中的64位如表67所示。信息分为两部分。前16位包括base codeword, table codeword 和 multiplier,它们一起用于计算要在块中使用的8个像素值。剩余的48位被划分为16个3位索引,用于为块中的每个像素选择这8个值中的一个。
The base codeword存储在前8位(位63…56)中,如表67第(a)部分所示。这是等式2中的第一项。
接下来,我们要获得modifier。表67第(a)部分中的位51…48形成一个4位索引,用于选择表68中所示的16个预先确定的“modifier tables”中的一个。
Intensity modifier sets for RGBA ETC2 alpha component
先获取base codeword,通过4位的table index找到表68种的第n行,然后每个纹素的3bit标识modifier table的第几个,得到的结果乘以multiplier的值,加到base codeword,即为目标alpha的值。

PVRTC

解压缩PVRTC编码的纹理意味着一个三步过程,该过程经过仔细优化,以提高硬件效率和降低功耗。以下以PVRTC 4-bpp为例

  1. 首先,为了解码一个texel(或一组4×4相邻texel),硬件识别需要哪四个64位数据“word”,并从缓存和/或内存中获取它们。然后将双线性插值应用于这些“word”中包含的颜色数据,以产生两个低分辨率图像(局部4×4)放大版本(PVRTC 2bpp为8×4)。
  2. 由一位制定下面modulation 的模式,左边0 右边1。调制数据嵌入用于在低分辨率图像的放大版本之间线性插值的数据字中。在放大过程和调制步骤中都有许多优化,它们有三个好处:最小化硬件需求、提高解压缩效率和降低功耗。
    模式表
  3. 其生成压缩后包含两张(w/4,h/4)大小的缩略图(w,h为原始图片的宽和高,可以理解为第4级的mipmap,但生成过程会比较mipmap的复杂),其中的每个pixel映射并对应到原始图像中的一个64x64的block上;然后使用1张与原始图像大小相同的modulate图,对应的每个pixel占2个bits,也即可对应四种调制方式,通过几种不同的调制方式还原出近似的原始像素值。
    在这里插入图片描述

如上图所示,两张(w/4,h/4)大小的缩略图,产生了2张高精度的(w, h)的放大图,然后通过每一个像素2位的modulation 图混合得到最终的效果,算法:

output= A + modulation(x, y) * (B- A)

bit占用如下:
bit占位图
压缩后的一个4x4的block中的bits的组成内容为:

  • 1bit:对应的融合方式,透明或不透明;
  • 32bits:对应于16个pixel,每个pixel有2bits的调制因子;
  • 31bits:对应两个缩略图中的该块映射到的两个像素上的颜色,若是透明模式,则两个颜色为RGBA44431
    RGBA34431;若是不透明模式,则两个颜色为RGBA5551,RGBA4551;

在解码时,为了解码任意像素,必须读取4个相邻的PVRTC块,使用这4个块来解码一个5x5块。
在这里插入图片描述
单从4bpp模式来看,PVRTC和BC、ETC非常相似,都有两个颜色值,但基本思想却是不同的。

PVRTC2

PVRTC2的数据字布局与PVRTC1非常相似,但存在两个主要差异:

  1. PVRTC2 为整个数据字具有单一的"不透明标记",而 PVRTC 对每个颜色段使用"不透明标志"
  2. PVRTC2 引入了用于子文本的"硬过渡标志"。将单个"不透明标志"设置为 1 表示两个颜色段不透明,而当颜色段为 0 时,必须以以下显示的透明模式解释两个色段。
    bit描述
    "硬过渡标志"和"调制标志"为解释调制数据提供了额外的选项。这使 PVRTC 中以前可用的选项数量翻倍。
    flag
    当处理包含颜色不连续性的纹理时,新的"非插值"和"局部调色板"模式可提高 PVRTC2 的质量。当纹理无法无缝平铺(图像边界上存在不连续性)时,开发人员应使用“非插值”模式,而包含具有各种不同颜色的局部区域的纹理将受益于“局部调色板”模式。

ASTC

在Khronos定义OpenGL ES 3.0的同时,还致力于开发一种业界领先的压缩格式,为开发人员提供更细粒度的控制。在2012年年中推出了ASTC纹理压缩格式。ASTC的关键在于,虽然它使用固定的128位/块,但与先前格式的固定4x4块不同,每个纹理在这128位中可以有不同大小的块。ASTC利用各种各样的方形和非方形块大小,提供了广泛的派生压缩比,从8bpp扩展到1bpp以下,如下所示:
在这里插入图片描述
因此,ASTC在调整质量和大小方面具有巨大的优势。替代格式通常为RGB或单通道数据提供4bpp,有些格式可以在该封装中容纳alpha,有些格式在第二个4bpp部分中提供更高质量的alpha或第二个单通道数据块。PVRTC是另一个提供较小的变体,具有2bpp模式。

此外,ASTC还支持1-4个通道,包括全alpha RGBA、普通RGB、2通道RG(LA)和1通道R(L/A)支持,以及自定义X+Y和XY+Z法线贴图支持。最终结果是ASTC处理大多数类型的纹理。

ASTC的另一个关键优势是,编码端点、加权等的方法是按块选择的,而不是全局选择的,因此编码器可以动态调整以分配128位,以便更好地表示每个块中的内容。这提供了比以前的格式更好的图像质量,即使在更高的压缩。

支持ASTC的硬件已经达到足够的市场份额,开发者应该认真考虑如何在项目中使用它:提高质量,减少存储容量,或者两者兼而有之。这在需要足够高级别的图形硬件(例如ASTC是给定的)的项目中尤其如此。
ASTC的压缩非常复杂,分了很多可变的配置数据,之后会专门出一篇文章研究。

推荐

Windows

对于使用DirectX 11或更高级别GPU的设备,如果保证支持BC7和BC6H格式,建议选择DXT1 four bits/pixel的RGB纹理-DXT1压缩格式。RGBA textures -BC7(质量越高,压缩速度越慢)或 DXT5(压缩速度越快),均为8位/像素。HDR textures -8 bits/pixel BC6H。如果您需要在PC上支持DirectX 10类GPU(2010年之前为NVIDIA GPU,2009年之前为AMD,2012年之前为Intel),则首选DXT5而非BC7,因为这些GPU不支持BC7或BC6H。

Android

可选 ASTC, ETC2 and ETC (ETC1 for RGB, ETC2 for RGBA)
LDR RGB and RGBA textures, 大多数现在的Android GPU 都支持 OpenGL ES 3.1 or Vulkan,也支持 ASTC
HDR textures, ASTC HDR 是安卓设备唯一的选择
OpenGL ES 2 不支持ETC2,Vulkan or OpenGL ES 3.0支持 ETC2

IOS

苹果设备 A8 chip (2014) 或者以上, ATSC对于 RGB 和RGBA 纹理是推荐的
如果需要对旧设备的支持,那么Apple设备支持从A7芯片开始的ETC/ETC2格式(2013)。对于更旧的设备,PVRTC是要使用的压缩格式。在iOS上您可以在播放器设置中配置默认纹理压缩格式,PVRTC为您提供了尽可能广泛的兼容性。ASTC是首选,但在A7设备(第一个Metal-enabled的设备)上不受支持,将在运行时解包。

ComputeShader

下面给出unity下使用computerShader动态压缩BC3 ETC2 ASTC的算法实现
链接: https://github.com/su366350579/textureCompression.

总结

本文讲述了几种现在unity主流的压缩算法,安卓:用ETC2基本都支持了;至于ASTC在Android 5.0/OpenGL ES 3.1后支持,市场大部分机型都支持(98.5%),可以考虑选择,但毕竟是安卓,要做好处理兼容性的心里准备。
IOS:在iPhone6以上(包含)都支持ASTC,6以下可以选择PVRTC2。

参考

imaginationtech for PVRTC.
imaginationtech for PVRTC2.
Unity Document - texture compresion.
Khronos Data Format Specification v1.1 rev 9.
Using ASTC Texture Compression for Game Assets.
几种主流贴图压缩算法的实现原理.
你所需要了解的几种纹理压缩格式原理.

  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Unity导航算法是一种用于游戏开发中的路径规划算法,用于实现游戏中角色的自动导航和避障功能。该算法的基本原理是寻找从起点到终点的最优路径,同时避开障碍物。 Unity导航算法的实现过程可以分为三个步骤:建立导航网格、搜索最优路径和动态避障。 首先,建立导航网格是将地图划分成一系列小方格的过程。每个小方格被标记为可通行或不可通行,通过区分地图中可移动的区域和障碍物,为后续的路径搜索提供基础。 然后,搜索最优路径是根据导航网格进行的寻路算法。典型的搜索算法是A*算法,它通过评估每个方格的成本,并利用启发式函数估计到目标的最短距离,以选择最优的路径。A*算法综合考虑了路径长度和启发式函数的估计,使得找到的路径较为准确和高效。 最后,在动态避障过程中,Unity导航算法会根据环境的实时变化,不断更新导航网格和寻路路径。当出现新的障碍物时,算法会对网格进行更新,重新计算最优路径,以保证角色能够绕开障碍物而到达目标。 总结来说,Unity导航算法通过建立导航网格、搜索最优路径和动态避障来实现角色的自动导航和避障功能。该算法的基本原理是利用A*算法在导航网格中寻找到目标的最优路径,并根据环境的实时变化进行动态调整。这种算法在游戏开发中起到了重要的作用,使得游戏角色能够智能地避开障碍物,并按照最优路径进行导航。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值