纹理压缩算法

一、什么是纹理压缩

我们知道游戏中对于3D物体表面细节的表现最重要的还是靠贴图来实现的,那么越是高分辨率越是真彩色的贴图自然表现力也是越强,但是同时带来的问题是所需占用的内存会成倍的上升,而节省内存这一点在目前的游戏中还是非常非常重要的。 所以各个平台上都在使用纹理压缩的技术,让纹理贴图在内存占用和显示效果能达到一个尽可能的平衡。

纹理压缩是为了解决内存、带宽问题,专为在计算机图形渲染系统中存储纹理而使用的图像压缩技术。

二、为什么要纹理压缩

图片格式:
图片格式是图片文件的存储格式,通常在磁盘、内存中存储和传输文件时使用。
例如:JPG、PNG、GIF、BMP等。

纹理格式:
纹理格式是显卡能够直接采样的纹理数据格式,通常在向显卡中加载纹理时使用。
在这里插入图片描述

  • 纹理压缩格式基于块压缩,能够更快读取像素所属字节块进行解压缩以支持随机访问。
  • 图片压缩格式基于整张图片进行压缩,无法直接实现单个像素的解析。
  • 图片压缩格式无法被GPU识别,还需要经CPU解压缩成非压缩纹理格式才能被识别。

三、常见纹理压缩格式

在这里插入图片描述
压缩比算法:

  • 像素大小 = 16-bytes / 分块宽高 * 8-bit;
  • 压缩率 = 原始像素大小(32-bit) / 像素块大小;
  • 图像大小 = 原始图片大小 / 压缩率;

假设一张4MB的1024*1024原始图片:

块宽高像素大小(bits)压缩率压缩后大小
4*4841MB
5*55.126.25655KB
8*8216256KB
10*101.2825163KB
12*120.8935.95113.93KB

3.1 非压缩格式

格式含义
RGBA8888(RGBA32)一个像素32位,包含A通道,即一个像素消耗4字节
RGBA4444(RGBA16))一个像素16位,包含A通道,即一个像素消耗2字节。
RG888(RGB24)一个像素24位,无A通道,即一个像素消耗3字节
RGB565(RGB16)一个像素16位,无A通道,即一个像素消耗2字

3.2 DirectX标准压缩-DXTC

DXTC纹理压缩格式来源于S3公司提出的S3TC算法,基本思想是把4x4的像素块压缩成一个64或128位的数据块,优点创建了一个固定大小且独立编码片段,没有共享查找表或其他依赖关系,简化了解码过程。

在DirectX中,使用一种叫做DXT的纹理压缩技术,目前这种技术被大部分显卡所支持,通过对DXT的了解,我们可以对纹理压缩技术管中窥豹。 DXT是一种DirectDraw表面,它以压缩形式存储图形数据,该表面可以节省大量的系统带宽和内存。即使不直接使用DXT表面渲染,也可以通过 DXT格式创建纹理的方法节省磁盘空间。Direct3D提供了D3DFMT_DXT1 ~ D3DFMT_DXT5共5种压缩纹理格式。其中,D3DFMT_DXT1支持15位RGB和1位alpha图形格式,D3DFMT_DXT2、D3DFMT_DXT3支持12位RGB和4位alpha,D3DFMT_DXT4、D3DFMT_DXT5则采取了线性插值方式生成alpha。
在这里插入图片描述
DXT1:
DXT1中的两个RGB颜色负责表示所在压缩的4×4像素块中颜色的两个极端值,然后通过线性插值我们可以再计算出两个中间颜色值,而16个2位索引则表明了这4×4个像素块所在像素的颜色值,2位可以表示4种状态,刚好可以完整表示color_0,color_1以及我们通过插值计算出的中间颜色值color_2和color_3,而对于具有一位Alpha的贴图,则只计算一个中间颜色值,color_3用来表示完全透明。

对于如何判断DXT1格式是表示不透明还是具有1位alpha的贴图,则是通过两个颜色值color_0和color_1来实现的,如果color_0的数值大于color_1则表示贴图是完全不透明的,反之则表示具有一位透明信息。

