Skip to content

Visual Files (Textures, UI, Inscriptions)

Myroslava Saveniuk edited this page Sep 24, 2026 · 2 revisions

Visual Files (Textures, UI, Inscriptions)

Last verified: 23.09.2026 | Game version: S.T.A.L.K.E.R.: Call of Pripyat (Steam, patch 1.6.02) | OS tested: Debian (Linux)
Status: Active — core workflow verified end-to-end

TL;DR

Game textures use the standard DDS format (DXT-compressed), not a proprietary algorithm — the .db archives are just containers around normal files. Editing a texture means: unpack → convert DDS→PNG → edit → convert PNG→DDS → drop into gamedata at the same relative path.

How textures work

  • Textures live in resources/textures/ inside the game archives (see Environment & Tools for unpacking).
  • Every .dds file has a matching .thm sidecar file with SDK/engine metadata (compression format, mip count, usage flags). It's auto-generated and not meant to be hand-edited.
  • Most UI text is NOT baked into textures. Labels, menu text, item names etc. are rendered from string tables (configs/text/*.xml) using a font — see the upcoming "Text & Localization" page. Only look at textures when the content is genuinely a graphic (icons, logos, in-world signage).

Texture atlases (XML-based)

Some UI graphics (faction logos, item icons) are packed as atlases: one large .dds image, with a matching XML file in configs/ui/textures_descr/ that maps a logical id to a pixel rectangle inside it.

Example — ui_logos.dds (1024×1024) described by configs/ui/textures_descr/ui_logos.xml:

<texture id="dolg_big" x="774" y="829" width="249" height="194" />
<texture id="bandit_big" x="769" y="1" width="249" height="194" />

To edit one logo, find its id in the matching XML, locate that rectangle in the PNG, edit only that region, and re-export the whole atlas (the file itself is not split — only the pixel data inside it is addressed by rectangle).

Item/weapon icons (grid-based atlas)

Some UI atlases (e.g. gamedata\textures\ui\ui_icon_equipment.dds) don't use pixel coordinates like ui_logos.dds — they use a grid instead, and the grid position is defined in the item's own .ltx file, not in a textures_descr XML.

Every weapon/item .ltx has an inventory placement block, e.g. for the [booster] item in configs/misc/items.ltx:

inv_grid_width  = 1
inv_grid_height = 1
inv_grid_x      = 3
inv_grid_y      = 18
  • inv_grid_x / inv_grid_y — position on the grid, counted in grid cells (not pixels), starting from 0 at the top-left. The count is of empty cells before the item, not including the item itself.
  • inv_grid_width / inv_grid_height — how many cells the icon occupies horizontally/vertically.
  • Grid cell size is 50×50px. To convert to pixel coordinates: pixel_x = inv_grid_x × 50, pixel_y = inv_grid_y × 50. Example above → pixel region x=150, y=900, 50×50.

Standalone textures (no atlas)

Many textures — in-world signage, most object/environment textures — are standalone files, not part of an XML atlas. Check with:

grep -rl "<filename, no extension>" ~/stalker_unpacked/configs

If this returns nothing from textures_descr/, the file has no atlas mapping — the whole image is the texture, no rectangle math needed.

Verified example: editing an in-world sign (standalone)

resources/textures/sign/sign_stop.dds — a standalone "STOP" sign texture (256×128, DXT1, no atlas).

1. Convert DDS → PNG

sudo apt install imagemagick
mkdir -p ~/stalker_edit
convert ~/stalker_unpacked/resources/textures/sign/sign_stop.dds ~/stalker_edit/sign_stop.png

2. Check the compression format (needed for step 4)

identify -verbose ~/stalker_unpacked/resources/textures/sign/sign_stop.dds | grep -i compression
# → Compression: DXT1

3. Edit

gimp ~/stalker_edit/sign_stop.png

Export as a new file (don't overwrite the source PNG): File → Export As → sign_stop_edited.png.

4. Convert PNG → DDS, matching the original compression

convert ~/stalker_edit/sign_stop_edited.png -define dds:compression=dxt1 ~/stalker_edit/sign_stop_edited.dds

(use dxt5 instead of dxt1 if the original texture has an alpha/transparency channel — check with GIMP's layer panel before converting)

5. Drop into gamedata, same relative path, original filename

mkdir -p "/path/to/Stalker Call of Pripyat/gamedata/textures/sign"
cp ~/stalker_edit/sign_stop_edited.dds "/path/to/Stalker Call of Pripyat/gamedata/textures/sign/sign_stop.dds"

The file in gamedata must be named exactly like the original (sign_stop.dds), not the _edited working name — the engine looks up textures by their original path/name.

6. Verify in-game

cd "/path/to/Stalker Call of Pripyat"
/path/to/xray-16/bin/x86_64/<config>/xr_3da -cop

Verified: the edited sign texture shows correctly in-game at its in-world location.

Verified example: recoloring an item icon (grid atlas)

resources/textures/ui/ui_icon_equipment.dds — atlas, 1024×2048, DXT5.

  1. Convert DDS → PNG:
   convert ~/stalker_unpacked/resources/textures/ui/ui_icon_equipment.dds ~/stalker_edit/ui_icon_equipment.png
  1. Open in GIMP, enable a 50×50px grid (Image → Configure Grid, then View → Show Grid) to line up with the game's convention.
  2. Locate the target item's cell using its inv_grid_x/inv_grid_y from step above (use Windows → Dockable Dialogs → Pointer for exact cursor coordinates while hovering).
  3. Edit the icon, export as a new file (e.g. ui_icon_equipment_edited.png).
  4. Convert back to DDS, matching the original format and disabling MIP maps:
   convert ~/stalker_edit/ui_icon_equipment_edited.png -define dds:compression=dxt5 -define dds:mipmaps=0 ~/stalker_edit/ui_icon_equipment_edited.dds
  1. Check the result matches the original's dimensions/format before copying:
   identify ~/stalker_edit/ui_icon_equipment_edited.dds
   # should still be 1024x2048, DXT5
  1. Drop into gamedata, original filename:
   cp ~/stalker_edit/ui_icon_equipment_edited.dds ".../gamedata/textures/ui/ui_icon_equipment.dds"

Verified: the recolored icon (tested on the bandage/booster item) shows correctly in the in-game inventory.

Pitfalls

  • The .thm file next to each .dds is metadata, not something to edit by hand — cat-ing it shows binary garbage, that's expected.
  • Compression format must match the original when converting back (identify -verbose | grep compression tells you which). Wrong format can break loading or corrupt colors/transparency.
  • A logical texture id in an atlas XML doesn't mean a separate file — it's a pixel rectangle inside one shared image.
  • Always keep the working PNG under a different name than the game's .dds name, and only rename to the original name at the final copy step into gamedata — avoids confusion about which file is the edited one.
  • Note on grid atlases: Weapons that can have attachments (e.g. a silencer) may visually use more grid space than their base icon shows — leave an empty cell to their right rather than placing another icon flush against them (per SDK guide, not independently verified here).

Texture categories (folders under resources/textures/)

Folder Contains
ui/ interface: logos, icons, menus, PDA elements
sign/ in-world signage (stop signs, hospital, radiation, etc.)
wpn/ weapon textures
veh/ vehicle textures
act/ actor/character textures
item/ item/equipment textures
artifact/ artifact icons/models
award/ achievements/rank icons
wall/, roof/, floor/, door/, crete/, briks/, wood/, tile/ building/environment surfaces
terrain/, grnd/, grad/ ground/landscape textures
sky/ sky, clouds
water/ water surfaces
trees/, vine/ vegetation
wind/ wind-affected foliage/effects
glass/, glas/ glass surfaces (note: two similarly named folders exist)
fx/, pfx/, glow/ effects (particles, glow)
decal/, wm/ decals, wall marks (bullet holes, blood, etc.)
lights/ light sources/lamps
detail/ detail/small decorative objects
prop/ props
mtl/ material textures
map/ map/PDA map textures
staff/, controller/ monster-related textures (Bloodsucker/Controller etc.)
intro/, outro/ intro/outro screen textures
internal/ engine-internal textures
editor/, ed/ SDK/editor-only textures (not used in-game)