[自学记录02|百人计划]纹理压缩
一、什么是纹理压缩
纹理压缩是为了解决内存、带宽问题,专为在计算机图形渲染系统中存储纹理而使用的图像压缩技术。
1.图片格式和纹理格式的区别
(1)图片格式
图片格式是图片文件的存储格式,通常在磁盘、内存中储存和传输文件时使用;例如:JPG、PNG、GIF、BMP等。
(2)纹理格式
纹理格式是显卡能够直接进行采样的纹理数据格式,通常在向显卡中加载纹理时使用。
2.纹理管线
纹理压缩格式基于块压缩,能够更快读取像素所属字节块进行解压缩以支持随机访问;图片压缩格式基于整张图片进行压缩,无法直接实现单个像素的解析;图片压缩格式无法被GPU识别,还需要经CPU解压缩成非压缩纹理格式才能被识别。
根据老师所讲的内容,我个人倾向于把图片格式理解为顺序表,读取不随机,也就是说使用的时候要进行查找,而纹理格式则不同,它类似于哈希表,GPU可以随机访问,这样大大提高了效率。
二、常见的纹理的格式
1.非压缩格式
2.压缩格式
(1)DXTC
DXTC纹理压缩格式来源于S3公司提出的S3TC算法,基本思想是把4×4的像素块压缩成一个64或128位的数据块,优点为创建了一个固定大小且独立的编码片段,没有共享查找表或其他依赖关系,简化了解码过程。
DXT1格式主要适用于不具透明度的贴图或仅具一位Alpha的贴图(非完全透明则即完全不透明)。
DXT1将每4×4个像素块视为一个压缩单位,压缩后的4×4个像素块占用64位,其中有2个16位的RGB颜色和16个2位索引,如
DXT1中的两个RGB颜色负责表示所在压缩的4×4像素块中颜色的两个极端值(极端值颜色为RGB565格式),然后通过线性插值我们可以再计算出两个中间颜色值,而16个2位索引则表明了这4×4个像素块所在像素的颜色值,(00,01,10,11)可以表示4种状态,刚好可以完整表示color_0,color_1以及我们通过插值计算出的中间颜色值color_2和color_3。而对于具有一位Alpha的贴图,则只计算一个中间颜色值color2,而color_3则用来表示完全透明。
对于如何判断DXT1格式是表示不透明还是具有1位alpha的贴图,则是通过两个颜色值color_0和color_1来实现的,如果color_0的数值大于color_1则表示贴图是完全不透明的,反之则表示具有一位透明信息。
而对比RGB24的格式,DXT1的压缩比达到了 6:1。(24*16 / 64 = 6)
DXT2和DXT3可以表示具有更复杂的透明信息的贴图,这两种格式采用的是显式的Alpha表示,我们知道了在DXT1中,我们使用64位数据来描述4*4的像素块的颜色信息,在DXT2和DXT3中,这部分颜色信息是不变的,而是通过另附加64位数据也就是每个像素4位来表示他们的Alpha透明信息,而这4位的Alpha的信息通常情况下我们可以采用直接编码的方式来表示即可。
这样每个4×4像素块占用128位也就是8个字,0~3字表示透明信息;4~7表示前面描述的颜色的信息。
DXT2和DXT3的不同之处在于,
DXT2中颜色是已经完成了Premultiplied by alpha操作(已完成颜色与alpha的混合,当透明度发生改变时,直接改变整体颜色值,不必再单独复合)
DXT3的Alpha信息则是相对独立的,之所以要区分开了则是为了适应不同的需要,因为有些场合需要独立的Alpha信息。
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的单位进行压缩,会造成一定的空间浪费,同样的大小会被占用,只是不会参与使用而已。
在Unity内贴图类型选为法线后会采用DXTnm压缩格式,它基于DXT5,该格式会把法线贴图R通道存入A通道,然后RB通道清除为1,这样可以将法线XY信息分别存入到RGB/A中分别压缩,以获得更高的精度,然后再根据XY构建出Z通道数据。
那么对于RGBA32格式,DXT2345的压缩率则为 4 :1 (32/128*16)
参考:DXT纹理压缩_lhc717的博客-CSDN博客
(2)ATI1/2(BC4/5)
ATI1(BC4),主要用于压缩高度图、法线图等具有单一灰度通道的纹理贴图,采用固定32字节块的压缩方式,每个块可以压缩4x4像素纹理数据。在每个压缩块中,只需要2个红色分量存储压缩后的数据,可以用两个8位整数、一个16位的整数、或者一个12位整数和一个4位整数存储这些数据。因此,在使用ATI1压缩算法时,搭配的纹理比原始纹理小约75%,这大大减少了存储空间的需求。
ATI1尤其适用于包含高度信息的纹理(如Displacement Maps),但对最终图像制品的视觉影响很小。不过,因为它不能进行色彩太多变化的压缩,所以它不适合用于HDR纹理(高动态范围纹理)。
总体而言,ATI1能够提供比较小的文件尺寸和较低的显存占用,同时还能满足设计师对细节的需求。
ATI1的压缩率:单通道8位:(64位/16像素) = 2 : 1
ATI2(BC5),主要用于压缩法线图和切线空间贴图等具有两个灰度通道的纹理贴图,采用固定块大小的压缩方式,每个块可以压缩4x4像素纹理数据。在每个压缩块中,采用两个分离的压缩算法(RG存储分别经过压缩的正半球和负半球法向量)。然后再对编码后的R通道和G通道进行解压合成Z轴信息得到完整的归一化法线向量。每个R和G通道都可以用3个8位整数、或者一个10位整数和一个6位整数存储,使得最终的压缩结果无需外部计算即可直接读取。
相比于ATI1,ATI2增加了红色和绿色Two-Step交替方法进行压缩,获得了更高的压缩率和更好的细节表现。但由于使用了两个分离的压缩算法,所以在解压的时候还需要进行额外的操作。另外,ATI2作为一种压缩纹理格式,对于最终的图像质量还需要在算法上进行精度控制和优化平衡。
ATI2的压缩率:双通道8位(16位):(2*64位/16像素) = 2 : 1
双通道16位(32位) :(2*64位/16像素) = 4 : 1
(3)BC6/7
BC6和BC7的官方原理说明:
BC6H 格式 - UWP applications | Microsoft Learn
BC7 格式 - UWP applications | Microsoft Learn
(4)ETC
上述我们说的DirectX选择了DXTC作为标准压缩格式,那对于OpenGL则选择了爱立信研发的ETC格式,几乎所有的安卓设备都可以支持ETC压缩,所以其在移动平台上被广泛应用;
ETC方案与DXTC具有相同特点,将4×4的像素单元压缩成64位数据块,并将像素单元水平或竖直朝向分为两个区块,每个像素颜色等于基础颜色加上索引指向的亮度范围。
第一行:24位 颜色信息(RGB444 * 2 或 RGB333 + RGB555)
第二行:32位 像素索引信息
第三行:8位 亮度索引信息
ETC1针对RGB24格式进行压缩,压缩后的结果是64位数据块的16个像素。
所以ETC1的压缩比为 6 : 1
因为ETC压缩在安卓上的良好兼容性和不错的效果,目前大多数安卓平台手游都采用了ETC压缩方案,但为了解决ETC1不支持Alpha的问题,我们可以采用两张纹理混合的方式来实现带Alpha通道的压缩。
ETC1和ETC2的差别:
ETC1要求长宽为2的次幂的贴图,它适用于所有安卓设备,压缩率比较高,但不适用于带Alpha通道的贴图。ETC2是ETC1的扩展,它要求长宽都能被4整除的贴图,且硬件要求OpenglES3.0和Opengl4.3以上,支持Alpha通道的压缩,但它的内存占用大于ETC1。
(5)ASTC
ASTC128位数据块中存储的信息:
11位:权重、高度信息,特殊块标识;
2位:Part数量
4位:16种插值端点模式(如LDR/HDR,RGB/RGBA)
111位:插值端点信息,纹素权重值,配置信息
详情参考:
ASTC纹理压缩格式详解 - 知乎 (zhihu.com)
(6)PVRTC
PVRTC旨在减少纹理数据的存储空间和带宽需求,从而提高性能和降低功耗。
PVRTC压缩算法包括两种版本:PVRTC1和PVRTC2。这里我们主要介绍PVRTC1的工作原理。
PVRTC1支持两种压缩比,4bpp(每像素4位)和 2bpp(每像素2位)。我们以4bpp为例:
压缩后的64位数据块中包含A,B两张图像,A和B都是在原本的基础上长和宽分别压缩了4倍后得到的低分辨率图像,A占了14位(RGB:554,RGBA:4433),B占了15位(RGB:555,RGBA:4443),同时对于16个像素,每个像素存储了2位调制数据(00,01,10,11),可以表示4个状态。同时还有一位的调制模式0/1,在不同调制模式下,4个状态可以得到不同的混合值,最终通过得到的混合值和A,B的颜色值可以得到最终的混合值,还有2位分别在A,B上表示不透明标值,用来判断是RGB存储还是RGBA存储,至于采用哪一个,会选用A和B中位数更高上面的不透明标值。
PVRTC2相较于PVRTC1有所改进,主要表现在颜色空间处理、边缘处理等方面,以获得更高的图像质量。总之,PVRTC通过将纹理划分为小块并利用颜色插值以及模拟像素技术,实现了较高的压缩比,从而降低了存储和带宽需求。这对于移动设备来说尤为重要,因为它们通常具有有限的硬件资源。
PVRTC1-4bpp的压缩率:对于RGB24,压缩率为24/4也就是 6 : 1。
对于RGBA32,压缩率为32/4也就是 8 : 1。
三、总结
1.画质比较
RGBA > ASTC 4×4 > ASTC 6×6 > ETC2 ≈ ETC1
2.压缩比
DXT1 6:1 DXT2/3 4:1
DXT4/5 4:1 ATI1 4:1
ATI2 4:1 BC6 6:1
BC7 3:1 PVRTC 6:1
ASTC 4:1~35.95:1
3.适配
英伟达和Unity官方对于不同类型贴图给出了不同的压缩方案建议,感兴趣的同学可以看下:
Using ASTC Texture Compression for Game Assets | NVIDIA Developer
Unity - Manual: Recommended, default, and supported texture compression formats, by platform (unity3d.com)
参考:
3600_纹理压缩_哔哩哔哩_bilibili
PPT:3600百人计划-纹理压缩 (qq.com)
相关文章:

