Skip to content

Chapter 4.3: Materials (.rvmat)

Home | << Previous: 3D Models | Materials | Next: Audio >>


Introduction

A material in DayZ is the bridge between a 3D model and its visual appearance. While textures provide raw image data, the RVMAT (Real Virtuality Material) file defines how those textures are combined, which shader interprets them, and what surface properties the engine should simulate -- shininess, transparency, self-illumination, and more. Every face on every P3D model in the game references an RVMAT file, and understanding how to create and configure them is essential for any visual mod.

This chapter covers the RVMAT file format, shader types, texture stage configuration, material properties, the damage-level material swap system, and practical examples drawn from DayZ-Samples.


Table of Contents


RVMAT Format Overview

An RVMAT file is a text-based configuration file (not binary) that defines a material. Despite the custom extension, the format is plain text using Bohemia's config-style syntax with classes and key-value pairs.

Key Characteristics

  • Text format: Editable in any text editor (Notepad++, VS Code).
  • Shader binding: Each RVMAT specifies which rendering shader to use.
  • Texture mapping: Defines which texture files are assigned to which shader inputs (diffuse, normal, specular, etc.).
  • Surface properties: Controls specular intensity, emissive glow, transparency, and more.
  • Referenced by P3D models: Faces in Object Builder's Resolution LOD are assigned an RVMAT. The engine loads the RVMAT and all textures it references.
  • Referenced by config.cpp: hiddenSelectionsMaterials[] can override materials at runtime.

Path Convention

RVMAT files live alongside their textures, typically in a data/ directory:

MyMod/
  data/
    my_item.rvmat              <-- Material definition
    my_item_co.paa             <-- Diffuse texture (referenced by the RVMAT)
    my_item_nohq.paa           <-- Normal map (referenced by the RVMAT)
    my_item_smdi.paa           <-- Specular map (referenced by the RVMAT)

File Structure

An RVMAT file has a consistent structure. Here is a complete, annotated example:

cpp
ambient[] = {1.0, 1.0, 1.0, 1.0};        // Ambient color multiplier (RGBA)
diffuse[] = {1.0, 1.0, 1.0, 1.0};        // Diffuse color multiplier (RGBA)
forcedDiffuse[] = {0.0, 0.0, 0.0, 0.0};  // Additive diffuse override
emmisive[] = {0.0, 0.0, 0.0, 0.0};       // Emissive (self-illumination) color
specular[] = {0.7, 0.7, 0.7, 1.0};       // Specular highlight color
specularPower = 80;                        // Specular sharpness (higher = tighter highlight)
PixelShaderID = "Super";                   // Shader program to use
VertexShaderID = "Super";                  // Vertex shader program

