BC7 is not lossless. Knowing what it compresses well and what it destroys is the difference between a clean pipeline and a subtle quality regression nobody can trace.
What BC7 Is
Every texture on your GPU has to live somewhere in memory, and uncompressed textures are expensive. A 1024² albedo at 8 bits per channel across four channels is 4 MB. Multiply that across every asset in a scene, and you're burning through VRAM and memory bandwidth fast.
Block compression fixes this by letting the GPU decode textures on the fly. Instead of storing raw pixel data, the texture is divided into 4×4 texel blocks, each encoded independently. The GPU decompresses each block in hardware at essentially zero cost.
source: reedbeta
BC7 is the highest-quality format in the BC family for standard 8-bit LDR textures. It stores 8 bits per pixel, same footprint as BC3, but delivers substantially better quality. The key difference is flexibility: BC7 has eight distinct encoding modes, and per block, the encoder picks whichever fits best. Whether that means subdividing the block into sub-regions, adjusting how many bits go to endpoints versus indices, or swapping the alpha channel with one of the RGB channels. That flexibility is what lets BC7 handle difficult blocks cleanly, sharp color transitions, complex gradients, without the banding you'd get from BC1 or BC3.
The trade-off is encoding time. BC7 can take minutes per texture at high quality settings. That's an offline cost, not a runtime one, so BC7 belongs in a precomputed asset pipeline, not anywhere that regenerates textures frequently.
What It Handles Well and What It Doesn't
Good candidates: albedo maps, color textures with smooth gradients, anything RGBA where quality matters. BC7 handles blocks with multiple color directions far better than older formats. BC1 and BC3 force all colors in a block onto a single line in RGB space. BC7 supports multiple lines per block, so sharp edges between very different hues that produce obvious artifacts in BC1 compress cleanly here.
Use something else for:
- Single-channel data (roughness, AO, masks): BC4 is half the size and purpose-built for it.
- Normal maps: BC5 stores two independent R8 channels for XY and derives Z in the shader. BC7 can store normals but you're wasting bits on a channel you don't need.
- HDR textures: BC7 is LDR only. BC6H handles 16-bit float channels.
Compression is lossy throughout the BC family. The block encoding approximates the original image and you can't recover it exactly. For color textures this is rarely visible. For data textures carrying precise float-range values, it can matter more.
Practical Takeaway
For albedo and RGBA color maps, BC7 is the right default on DX11+/OpenGL 4.2+ hardware. Run it offline at max quality.
If encoding time is a bottleneck during development, BC3 works as a fast stand-in and you swap to BC7 for shipping builds. The quality difference is real but only matters in the final product.
Quick reference: BC4 for single-channel data, BC5 for normal maps (XY only), BC6H for HDR, BC7 where quality color compression or precision matters.
© 2026 Stefan Groenewoud — All views are my own, not those of my employer.
