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 ispadding
(4 bytes) - And if the previous value was
padding
then this is thecount
instead (4 bytes)
- Either
- 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)
- Each object has a
Objects
Object types
Type | Value | Description |
---|---|---|
Shader | 0x7F3552D1 | Contains a list of techniques with shader passes |
Shader Pass | 0x214b1aaf | Contains render and sampler state along with a vertex and pixel shader |
Shader Library | 0x12812C1A | Contains 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 aint
or along
(1 byte)- if
b
is equal to0
value4
, the value of the render state (4 bytes)
- else if
b
is not equal to0
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 aint
or along
(1 byte)- if
b
is equal to0
value4
, the value of the render state (4 bytes)
- else if
b
is not equal to0
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;