class Stage1                               // Texture stage: Normal map
{
    texture = "MyMod\data\my_item_nohq.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

class Stage2                               // Texture stage: Diffuse/Color map
{
    texture = "MyMod\data\my_item_co.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

class Stage3                               // Texture stage: Specular/Metallic map
{
    texture = "MyMod\data\my_item_smdi.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

Top-Level Properties

These are declared before the Stage classes and control the material's overall behavior:

PropertyTypeDescription
ambient[]float[4]Ambient light color multiplier. {1,1,1,1} = full, {0,0,0,0} = no ambient.
diffuse[]float[4]Diffuse light color multiplier. Usually {1,1,1,1}.
forcedDiffuse[]float[4]Additive override to diffuse. Usually {0,0,0,0}.
emmisive[]float[4]Self-illumination color. Non-zero values make the surface glow. Note: Bohemia uses the misspelling emmisive, not emissive.
specular[]float[4]Specular highlight color and intensity.
specularPowerfloatSharpness of specular highlights. Range 1-200. Higher = tighter, more focused reflection.
PixelShaderIDstringName of the pixel shader program.
VertexShaderIDstringName of the vertex shader program.

Shader Types

The PixelShaderID and VertexShaderID values determine which rendering pipeline processes the material. Both should usually be set to the same value.

Available Shaders

ShaderUse CaseTexture Stages Required
SuperStandard opaque surfaces (weapons, clothing, items)Normal, Diffuse, Specular/Metallic
MultiMulti-layered terrain and complex surfacesMultiple diffuse/normal pairs
GlassTransparent and semi-transparent surfacesDiffuse with alpha
WaterWater surfaces with reflection and refractionSpecial water textures
TerrainTerrain ground surfacesSatellite, mask, material layers
NormalMapSimplified normal-mapped surfaceNormal, Diffuse
NormalMapSpecularNormal-mapped with specularNormal, Diffuse, Specular
HairCharacter hair renderingDiffuse with alpha, special translucency
SkinCharacter skin with subsurface scatteringDiffuse, Normal, Specular
AlphaTestHard-edge transparency (foliage, fences)Diffuse with alpha
AlphaBlendSmooth transparency (glass, smoke)Diffuse with alpha

Super Shader (Most Common)

The Super shader is the standard physically-based rendering shader used for the vast majority of items in DayZ. It expects these core texture stages (matching real gorka_normal.rvmat):

Stage1 = Normal map (_nohq)
Stage2 = Diffuse/Color map (_co)
Stage3 = Macro map (_mc)
Stage4 = Ambient Shadow (_as)
Stage5 = Specular/Metallic map (_smdi)
Stage6 = Fresnel (_fr)
Stage7 = Environment map (_env)

If you are creating a mod item (weapon, clothing, tool, container), you will almost always use the Super shader.

Glass Shader

The Glass shader handles transparent surfaces. It reads alpha from the diffuse texture to determine transparency:

cpp
PixelShaderID = "Glass";
VertexShaderID = "Glass";

class Stage1
{
    texture = "MyMod\data\glass_nohq.paa";
    uvSource = "tex";
    class uvTransform { /* ... */ };
};

class Stage2
{
    texture = "MyMod\data\glass_ca.paa";    // Note: _ca suffix for color+alpha
    uvSource = "tex";
    class uvTransform { /* ... */ };
};

Texture Stages

Each Stage class in the RVMAT assigns a texture to a specific shader input. The stage number determines what role the texture plays.

Stage Assignments for the Super Shader

StageTexture RoleTypical SuffixDescription
Stage1Normal map_nohqSurface detail, bumps, grooves
Stage2Diffuse / Color map_co or _caBase color of the surface
Stage3Macro map_mcLarge-scale color variation
Stage4Ambient Shadow_asPre-baked ambient occlusion (optional)
Stage5Specular / Metallic map_smdiShininess, metallic properties, detail
Stage6Fresnel_frFresnel reflection intensity (optional)
Stage7Environment map_envEnvironment/reflection map (optional)

Stage Properties

Each stage contains:

cpp
class Stage1
{
    texture = "path\to\texture.paa";    // Path relative to P: drive
    uvSource = "tex";                    // UV source: "tex" (model UVs) or "tex1" (2nd UV set)
    class uvTransform                    // UV transformation matrix
    {
        aside[] = {1.0, 0.0, 0.0};     // U-axis scale and direction
        up[] = {0.0, 1.0, 0.0};        // V-axis scale and direction
        dir[] = {0.0, 0.0, 0.0};       // Not typically used
        pos[] = {0.0, 0.0, 0.0};       // UV offset (translation)
    };
};

UV Transform for Tiling

To tile a texture (repeat it across a surface), modify the aside and up values:

cpp
class uvTransform
{
    aside[] = {4.0, 0.0, 0.0};     // Tile 4x horizontally
    up[] = {0.0, 4.0, 0.0};        // Tile 4x vertically
    dir[] = {0.0, 0.0, 0.0};
    pos[] = {0.0, 0.0, 0.0};
};

This is commonly used for terrain materials and building surfaces where the same detail texture repeats.


Material Properties

Specular Control

The specular[] and specularPower values work together to define how shiny a surface appears:

Material Typespecular[]specularPowerAppearance
Matte plastic{0.1, 0.1, 0.1, 1.0}10Dull, wide highlight
Worn metal{0.3, 0.3, 0.3, 1.0}40Moderate shine
Polished metal{0.8, 0.8, 0.8, 1.0}120Bright, tight highlight
Chrome{1.0, 1.0, 1.0, 1.0}200Mirror-like reflection
Rubber{0.02, 0.02, 0.02, 1.0}5Almost no highlight
Wet surface{0.6, 0.6, 0.6, 1.0}80Slick, medium-sharp highlight

Emissive (Self-Illumination)

To make a surface glow (LED lights, screens, glowing elements):

cpp
emmisive[] = {0.2, 0.8, 0.2, 1.0};   // Green glow

The emissive color is added to the final pixel color regardless of lighting. An _li emissive map in a later texture stage can mask which parts of the surface glow.

Two-Sided Rendering

For thin surfaces that should be visible from both sides (flags, foliage, cloth):

cpp
renderFlags[] = {"noZWrite", "noAlpha", "twoSided"};

This is not a top-level RVMAT property but is configured in config.cpp or through the material's shader settings depending on the use case.


Health Levels (Damage Material Swaps)

DayZ items degrade over time. The engine supports automatic material swapping at different damage thresholds, defined in config.cpp using the healthLevels[] array. This creates the visual progression from pristine to ruined.

healthLevels[] Structure

cpp
class MyItem: Inventory_Base
{
    // ... other config ...

