For game developers
What Is a Texture Atlas? How One 512 px Image Colors a Whole Kit
Short answer: a texture atlas is one image that holds the colors or textures for many objects at once. Each model's UV coordinates point at its own small region of that image, so a whole set of props can share one texture and one material. Engines can then batch those objects into fewer draw calls, and you load one file instead of dozens. Low-poly games lean on atlases because flat or gradient colors pack into a very small image.
This explainer uses the atlas behind our Larkspur Farmstead and Saltlight Village collections as the worked example. The numbers come from the delivered files and from the live product pages, checked in October 2026. More kits built the same way are in game assets.

What a texture atlas is
Without an atlas, every object usually gets its own texture: a wood image for the table, another for the chair, a third for the plates. Each texture tends to come with its own material. With an atlas, those images are packed side by side into one larger image, and each model is UV unwrapped so its faces land on the right part of it. The Arm real-time art guide for Mali GPUs describes it the same way: instead of one texture per mesh, several meshes share one larger texture, and the UV islands are arranged to match the regions they use.
The term covers several layouts. A 2D sprite sheet is an atlas of animation frames. A decal sheet packs cracks, stains and signs. A painted atlas packs hand-painted or baked textures for a group of props. The kind most low-poly kits use is the simplest of all: a palette or gradient atlas, where each small cell is just one color, and models pick their color by where their UVs sit.
Why games use texture atlases
The main reason is draw calls. A draw call is the CPU telling the GPU to draw something with a given set of resources. When objects use different materials and textures, the engine has to switch state between them. When they share one material and one atlas, the engine can group them. The Arm guide notes that atlasing lets static objects that share the atlas and the same material be batched, and that fewer draw calls help most when a game is CPU-bound.
There are two smaller wins. You load and track fewer texture files, which keeps memory and project clutter down. And a shared palette keeps a world visually consistent: if every roof samples the same shingle cells, roofs from different kits match without anyone color-correcting them.
The trade-offs are real too. An atlas has a fixed resolution, so it suits stylized color work better than close-up photographic detail. Tiling a texture across a large surface does not work inside an atlas region the way it does with a separate repeating texture. And if your engine does not batch the objects, or they use different shaders anyway, you keep the tidiness but lose most of the performance benefit.
How our gradient atlas is laid out
Every Larkspur and Saltlight asset samples one image: a 512 x 512 px PNG divided into a 16 x 16 grid of 32 px cells. That is 256 cells. Each cell holds one hue as a vertical gradient: lighter at the top, as if sunlit, and darker at the bottom, as if in shade, with a slight drift from cooler on the left to warmer on the right. Cells are grouped into families in rows: limestone and whitewash, timber and bark, thatch and straw, barn paint and shingle, iron, tin and glass, soil and rock, and so on.
| Property | Larkspur atlas | Saltlight atlas |
|---|---|---|
| Image size | 512 x 512 px PNG | 512 x 512 px PNG |
| Grid | 16 x 16 cells, 32 px each | 16 x 16 cells, 32 px each |
| Material | one shared material, roughness 0.85, metallic 0 | one shared material, roughness 0.85, metallic 0 |
| Glow | separate emissive image, black except the glow cells | separate emissive image, black except the glow cells |
| Example collection | Larkspur Farmstead: 67 assets, 90,748 triangles | Saltlight Village: 69 assets, 75,399 triangles |
| Atlas copies in the download | 67, all identical | 69, all identical |
Because the color lives in a gradient rather than in painted detail, 32 px per cell is plenty. The model's own shape does the rest: a face that sits low on a wall maps to the darker part of its cell, a face near the top maps to the lighter part, so even a flat-colored prop reads with soft shading before any lighting is added.
Larkspur adds one more rule. The top 15% of every cell is reserved for faces that point at the sky (a face normal with an upward component of 0.5 or more, so slopes up to 60 degrees). Every other face maps into the lower 76% of the cell, and a 9% gutter between the two bands is sampled by no face at all. That keeps roof tops, foliage tops and paths in their own band, so a recolored version of the atlas can change what faces the sky without touching the tops of walls, posts and trunks.
One prop, cell by cell
Abstract layouts are easier to follow with a real file. We read the UV coordinates of the delivered GLB of the Farmhouse Kitchen Dresser and mapped every vertex to its atlas cell.