DXT2、DXT3 :
DXT2和DXT3可以表示具有更复杂的透明信息的贴图,这两种格式采用的是显式的Alpha表示,我们知道了在DXT1中,我们使用64位数据来描述4*4的像素块的颜色信息,在DXT2和DXT3中,这部分颜色信息是不变的,而是通过另附加64位数据也就是每个像素4位来表示他们的Alpha透明信息,而这4位的Alpha的信息通常情况下我们可以采用直接编码的方式来表示即可。

这样每个4×4像素块占用128位也就是8个字,03字表示透明信息;47表示前面描述的颜色的信息。

DXT2和DXT3的不同之处在于,DXT2中颜色是已经完成了Premultiplied by alpha操作(已完成颜色与alpha的混合,当透明度发生改变时,直接改变整体颜色值,不必再单独复合),DXT3的Alpha信息则是相对独立的,之所以要区分开了则是为了适应不同的需要,因为有些场合需要独立的Alpha信息。

在这里插入图片描述
DXT4、DXT5 :
DXT4、DXT5也是用于表示具有复杂的透明信息的贴图,与2和3不同的是4和5的Alpha信息是通过线性插值计算所得,类似于DXT1的颜色信息。同样的,每4×4的像素块的透明信息占用64位,所不同的是,64位中采用了2个8位的alpha值和16个3位的索引值,既然每个像素的索引占3位,那么可以表示8种不同的透明状态。

在这里插值的方法有两种,一种用于表示具有完全透明和完全不透明的状态,另一种则是仅在给出的极端值alpha_0和alpha_1中进行插值。区分的方法也是通过比较alpha_0和alpha_1的大小来实现的,如果alpha_0大于alpha_1,则通过插值计算剩下的6个中间alpha值;否则,只通过插值计算4个中间alpha值,alpha_6直接赋值0,alpha_7直接赋值255。

DXT4和DXT5的区别同DXT2和DXT3的区别相同,DXT4的颜色值是理解为已经完成Premultiplied by alpha操作的。

另外需要注意的是,所有的压缩纹理格式都是2的幂,因为纹理压缩的单位是4×4像素,所以如果贴图的大小位16×2或者8×1这样的比例,系统会同样采用4×4的单位进行压缩,会造成一定的空间浪费,同样的大小会被占用,只是不会参与使用而已。

3.3 ETC

ETC(爱立信纹理压缩)格式最初是为了在移动设备中使用而开发的。今天,它是基于Android的设备的标准压缩方案。ETC1格式通过和WEBGL_compressed_texture_etc1扩展在OpenGL ES和WebGL中被支持。自OpenGL 4.3以来,ETC1和ETC2规范是OpenGL核心配置文件的一部分。

该压缩方案的第一个版本PACKMAN于2004年推出。后来,在2005年提出了名为iPACKMAN的增强版。这个版本更被称为ETC1,被广泛用于移动设备。这个压缩方案的后续发展导致了2007年ETC2格式的出现。
在这里插入图片描述
PACKMAN的核心思想

ETC压缩的主要思想是基于一个众所周知的色彩感知事实,即人眼对亮度而不是色度更敏感。因此,每个子块中只存储一种基色(ETC1/ETC2包括两个子块),但亮度信息是以每个顶点为基础存储的。亮度偏移是由一个单一的整数值来设定的,它被加到所有的颜色成分上。一个子块内只有四个不同的亮度偏移,所以只有四种不同的颜色可用。这些颜色可以被看作是一个局部调色板。

如果一个压缩块所占的位数与总线宽度相同,那么就可以避免流水线停顿,从而简化了硬件实现。由于移动设备在内存大小和总线宽度方面受到严格限制,因此考虑在PACKMAN中使用2x4瓦片。结果是,压缩块只占用32位。因此,压缩级别为4bpp,与BC1的压缩级别相当。

一个块中只存储一种RGB444基色。其他颜色是通过改变文本的亮度获得的。虽然基本思路与BC1相去甚远,但解码过程却非常相似。首先,四色局部调色板被恢复。然后,索引表被用来从这个调色板中挑选颜色见下图。然而,由于块的大小较小,只有4位用于指定亮度变化和调色板中的三种额外颜色。因此,这4位被用来对预定的亮度集之一进行编码。

在这里插入图片描述

3.4 PVRTC

