Texture formats, compression and mipmaps
How game engines store textures on the GPU; the BCn family (BC1, BC3, BC4, BC5, BC7) on desktop and console, ASTC and ETC2 on mobile, normal map compression, sRGB flags, mipmaps and power-of-two sizes, texture streaming, memory arithmetic and Unreal's texture groups.
A GPU does not read PNG or JPEG files. Engines convert every texture to a block-compressed format that the graphics card can sample directly, and add mipmaps, smaller copies for distant surfaces. Godot sums up why: VRAM compression reduces memory and bandwidth, and "These factors combined make VRAM compression a must-have for 3D games with high-resolution textures" (Godot documentation: Importing images).
As an artist you rarely pick the format by hand, but you choose the texture type, size and compression setting, and those decide most of a scene's texture memory. Hugh Chew's video Your Textures Are Killing Performance, Here's Why is a good artist-level overview: it separates the costs into VRAM, compression, GPU texture sampling and draw calls, then covers channel packing, streaming and mipmaps with a UE5 compression demo (YouTube: Your Textures Are Killing Performance, Here's…).
#How block compression works
All common GPU formats cut the image into small blocks (usually 4 × 4 pixels) and store each block in a fixed number of bytes. For the BCn family, each block stores two endpoint colours and a small index per pixel saying where it sits between them (Nathan Reed's coding blog: Understanding BCn Texture Compression Formats). The size is fixed, so the GPU can jump straight to any block, and the result is always "a 4:1 or 8:1 compression ratio" against uncompressed 8-bit RGBA (Nathan Reed's coding blog: Understanding BCn Texture Compression Formats).
The cost is lower quality. Each block can only hold a limited range of colours, so sharp colour changes and smooth gradients suffer. Reed shows why: BC1 stores its two endpoints "using RGB 5:6:5 format", and in his test it fails on a smooth gradient (Nathan Reed's coding blog: Understanding BCn Texture Compression Formats).
#The BCn family (desktop and console)
| Format | Bits per pixel | Channels | Typical use | Unreal setting |
|---|---|---|---|---|
| BC1 (DXT1) | 4 | RGB, optional 1-bit alpha | Base colour without alpha; cut-out masks | Default, no alpha (Unreal Engine documentation) |
| BC3 (DXT5) | 8 | RGBA | Colour with smooth alpha; colour plus a packed mask | Default, with alpha (Unreal Engine documentation) |
| BC4 | 4 | One channel | Height, gloss, single masks | Alpha (Unreal Engine documentation) |
| BC5 | 8 | Two channels | Tangent-space normal maps | Normalmap (Unreal Engine documentation) |
| BC6H | 8 | RGB, half-float HDR | HDR skies, light probes | HDR Compressed (Unreal Engine documentation) |
| BC7 | 8 | RGB or RGBA | High-quality colour, with or without alpha | BC7 (Unreal Engine documentation) |
Bits per pixel and uses from Nathan Reed's overview (Nathan Reed's coding blog: Understanding BCn Texture Compression Formats).
Reed says BC2 is "never used nowadays" (Nathan Reed's coding blog: Understanding BCn Texture Compression Formats), and that BC7 handles gradients well: "BC7 also works extremely well on the gradient example, where BC1 failed miserably" (Nathan Reed's coding blog: Understanding BCn Texture Compression Formats). Unity's recommendation for modern desktop GPUs is DXT1 for RGB, BC7 for higher-quality RGBA (or DXT5 for faster compression), and BC6H for HDR (Unity Manual: Choose a GPU texture format by platform).
#Normal maps
Normal maps get their own format because colour compression distorts directions. BC5 stores only X and Y, each with its own endpoints, and the shader reconstructs Z (Nathan Reed's coding blog: Understanding BCn Texture Compression Formats). Unreal's Normalmap setting uses BC5 (Unreal Engine documentation: Texture Compression Settings). Godot imports normal maps as the equivalent RGTC format, noting that regular compression produces artefacts that "don't look that nice in normal maps" (Godot documentation: Importing images). Unity HDRP requires tangent-space normal maps to be BC7, BC5 or DXT5nm (High Definition Render Pipeline manual 17.0: Lit material Inspector reference). See normal map.
#Mobile: ASTC and ETC2
Phones and tablets use different formats.
- ASTC is Unity's recommended format for iOS and modern Android; "ASTC is the most flexible format" (Unity Manual: Choose a GPU texture format by platform). Its block size is adjustable, trading quality for size "all the way from eight bits/pixel (4x4 block size) down to 0.89 bits/pixel (12x12 block size)" (Unity Manual: Choose a GPU texture format by platform).
- ETC2 is the fallback for older Android devices (OpenGL ES 3.0 or Vulkan); older still ETC1 has no alpha channel (Unity Manual: Choose a GPU texture format by platform).
- Godot uses ETC2 on mobile and web by default, and ASTC when High Quality is enabled (Godot documentation: Importing images).
Because the block size is chosen per texture, you can spend fewer bits on soft, distant textures and more on hero assets and UI.
#The sRGB flag
Compression format and colour space are separate choices. Colour textures are stored in sRGB and data textures in linear (see texture maps explained). glTF notes that "Graphics APIs usually support dedicated sRGB texture format enums that enable correct transfer function decoding and texture filtering" (Khronos Group: glTF 2.0 Specification). In practice:
- Unity: the sRGB (Color Texture) checkbox; on for albedo, off for anything you "need the exact value for" (Unity Manual: Default texture import settings reference).
- Unreal: the sRGB checkbox, plus compression settings that switch it off automatically, such as Masks, which "will disable sRGB as texture masks should not be gamma corrected" (Unreal Engine documentation: Texture Compression Settings).
- Godot: Compress > Channel Pack defaults to "sRGB Friendly", which avoids the RG format "as it does not support sRGB color" (Godot documentation: Importing images).
#Mipmaps
A mipmap chain is a series of "progressively smaller and lower resolution versions of a single texture" (Unity Manual: Introduction to mipmaps). When a surface is far away, the GPU samples a smaller level. This "can speed up rendering operations and reduce rendering artifacts" such as shimmering (Unity Manual: Introduction to mipmaps). Each level halves the width and height, so Epic's tables show a 2048² texture with 12 mips down to 1 × 1 (Unreal Engine documentation: Texture Format Support and Settings in Unreal…).
The cost is memory: "Mipmaps increase the size of a texture by 33%, both on disk and in memory" (Unity Manual: Introduction to mipmaps). Mips are also the reason UV padding matters: small mips blur neighbouring islands together.
#Power-of-two sizes
Textures are traditionally 256, 512, 1024, 2048 or 4096 px on each side. Halving divides evenly all the way down to 1 × 1, and block compression needs sizes that are multiples of 4. benui's Unreal notes summarise it: "Power-of-two textures are supported by both compression and mipmap generation", and DXT5 "is only available for textures that are a multiple of 4" (Unreal Garden: UI Texture Size and Compression).
The rules have relaxed. benui notes that from Unreal 5.1 "Mip maps are now supported on non-power-of-two textures", but that Unreal has only supported streaming power-of-two textures since 4.16 (Unreal Garden: UI Texture Size and Compression). Unity can rescale a non-power-of-two image to the nearest power of two on import (Unity Manual: Default texture import settings reference). Rectangular power-of-two sizes such as 2048 × 1024 are fine; square is not required on desktop, though Unity notes that the old PVRTC mobile formats "require Textures to be square" (Unity Manual: Default texture import settings reference).
For 3D, keep to power-of-two sizes unless you have a reason not to.
#Worked example: texture memory
Texture memory is simple arithmetic: pixels × bytes per pixel × 4/3 for mips.
#Texture streaming
Engines do not keep every mip of every texture in memory. Texture streaming loads and unloads mip levels as you move. Unreal's streamer calculates the resolution each texture needs from the viewpoint "to get a good texel per pixel ratio", checks whether "the streaming memory pool is big enough", and if not, drops quality "one mip at a time, until the planned solution gets under budget" (Unreal Engine documentation: Texture Streaming Overview). Unseen textures lose mips first (Unreal Engine documentation: Texture Streaming Overview).
When a scene is over budget, textures look blurry because their high mips never load. Unreal's texture-streaming view modes show where loaded mips are too low or too high, colouring objects red for "2X+ mips missing" and green for "2X+ extra mips" (Unreal Engine documentation: Building Texture Streaming Data in Unreal…). Unity has a comparable Mipmap Streaming option per texture (Unity Manual: Default texture import settings reference). See virtual texturing for the related page-based approach.
#Unreal texture groups and LOD bias
Unreal assigns each texture to a texture group (LOD group) such as World, WorldNormalMap, Character, Weapon, Vehicle, Effects, Skybox or UI (Unreal Engine documentation: Texture Format Support and Settings in Unreal…). Each group sets limits for every texture in it:
- MaxLODSize / MinLODSize: the largest and smallest mip that will be used, as powers of two between 1 and 8192 (Unreal Engine documentation: Texture Format Support and Settings in Unreal…).
- LODBias: skips top mips. "A LODBias of 0 is the main (native) texture resolution"; a bias of 1 on a 1024² texture uses the 512² mip (Unreal Engine documentation: Texture Format Support and Settings in Unreal…).
- MinMagFilter and mip generation settings (Unreal Engine documentation: Texture Format Support and Settings in Unreal…).
A texture's own LOD Bias is added to its group's: a group bias of 1 plus a texture bias of 1 gives 2 (Unreal Engine documentation: Texture Format Support and Settings in Unreal…). Groups are configured per platform in the project's DefaultDeviceProfiles.ini (Unreal Engine documentation: Texture Format Support and Settings in Unreal…). This lets one project keep 4K source textures and halve them automatically on a weaker platform, without re-exporting anything.
Unreal also limits textures to 14 mips by default, capping the largest rendered texture at 8192 (Unreal Engine documentation: Texture Format Support and Settings in Unreal…).
#Common mistakes
- Normal maps compressed as colour. Use the engine's normal map type (BC5/RGTC) (Unreal Engine documentation: Texture Compression Settings; Godot documentation: Importing images).
- Data textures with sRGB on, or colour textures with it off (Unity Manual: Default texture import settings reference).
- Alpha you do not need. An empty alpha channel can push BC1 to BC3 or BC7 and double memory (Nathan Reed's coding blog: Understanding BCn Texture Compression Formats).
- Non-power-of-two 3D textures that then fail to stream in Unreal (Unreal Garden: UI Texture Size and Compression).
- Mipmaps disabled on 3D textures. Godot warns against disabling Detect 3D because mipmaps prevent textures "from looking grainy at a distance" (Godot documentation: Importing images).
- 4K by default. Choose resolution from texel density and viewing distance, then let LOD bias trim it per platform.
#In different tools
- Unreal Engine: Compression Settings per texture (Default, Normalmap, Masks, Grayscale, Displacementmap, Alpha, HDR, BC7) (Unreal Engine documentation: Texture Compression Settings); texture groups and LOD Bias (Unreal Engine documentation: Texture Format Support and Settings in Unreal…).
- Unity: platform-specific format overrides; Unity's per-platform recommendations (Unity Manual: Choose a GPU texture format by platform); Generate Mipmap and Mipmap Streaming in the importer (Unity Manual: Default texture import settings reference).
- Godot: VRAM Compressed (S3TC, BPTC or ETC2 by platform), Basis Universal, High Quality, Normal Map (Godot documentation: Importing images).
- Authoring: export lossless (PNG, TGA, TIFF or EXR) and let the engine compress. See texture file formats.
#Further reading and watching
References
- · Importing images (documentation source) · Godot documentation (GitHub) · docs · accessed 2026-10-21
- · Your Textures Are Killing Performance, Here's Why · YouTube, 2026 · video · accessed 2026-10-21
- · Understanding BCn Texture Compression Formats · Nathan Reed's coding blog, 2012 · article · accessed 2026-10-21
- · Texture Compression Settings (Unreal Engine 4.27) · Unreal Engine documentation, 2021 · docs · accessed 2026-10-21
- · Choose a GPU texture format by platform · Unity Manual (6000.2) · docs · accessed 2026-10-21
- · Lit material Inspector reference (HDRP) · High Definition Render Pipeline manual 17.0 · docs · accessed 2026-10-21
- · glTF 2.0 Specification · Khronos Group (GitHub) · docs · accessed 2026-10-21
- · Default texture import settings reference · Unity Manual (6000.2) · docs · accessed 2026-10-21
- · Introduction to mipmaps · Unity Manual (6000.2) · docs · accessed 2026-10-21
- · Texture Format Support and Settings in Unreal Engine · Unreal Engine documentation · docs · accessed 2026-10-21
- · UI Texture Size and Compression · Unreal Garden, 2022 · article · accessed 2026-10-21
- · Texture Streaming Overview (Unreal Engine 4.27) · Unreal Engine documentation, 2021 · docs · accessed 2026-10-21
- · Building Texture Streaming Data in Unreal Engine · Unreal Engine documentation · docs · accessed 2026-10-21
Pages that link here
- Real-time vs. offline rendering Topic
- 3D file formats Reference
- Texture file formats Reference
- Polygon and triangle budgets Topic
- Impostors and billboards Key term
- UV packing and padding Topic
- Lightmap UVs Key term
- Colour space: sRGB and linear Key term
- Texture maps explained Reference
- Normal map Key term
- Channel packing (ORM) Key term
- Mipmaps Key term
- Texture streaming Key term
- Bit depth and banding Key term
- Opacity, masked and translucent materials Key term
- Trim sheets Topic
- Texture atlases Topic
- Texture arrays Key term
- Virtual texturing Key term
- Texture memory (VRAM) Key term
- Essential talks and videos Reference
- Books Reference
Last updated 2026-10-22