| Mesh in the GLB | Triangles | Atlas cells used | What the cells are |
|---|---|---|---|
| Dresser (main) | 2,878 | 6 of 256 | honey timber, dark honey timber, raw plank, cream and blue crockery, dark iron |
| Dresser LOD1 | 1,196 | the same 6 | identical UV regions to the main mesh |
| Sage-painted dresser | 2,878 | 7 of 256 | sage paint cells replace the honey timber; plank, crockery and iron stay |
| Collision proxy | 12 | none | invisible, not textured |
Two things stand out. The lighter LOD1 mesh points at exactly the same cells as the full mesh, so it keeps its colors when the engine swaps detail levels. And the sage-painted copy has the same triangle count and the same shape; only its UVs move to different cells. A color option in an atlas workflow costs no extra texture at all. The smaller Bedside Table is even simpler: 342 triangles across a frame and a drawer, using three timber cells between them.
Filtering, mipmaps and color bleeding
The classic atlas problem is bleeding: at a distance, color from one cell creeps into its neighbor and you see a thin wrong-colored line along an edge. It comes from texture filtering. Smooth filtering blends nearby texels, and mipmaps, the smaller copies of a texture the GPU uses for distant objects, average neighboring texels together. Arm's guide recommends using mipmaps anyway, because they reduce shimmering and save bandwidth on far objects, so the atlas has to be built to survive them.
Our atlas handles this in three ways. UVs stay at least 1 px inside their cell, so normal filtering never reaches across a cell border. The cells are smooth gradients, so blending inside a cell changes nothing you can see. And the Larkspur sky gutter means the top band and the side band never sample each other. In the GLB files, the sampler is set to linear magnification, linear-mipmap-linear minification and clamp-to-edge wrapping, the standard enum values listed in the Khronos glTF specification.
If you build your own atlas, the usual guidance is the same: leave padding between regions, keep the atlas size a power of two so mipmaps divide cleanly, and test at a distance, because bleeding rarely shows up close to the camera.
Texture atlas UV math in OpenGL, WebGL and other APIs
At the graphics API level an atlas is an ordinary 2D texture. Nothing in OpenGL, WebGL, Vulkan or Direct3D knows about regions; the region lives entirely in the UV coordinates. For a region that starts at pixel (x, y) and is w by h pixels inside an atlas of W by H pixels, the UV rectangle runs from (x / W, y / H) to ((x + w) / W, (y + h) / H). In our 512 px atlas, the cell in column 3, row 5 (counting from 0) starts at pixel (96, 160), so its UVs run from (0.1875, 0.3125) to (0.25, 0.375).
Three details catch people out:
- Inset by half a texel. Shrink the rectangle by 0.5 / W in u and 0.5 / H in v on each side, so bilinear filtering only samples texels inside the region.
- Know which way v points. Image files usually store the top row at the start, while OpenGL treats the row it receives at the start as v = 0. Many loaders flip images on upload for that reason, and glTF defines its UV origin at the top left of the image. Check your loader before you compute v.
- Wrap modes apply to the whole texture. Repeat and clamp-to-edge settings act on the full atlas, never on one region. To tile a pattern inside a region, the shader has to wrap the coordinate itself (take the fractional part and remap it into the region), and the region needs extra padding or seams appear at smaller mip levels.
When regions must tile, or bleeding is hard to avoid, a texture array is the usual alternative. Each layer is a separate image of the same size and format, picked by a layer index, so filtering and wrapping work per layer and nothing bleeds across. The cost is that every layer must share one size, and older targets such as WebGL 1 do not support arrays. For flat and gradient color work like ours, a plain atlas is simpler and runs everywhere.
Working with a shared atlas in your project
- Keep one copy. Each asset folder in the download carries its own copy of the atlas so that any single asset works on its own. Once several assets are in one project, point every material at a single copy. Two copies of the same image are still two textures to load.
- Keep one material. The gain comes from shared state. Duplicating the material per object, even with the same image, can split batches again.
- Do not crop or re-pack it. The UVs assume the exact 16 x 16 layout, so moving or trimming cells breaks every model that uses them.
- Recolor by editing cells. Painting a cell a new color recolors every face that samples it, across every asset. That is the fastest way to re-theme a set, and the reason the cell coordinates never change between releases.
- Bring the emissive image too. Lamps and windows glow from a second image that is black except for the glow cells, so it adds light only where intended.
For the other checks that make a model ready for a level, such as scale, pivots, LODs and collision, see our game-ready 3D models checklist. For how triangle counts fit into the same budget, see how many triangles is low poly. If your target is a headset in the browser, draw calls matter even more; our WebXR explainer covers that budget.
Common questions
Are texture atlases worth it?
For many small stylized props, usually yes: one material and one small image for a whole set means fewer state changes and fewer files. For large surfaces that need tiling detail, or for hero objects seen up close, a dedicated texture is often the better fit. Many projects mix both.
Are texture atlases still used?
Yes. Sprite sheets, UI icon sheets, decal sheets and palette atlases for low-poly worlds are all atlases. The reason for them, sharing one texture and material so objects can be drawn together, still applies.
How do you make a texture atlas?
Either plan it up front and unwrap models straight onto its regions, which is how gradient and palette atlases are made, or finish the models and then pack their separate textures into one image and move their UV islands to match. The Arm guide describes both routes; planning ahead takes more design work, packing afterwards means rearranging the UVs.
How much padding does a texture atlas need?
Enough to survive the mip levels you actually use. Each mip level halves the image, so a 1 px gap at full size is gone by the next smaller level. Common practice is to pad regions by several pixels, extend each region's edge colors outward into the padding, and align regions to power-of-two boundaries so they stay separate as the image shrinks. Our 32 px cells sit on a power-of-two grid, so cell borders stay aligned all the way down to the 16 x 16 px mip, where each cell has become a single texel.
What size should a texture atlas be?
It depends on the detail it carries. Painted or photographic atlases often need large images. A gradient atlas needs very little: our 256 color cells fit in 512 x 512 px because each cell holds a smooth ramp rather than fine detail.
Assets in this guide
Bedside Table with Drawer
Beds and bedroom · Larkspur Farmstead
€4,00
- Asset collection
Larkspur Farmstead: Complete Collection
67 assets · Larkspur Farmstead
€89,00
Includes 67 assets worth €507,00 separately
- Kit
Farmhouse Interior Kit
18 assets · Larkspur Farmstead
€52,00
Includes 18 assets worth €131,00 separately
Farmhouse Kitchen Dresser
Kitchen fittings · Larkspur Farmstead
€12,00
- Kit
Whitewash House Modules Kit
21 assets · Saltlight Village
€48,00
Includes 21 assets worth €119,00 separately
- Asset collection
Saltlight Village: Complete Collection
69 assets · Saltlight Village
€89,00
Includes 69 assets worth €490,00 separately