PVRTC (PowerVR Texture Compression)由Imagination公司专为PowerVR显卡核心设计,由于专利原因一般它只被用于苹果的设备,仅Iphone、Ipad和部分PowerVR的安卓机支持。这可能是这几种压缩格式中最不公开的技术。

PVRTC不同于DXT和ETC这类基于块的算法,而将整张纹理分为了高频信号和低频信号,低频信号由两张低分辨率的图像A和B表示,这两张图在两个维度上都缩小了4倍,高频信号则是全分辨率但低精度的调制图像M,M记录了每个像素混合的权重。要解码时,A和B图像经过双线性插值(bilinearly)宽高放大4倍,然后与M图上的权重进行混合。

在这里插入图片描述

PVRTC 4-bpp模式下,每4x4像素占一个64位数据块,2-bpp模式下每8x4像素会有一个64位数据块。两者大同小异,我们仅说4-bpp模式。

4-bpp模式下,A和B图缩小后都只保存一个颜色值,如下图所示,A图比B图少1位,但两张图都可以选择以RGB或ARGB的方式存储(最高位决定为哪种),A色可以用RGB554或ARGB3443格式编码,B色可以用RGB555或ARGB3444格式编码。
在这里插入图片描述
在解码时,为了解码任意像素,必须读取4个相邻的PVRTC块,使用这4个块来解码一个5x5块。
在这里插入图片描述
使用双线性过滤来对A和B图进行扩大,然后A和B图根据M图与“Mode”位进行混合,这里的"Mode"位为1时,M图中10值像素被看作是开启了"punch-through alpha",alpha通道会被强制清零,这种神奇的操作是为了兼容旧应用程序,具体就不说了。
在这里插入图片描述
单从4bpp模式来看,PVRTC和BC、ETC非常相似,都有两个颜色值,但基本思想却是不同的。

Unity几种PVRTC的纹理压缩格式:

  1. 苹果的所有移动设备都支持PVRTC。
  2. PVRTC2质量比PVRTC更高,而且支持NPOT(非2次幂纹理),是PVRTC的升级版,。
  3. PVRTC和PVRTC2都支持4-bpp和2-bpp的ARGB格式。
  4. RGB PVRTC 4 bit :4 bits/pixel,对RGB压缩比6:1,安卓设备需要PowerVR Series 5以上。
  5. RGBA PVRTC 4 bit :4 bits/pixel,对RGBA压缩比8:1,3位Alpha值,设备同上。
  6. RGB PVRTC 2 bit :2 bits/pixel,对RGB压缩比6:1,安卓和IOS设备需要PowerVR Series
    5X以上。
  7. RGBA PVRTC 2 bit :2 bits/pixel,对RGBA压缩比8:1,3位Alpha值,设备同上。

3.5 ASTC

ASTC(自适应可扩展纹理压缩)是由ARM和AMD联合开发的,并在2012年提出。格式规范被Khronos联盟批准并在OpenGL中采用。适当的OpenGL和OpenGL ES扩展被称为KHR_texture_compression_astc_hdr 。从Mali-T628和Mali-T678开始,所有ARM图形核心都有ASTC硬件支持。专利属于ARM。然而,ASTC是完全开放和免版税的格式。

每个用例都对压缩方案提出了自己的要求:

  • 来自1-4分量的纹理支持。虽然单通道纹理可以使用BC7、PVRTC2或ETC2来存储,但大量的比特会被浪费在空通道上。
  • 在不相关的通道的情况下,质量可以接受。这对法线图和RGBA图像很重要。
  • 支持LDR和HDR。BC6H可以用于HDR纹理压缩,但它不支持alpha通道。
  • 跨平台。特别是,PVRTC只在iOS平台上可用,BC6H/BC7在移动设备中缺失,ETC不被桌面GPU所支持。对于跨平台应用程序的开发者来说,这可以说是非常不方便的。
  • 比特率/质量比的灵活性。根据纹理类型的不同,可以接受不同程度的压缩伪影,因为不同图像的可压缩性是不同的。以前提到的格式提供的比特率/质量选项不超过两个(BC1/BC7或PVRTC 4bpp/2bpp)。由于不能使用5bpp的压缩级别(如果4bpp的质量略显不足),必须使用8bpp的选项。它使带宽增加了一倍,但质量却没有明显改善。
  • 支持2D和3D纹理。