    healthLevels[] =
    {
        // {health_threshold, {"material_set"}},

        {1.0, {"MyMod\data\my_item.rvmat"}},           // Pristine (100% health)
        {0.7, {"MyMod\data\my_item_worn.rvmat"}},       // Worn (70% health)
        {0.5, {"MyMod\data\my_item_damaged.rvmat"}},     // Damaged (50% health)
        {0.3, {"MyMod\data\my_item_badly_damaged.rvmat"}},// Badly Damaged (30% health)
        {0.0, {"MyMod\data\my_item_ruined.rvmat"}}       // Ruined (0% health)
    };
};

How It Works

  1. The engine monitors the item's health value (0.0 to 1.0).
  2. When health drops below a threshold, the engine swaps the material to the corresponding RVMAT.
  3. Each RVMAT can reference different textures -- typically progressively more damaged-looking variants.
  4. The swap is automatic. No script code is needed.

Damage Texture Progression

A typical damage progression:

LevelHealthVisual Change
Pristine1.0Clean, factory-new appearance
Worn0.7Slight scuffing, minor scratches
Damaged0.5Visible scratches, discoloration, dirt
Badly Damaged0.3Heavy wear, rust, cracks, peeling paint
Ruined0.0Severely degraded, broken appearance

Creating Damage Materials

For each damage level, create a separate RVMAT that references progressively more damaged textures:

data/
  my_item.rvmat                    --> my_item_co.paa (clean)
  my_item_worn.rvmat               --> my_item_worn_co.paa (light damage)
  my_item_damaged.rvmat            --> my_item_damaged_co.paa (moderate damage)
  my_item_badly_damaged.rvmat      --> my_item_badly_damaged_co.paa (heavy damage)
  my_item_ruined.rvmat             --> my_item_ruined_co.paa (destroyed)

Tip: You do not always need unique textures for every damage level. A common optimization is to share the normal and specular maps across all levels and only change the diffuse texture:

my_item.rvmat           --> my_item_co.paa
my_item_worn.rvmat      --> my_item_co.paa  (same diffuse, lower specular)
my_item_damaged.rvmat   --> my_item_damaged_co.paa
my_item_ruined.rvmat    --> my_item_ruined_co.paa

Using Vanilla Damage Materials

DayZ provides a set of generic damage overlay materials that can be used if you do not want to create custom damage textures:

cpp
healthLevels[] =
{
    {1.0, {"MyMod\data\my_item.rvmat"}},
    {0.7, {"DZ\data\data\default_worn.rvmat"}},
    {0.5, {"DZ\data\data\default_damaged.rvmat"}},
    {0.3, {"DZ\data\data\default_badly_damaged.rvmat"}},
    {0.0, {"DZ\data\data\default_ruined.rvmat"}}
};

How Materials Reference Textures

The connection between models, materials, and textures forms a chain:

P3D Model (Object Builder)
  |
  |--> Face assigned to RVMAT
         |
         |--> Stage1.texture = "path\to\normal_nohq.paa"
         |--> Stage2.texture = "path\to\color_co.paa"
         |--> Stage3.texture = "path\to\specular_smdi.paa"

Path Resolution

All texture paths in RVMAT files are relative to the P: drive root:

cpp
// Correct: relative to P: drive
texture = "MyMod\data\textures\my_item_co.paa";

// This means: P:\MyMod\data\textures\my_item_co.paa

When packed into a PBO, the path prefix must match the PBO's prefix:

PBO prefix: MyMod
Internal path: data\textures\my_item_co.paa
Full reference: MyMod\data\textures\my_item_co.paa

hiddenSelectionsMaterials Override

Config.cpp can override which material is applied to a named selection at runtime:

cpp
class MyItem_Green: MyItem
{
    hiddenSelections[] = {"camo"};
    hiddenSelectionsTextures[] = {"MyMod\data\my_item_green_co.paa"};
    hiddenSelectionsMaterials[] = {"MyMod\data\my_item_green.rvmat"};
};

This allows creating item variants (color schemes, camo patterns) that share the same P3D model but use different materials.


Creating an RVMAT from Scratch

Step-by-Step: Standard Opaque Item

