当前位置: 首页 > news >正文

Unity性能优化之纹理格式终极篇

知识早班车

1、当n大于1时,2的n次幂一定能被4整除;证明:2^n = 2^2*2^(n-1) = 4*2^(n-1)

2、4的倍数不一定都是2的次幂;证明:4*3 = 12;12不是2的次幂

3、Pixel(像素)是组成图片的最小单位;Byte(字节)是计算机文件大小的最小单位;bit(比特/位)是计算机处理运算的最小单位

4、常见的RGB 16位,ARGB/RGBA 16位,RGB 24位,ARGB/RGBA 32位等,它们通常的通道分配有:

RGB 16位 = RGB565 = RGB555(最高位不用)、ARGB/RGBA 16位 = ARGB4444 = RGBA4444 = ARGB1555 = RGBA5551

RGB 24位 = RGB888、ARGB/RGBA 24位 = ARGB/RGBA6666、RGB 32位 = RGB888(剩余8位保留)、ARGB/RGBA 32位 = ARGB/RGBA8888

知识始发站

我们在做资源优化时,必然少不了对纹理格式的处理。任何图片文件格式在导入Unity后,都会被转换为Textur2D格式,然后我们可以在Texture2D的导入设置选项中根据不同平台,设置纹理的压缩格式。

那么,为什么我们需要纹理压缩格式呢?

例如RGB565、ARGB4444、ARGB1555、RGB888、ARGB8888等未经压缩的图片格式,是能够被GPU直接读取的原生纹理格式。但在低端硬件设备或移动平台下,有两个问题需要解决:内存+带宽;

1、例如ARGB8888格式中一个像素占4Byte,如果是512x512分辨率内存占用为:512x512x4B=1048576B=1M,这种内存消耗在低端设备上根本无法接受。

2、另一个重要的是数据传输时的带宽,带宽是发热的元凶,在渲染3D场景时,会有大量的贴图被传输到GPU,若不限制,总线带宽很快就会成为瓶颈,手机秒变暖手宝,严重的还会影响渲染性能。

因此我们需要一种内存占用既小又能被GPU读取的格式——压缩纹理格式。纹理压缩对应的算法是以某种形式的固定速率有损向量量化将固定大小的像素块编码进固定大小的字节块中。

有损:表示对于渲染来说,有损压缩是可以接受的,一般选择压缩格式时需要在纹理质量和文件大小上寻求一个平衡。

固定速率压缩:因为GPU需要能够高效的随机访问一个像素,这意味着对任意像素,解码速度不该有太大的变化。因此,我们常见的贴图压缩算法都是有损压缩。相反例如zip则是一种可变速率压缩。

向量量化:一种量化技术,将一组大量的点(向量)分成具有近似相同数量的最接近它们的点的组。每个组用它的质心点表示,因此存在数据误差,适用于有损压缩。放到纹理压缩中来理解,就例如将4x4块像素的颜色以2个基色来表示。

编码和解码速度:一般来说编码速度慢没关系,因为通常纹理压缩只需要在游戏打包时进行一次,对于用户运行时体验完全没有影响。但解码速度必须足够快,而且基本上不影响渲染性能。

压缩比:通常以比特率或每像素的平均比特数(bits per pixel, bpp)表示,常见的为1~8bpp。一般RGB原生纹理的像素指24位,即每个像素占24位(bit),现有4bpp表示每个像素占4位(bit),那么可认为4bpp表示压缩比例为6:1.

另Unity对导入的资源图片,不管是PNG格式还是JPG格式,统统都会转换为Unity引擎当中处理的Texture2D格式,

为什么我们不使用png,jpg这类常见的压缩格式?

尽管jpg、png的压缩率很高,但并不适合纹理,主要问题是不支持像素的随机访问,这对GPU相当不友好,GPU渲染时只使用需要的纹理部分,我们总不能为了访问某个像素去解码整张纹理吧?不知道顺序,也不确定相邻的三角形是否在纹理上采样也相邻,很难有优化。这类格式更适合下载传输以及减少磁盘空间而使用。

常见的纹理压缩格式

1、ETC

ETC主要是android的标准压缩方案,其原理简单来说是将4x4的像素块编码为2x4或4x2像素的两个块的方法,每个块指定一个基色,每个像素的颜色通过一个编码为相对这些基色偏移的灰度值确定。

