Skip to main content

Shader File Format

This file describes the .shaders file format used by Payday 2. It's a custom format used to store the shaders used by the game.

(All values are stored in little endian.)

Headers

The file is structured as follows:

  • The start of the file is the padding and the number of Objects:
    • Either count or -1 (4 bytes)
    • If the previous value was -1, then this is padding (4 bytes)
    • And if the previous value was padding then this is the count instead (4 bytes)
  • A list of Objects:
    • Each object has a type according to Types (4 bytes)
    • A reference id so this object can be referenced to by other objects (4 bytes)
    • The size of the object (4 bytes)
    • The data of the object (size bytes)

Objects

Object types

TypeValueDescription
Shader0x7F3552D1Contains a list of techniques with shader passes
Shader Pass0x214b1aafContains render and sampler state along with a vertex and pixel shader
Shader Library0x12812C1AContains a list of shader templates

Shader Library

The Shader Library Object contains a list of shader templates.

It is structured as follows:

  • count, the number of shader templates (4 bytes)
  • A list of references to shader templates:
    • The lookup8 hash of the shader templates name (8 bytes)
    • The reference id to the shader template object (4 bytes)

Shader

The Shader Object contains a list of techniques each containing a list of passes.

It is structured as follows:

  • count, the number of techniques (4 bytes)
  • A list of techniques:
    • The lookup8 hash of the technique name (8 bytes)
    • count, the number of passes (4 bytes)
      • reference id to the shader pass object (4 bytes)

Shader pass

The Shader Pass Object contains the bulk of the relevant data for the shaders. It contains the render and sampler state along with the vertex and pixel shader.

It is structured as follows:

  • render_state_count, the number of render states (4 bytes)
  • A list of render states according to Render States
  • sampler_state_count, the number of sampler states (4 bytes)
  • A list of sampler states according to Sampler States
  • vertex_shader_size, the size of the vertex shader data (4 bytes)
  • vertex_shader_data, the vertex shader data (vertex_shader_size bytes)
  • pixel_shader_size, the size of the pixel shader data (4 bytes)
  • pixel_shader_data, the pixel shader data (pixel_shader_size bytes)

Render States

A Render State contains information how this shader should render.

It is structured as follows:

  • id, the D3DRENDERSTATETYPE as a 32 bit integer (4 bytes)
  • b, whether is value is a int or a long (1 byte)
  • if b is equal to 0
    • value4, the value of the render state (4 bytes)
  • else if b is not equal to 0
    • value8, the value of the render state (8 bytes)

Sampler States

A Sampler State contains information about how a sampler should sample a texture.

It is structured as follows:

  • id, the id the sampler (4 bytes)
  • state_count, the number of state for this sampler (4 bytes)
  • A list of states:
    • id, the D3DSAMPLERSTATETYPE as a 32 bit integer (4 bytes)
    • b, whether is value is a int or a long (1 byte)
    • if b is equal to 0
      • value4, the value of the render state (4 bytes)
    • else if b is not equal to 0
      • value8, the value of the render state (8 bytes)

ImHex Pattern

import std.sys;
import std.string;

enum ObjectType: u32 {
Shader = 0x7F3552D1,
ShaderPass = 0x214b1aaf,
ShaderLibrary = 0x12812C1A
};

struct Header {
ObjectType type;
u32 ref_id;
u32 size;
};

struct Technique {
u64 hash;
u32 pass_count;
u32 passes[pass_count];
};

struct ShaderRef {
u64 hash;
u32 ref_id;
};

struct StateVar {
u32 id;
u8 b;
if(b == 0) {
u32 value4;
} else {
u64 value8;
}
};

struct SamplerState {
u32 id;
u32 state_count;
StateVar states[state_count];
};

struct ObjectShader {
u32 technique_count;
Technique techniques[technique_count];
};

struct ObjectShaderLibrary {
u32 template_count;
ShaderRef templates[template_count];
};

struct ObjectShaderPass {
u32 render_state_count;
StateVar render_states[render_state_count];
u32 sampler_state_count;
SamplerState sampler_states[sampler_state_count];
u32 vertex_shader_size;
char vertex_shader_bytes[vertex_shader_size];
u32 pixel_shader_size;
char pixel_shader_bytes[pixel_shader_size];
};

struct Object {
Header header;
u32 start = $;

if(header.type == ObjectType::Shader) {
ObjectShader object_shader [[inline]];
} else if(header.type == ObjectType::ShaderLibrary) {
ObjectShaderLibrary object_shader_library [[inline]];
}
else {
ObjectShaderPass object_shader_pass [[inline]];
}

u32 remaining = header.size - ($ - start);

std::assert(remaining == 0,
"Object has invalid size, " + std::string::to_string(remaining) + " remaining");
};

struct FileHeader {
s32 value [[hidden]];
if(value == -1) {
padding[4];
u32 object_count;
} else {
u32 object_count = value;
}

Object objects[object_count];
};

FileHeader header @ 0;