Textures & Materials¶
Fallout 4 uses two formats for surface data: DDS for texture images and BGSM/BGEM for material definitions that reference those textures and control shading parameters.
Material Organization¶
The material system in FO4 has four distinct concepts:
- MaterialObjects are visual appearance presets referenced by objects in the ESM.
- TextureSets (TXST records) contain the actual diffuse/normal/specular/glow/etc. texture paths.
- MaterialSwaps (MSWP records) are runtime material substitutions that let variants of the same model render with different surfaces (see Material Swaps).
- MaterialTypes (MATT records) define physics and surface behavior (footstep sounds, impact effects, friction, restitution) and are separate from the visual material system.
The two on-disk material file formats (.bgsm and .bgem) are referenced from NIF meshes
and define shading parameters and texture slot bindings.
DDS (DirectDraw Surface)¶
Standard Microsoft texture format. FO4 textures are stored in BA2 archives as DX10-type entries (see BA2) and can also appear as loose files.
DDS File Header¶
magic uint32 — 0x20534444 ("DDS ")
header_size uint32 — 124
flags uint32 — DDSD_* bitfield
height uint32
width uint32
pitch_or_linear_size uint32
depth uint32
mip_map_count uint32
reserved1 uint32[11]
pixel_format DDSPF (32 bytes, see below)
caps uint32
caps2 uint32
caps3 uint32
caps4 uint32
reserved2 uint32
When pixel_format.flags has DDPF_FOURCC and fourCC == "DX10", a DX10 extended header
follows immediately after the main header:
dxgi_format uint32 — DXGI_FORMAT enum
resource_dim uint32 — 3 = texture2D
misc_flag uint32 — 4 = cubemap
array_size uint32
misc_flags2 uint32
Common FO4 Texture Formats¶
| DXGI Format | FourCC | Use |
|---|---|---|
| BC1_UNORM (71) | DXT1 | Opaque diffuse maps |
| BC3_UNORM (77) | DXT5 | Diffuse with alpha |
| BC4_UNORM (80) | ATI1 | Single-channel masks (gloss, env mask) |
| BC5_UNORM (83) | ATI2 | Normal maps — stores X and Y; Z = sqrt(1-X²-Y²) |
| BC7_UNORM (98) | — | High-quality RGBA (newer assets) |
| R8G8B8A8_UNORM (28) | — | Uncompressed RGBA |
Texture Slots (by NIF BSShaderTextureSet index)¶
| Index | Role | Notes |
|---|---|---|
| 0 | Diffuse / albedo | sRGB |
| 1 | Normal map | BC5 XY; reconstruct Z |
| 2 | Environment mask | Grayscale; controls env map intensity |
| 3 | Glow / emissive | sRGB |
| 4 | Height / parallax | Grayscale |
| 5 | Environment / cube map | sRGB |
| 6 | Inner layer / backlight | sRGB |
| 7 | Specular / smoothness | Grayscale (R) + smoothness (A) |
Texture Path Conventions¶
All paths in NIF and BGSM/BGEM files are relative to the Data\ directory:
textures\architecture\buildings\brickwall01_d.dds ← diffuse
textures\architecture\buildings\brickwall01_n.dds ← normal
textures\architecture\buildings\brickwall01_s.dds ← specular/smooth
Common suffixes:
| Suffix | Meaning |
|---|---|
_d |
Diffuse |
_n |
Normal |
_s |
Specular / smoothness |
_g |
Glow / emissive |
_e |
Environment map |
_em |
Environment mask |
_sk |
Skin |
_p |
Height / parallax |
BGSM — Bethesda Material (Lit Surface)¶
BGSM files define material parameters for geometry rendered with BSLightingShaderProperty.
They are plain binary structs with a version prefix.
Extension: .bgsm — stored under Data\Materials\.
File Structure¶
"BGSM" char[4] — magic
version uint32 — determines which optional fields are present
base_object BGEM_Base — shared base class fields (see below)
[type-specific fields]
Base Class (BGSMBase) Fields¶
tile_u bool
tile_v bool
uv_offset_u float32
uv_offset_v float32
uv_scale_u float32 — default 1.0
uv_scale_v float32 — default 1.0
alpha float32 — overall opacity, 0.0–1.0 (default 1.0)
alpha_blend_mode uint8 — 0=None, 1=Standard, 2=Additive, 3=Multiplicative
alpha_test_ref uint8 — cutoff threshold 0–255 (default 128)
alpha_test bool — enable alpha test
z_buffer_write bool — write to depth buffer (default true)
z_buffer_test bool — test against depth buffer (default true)
screen_space_reflections bool
wetting_occlusion_map bool
decal bool
two_sided bool
decal_no_fade bool
non_occluder bool
refraction bool
refraction_falloff bool
refraction_power float32
environment_mapping bool — (v ≤ 2)
environment_mapping_mask float32 — (v ≤ 2)
grayscale_to_palette_color bool
mask_writes uint8 — bitfield: ALBEDO=1, NORMAL=2, SPECULAR=4, AO=8, EMISSIVE=16, GLOSS=32 (v ≥ 6)
BGSM-Specific Fields¶
diffuse_texture string
normal_texture string
smooth_spec_texture string
greyscale_texture string
env_map_texture string — (v ≤ 2)
glow_texture string
inner_layer_texture string — (v ≤ 2)
wrinkles_texture string — (v ≤ 2)
displacement_texture string
specular_texture string — (v ≥ 3)
lighting_texture string — (v ≥ 3)
flow_texture string — (v ≥ 3)
distance_field_alpha_texture string — (v ≥ 17)
enable_editor_alpha_ref bool
translucency bool — (v ≥ 8)
translucency_thick bool
translucency_mixed_with_normal bool
translucency_subsurface_color Color3 (3× float32)
translucency_transmissive_scale float32
translucency_turbulence float32
rim_lighting bool
rim_power float32
backlight_power float32
subsurface_lighting bool
subsurface_lighting_rolloff float32
specular_enabled bool
specular_color Color3 (3× float32)
specular_mult float32 — default 1.0
smoothness float32 — inverse roughness; 1.0 = mirror
fresnel_power float32 — default 5.0
wetting_control_spec_scale float32
wetting_control_spec_power float32
wetting_control_spec_min_var float32
wetting_control_env_map_scale float32
wetting_control_fresnel_power float32
wetting_control_metalness float32
pbr bool — (v ≥ 3)
custom_porosity bool — (v ≥ 3)
porosity_value float32 — (v ≥ 3)
hair_soft_lighting bool
hair_softness float32
emit_enabled bool
emittance_color Color3 — (if emit_enabled)
emittance_mult float32 — (if emit_enabled)
model_space_normals bool
external_emittance bool
lum_emittance float32 — (v ≥ 12)
use_adaptive_emissive bool — (v ≥ 13)
adaptive_emissive_exposure_offset float32
adaptive_emissive_final_exposure_min float32
adaptive_emissive_final_exposure_max float32
back_lighting bool
receive_shadows bool
hide_secret bool
cast_shadows bool
dissolvefade bool
assume_shadowmask bool
glowmap bool
environment_mapping_window bool
environment_mapping_eye bool
tessellate bool
displacement_tex_bias float32
displacement_tex_scale float32
tessellation_pn_scale float32
tessellation_base_factor float32
tessellation_fade_distance float32
grayscale_to_palette_scale float32
skew_specular_alpha bool — (v ≥ 1)
terrain bool — (v ≥ 3)
terrain_threshold_falloff float32
terrain_tiling_distance float32
terrain_rotation_angle float32
BGEM — Bethesda Material (Effect Shader)¶
BGEM files define material parameters for geometry rendered with BSEffectShaderProperty.
Used for particles, triggers, glass, atmospheric effects, and other non-standard surfaces.
Extension: .bgem — stored under Data\Materials\.
File Structure¶
"BGEM" char[4] — magic
version uint32
base BGSMBase — same base class as BGSM
[effect-specific fields]
BGEM-Specific Fields¶
base_texture string
greyscale_texture string
env_map_texture string
normal_texture string
env_mask_texture string
specular_texture string — (v ≥ 11)
lighting_texture string — (v ≥ 11)
glow_texture string — (v ≥ 11)
blood_enabled bool
effect_lighting_enabled bool
falloff_enabled bool
falloff_color_enabled bool
grayscale_to_palette_alpha bool
soft_enabled bool
base_color Color4 (4× float32)
base_color_scale float32
falloff_start_angle float32
falloff_stop_angle float32
falloff_start_opacity float32
falloff_stop_opacity float32
lighting_influence uint8
env_map_min_lod uint8
soft_depth float32
emit_enabled bool
emittance_color Color3 — (if emit_enabled)
emittance_mult float32 — (if emit_enabled)
model_space_normals bool
external_emittance bool
lum_emittance float32 — (v ≥ 12)
use_adaptive_emissive bool — (v ≥ 13)
adaptive_emissive_exposure_offset float32
adaptive_emissive_final_exposure_min float32
adaptive_emissive_final_exposure_max float32
effect_pbrspecular bool
glass_enabled bool — (v ≥ 21)
glass_roughness_scratch_texture string
glass_dirt_overlay_texture string
glass_dirt_overlay_alpha float32
glass_dirt_overlay_normal_strength float32
glass_fresnel_color Color3
glass_refraction_scale_base float32
glass_blur_scale_base float32
glass_blur_scale_base2 float32
Alpha Blending Modes¶
Both BGSM and BGEM share the same alpha_blend_mode enum:
| Value | Mode | Blend equation |
|---|---|---|
| 0 | None | Opaque |
| 1 | Standard | src_alpha × src + (1 − src_alpha) × dst |
| 2 | Additive | src + dst |
| 3 | Multiplicative | src × dst |
Alpha testing (alpha_test = true) discards pixels where the alpha channel is below
alpha_test_ref / 255.0, regardless of blend mode.
Greyscale-to-Palette System¶
Many FO4 diffuse textures are not color images — they are grayscale intensity masks that the
runtime shader combines with a small color look-up table (LUT) to produce the final pixel color.
Materials that use this path have a non-empty greyscale_texture field pointing to the LUT,
grayscale_to_palette_color = true, and a grayscale_to_palette_scale modulator.
How it works at runtime¶
- The diffuse texture (e.g.
bricks01_d.dds) stores only luminance information. Decoded RGB values look washed-out or purple/lavender because the DXT1 block colors are packed for indexing, not display. - The LUT (e.g.
Bricks01Grad01.dds) is a tiny uncompressed BGRA gradient — typically 32 × 128 pixels. Each row is one output color; rows are indexed top-to-bottom by luminance. - For every rendered pixel the shader computes a perceptual luminance from the diffuse sample, converts it to a LUT row index, and reads the gradient color from the middle column of that row. That color replaces the sampled diffuse RGB.
LUT sampling¶
gray = int(0.299*r + 0.587*g + 0.114*b) # perceptual luminance
row = min(int(gray * 128 / 256), 127) # map 0..255 → 0..127
color = lut[row] # read middle column (x = 16) of that row
The LUT DDS is uncompressed BGRA, so its pixel data starts at byte 128 (after the 128-byte DDS header) and every pixel is 4 bytes in BGRA order.
Detecting palette-indexed diffuses¶
If a _d.dds decodes to an average purple/lavender hue (high R and B, low G) and its BGSM has
a non-empty greyscale_texture, it is a palette source — do not treat the raw RGB as the final
color.
Remap Textures¶
FO4's layered-material shader supports per-material color tinting through "remap" palette
textures. Their filenames contain the token remap (e.g. ResidentialSidingRemap01_d.dds,
RetailTrimRemap01_d.dds). Decoded directly, they appear flat purple/magenta because they
store a tint palette, not a finished color image.
The non-remap sibling texture (same name with remap stripped — e.g. ResidentialSiding01_d.dds)
is the properly colored base texture that ships alongside it.
To substitute a remap texture with its base version, strip remap from the filename only
(leave the directory path intact). Only strip when remap is a standalone token — i.e. not
followed by another letter — so names like remapped or remapping are left alone.
String Encoding in BGSM/BGEM¶
All string fields use a length-prefixed format:
An empty string has length = 0 with no following bytes.