Unity中常用的ETC压缩格式有:

  • RGB ETC1 4bit:4bit/pixel,对RGB压缩比为6:1,不支持alpha,绝大多数android设备都支持

  • RGB ETC2 4 bit:4 bits/pixel,对RGB压缩比6:1。不支持Alpha,ETC2兼容ETC1,压缩质量可能更高,但对于色度变化大的块误差也更大,需要在OpenGL ES 3.0和OpenGL 4.3以上版本。

  • RGBA ETC2 8bit:8 bits/pixel,对RGBA压缩比4:1。支持完全的透明通道,版本要求同上。

  • RGB +1bit Alpha ETC2 4bit:4 bits/pixel。支持1bit的Alpha通道,也就是只支持镂空图,图片只有透明和不透明部分,没有中间的透明度。

2、DXT 原名S3TC(S3 Texture Compression )

其原理简单来说,是由一对低精度的“基色”来描述一个4x4的RGB像素块,并允许每个像素在这些基色之间指定一个插值。S3TC有多种变体,每种都是为特定类型的图像数据设计,但它们都是将4x4的像素块转换为64位或128位的数据

3、ASTC

ASTC是android和ios平台下的一种高质量压缩方式,支持android5.0和iphone6以上的机型。它也是一种基于块的有损压缩算法,它的块是固定大小为128位,虽然是固定大小,但是与先前格式的固定4x4块不同,每个纹理在这128位中可以有不同大小的块,可以是方形和非方形,2D纹理编码中,它从4x4到12x12像素都有,对应的压缩比1~8bpp。它的特点有很多:

  • 较高的灵活性:支持1-4分量的贴图

  • 压缩率/质量灵活可变:根据不同图片会选择不同压缩率级别的算法

  • 支持2D/3D贴图

  • 跨平台:iOS、安卓、PC

  • 同时支持LDR和HDR:BC6H虽然支持HDR但不支持Alpha通道

块越大,压缩质量越差,但是图片越小。ASTC的比特率可以在小数级变化,这种技术称为BISE(Bounded Integer Sequence Encoding)。

但要注意的是尽管纹理可以被编码为1-4通道图像,但是解码后的值总是以RGBA格式输出。在LDR sRGB模式下,颜色值以8位整数的形式返回,而如果是HDR则将以16位浮点数的形式返回。

在设置ASTC格式时,还需注意一下几点:

  • 法线贴图:尽量选择4x4,避免丢失过多数据。

  • 细节处的贴图:选择4x4或6x6,否则会丢失细节。

  • 一般贴图:选择6x6或8x8。4、无关紧要但尺寸特别大的图:可考虑8x8或10x10或12x12,不然打包出来太大。

通过以上三种压缩格式我们发现,三种压缩算法中都用到了4x4的像素块做运算,这让我们不禁想到了,我们在做图片优化时,经常要求美术同学在输出图片尺寸时,保持长宽为4的倍数的原因了,这样我们在对导入Unity的图片进行压缩格式设置的时候才会起到更好的效果。不过,可能还会有同学提出疑问,为什么有时候会听到把图片尺寸设置成2的次幂呢?这是因为最初的ETC压缩算法不支持透明通道,图片宽高要求必须是2的次幂,还有就是ios平台下的PVRTC压缩格式也是仅支持2的次幂,再加上当n>1时,2^n一定为4的倍数,所以就有要求图片输出尺寸为2的次幂的要求;好在现在andorid平台大多都支持ETC1/ETC2,ETC2是ETC的扩展,支持透明通道,且图片宽高只要是4的倍数即可;PC平台也都支持DXT1/DXT5/DXT5,DXT3和DXT5原理同DXT1一样,只不过DXT3和DXT5支持透明通道,也要求图片宽高只要是4的倍数即可;ASTC格式也被越来越多的平台所支持,所以我们在设置图片尺寸时,只需要设置为4的倍数即可。还有就是Generate Mip Maps如果是开启状态下,只有2的次幂才能被压缩,因为生成mipmap必须是2的次幂的像素。

知识小贴士:

1、对于图片,现在有sprite atlas来对图片进行管理,凡是要打进图集的图片,尺寸可以不必遵循4的倍数设置,因为这些图最终是打进图集的,我们可以对图集进行4的倍数的设置,不过这样做的一个缺点就是图集为了保持设置的4的倍数的尺寸,不得不浪费一些空间,所以最好的方式还是将所有图片都设置成4的倍数;不进图集的图片的尺寸就要严格控制了,最好为4的倍数,且最大尺寸不要超过1024x1024。

