Skip to content

Atlas Manager

Shmellyorc edited this page Aug 31, 2026 · 6 revisions

The Atlas Manager is a texture atlasing system that automatically packs textures into larger texture pages to reduce draw calls and improve rendering performance. It handles page allocation, texture packing, LRU eviction, and fragmentation management.


Overview

Texture atlasing is a technique where multiple smaller textures are combined into a single larger texture. This reduces the number of draw calls because the renderer can draw many sprites from the same texture in a single batch.

Without Atlasing With Atlasing
One draw call per texture One draw call per atlas page
100 textures = 100 draw calls 100 textures = 1 draw call
Texture switches are expensive Texture switches are minimized
Poor batching efficiency Excellent batching efficiency

The Atlas Manager handles all of this automatically. You don't need to think about it. Just pack your textures and the system handles the rest.


How It Works

Pages

The atlas is divided into pages. Each page is a fixed-size render texture (default: 2048x2048 pixels). Textures are packed into these pages until they are full, then the next page is used.

Page 0                    Page 1                    Page 2
┌────────────────────┐   ┌────────────────────┐   ┌────────────────────┐
│ [Tex A] [Tex B]    │   │ [Tex G] [Tex H]    │   │ [Tex M] [Tex N]    │
│ [Tex C]            │   │ [Tex I]            │   │ [Tex O] [Tex P]    │
│ [Tex D] [Tex E]    │   │ [Tex J] [Tex K]    │   │                    │
│ [Tex F]            │   │ [Tex L]            │   │                    │
└────────────────────┘   └────────────────────┘   └────────────────────┘

Packing Algorithms

The Atlas Manager supports two packing algorithms through the IAtlasPacker interface.

GuillotinePacker

The Guillotine algorithm maintains a list of free rectangles and selects the best fit for each texture.

Feature Description
Strategy Best area fit (smallest free rectangle that fits)
Search Time O(n) where n is the number of free rectangles
Fragmentation Tends to create more fragmentation over time
Best For Textures of varying sizes

How it works:

  1. Maintains a list of free rectangles in the atlas
  2. When packing, finds the free rectangle with the smallest area that fits the texture
  3. Splits the chosen rectangle into remaining free space
  4. When freeing, merges adjacent free rectangles to reduce fragmentation
  5. Defragmentation repacks all textures to optimize space

SkylinePacker

The Skyline algorithm maintains a skyline of the topmost occupied pixels and places textures in the lowest available position.

Feature Description
Strategy Lowest Y position that fits the texture width
Search Time O(n²) where n is the number of skyline nodes
Fragmentation Less fragmentation than Guillotine
Best For Textures of similar sizes

How it works:

  1. Maintains a skyline (topmost occupied Y position for each X coordinate)
  2. When packing, finds the lowest Y position that can accommodate the texture width
  3. Places the texture at that position and updates the skyline
  4. When freeing, inserts free space back into the skyline
  5. Defragmentation repacks all textures in order of position

AtlasManager

The AtlasManager is the main class that manages the entire atlasing system.

Singleton Access

var atlas = AtlasManager.Instance;

Packing Textures

// Pack a texture into the atlas
if (atlas.TryPack(sfTexture, srcRect, out var packedRect, out var pageId))
{
    // Texture was packed at packedRect on page pageId
    var pageTexture = atlas.GetPageTexture(pageId);
    
    // Draw using the atlas texture
    batcher.DrawBypassAtlas(pageTexture, dstRect, packedRect, Color.White);
}

Getting Page Textures

// Get the texture for a specific page
SFTexture pageTexture = atlas.GetPageTexture(pageId);

Metrics

// Get atlas metrics
var metrics = atlas.GetMetrics();

Console.WriteLine($"Pages: {metrics.UsedPages}/{metrics.TotalPages}");
Console.WriteLine($"Usage: {metrics.PercentageFull:F1}%");
Console.WriteLine($"Textures: {metrics.TextureCount}");
Console.WriteLine($"Evictions: {metrics.EvictionCount}");

Processing Defragmentation

// Process pending defragmentation moves (call once per frame)
bool stillDefragging = atlas.ProcessPendingDefragMoves(maxMovesPerFrame: 10);

Clearing

// Clear all atlas data
atlas.Clear();

LRU Eviction