  1. Create your texture files:

    • my_item_co.paa (diffuse color)
    • my_item_nohq.paa (normal map)
    • my_item_smdi.paa (specular/metallic)
  2. Create the RVMAT file (plain text):

cpp
ambient[] = {1.0, 1.0, 1.0, 1.0};
diffuse[] = {1.0, 1.0, 1.0, 1.0};
forcedDiffuse[] = {0.0, 0.0, 0.0, 0.0};
emmisive[] = {0.0, 0.0, 0.0, 0.0};
specular[] = {0.5, 0.5, 0.5, 1.0};
specularPower = 60;
PixelShaderID = "Super";
VertexShaderID = "Super";

class Stage1
{
    texture = "MyMod\data\my_item_nohq.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

class Stage2
{
    texture = "MyMod\data\my_item_co.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

class Stage3
{
    texture = "MyMod\data\my_item_smdi.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};
  1. Assign in Object Builder:

    • Open your P3D model.
    • Select faces in the Resolution LOD.
    • Right-click --> Face Properties.
    • Browse to your RVMAT file.
  2. Test in-game via file patching or PBO build.


Real Examples

DayZ-Samples Test_ClothingRetexture

The official DayZ-Samples include a Test_ClothingRetexture example that demonstrates the standard material workflow:

cpp
// From DayZ-Samples retexture example
ambient[] = {1.0, 1.0, 1.0, 1.0};
diffuse[] = {1.0, 1.0, 1.0, 1.0};
forcedDiffuse[] = {0.0, 0.0, 0.0, 0.0};
emmisive[] = {0.0, 0.0, 0.0, 0.0};
specular[] = {0.3, 0.3, 0.3, 1.0};
specularPower = 50;
PixelShaderID = "Super";
VertexShaderID = "Super";

class Stage1
{
    texture = "DZ_Samples\Test_ClothingRetexture\data\tshirt_nohq.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

class Stage2
{
    texture = "DZ_Samples\Test_ClothingRetexture\data\tshirt_co.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

class Stage3
{
    texture = "DZ_Samples\Test_ClothingRetexture\data\tshirt_smdi.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

Metallic Weapon Material

A polished weapon barrel with high metallic response:

cpp
ambient[] = {1.0, 1.0, 1.0, 1.0};
diffuse[] = {1.0, 1.0, 1.0, 1.0};
forcedDiffuse[] = {0.0, 0.0, 0.0, 0.0};
emmisive[] = {0.0, 0.0, 0.0, 0.0};
specular[] = {0.9, 0.9, 0.9, 1.0};        // High specular for metal
specularPower = 150;                        // Tight, focused highlight
PixelShaderID = "Super";
VertexShaderID = "Super";

// ... Stage definitions with weapon textures ...

Emissive Material (Glowing Screen)

A material for a device screen that emits light:

cpp
ambient[] = {1.0, 1.0, 1.0, 1.0};
diffuse[] = {1.0, 1.0, 1.0, 1.0};
forcedDiffuse[] = {0.0, 0.0, 0.0, 0.0};
emmisive[] = {0.05, 0.3, 0.05, 1.0};      // Soft green glow
specular[] = {0.5, 0.5, 0.5, 1.0};
specularPower = 80;
PixelShaderID = "Super";
VertexShaderID = "Super";

// ... Stage definitions including _li emissive map in Stage7 ...

Common Mistakes

1. Wrong Stage Order

Symptom: Texture appears scrambled, normal map shows as color, color shows as bumps. Fix: Ensure Stage1 = normal, Stage2 = diffuse, Stage3 = macro, Stage5 = specular (for the Super shader). See the Stage Assignments table above.

2. Misspelling emmisive

Symptom: Emissive does not work. Fix: Bohemia uses emmisive (double m, single s). Using the correct English spelling emissive will not work. This is a known historical quirk.

3. Texture Path Mismatch

Symptom: Model appears with default gray or magenta material. Fix: Verify that texture paths in the RVMAT exactly match the file locations relative to P: drive. Paths use backslashes. Check capitalization -- some systems are case-sensitive.

4. Missing RVMAT Assignment in P3D

Symptom: Model renders with no material (flat gray or default shader). Fix: Open the model in Object Builder, select faces, and assign the RVMAT via Face Properties.

5. Using Wrong Shader for Transparent Items

Symptom: Transparent texture appears opaque, or entire surface vanishes. Fix: Use Glass, AlphaTest, or AlphaBlend shader instead of Super for transparent surfaces. Use _ca suffix textures with proper alpha channels.


Best Practices

