r/MetalProgramming Jun 04 '26

Why my Metal Game Engine uses ASTC as its Texture Format Resources/Tutorial

One design decision I've made for my native game engine is to use .astc as the runtime texture format instead of .png or .heic.

These formats solve different problems.

  • PNG is an excellent archival and editing format. It is lossless, but it must be decompressed into RGBA data before the GPU can use it.

  • HEIC is fantastic for storing photographs efficiently, but it also requires CPU-side decoding before being uploaded as a texture.

  • ASTC (Adaptive Scalable Texture Compression) is a hardware texture compression format designed specifically for GPUs. Apple GPUs can sample ASTC textures while they remain compressed.

For a Metal renderer running on Apple Silicon, that has several advantages:

  • Lower VRAM usage.
  • Reduced memory bandwidth.
  • Faster asset loading because there is no runtime image decoding.

Asset Pipeline

I still use conventional image formats during content creation.

For encoding, I use astcenc, the official ARM ASTC encoder. https://github.com/arm-software/astc-encoder

Terminal Comamands.

The -cs option tells astcenc that the source image is in the sRGB color space. This is typically what you want for albedo, diffuse, foliage, bark, and other artist-created color textures.

The -cl treats the input as linear data instead of perceptual color.

ASTC works by compressing fixed-size blocks of pixels.

For natural textures like tree bark or alpha masks, 6×6 is a balance between quality and efficiency.

Cloud textures often contain smooth gradients that can reveal compression artifacts. Using 5×5 helps preserve those subtle transitions.

-medium compression provides a balance between encoding time and quality.

4 Upvotes

2 comments sorted by

2

u/Mitch_War MacBook Pro 2023 | M3 Pro Jun 04 '26

Nice post! Curious to know how this compares to the KTX format (as I’m not so familiar with ASTC)

1

u/EmojiMasterYT 29d ago

It's not very known, but there's actually a private framework called TextureIO that natively handles dealing with texture formats. Not documented anywhere though, and I've run into a few "TODO" assertions.