2、关闭Read/Write 选项,因为开启此选项将会允许从脚本来访问纹理数据,将会产生纹理数据的副本, 副本会占用内存, 等同于一个纹理数据会有双倍的内存消耗。

3、Filter Mode设为Bilinear的纹理:Trilinear 三线性过滤(三线性插值), 纹理会在不同的 mip 水平之间进行模糊 ,从而增加 GPU 开销。

4、Sprite纹理关闭Mipmap:Mipmap 开启后,内存会是未开启 Mipmap 的 1.33 倍, 因为 Mipmap 会生成一组长宽依次减少一倍的纹理序列, 一直生成到 1*1。Mipmap 提升 GPU 效率; 一般用于 3D 场景或角色, UI 不建议开启。

5、Wrap 模式设置为 Clamp:Wrapmode 使用了 Repeat 模式, 容易导致贴图边缘出现杂色

以PC平台为例:

如果导入的图片长宽尺寸为4的倍数也为2的次幂,则会被压缩为RGB Compressed DXT1 或者RGBA Compressed DXT5;

如果导入的图片长宽为4的倍数但不为2的次幂,则会被压缩为(NPOT)RGB Compressed DXT1 或者(NPOT)RGBA Compressed DXT5;

如果导入的图片长宽不为4的倍数也不为2的次幂,则会被压缩为(NPOT) RGB24/(NPOT) RGBA32,这些都为未压缩格式,非常占用内存

相关文章:

Unity性能优化之纹理格式终极篇

知识早班车:1、当n大于1时,2的n次幂一定能被4整除;证明:2^n 2^2*2^(n-1) 4*2^(n-1)2、4的倍数不一定都是2的次幂;证明:4*3 12;12不是2的次幂3、Pixel(像素)是组成图片…...

【Spark分布式内存计算框架——Spark SQL】9. Dataset(下)RDD、DF与DS转换与面试题

5.3 RDD、DF与DS转换 实际项目开发中,常常需要对RDD、DataFrame及Dataset之间相互转换,其中要点就是Schema约束结构信息。 1)、RDD转换DataFrame或者Dataset 转换DataFrame时,定义Schema信息,两种方式转换为Dataset时…...

Windows 环境下,cmake工程导入OpenCV库

目录 1、下载 OpenCV 库 2、配置环境变量 3、CmakeLists.txt 配置 1、下载 OpenCV 库 OpenCV官方下载地址:download | OpenCV 4.6.0 下载完毕后解压,便可以得到下面的文件 2、配置环境变量 我们需要添加两个环境变量,一个是 OpenCVConfi…...

微服务架构设计模式-(16)重构

绞杀者应用程序 由微服务组成的应用程序,将新功能作为服务,并逐步从单体应用中提取服务来实现。好处 尽早并频繁的体现价值 快速开发交付,使用 与之相对的是“一步到位”重构,这时间长,且期间有新的功能加入&#xff…...

数据结构:归并排序和堆排序

归并排序 归并排序(merge sort)是利用“归并”操作的一种排序方法。从有序表的讨论中得知,将两个有序表“归并”为一个有序表,无论是顺序表还是链表,归并操作都可以在线性时间复杂度内实现。归并排序的基本操作是将两个位置相邻的有序记录子序列R[i…m]R[m1…n]归并为一个有序…...

基于easyexcel的MySQL百万级别数据的excel导出功能

前言最近我做过一个MySQL百万级别数据的excel导出功能,已经正常上线使用了。这个功能挺有意思的,里面需要注意的细节还真不少,现在拿出来跟大家分享一下,希望对你会有所帮助。原始需求:用户在UI界面上点击全部导出按钮…...

js-DOM02

1.DOM查询 - 通过具体的元素节点来查询 - 元素.getElementsByTagName() - 通过标签名查询当前元素的指定后代元素 - 元素.childNodes - 获取当前元素的所有子节点 - 会获取到空白的文本子节点 …...

作为一名开发工程师,我对 ChatGPT 的一些看法

ChatGPT 又又火了。 ChatGPT 第一次爆火是2022年12月的时候,我从一些球友的讨论中知道了这个 AI 程序。 今年2月,ChatGPT 的热火更加猛烈,这时我才意识到,原来上次的热火只是我们互联网圈子内部火了,这次是真真正正的破圈了,为大众所熟悉了。 这个 AI 程序是一个智能问…...

