跳到主要内容
腾讯题库 · Q40

原题 Q40 · 当前收录 39 / 49

学习状态 未开始

纹理压缩格式

工具与管线 compression · mobile 对应课程:性能与移动管线

面试官问

PDF 第 85 页

请解释“纹理压缩格式”(ETC2、ASTC、DXT)在 Android 与 iOS 平台的选型原则。(常问题,理清逻辑)

学习进度

0/9 已勾

只保存在这台浏览器;勾满 9 项即视为本题完成。

先把题目说成人话

一张角色脸贴图要塞进手机:装得太松会占满内存,压得太狠又会在脸颊和文字边缘出现方块。把图片按固定小块打包的方法叫纹理压缩(Texture Compression)。选择前要先问设备能否直接读取这种盒子、图里有没有透明、玩家会从多近看它,再决定每块保留多少信息;格式名只是起点,设备支持、块大小和贴图用途才决定结果。

这是虚构教学故事,不是个人项目经历。

场景:先让问题变得看得见

项目要同时发布到两类手机。角色脸、地表、表面方向图、界面和带透明的特效图原本套用同一打包规则:新设备能直接显示,旧测试机却要先把图片撑成更大的临时形式,内存突然上涨;表面方向图还被当成普通颜色变亮,导致光照方向出错。

问题不是找一个“全平台最好”的名字,而是看每种图片要保什么、每台最低设备能原生读什么,以及不支持时会怎样回退。固定大小的压缩盒只是把这三件事连起来的中间层。

(右脑)画面: 同一张脸被印在两张方格纸上。一张纸的格子很细,眼睫、皮肤的缓慢明暗和嘴角都还在;另一张纸把许多小格并成大格,拿起来轻了不少,贴近看时,眼睫先断掉,脸颊的渐变也变成一块一块。远看两张纸也许差不多,镜头推近后,它们丢掉的东西才逐渐露出来。

(左脑)对表: 先把固定盒子对应到块压缩格式,再把“一个盒子覆盖多少方格”对应到块宽和块高。自适应可伸缩纹理压缩(ASTC)的每块固定为 128 bit:覆盖 8×8 个纹素时,128÷64=2 bit/texel;改成 4×4 时,128÷16=8 bit/texel。因此相同尺寸和 mip 链下,从 ASTC 8×8 改为 4×4,纹理数据约变为 4 倍。随后再按设备原生格式、颜色或线性数据、透明通道、mip 与目标观看距离选候选;构建日志、SystemInfo、内存分析和真机画面分别验证实际格式、回退、驻留容量和块伪影,源 PNG 大小不能代替这些证据。

小明:先形成一个完整猜测

小明据此提出统一方案:“Android 用 ETC2,iOS 用 ASTC,最高画质全上 ASTC 4×4。”这个猜测有清楚的方向:平台分开、画质用块大小控制。

但它还没有检查最低系统与 GPU 支持、贴图用途和 alpha。ETC2 是 OpenGL ES 3.0 级别的常见基础能力,不是所有历史 Android 设备的共同底线;ASTC 也要以项目实际支持的 Apple 芯片与 Android GPU 矩阵为准。设备不支持构建内格式时,Unity 可能在运行时解压成更大的格式,容量和加载表现会完全改变。

小红:把猜测放回现实检查

小红把对象、单位和边界逐项核对。她先用项目最低设备清单和 SystemInfo.SupportsTextureFormat 验证格式支持,再按贴图内容建立对照:

  • 角色脸和 UI 有细线、渐变或文字,先比较 ASTC 4×4、6×6 的块伪影,不默认最小块。
  • 大面积地表允许更粗块,可比较 6×6 或 8×8;是否合格由目标距离和 mip 画面决定。
  • 法线、Mask 等数据贴图关闭 sRGB,并在对应平台格式下检查通道误差。
  • Alpha 是否存在会改变 ETC2、BC/DXT 的具体格式与 bit rate,不能只写一个家族名。

她还把 DXT 放回正确位置:DXT1/5 即 BC1/3,常见于桌面平台;Unity 的 iOS 目标不把它作为支持格式,Android 也只有特定硬件/构建目标可能使用,不能作为 Android、iOS 的统一原生基线。

我:用检查结果修正模型

我把选择改为“平台能力 × 贴图用途 × 质量档”的表,而不是两条口号。现代且确认支持 ASTC 的设备使用 ASTC,并按资产敏感度选块;以 GLES3 为最低线的 Android 包可以使用 ETC2;还要覆盖更老设备时,准备项目允许的 ETC1/独立 alpha、较低质量资产或单独分发包。iOS 同样以最低目标设备实测,不把“iOS”三个字当成 ASTC 保证;若项目仍覆盖不支持 ASTC 的历史 Apple 设备,还要验证 Unity 对应版本的 PVRTC 构建路径或拆分内容包,而不是指望运行时自动补救。

回退也在构建前设计:按设备族打不同纹理目标或内容包,启动时选择已验证的格式;若只能依赖 Unity 的运行时 fallback,就把解压后的内存、加载时间和画质纳入预算。最终检查的是目标设备上的 Resident Memory、加载与画面,不是 Texture Importer 里显示的一个压缩名称。

(右脑)画面修正: 小明按手机系统给所有图片换上同一种盒子,直到一台旧手机打不开盒子,只能把内容全部倒进更大的托盘,内存反而涨了。小红把角色脸、普通地面、带透明边缘的叶片和记录表面方向的图片分开比较,又在真正要运行的设备上逐张打开。这样选出来的盒子不再只是名字看起来先进,而是那台机器确实能直接读取,而且重要的细节没有先被压坏。

(左脑)严格对表: 对每个设备族先列原生支持格式和最低系统,再对每类资产标注颜色/数据、alpha、分辨率、mip 与质量阈值;用 128/(blockWidth×blockHeight) 计算 ASTC bpp,并按整块和 mip 估算容量;制作候选构建,在真机核对实际格式、驻留内存、加载时间和块伪影;不支持时选择预先构建的替代内容,不静默依赖解压。只有所有最低设备均无意外 fallback、数据贴图保持线性解释且容量与画质同时过门禁,格式表才可发布。

老师解惑

  • ASTC 的 bit rate 为 128÷(块宽×块高)。所以 4×4 是 8 bpp,8×8 是 2 bpp。
  • ETC2 RGB 与带完整 Alpha 的 ETC2 RGBA 不是同一容量;BC1 与 BC3 也不能只用“DXT”概括。
  • 完整 mip 链通常在基础层之上增加约三分之一数据,块边界和极小 mip 会产生少量偏差。
  • 颜色贴图通常按 sRGB 解码;法线、粗糙度和 Mask 是数据,应按线性数据解释。

工具分工

  • Unity Texture Importer 平台覆盖:为 Android、iOS 分别设置格式、质量和最大尺寸。
  • SystemInfo 与设备清单:验证运行设备是否原生支持首选格式。
  • Memory Profiler 与真机画面对照:检查 fallback 后的实际驻留内存、块伪影和加载成本。
  • texture-compression Lab:观察块大小、bit rate、alpha 与画质之间的关系。

记忆钩子

先问设备能不能原生读,再按贴图用途选块;ASTC 8×8 换 4×4,清晰度提高,数据约变四倍。

这是教学场景,不是目标项目的真实捕获或个人经历。

下一步:验证这条因果

贴图用途、颜色空间、块预算与目标设备能力怎样共同决定格式和 fallback。

教学边界:结构图不编码真实纹理;最终格式、画质、显存与运行时回退必须用 Unity 构建和目标真机确认。

进入教学 Lab:「Unity 纹理格式:先看用途和设备,再谈压缩」