When the atlas is full, the Atlas Manager evicts the least recently used textures to make room for new ones.

Step What Happens
1 Atlas is full
2 Least recently used texture is identified
3 Texture is removed from the atlas page
4 Space is freed for the new texture
5 New texture is packed into the freed space

Evictions are tracked in the AtlasMetrics structure.


Defragmentation

Over time, packing and freeing textures can leave fragmented free space that cannot be used for larger textures. Defragmentation rearranges packed textures to consolidate free space into larger contiguous blocks.

When Defragmentation Triggers

Condition Action
No free space found in any page Find the most fragmented page
Fragmentation > threshold (default: 30%) Defragment that page
Space is freed Continue

Defragmentation Process

  1. Identify the most fragmented page
  2. Get all textures on that page
  3. Repack them into a clean atlas page
  4. Queue move operations for processing over multiple frames
  5. Update packed positions in the map

Processing Moves

Defragmentation is spread across multiple frames to avoid frame rate hitches.

// Process up to 10 moves per frame
atlas.ProcessPendingDefragMoves(10);

Configuration

Atlas settings are configured through GameSettings.

var settings = GameSettings.Instance
    .SetAtlasPageSize(2048)                // Page size in pixels
    .SetAtlasPageCount(4)                   // Number of pages
    .SetAtlasDefragThreshold(0.3f)          // 30% fragmentation triggers defrag
    .SetAtlasDefragMovesPerFrame(10)       // Moves per frame
    .SetAtlasPacker(typeof(SkylinePacker))  // Packing algorithm
    .Build();

Settings Reference

Setting Description Default
AtlasPageSize Size of each atlas page in pixels 2048
AtlasPageCount Number of atlas pages 4
AtlasDefragThreshold Fragmentation percentage that triggers defrag 30%
AtlasDefragMovesPerFrame Number of texture moves per frame during defrag 10
AtlasPacker Packing algorithm to use SkylinePacker

Performance

Draw Call Reduction

Scenario Without Atlas With Atlas
50 textures 50 draw calls 1 draw call
500 textures 500 draw calls 1-2 draw calls
5000 textures 5000 draw calls 3-5 draw calls

Memory Usage

Component Memory Usage
Atlas page (2048x2048) 16 MB
Atlas page (4096x4096) 64 MB
Texture data (in packer) Minimal

Defragmentation Performance

Metric Value
Moves per frame Configurable (default: 10)
Time per move ~0.1-0.5 ms
Total defrag time Spread across frames

Examples

Basic Usage

public class MyGame : Game
{
    private AtlasManager _atlas;
    private SpriteBatcher _batcher;

    protected override void OnEnter()
    {
        _atlas = AtlasManager.Instance;
        _batcher = new SpriteBatcher();
    }

    protected override void OnUpdate(FrameTime frameTime)
    {
        // Process defragmentation moves
        _atlas.ProcessPendingDefragMoves(10);
    }

    protected override void OnDraw(FrameTime frameTime)
    {
        // Pack and draw textures
        var texture = AssetManager.Instance.Load<Texture>("player.png");
        
        if (_atlas.TryPack(texture, texture.Bounds, out var packedRect, out var pageId))
        {
            var pageTexture = _atlas.GetPageTexture(pageId);
            
            _batcher.Begin(SortMode.BackToFront);
            _batcher.DrawBypassAtlas(pageTexture, new Rect2(100, 100, 64, 64), packedRect, Color.White);
            _batcher.End();
        }
    }
}

Monitoring Atlas Usage

public void CheckAtlasHealth()
{
    var metrics = AtlasManager.Instance.GetMetrics();
    
    if (metrics.PercentageFull > 90f)
    {
        Console.WriteLine("Atlas is nearly full! Consider increasing page count.");
    }
    
    if (metrics.EvictionCount > 100)
    {
        Console.WriteLine("High eviction count. Atlas may be too small.");
    }
}

Summary

Feature Description
Texture Atlasing Combines textures into larger pages
Automatic Packing Textures are packed automatically
Multiple Algorithms Guillotine and Skyline packing
LRU Eviction Least recently used textures are evicted
Defragmentation Fragmented space is consolidated
Page Management Multiple pages are managed automatically
Metrics Usage statistics are tracked

Back to Home

Clone this wiki locally