Flask中基于Token的身份认证

Flask提供了多种身份认证方式,其中基于Token的身份认证是其中一种常用方式。基于Token的身份认证通常是在用户登录之后,为用户生成一个Token,然后在每次请求时用户将该Token作为请求头部中的一个参数进行传递,服务器端在接收到请求…...

波奇学数据结构:时间复杂度和空间复杂度

数据结构:计算机存储,组织数据方式。数据之间存在多种特定关系。时间复杂度:程序基本操作(循环等)执行的次数大O渐进法表示法用最高阶的项来表示,且常数变为1。F(n)3*n^22n1//F(n)为…...

移动OA办公系统为企业带来便捷办公

移动OA系统是指企业员工同手机等移动设备来使用OA办公系统,在外出差的员工只需要通过OA系统的手机APP就可以接收相关的新信息。PC办公与移动OA办公的相结合,构建用户单位随时随地办公的一体化环境。 相比PC办公,移动OA办公给企业带来更多的便…...

什么是Type-c口?Type-c口有什么优势?

什么是Type-C接口 Type-C接口有哪些好处坏处 说起“Type-C”,相信大家都不会陌生,因为最近拿它大做文章的厂商着实不少,但要具体说清楚Type-C是什么,估计不少人只能说出“可以正反插”“USB的一种”之类的大概。其实,T…...

Go开发者常犯的错误,及使用技巧 (1)

代码规范 命名不规范 变量名要有意义,不能随便取a,b,c 如果只是纯粹的算法题,这样问题不大。但工程上的代码可读性要求较高,不能随意命名变量名,例如: for _, v : range userList {// ... }如果for语句块简短还好&…...

Servlet 作业

一、填空题1. Servlet 中使用Session 对象的步骤为:调用HttpServletRequest.getSession()的得到Session对象,查看Session对象,在会话中保存数据。2. http 全称是_HyperText Transfer Protocol3. 用户可以有多种方式请求Servlet,如…...

Hive高阶函数:explode函数、Lateral View侧视图、聚合函数、增强聚合

Hive高阶函数 文章目录Hive高阶函数explode函数Lateral View侧视图原理语法聚合函数增强聚合grouping setsCUBEROLL UPexplode函数 explode接收map、array类型的数据作为输入,然后把输入数据中的每个元素拆开变成一行数据,一个元素一行。explode执行效果…...

信息系统服务管理

一、信息系统服务业及发展二、信息系统工程监理的概念及发展三、信息系统运行维护的概念和发展 IT服务管理(ITSM) 四、信息技术服务管理的标准和框架 IT服务标准体系(ITSS) 一、信息系统服务业及发展 总结:前景很好 二、信息系…...

Windows10 安装ElasticStack8.6.1

一、安装ElasticSearch8.6.1 1.官网下载ElasticSearch8.6.1压缩包后解压 2.安装为服务 elasticsearch-service.bat install 3.运行 elasticsearch-service.bat start 4.通过浏览器访问 http://localhost:9200/ 提示需要登录,但不知密码是啥。 5.重置密码 ela…...

gRPC 非官方教程

一、 简介 gRPC的定义: 一个高性能、通用的开源RPC框架主要面向移动应用开发: gRPC提供了一种简单的方法来精确地定义服务和为iOS、Android和后台支持服务自动生成可靠性很强的客户端功能库。基于HTTP/2协议标准而设计,基于ProtoBuf(Protoc…...

6.2【人工智能与深度学习】RNN、GRU、远程服务管理、注意力、Seq2 搜索引擎和内存网络

【人工智能与深度学习】RNN、GRU、远程服务管理、注意力、Seq2 搜索引擎和内存网络底层原理介绍 深度学习架构循环神经网络(RNN)循环网络:摊开循环的网络的循环循环神经网络的技巧乘法模组注意模组门控循环单元(GRU)长期短期记忆(Long Short-Term Memory,简称LSTM)序列到序列…...

软件工程复习

软件工程简介 软件: -在执行时提供所需的功能和性能的指令; -使程序能够充分操作信息的数据结构; -描述这些程序的操作和使用情况的文档。 软件定义:计算机程序和相关文档。 软件特点:软件没有质量;它并不…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...