一个新的压缩方案是在考虑了所有这些要求后开发的。ASTC格式有一个固定大小的128位块。然而,对于2D纹理来说,编码的Tile尺寸从4x4到12x12 texels不等,对于3D纹理来说,从3x3x3到6x6x6不等。所有支持的Tile尺寸和相应的比特率可以在上表中找到。增量 "一栏显示,比特率可以以非常细的步骤扩展。在ASTC规范中,Tile尺寸也被称为块足迹。

在这里插入图片描述
ASTC是我们文章中描述的最灵活的格式,因为它也支持LDR、HDR、2D和3D纹理,最多有4个组件。它甚至支持低于1bpp的比特率。

从概念上讲,ASTC与S3TC/BC7类似:一个压缩块中最多存储四个端点对和插值权重,只支持预定义的分区,特定的分区由分区ID指定,也存储在一个块中。在弱相关的情况下,独立的索引表被存储在该通道中。每个独立的编码被称为一个平面。

也许,最主要和最有趣的ASTC创新是用小数位对整数值进行编码的技术,称为BISE。同时,BISE可以在硬件中有效实现。

参考链接:ASTC纹理压缩格式详解

3.6总结

在这里插入图片描述
画质比较 : RGBA > ASTC 4×4 > ASTC 6×6 > ETC2 ≈ ETC1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/488556.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解决Spring Gateway配置单个路由超时时间不生效的问题

之前springcloud gateway项目是的路由配置都是静态配置在项目的application.yml文件中,不能实现路由的热更新。前期业务发展也比较缓慢,新增路由的场景频率不是很高,最近业务越来越广,新增项目频率明显升高,所以想着把…

第44期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区,集成了生成预训练Transformer(GPT)、人工智能生成内容(AIGC)以及大语言模型(LLM)等安全领域应用的知识。在这里,您可以找…

数据结构:Trie(前缀树/字典树)

文章目录 一、介绍Trie1.1、Trie的结点结构1.2、Trie的整体结构 二、Trie的操作2.1、Trie插入操作2.2、Trie查找操作2.3、Trie前缀匹配操作2.4、Trie删除操作 三、实战3.1、实现Trie(前缀树) 一、介绍Trie Trie 又称字典树、前缀树和单词查找树&#xff…

flask_restful渲染模版

渲染模版就是在 Flask_RESTful 的类视图中要返回 html 片段代码,或 者是整个html 文件代码。 如何需要浏览器渲染模板内容应该使用 api.representation 这个装饰器来定 义一个函数, 在这个函数中,应该对 html 代码进行一个封装&#xff…

vue2 key的作用和原理

我们在写v-for的时候都会绑定一个key值,这个key在vue中有什么作用呢,不写可以吗? 目标 1 key有什么作用 2 如何不写key会产生什么影响 3 key使用原理 key的作用 可以看vue2官网上给的解释,“给vue一个提示,以便跟踪每个节点的身份”,这样听着很模棱两可,到底是什么作用…

解决“Pycharm中Matplotlib图像不弹出独立的显示窗口”问题

matplotlib的绘图的结果默认显示在SciView窗口中, 而不是弹出独立的窗口, 这样看起来就不是很舒服,不习惯。 通过修改设置,改成独立弹出的窗口。 File—>Settings—>Tools—>Python Scientific—>Show plots in toolwindow 将√去掉即可

在for循环加判断条件当条件都满足时,同时显现的解决方法

