Extracts and helps identify shaders from Unreal material shadermaps. Supports materials from UE4.25 and above.
- Download FModel.
- Enable "Serialize Inline Shader Maps" in Settings.

Depending on whether or not your game uses shader archives, the first steps will be different.
- Export a JSON of your material from FModel.
- With Python 3, run this command:
python parseAndDecompressShaders.py (exported JSON file). Make suredecompress_shader.exeis in the same directory. This will extract and decompress the DXBC/DXIL shaders from the exported JSON.
- If your game is Unreal Engine 5 and uses IO Store, you'll need to use retoc to convert the containers to .pak files. Then, continue the following steps using paks only, not the ucas/utoc files.
- Export the shader archive as both JSON and binary from FModel.
- In your material, search for "ResourceHash". Store the hash for the next step.
- With Python 3, run this command:
python extractShaderFromArchive.py (exported JSON file) (exported archive binary) (hash) (output name). Make suredecompress_shader.exeis in the same directory. This will extract and decompress the DXBC/DXIL shaders from the exported JSON and archive, using the hash to identify the shadermap.
- Dump FNames from your game using your preferred UE4 SDK dumper. If you can't do this, skip to step 3.
- Navigate to the ShaderHash folder, and run this command:
shaderhash (FName string) (FName internal number). You should run this command for a vertex factory (eg. FLocalVertexFactory) and a shader type (eg. TBasePassPSFNoLightMapPolicy). This will print the hashes for the given names. Skip to step 4. - Take the vertex factory type name and shader hashes from the list at the bottom of this README. For a skeletal mesh, you want FGPUSkinPassthroughVertexFactory for the vertex factory, TBasePassVSFNoLightMapPolicy for the vertex shader, and TBasePassPSFNoLightMapPolicy for the pixel shader.
- In the exported JSON, search for the vertex factory hash. This should bring you to "VertexFactoryTypeName". Then, search for the shader type hash. This should be in the "ShaderTypes" array right below the VertexFactoryTypeName. Then, in the "Shaders" array below it, find the shader at the same index as the shader type hash. Search for "ResourceIndex". The value right next to it is the index of the exported DXBC/DXIL file that contains the code for that shader (eg. ResourceIndex 10, {MaterialName}.json10.dxbc).
- For easier analysis of the shader, run this tool on the exported DXBC files: https://github.com/Quon/HLSLDecompiler/releases/tag/0.2
- In the case of DXIL files, use https://github.com/microsoft/DirectXShaderCompiler to disassemble the shaders.
Note: replace preshaderToUniformBuffer.py with the one that fits your UE4/5 version.
- With Python 3, run this command:
python extractPreshader.py (exported JSON file). This will output a new file in the directory, with "_preshader.bin" at the end. - With Python 3, run this command:
python preshaderToUniformBuffer.py (exported JSON file). This will output a new JSON in the directory, with "_preshader.json" at the end. - The last cbuffer in your decompiled shader should be the "Material" cbuffer, which this preshader JSON maps to.
- UE5:
- Numeric parameters are packed to form four floats. Packing works as follows:
- Float1: cbuffer[i].(x)(y)(z)(w). Can start at any part of the index.
- Float2: cbuffer[i].(xy)(zw). Can start at the front or the middle of the index.
- Float3: cbuffer[i].xyz. Must start at the front of the index.
- Float4: cbuffer[i].xyzw. Must start at the front of the index, and is always a full index.
- Numeric parameters are packed to form four floats. Packing works as follows:
- UE5:
FLocalVertexfactory: 11475683181038621400
FGPUSkinPassthroughVertexFactory: 7884826846012382956
FParticleSpriteVertexFactory: 1936260693301728965
FMeshParticleVertexFactory: 3257961110001812583
FNiagaraSpriteVertexFactory: 13168243933419104092
FNiagaraMeshVertexFactory: 3257961110001812583
FNiagaraRibbonVertexFactory: 549208615835106585
TBasePassVSFNoLightMapPolicy: 16833942227387653686
TBasePassPSFNoLightMapPolicy: 4974208445782451494