ASTC(Adaptive Scalable Texture Compression)是Arm与AMD合作开发的新一代纹理压缩标准,已被Khronos Group采纳为开放标准。与传统压缩方案相比,其革命性突破在于采用128位固定大小的压缩块(无论块尺寸如何),通过智能分配比特率实现动态质量调节。
ASTC采用基于块的预测编码方案,每个4x4到12x12的像素块被压缩为128位数据包。关键技术包括:
典型压缩流程:
实测发现:4x4块适合高细节纹理(如金属表面),而8x8块更适合平滑渐变(如天空盒)
ASTC提供从4x4到12x12共10种块尺寸选择(桌面端还支持3D块如4x4x4)。不同尺寸的典型应用场景:
| 块尺寸 | 比特率(bpp) | 适用场景 | 内存节省vs RGBA8 |
|---|---|---|---|
| 4x4 | 8.00 | 法线贴图/高细节漫反射 | 75% |
| 6x6 | 3.56 | 移动端角色纹理 | 89% |
| 8x8 | 2.00 | UI背景/天空盒 | 94% |
| 12x12 | 0.89 | 远景贴图/遮罩 | 97% |
在Unity项目中实测数据:
移动端支持通过不同扩展组合实现功能分级:
mermaid复制graph TD
A[OpenGL ES 3.2核心] -->|强制支持| B[2D LDR]
B --> C[KHR_texture_compression_astc_ldr]
C --> D[KHR_texture_compression_astc_sliced_3d]
D --> E[KHR_texture_compression_astc_hdr]
E --> F[OES_texture_compression_astc]
关键扩展功能对比:
| 扩展名 | 2D | 切片3D | 体积3D | LDR | HDR |
|---|---|---|---|---|---|
| GLES3.2 Core | ✓ | ✗ | ✗ | ✓ | ✗ |
| KHR_texture_compression_astc_ldr | ✓ | ✗ | ✗ | ✓ | ✗ |
| KHR_texture_compression_astc_sliced_3d | ✓ | ✓ | ✗ | ✓ | ✗ |
| KHR_texture_compression_astc_hdr | ✓ | ✓ | ✗ | ✓ | ✓ |
| OES_texture_compression_astc | ✓ | ✓ | ✓ | ✓ | ✓ |
Vulkan 1.0+通过物理设备特性检测支持情况:
cpp复制VkPhysicalDeviceFeatures features;
vkGetPhysicalDeviceFeatures(device, &features);
if (features.textureCompressionASTC_LDR) {
// 基础LDR支持
}
VkPhysicalDeviceASTCDecodeModeFeaturesEXT decodeFeatures{};
decodeFeatures.pNext = nullptr;
if (vkGetPhysicalDeviceFeatures2) {
VkPhysicalDeviceFeatures2 features2{};
features2.pNext = &decodeFeatures;
vkGetPhysicalDeviceFeatures2(device, &features2);
if (decodeFeatures.decodeModeSharedExponent) {
// 支持RGB9e5解码模式
}
}
注意:Android 10+设备必须支持ASTC LDR,但HDR需要检查VK_EXT_texture_compression_astc_hdr
Android平台推荐设置组合:
csharp复制// 在Editor脚本中批量设置纹理参数
TextureImporterPlatformSettings androidSettings = new TextureImporterPlatformSettings();
androidSettings.overridden = true;
androidSettings.name = "Android";
androidSettings.format = TextureImporterFormat.ASTC_6x6;
androidSettings.textureCompression = TextureImporterCompression.Compressed;
// 法线贴图特殊处理
if (importer.textureType == TextureImporterType.NormalMap) {
androidSettings.format = TextureImporterFormat.ASTC_4x4;
importer.convertToNormalmap = true;
importer.normalmapFilter = TextureImporterNormalFilter.Standard;
}
iOS平台需注意:
通过Texture Streaming减少内存占用:
csharp复制QualitySettings.masterTextureLimit = 1; // 降低默认mip级别
QualitySettings.streamingMipmapsMemoryBudget = 256; // MB
csharp复制Texture2D.LoadImageIntoMemoryAsync(path).completed += (op) => {
op.result.Compress(ASTC_6x6);
};
实测数据对比(场景包含200张2048x2048纹理):
| 方案 | 内存占用 | 加载时间 | 帧率 |
|---|---|---|---|
| 未压缩 | 3.2GB | 12.7s | 24fps |
| ASTC 6x6 | 356MB | 4.2s | 58fps |
| ASTC+Streaming | 128MB | 1.8s | 60fps |
在DefaultEngine.ini中配置格式优先级:
ini复制[Android]
TextureFormatPriority=ASTC_4x4,ASTC_6x6,ETC2
[Android_ETC1A]
TextureFormatPriority=ETC1A
通过Runtime Texture Switching实现动态适配:
cpp复制// 在GameInstance初始化时检测设备能力
FTextureFormatSettings Settings;
if (FAndroidMisc::SupportsASTC()) {
Settings.Format = TEXF_ASTC4x4;
} else if (FAndroidMisc::SupportsETC2()) {
Settings.Format = TEXF_ETC2;
} else {
Settings.Format = TEXF_ETC1;
}
UTexture* Texture = LoadObject<UTexture>(nullptr, TEXT("/Game/Textures/Character"));
Texture->SetTextureFormat(Settings);
hlsl复制void ApplyASTCOptimization(
Texture2D ColorTex,
float2 UV,
out float3 Color
) {
// ASTC解码后可能需要gamma校正
Color = pow(ColorTex.Sample(Sampler, UV).rgb, 2.2);
// 法线贴图特殊处理
#if NORMAL_MAP
Color = Color * 2.0 - 1.0; // 从[0,1]转到[-1,1]
#endif
}
bash复制astcenc -cl example.png example.astc 6x6 -fast -thorough 4
code复制android.enableTextureCompressionFormatCheck=true
python复制# 使用Python脚本预处理纹理
import cv2
img = cv2.imread("input.png")
kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
sharpened = cv2.filter2D(img, -1, kernel)
cv2.imwrite("preprocessed.png", sharpened)
csharp复制TextureImporter importer = ...;
var analyzer = new TextureAnalyzer(importer);
if (analyzer.DetailScore > 0.7f) {
importer.SetPlatformFormat("Android", TextureImporterFormat.ASTC_4x4);
} else if (analyzer.GradientScore > 0.5f) {
importer.SetPlatformFormat("Android", TextureImporterFormat.ASTC_6x6);
} else {
importer.SetPlatformFormat("Android", TextureImporterFormat.ASTC_8x8);
}
ACES颜色空间下的ASTC HDR配置:
csharp复制PlayerSettings.colorSpace = ColorSpace.Linear;
GraphicsSettings.useHDR = true;
hlsl复制float3 ApplyACES(float3 x) {
const float A = 2.51;
const float B = 0.03;
const float C = 2.43;
const float D = 0.59;
const float E = 0.14;
return saturate((x*(A*x+B))/(x*(C*x+D)+E));
}
适用于医学影像或体渲染的3D ASTC配置:
bash复制toktx --t2 --3d --genmipmap --bcmp volume.ktx2 --blocksize 6x6x6 input_*.png
csharp复制using KtxUnity;
var loader = new KtxTextureLoader();
loader.LoadTextureFromBytes(ktxData, (result) => {
result.texture.dimension = UnityEngine.Rendering.TextureDimension.Tex3D;
});
实测数据对比(256x256x256体积纹理):
| 格式 | 原始大小 | 压缩大小 | 加载时间 |
|---|---|---|---|
| RAW RGBA16 | 128MB | 128MB | 1.2s |
| ASTC 6x6x6 | 128MB | 8MB | 0.4s |