一、代码示例 function fu(s) {str ;ste ;console.log(s);let Things s;for (let i 0; i < Things.length; i) {if (Things[i].pid kk) {console.log(Things[i].pid);ste <div class"commodity_nei"><div class"zxc_pic"><div cl…

数据库专题(oracle基础和进阶)

前言 本专题主要记录自己最近学的数据库&#xff0c;有兴趣一起补习的可以一起看看&#xff0c;有补充和不足之处请多多指出。希望专题可以给自己还有读者带去一点点提高。 数据库基本概念 本模块有参考&#xff1a;数据库基本概念-CSDN博客 数据库管理系统是一个由互相关联的…

Java两地经纬度通过高德api获取两地距离(公里)

代码如下&#xff1a; String startLongitude entity.getLONGITUDE(); // 起点&#xff08;当前位置&#xff09;经度String startLatitude entity.getLATITUDE(); // 起点纬度String endLongitude entity.getLO(); // 终点经度String endLatitude entity.getLA(); …

Midjourney AI绘图工具介绍及使用

介绍 Midjourney是一款目前被誉为最强的AI绘图工具。只要输入想到的文字&#xff0c;就能通过人工智能产出相对应的图片。 官网只是宣传和登录入口&#xff0c;提供个人主页、订阅管理等功能&#xff0c;Midjourney实际的绘画功能&#xff0c;是在另外一个叫discord的产品中实…

计算机基础(中断、IO)

操作系统 设备交互 CPU 与 IO 设备交互过程 CPU 通过设备控制器&#xff08;驱动&#xff1f;&#xff09;与计算机外设进行交互。可以将控制器想象成编程语言中的接口&#xff0c;然后不同地计算机外设的控制器去实现这个接口&#xff0c;CPU 只需要调用接口而无需关注具体地…

记录三菱:Works2-计数器

参数设置&#xff1a;D200-D511掉电保持&#xff0c;这个范围可以更改 加减计数器 第一种&#xff1a; 第二种&#xff1a; 第三种&#xff1a; 例如&#xff1a;完成下面的功能 可以在触摸屏上仿真测试一下

unity学习(70)——编译游戏发生错误2

1.全屏问题其实无所谓&#xff0c;windows用tab可以切出来的。 2.现在主要问题是服务器try了以后虽然不崩溃了&#xff0c;但不再显示2个实例对象了&#xff0c;unity和exe此时都只能看到一个实例对象 2.1把之前报错位置的try-catch先注释掉 2.2 unity中此时登录666账号&…

2015年认证杯SPSSPRO杯数学建模D题(第二阶段)城市公共自行车全过程文档及程序

2015年认证杯SPSSPRO杯数学建模 D题 城市公共自行车 原题再现&#xff1a; 城市交通问题直接影响市民的生活和工作。在地形平坦的城市&#xff0c;公共自行车出行系统是一种很好的辅助手段。一般来说&#xff0c;公共自行车出行系统由数据中心、驻车站点、驻车桩、自行车&…

【Linux】信号量与信号

目录 先导知识 信号量 信号 信号概念及产生信号的一般方式 进程递达、阻塞和捕捉 信号集操作函数 信号的捕捉 可重入函数 先导知识 信号量与信号没有任何关系&#xff0c;它们是两个完全不同的概念&#xff01; 操作系统的本质&#xff0c;就是一个死循环&#xff1b;…

Django日志(四)

一、Filters介绍 过滤器用于从logger传递给handler的哪些日志要做额外控制 默认情况下,满足日志级别的任何消息都将处理。只要级别匹配,任何日志消息都会被处理。不过,也可以通过添加 filter 来给日志处理的过程增加额外条件。例如,可以添加一个 filter 只允许某个特定来源…

【C++】模板与泛型编程

文章目录 1. 泛型编程2. 函数模板2.1 函数模板概念2.2 函数模板格式2.3 函数模板的原理2.4 函数模板的实例化2.5 模板参数的匹配原则 3. 类模板3.1 类模板的定义格式3.2 类模板的实例化 4. 非类型模板参数5. 模板的特化5.1 概念5.2 函数模板特化5.3 全特化5.4 偏特化5.5 类模板…

Android 系统应用 pk8签名文件转jks或keystore教程

一、介绍 签名文件对于我们在做应用开发中&#xff0c;经常遇到&#xff0c;且签名文件不仅仅是保护应用安全&#xff0c;还会涉及到应用与底层之间的数据共享和API文件等问题。 在Android中&#xff0c;签名文件同样也存在这个问题。但是android中又区分系统应用和普通应用。系…

汉明校验·简明教程

汉明校验 一、简介 汉明码是由 Richard Hanming 于 1950 年提出的&#xff0c;它具有一位纠错能力。 新增的汉明码校验位数应满足如下关系&#xff1a; 2 k ⩾ n k 1 2^{k}\geqslant nk1 2k⩾nk1&#xff0c;其中k为校验位位数&#xff0c;n位数据位数。 二、汉明码生成 确…