# How the ImGui Font Atlas Works and How to Optimize Its Size

> Understand the ImGui font atlas and optimize its size. Learn to reduce memory footprint by limiting glyph ranges, adjusting oversampling, and using the dynamic font system.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: internals
- Published: 2026-07-16

---

**The ImGui font atlas (`ImFontAtlas`) packs all registered font glyphs into a single CPU-side bitmap texture that gets uploaded to the GPU, and you can minimize its memory footprint by reducing oversampling, limiting glyph ranges, and leveraging the dynamic font system introduced in v1.92.**

The `ImFontAtlas` structure in the ocornut/imgui repository serves as the central manager for all text rendering within an ImGui context, consolidating every required glyph into a unified texture atlas. Understanding how this packing mechanism works in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h) and [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) is essential for keeping memory usage low and avoiding costly texture reallocations in immediate-mode GUI applications.

## What Is the ImGui Font Atlas?

`ImFontAtlas` is the core structure that stores **all** fonts used by an ImGui context. It lives inside `ImGuiIO::Fonts` and manages the entire lifecycle of font rendering:

- **Font Registration**: The `AddFont...` family of methods creates `ImFont` objects and registers them with the atlas.
- **Glyph Packing**: Each glyph is turned into a rectangular region and packed into a single texture using the `ImFontAtlasBuilder` (defined in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h) lines 3987–4011).
- **Texture Creation**: The `ImFontAtlas::Build()` method generates a CPU-side bitmap (RGBA or Alpha8) and prepares it for backend upload as `ImTextureRef`.

The atlas texture grows incrementally, starting at 512×128 pixels, and resizes automatically when new glyphs are requested.

## How the Font Atlas Packs Glyphs

The packing process occurs in three distinct stages as implemented in the source code:

1. **Rect Packing**: The `ImFontAtlasBuilder` calculates bounding boxes for each glyph using the configured `OversampleH` and `OversampleV` values, then packs these rectangles into the atlas texture.
2. **Rasterization**: For each packed rectangle, the builder rasterizes the glyph bitmap using either stb_truetype or FreeType (if `IMGUI_ENABLE_FREETYPE` is defined).
3. **Texture Build**: The `ImFontAtlasBuildMain` function (defined in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h) line 4019) assembles the final bitmap and stores it in `ImTextureData` within the atlas.

Runtime text rendering (`ImDrawList::AddText`, `ImGui::Text`) fetches UV coordinates from this packed texture to render individual glyphs.

## Why the Atlas Texture Can Grow Too Large

Several default behaviors in the ImGui font atlas can cause excessive memory consumption:

- **Oversampling**: Each glyph is rasterized with `OversampleH`/`OversampleV` (default 2×2), quadrupling the base pixel requirements.
- **Unicode Ranges**: Loading fonts with full Unicode ranges (e.g., CJK) creates thousands of glyphs.
- **Power-of-Two Height**: By default, the atlas height rounds up to the next power of two unless you set `ImFontAtlasFlags_NoPowerOfTwoHeight`.
- **Default Embedded Font**: The bundled `ProggyClean` bitmap font (~26 KB) is added automatically unless explicitly disabled.

## How to Optimize the ImGui Font Atlas Size

### Remove the Default Bitmap Font

Disable the embedded default font to reclaim ~26 KB of texture space:

```cpp
// In imconfig.h, before including imgui.h:
#define IMGUI_DISABLE_DEFAULT_FONT

```

### Reduce Oversampling

Lower the `ImFontConfig` oversampling values to halve texture dimensions:

```cpp
ImFontConfig cfg;
cfg.OversampleH = 1;
cfg.OversampleV = 1;
io.Fonts->AddFontFromFileTTF("myfont.ttf", 16.0f, &cfg);

```

### Limit Glyph Ranges

Use `ImFontGlyphRangesBuilder` to include only characters your application actually needs:

```cpp
ImFontGlyphRangesBuilder builder;
builder.AddText("Hello World"); // Only these glyphs
ImVector<ImWchar> ranges;
builder.BuildRanges(&ranges);

io.Fonts->AddFontFromFileTTF("myfont.ttf", 16.0f, nullptr, ranges.Data);

```

### Avoid Power-of-Two Height

Allow the atlas to use exact dimensions rather than rounding up:

```cpp
io.Fonts->Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;

```

### Pre-Allocate Texture Size

Prevent early growth reallocations by setting minimum texture dimensions:

```cpp
ImFontAtlas* atlas = io.Fonts;
atlas->TexMinWidth = 1024;
atlas->TexMinHeight = 1024;

```

