SuperAPI AI 工具集

texture-packing-variant-stripping

编程与开发

查看项目

更新于 10-15 08:24

技能介绍

用途 该技能用于 Unity 项目中的纹理与着色器优化,主要面向移动端与 WebGL 场景,解决纹理采样过多、显存带宽占用高、着色器变体数量膨胀、构建体积过大和着色器编译缓慢等问题。当用户涉及通道打包、纹理打包、mask map、MODS map、RMA、着色器变体、变体剥离、multi_compile、shader_feature、构建体积、着色器关键字、Always Included Shaders、IPreprocessShaders,或抱怨着色器编译慢、构建体积大时,可触发使用。

纹理通道打包 通道打包把多张灰度图存入单张 RGBA 纹理,可同时减少纹理采样次数和内存带宽——而内存带宽正是移动端的主要瓶颈。 标准 URP 打包约定(Mask Map,单张 RGBA):R=金属度(Metallic),G=环境光遮蔽(Occlusion/AO),B=细节遮罩(Detail mask,或自定义),A=平滑度(Smoothness)。 最佳实践:把视觉上最重要的遮罩放在绿色通道,因为人眼对绿色最敏感,且多数纹理压缩格式(ETC2、ASTC、DXT)会给绿色分配更多比特;把总是一起采样的数据打包到同一纹理,例如金属度与平滑度常同时采样;打包遮罩纹理使用线性色彩空间而非 sRGB,在 Unity 中应取消非颜色数据(粗糙度、AO、金属度、高度)的 sRGB 导入勾选。 一次纹理采样可替代四次:原做法需分别对 _MetallicMap、_AOMap、_DetailMask、_SmoothnessMap 采样并取 .r 分量;优化后用一次 SAMPLE_TEXTURE2D 采样 _MaskMap 得到 half4,再按 .r/.g/.b/.a 取出金属度、AO、细节遮罩与平滑度。 进阶:地形打包。Unity Shader Graph 17.4 的地形示例展示了将 4 层地形的 12 次纹理采样减少至 5 次的打包方式,包括 CNS 打包(Color 的 RGB + Normal 的 RG 并在 B 重建 + Smoothness)以及 CHNOSArray 纹理数组(打包 Color、Height、Normal、Occlusion、Smoothness)。 HLSL 提供了通道打包辅助函数 PackChannels,把四个灰度值合入 half4;以及 UnpackNormalRG,从 XY 重建法线 Z:n.xy = normalRG * 2.0h - 1.0h,n.z = sqrt(1.0h - saturate(dot(n.xy, n.xy)))。

着色器变体管理 变体爆炸问题:每个 multi_compile 关键字会以乘法方式使变体数量翻倍。例如 #pragma multi_compile _ _A 产生 2 个变体;#pragma multi_compile _ _A _B 产生 3 个;两个各自二选一的关键字组合为 2×2=4 个;三个则组合为 2×2×2=8 个。叠加 URP 内置关键字(阴影、雾、附加光源等)后,单个着色器可生成上千个变体。 影响:构建时间可达 20 分钟以上(复杂着色器);着色器数据体积可达 100MB 以上(对 WebGL 尤为关键);运行时因变体切换带来 20%–40% 的额外绘制调用内存开销;WebGL 上着色器编译阻塞主线程,变体越多卡顿越久。 shader_feature 与 multi_compile 的差异:shader_feature 只编译构建中材质实际用到的变体,用于材质级开关,未用变体会被自动剥离;multi_compile 编译全部组合,用于全局状态(雾、阴影),无论是否使用都会包含。两者的本地版本分别为 shader_feature_local(上限 64)与 multi_compile_local(上限 64),全局版本分别为 shader_feature(上限 256)与 multi_compile(上限 256)。原则是:凡是自己可控的(材质开关、功能标志)都用 shader_feature;只有 Unity 全局控制的(雾、光照贴图、实例化)才用 multi_compile。 推荐的 URP 关键字剥离:在 IPreprocessShaders 实现中,若不使用相应功能,可剥离这些关键字——_ADDITIONAL_LIGHTS(只用主光时)、_ADDITIONAL_LIGHT_SHADOWS(无附加光阴影时)、_SHADOWS_SOFT(只用硬阴影时)、_MIXED_LIGHTING_SUBTRACTIVE(不用混合光照时)、_SCREEN_SPACE_OCCLUSION(不用 SSAO 时)、LIGHTMAP_SHADOW_MIXING(不混合光照贴图与实时光时)、_LIGHT_LAYERS(不用光照层时)、_REFLECTION_PROBE_BLENDING(不混合反射探针时)、_REFLECTION_PROBE_BOX_PROJECTION(不用盒投影时)。 URP Asset 特性剥离:在 URP Asset 设置中关闭未用特性以避免其变体被编译——Additional Lights 设为 Off(仅用方向光时)、Shadows 减少级联数量并关闭软阴影、未使用则关闭 Post-Processing、不需要则关闭 HDR、使用烘焙反射则关闭 Environment Reflections。 平台条件编译:通过 SHADER_API_MOBILE、SHADER_API_GLES、SHADER_API_GLES3 等宏区分,在移动端/WebGL 走简化路径,桌面端走完整特性路径;示例中 frag 函数在非移动端才叠加法线与光照采样。

移动/Web 纹理压缩 格式对照:ASTC 4×4 适用于 Android(ES 3.0+)与 iOS,8 比特/像素,质量最佳,是所有移动端的首选;ASTC 6×6 同为 Android(ES 3.0+)与 iOS,3.56 比特/像素,质量良好,用于次要纹理;ASTC 8×8 同为 Android(ES 3.0+)与 iOS,2 比特/像素,质量可接受,用于背景/远景纹理;ETC2 适用于 Android(ES 3.0+)与 WebGL 2.0,4–8 比特/像素,质量良好,是 WebGL 2.0 默认;ETC1 适用于 Android(ES 2.0),4 比特/像素,质量一般,不支持 alpha 通道;PVRTC 适用于较老 iOS,2–4 比特/像素,质量不定,属遗留方案,优先用 ASTC。对通道打包纹理,应使用 ASTC 4×4 或 ETC2 并配合线性色彩空间;避免用 PVRTC 处理遮罩图,其块压缩会在锐利遮罩边界产生可见瑕疵。

优化检查清单 所有灰度图已打包进共享纹理的 RGBA 通道;打包纹理按 Linear(非 sRGB)导入;最重要的遮罩数据放在绿色通道;材质开关用 shader_feature 而非 multi_compile;尽量使用本地关键字(shader_feature_local);在 URP Asset 中关闭未用的 URP 特性;清理 Always Included Shaders 列表(Project Settings > Graphics);为未用关键字添加 IPreprocessShaders 剥离脚本;检查构建日志中的变体数量(查找 “Compiled N shader variants”);所有移动端纹理使用 ASTC 或 ETC2 压缩;从项目中移除 Standard Shader(改用 Simple Lit 或自定义着色器)。