  1. Start from a working example. Copy an RVMAT from DayZ-Samples or a vanilla item and modify it. Starting from scratch invites typos.

  2. Keep materials and textures together. Store the RVMAT in the same data/ directory as its textures. This makes the relationship obvious and simplifies path management.

  3. Use the Super shader unless you have a reason not to. It handles 95% of use cases correctly.

  4. Create damage materials even for simple items. Players notice when items do not visually degrade. At minimum, use vanilla default damage materials for the lower health levels.

  5. Test specular in-game, not just in Object Builder. The editor lighting and in-game lighting produce very different results. What looks perfect in Object Builder may be too shiny or too dull under DayZ's dynamic lighting.

  6. Document your material settings. When you find specular/power values that work well for a surface type, record them. You will reuse these settings across many items.


Observed in Real Mods

PatternModDetail
Shared damage RVMAT across all itemsExpansion (multiple modules)Reuses a common set of damage-level RVMATs (worn, damaged, ruined) instead of per-item variants to reduce file count
Emissive materials for screen glowCOT (Admin Tools)Uses emmisive[] values in RVMAT for tablet/device screen effects visible at night
Glass shader for vehicle windowsDayZ-Samples (Test_Vehicle)Demonstrates PixelShaderID = "Glass" with _ca textures for transparent windshield panels

Compatibility & Impact

  • Multi-Mod: RVMAT paths are per-PBO and do not collide across mods. However, hiddenSelectionsMaterials[] overrides in config.cpp follow last-loaded-wins priority, so two mods overriding the same vanilla item's material will conflict.
  • Performance: Each unique RVMAT referenced on a single P3D model creates a separate draw call. Consolidating faces under fewer materials reduces GPU overhead, especially for complex scenes.
  • Version: The RVMAT text format and shader names (Super, Glass, AlphaTest) have been stable since DayZ 1.0. No structural changes have been introduced in recent updates.

PreviousUpNext
4.2 3D ModelsPart 4: File Formats & DayZ Tools4.4 Audio

Released under CC BY-SA 4.0 | Code examples under MIT License