### Use the Dynamic Font System (v1.92+)

Starting with Dear ImGui v1.92, glyphs are added on demand. Simply load fonts without explicit ranges, and the backend requests glyphs lazily:

```cpp
// No ranges needed - glyphs loaded as encountered
io.Fonts->AddFontFromFileTTF("myfont.ttf", 16.0f);

```

### Prefer FreeType Over stb_truetype

FreeType rasterizes at exact sizes, often allowing lower oversampling:

```cpp
// In imconfig.h:
#define IMGUI_ENABLE_FREETYPE

```

### Merge Fonts Efficiently

Keep primary fonts small and merge supplemental fonts only for missing glyphs:

```cpp
ImFontConfig cfg;
cfg.MergeMode = true;
io.Fonts->AddFontDefault(); // Base UI font
io.Fonts->AddFontFromFileTTF("CJK_Supplement.otf", 16.0f, &cfg);

```

### Pack Custom Rectangles

For icons, use custom rectangles instead of loading entire icon fonts:

```cpp
int rectId = io.Fonts->AddCustomRectFontGlyph(font, ICON_FA_STAR, 16, 16, 16);

```

## Practical Implementation Example

Complete workflow combining multiple optimization techniques:

```cpp
// 1. Configure atlas settings
ImGuiIO& io = ImGui::GetIO();
ImFontAtlas* atlas = io.Fonts;

// Disable power-of-two height (saves VRAM)
atlas->Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;

// Pre-allocate to avoid reallocations
atlas->TexMinWidth = 1024;
atlas->TexMinHeight = 1024;

// 2. Load primary font with reduced oversampling
ImFontConfig cfg;
cfg.OversampleH = 1;
cfg.OversampleV = 1;
ImFont* uiFont = atlas->AddFontFromFileTTF("ProggyVector.ttf", 0.0f, &cfg);

// 3. Add specific glyph ranges only
ImFontGlyphRangesBuilder rangeBuilder;
rangeBuilder.AddText(u8"こんにちは世界");
ImVector<ImWchar> ranges;
rangeBuilder.BuildRanges(&ranges);

cfg.MergeMode = true;
atlas->AddFontFromFileTTF("NotoSansCJKjp-Medium.otf", 0.0f, &cfg, ranges.Data);

// 4. Build and upload
atlas->Build();

```

## Summary

- **ImFontAtlas** stores all glyphs in a single texture managed through `ImGuiIO::Fonts`.
- The **packing algorithm** in `ImFontAtlasBuilder` (defined in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h)) handles rectangle packing and rasterization.
- **Reduce memory** by disabling the default font (`IMGUI_DISABLE_DEFAULT_FONT`), lowering `OversampleH/V` to 1×1, and setting `ImFontAtlasFlags_NoPowerOfTwoHeight`.
- **Limit glyphs** using `ImFontGlyphRangesBuilder` or rely on the **dynamic font system** (v1.92+) to load glyphs on demand.
- **Pre-allocate** texture dimensions via `TexMinWidth` and `TexMinHeight` to prevent runtime reallocations.
- Consider **FreeType** for better quality at lower oversampling values compared to stb_truetype.

## Frequently Asked Questions

### What is the default size of the ImGui font atlas texture?

The atlas starts at **512×128 pixels** and grows dynamically as more glyphs are added. According to the source code in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h), the texture expands automatically when the packing algorithm runs out of space, which can trigger costly GPU texture reallocations if not pre-configured.

### How does oversampling affect the atlas texture size?

Oversampling multiplies the texture size by the product of `OversampleH` and `OversampleV`. The default 2×2 configuration creates four times as many pixels per glyph compared to 1×1. Reducing these values to 1 in `ImFontConfig` cuts the atlas memory footprint by up to 75% for large font sets.

### Can I load fonts without pre-building all glyphs?

Yes, starting with Dear ImGui v1.92, you can use the **dynamic font system** by calling `AddFontFromFileTTF` without specifying explicit glyph ranges. The backend requests glyphs lazily as they are encountered in text, keeping the initial atlas size minimal and growing it only when new characters appear.

### Is FreeType better than stb_truetype for ImGui font atlases?

FreeType often produces higher quality text at lower oversampling values, which can reduce atlas size. To enable it, define `IMGUI_ENABLE_FREETYPE` in your build configuration and include [`misc/freetype/imgui_freetype.h`](https://github.com/ocornut/imgui/blob/main/misc/freetype/imgui_freetype.h). FreeType also supports color glyphs and advanced hinting, though it adds a dependency on the FreeType library.