[自学记录02|百人计划]纹理压缩
一、什么是纹理压缩 纹理压缩是为了解决内存、带宽问题,专为在计算机图形渲染系统中存储纹理而使用的图像压缩技术。 1.图片格式和纹理格式的区别 (1)图片格式 图片格式是图片文件的存储格式,通常在磁盘、内存中储存和传输文件时使用;例如…...

C++泛型编程之模板
目录 一、什么是泛型编程 二、函数模板 2.1函数模板的概念 2.2函数模板格式 2.3函数模板的原理 2.5函数模板的实例化 2.6模板参数的匹配原则 三、类模板 3.1类模板的定义格式 3.2 类模板的实例化 四、非类型模板参数 五、模板的特化 5.1模板特化的概念:…...

极氪汽车 APP 系统云原生架构转型实践
作者:极氪汽车 前言 新能源汽车已经成为我国汽车市场再次崛起的关键支柱,随着新能源汽车市场的快速发展,不同类型的品牌造车厂商呈现出百花齐放的态势。极氪汽车是吉利控股集团旗下高端纯电汽车新品牌,2021 年 4 月极氪发布首款…...

一个UDP下载服务器的实现(模拟下载文件)
本期分享的主要是使用UDP实现文件下载功能,需要自己编写服务器和客户端,实现的功能主要有以下几个: (1)服务器可以为请求的用户下发文件数据(前提是服务器得有这个数据文件) (2&…...

01.hadoop上课笔记之hadoop介绍
1.大数据介绍 可以对未来数据预测 google通过搜索预测流感,足球球员有一 定关联…caict可以得到数据hbase hive林子雨mooc数据要进行挖掘(推断更多信息) 2.大数据是非结构化数据多:声音,图片… 3.大数据影响因素 大多快低 tb pb eb zb 1.硬件 2.网络带宽 4.大数据的特征 数据量…...

小鹏汽车Q1财报:押注G6、大力降本,明年智驾BOM降半
作者 | 德新编辑 | 王博 小鹏汽车本周发了Q1财报,数据不好看,以致于在微博端也发了公开信。 那后续呢? 小鹏第二季度指引是,总交付数量约为2.1 - 2.2万辆,收入预计约为45 - 47亿元;四季度,…...

VMware ESXi 8.0U1a 发布 - 领先的裸机 Hypervisor
VMware ESXi 8.0U1a 发布 - 领先的裸机 Hypervisor 请访问原文链接:https://sysin.org/blog/vmware-esxi-8-u1/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org 2023-06-01, VMware vSphere 8.0U1a 发布。 详见&am…...

Unity的IPreprocessBuild:深入解析与实用案例
Unity IPreprocessBuild Unity IPreprocessBuild是Unity引擎中的一个非常有用的功能,它可以让开发者在构建项目时自动执行一些操作。这个功能可以帮助开发者提高工作效率,减少手动操作的时间和错误率。在本文中我们将介绍Unity IPreprocessBuild的使用方…...

htmlCSS-----CSS选择器(下)
目录 前言: 2.高级选择器 (1)子代选择器 (2)伪类选择器 (3)后代选择器 (4)兄弟选择器 相邻兄弟选择器 通用兄弟选择器 (5)并集选择器 &am…...

RDK X3 Module发布,全新软硬件平台加速实现量产级产品落地
机器人开发是一段美妙的旅程。GEEKROS创始人杨状状是地平线社区的一名开发者,热衷于鼓捣各类机器人,2022年,状状第一时间就拿到了地平线旭日X3派(简称旭日X3派),基于TogetheROS™.Bot机器人操作系统&#x…...

【面试实战】Redis缓存设计
文章目录 Redis缓存出现的问题🙎♂️面试官:什么是缓存雪崩?🙎♂️面试官:怎样解决缓存雪崩?🙎♂️面试官:什么是缓存击穿?🙎♂️面试官:怎样解决缓存击穿?🙎♂️面试官:什么是缓存穿透?🙎♂️面试官:怎样解决缓存穿透?🙎♂️面试官:…...

如何解决js定时器不准确问题
为什么会出现定时器不准确呢? 这个其实就得提到js执行机制了,叫做事件循环Eventloop 循环机制中,异步事件 setInterval 到时后会把回调函数放入消息队列中Event Queue,主线程的宏任务执行完毕后依次执行消息队列的微任务ÿ…...

学习笔记——vue中使用el-dropdown组件报错
今天在工作中,发现使用el-select做的下拉框,下拉菜单展开后,鼠标点击下拉框之外的区域时,下拉菜单没有收起。然后,我打开控制台,发现了这个错误。 Uncaught TypeError: Cannot read properties of null (re…...

Java之旅(八)
Java 条件运算符 Java 条件运算符用于根据一个条件表达式的布尔值来决定程序执行的流程。条件运算符有三种类型:if、else 和 switch。 if 语句的一般格式如下: if (condition) {// 条件为 true 执行的代码块 } 其中,condition 是一个 bool…...

华为OD机试真题(Java),四则运算(100%通过+复盘思路)
一、题目描述 输入一个表达式(用字符串表示),求这个表达式的值。 保证字符串中的有效字符包括[‘0’-‘9’],‘+’,‘-’, ‘*’,‘/’ ,‘(’, ‘)’,‘[’, ‘]’,‘{’ ,‘}’。且表达式一定合法。 数据范围:表达式计算结果和过程中满足∣val∣≤1000 ,字符串长度满…...

HTML表单标签form分析
说明:在html的标签中,表单标签与后台联系密切,像用户登录、注册,都是用到页面的表单标签,用户将信息填入到表单中,提交到后端业务中校验处理,再将结果反馈给前端页面。 表单内的标签分别有&…...

Qt 项目文件Pri详解
在Qt项目中,pri文件(.pri)是一种类似于makefile的文件,用于定义Qt项目中的编译规则。通常可以用pri文件来配置Qt库、头文件、源文件、链接库等信息,这样可以把这些信息定义在一个文件中,避免在每个工程中都进行重复配置࿰…...

Keil 5 MDK 发律师函警告了,如何用STCubeIDE开发标准库的程序(STM32F103C8T6为例)
用STCubeIDE进行标准库开发 1、CubeIDE介绍 https://www.stmcu.com.cn/ecosystem/Cube/STM32CubeIDE 2、CubeIDE下载 点击上面的链接,登录即可下载 3、搭建Demo工程 新建一个工作空间 创建一个工程 选择芯片-STM32F103C8T6 填写工程信息 添加标准库到工程 标…...

接口测试--apipost接口断言详解
在做接口测试的时候,会对接口进行断言,一个完整的接口测试,包括:请求->获取响应正文->断言。 一、apipost如何进行断言 apipost的断言设置实在后执行脚本中进行编写的。apipost本身提供了11中断言: apt.asser…...

YYDS练手 130道python练习题 完整版PDF
近年来,Python在编程语言界里赚足了风头,无论是受欢迎程度,还是薪资待遇,都非常可观,相应的,Python岗位要求也越来越高,无论你是零基础还是老前辈,在Python面试中都不能轻视。 不打…...

2-python的变量类型
内容提要 主要回顾了python中的变量类型,区分它们和c中的区别 python中的数字没有long python中的字符串不能被改变,也就是说不能对其内字符元素进行赋值操作 python中列表的数据类型与c访问方式有一定的区别列表的下标可以是负数,无论正负&…...

Python之并发编程一背景知识
一、开篇介绍 顾名思义,进程即正在执行的一个过程。进程是对正在运行程序的一个抽象。 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一。操作系统的其他所有内容都是围绕进程的概念展…...

Redis分区
分区 Redis是单线程的,如何提高多核CPU的利用率? 可以在同一个服务器部署多个Redis的实例,并把他们当作不同的服务器来使用,在某些时候,无论如何一个服务器是不够的, 所以,如果你想使用多个CPU&…...

代码随想录算法训练营第56天 | 583、72
583. 两个字符串的删除操作 题目描述 给定两个单词 word1 和 word2 ,返回使得 word1 和 word2 相同所需的最小步数。 每步 可以删除任意一个字符串中的一个字符。 示例1: 输入: w o r d 1 " s e a " , w o r d 2 " e a t …...

c++输入输出文件操作stream
系列文章目录 C IO库 文章目录 系列文章目录前言一、文件IO概述coutcin其他istream类方法 文件输入和输出内核格式化总结 前言 一、文件IO 概述 c程序把输入和输出看作字节流。输入时,程序从输入流中抽取字节:输出时,程序将字节流插入到输…...

【小呆的力学笔记】非线性有限元的初步认识【三】
文章目录 1.2.2 基于最小势能原理的线性有限元一般格式1.2.2.1 离散化1.2.2.2 位移插值1.2.2.3 单元应变1.2.2.4 单元应力1.2.2.5 单元刚度矩阵1.2.2.6 整体刚度矩阵1.2.2.7 处理约束1.2.2.8 求解节点载荷列阵1.2.2.9 求解位移列阵1.2.2.10 计算应力矩阵等 1.2.2 基于最小势能原…...

python计算闰年
这里说明一下:看到网上很多写python计算闰年的,有很多是不同。 有份省级期刊万年历计算公元1-10000年的闰年 算法如下:4000年停闰一次。区别其他算法,有些是3200年停闰一次。 def division(dividend, divisor) -> bool:"…...

聊聊如何使用Js写一个简单的二级联动和三级联动呢?
前言:咳咳哈,大佬说:"这不是有手就行了?"好吧,这里不做过多罗里吧嗦,真的不过多吹,我们在下面直接上代码上注释。 文章目录: 原Js二级联动实现原Js三级联动实现 一、二级…...

IPv4 和 IPv6 的特点、区别以及在互联网中的应用
在当今互联网时代,IP 地址是连接和通信的基础。IPv4(Internet Protocol version 4)和 IPv6(Internet Protocol version 6)是两种常见的 IP 地址版本。IPv4 是最早广泛使用的 IP 地址协议,而 IPv6 则是 IPv4…...

JavaScript处理移动web交互
touch对象和touchevent touch事件 touch对象 每一次发生touch事件时就会产生一个touch对象,类似事件处理函数中的事件对象。 <div class" "><button class"child" style"height: 400px; width: 400px">我是按钮</b…...