Pragma Engine


What is Pragma?

patreon_logo32.png youtube_social_square_red32.png Twitter_Social_Icon_Square_Color32.png Artboard-1_32.png Discord-Logo-Color.png

Pragma is a free, open source custom game engine written in C++. Here is an overview over some of its core features:

Pragma is currently in an early beta, some features may not be fully functional at the moment or are unfinished/experimental.


Pragma also ships with the Pragma Filmmaker, an open source alternative to the Source Filmmaker.

You can use the Book Navigation on the left to navigate to the next page, which has details on how to download and install Pragma.

Click the firefox_2020-08-12_15-57-16.png button at the top right for other topics (such as the API documentation for developers).




System requirements

A Linux build will be available in the future.




Latest Version: PFM v0.4.2 (2021-06-22)




Source Code

Pragma and PFM are both completely open-source on GitHub, which means you can also build them yourself.


Version 1.0.2 [2021-09-13]

Filmmaker v0.4.3







Version 1.0.1 [2021-06-22]

Filmmaker v0.4.2






Version 0.9.15 [2021-05-30]

Filmmaker v0.4.1






Version 0.9.14 [21-04-16]



Version 0.9.13 [2021-03-14]



Version 0.9.12 [2021-02-08]



Version 0.9.11 [2020-11-11]



Version 0.9.10



Pragma crashes on startup

If Pragma crashes on startup, please ensure that your system fulfills the system requirements and that your graphics drivers are up to date.

If you have multiple GPUs, please make sure to enable your high-default GPU as the default for Pragma. You can follow the instructions on this page to do so.


There is no text in the main menu

Try adding -graphics_api vulkan to the launch options in Pragma to switch to the Vulkan renderer:



I have an AMD GPU and Pragma/PFM crashes on startup

This should be fixed in newer versions of PFM, until they are released publicly, you can try this temporary fix:

  1. Go to the Pragma root folder
  2. Remove the `cache` directory
  3. Go to `Pragma/shaders/world/eye/`
  4. Rename `fs_eye.gls` to `fs_eye_bak.gls`
  5. Launch PFM

Character eyes won't be rendered properly in the real-time render viewport, but it shouldn't be freezing anymore.

Asset Import / Export


Pragma comes with the following export capabilities:

Exporting Assets

If you want to export a model or material, the easiest way to do so is via the Filmmaker interface. Simply open the model/material catalog, right click on the model icon, then click "Export asset":


If you want to export a different asset type, or need more control, you can use the export command utility instead. To use it, start a game in Pragma first. You can either load a map (which map doesn't matter), or run "map empty" in the console. Once the map has been loaded, you can use the "util_export_asset" console command with the following parameters:

Models only:

If you want to use Pragma to export Source Engine assets, you generally don't have to copy any of the assets to Pragma, the Engine should be able to locate the assets automatically as long as they're part of one of your installed Source Engine games on Steam.


Usage Examples

Exporting a material (including textures):

util_export_asset -material "brick/brick_1a" -verbose -image_format png

Exporting a texture:

util_export_asset -texture "concrete/concrete_5_floor_3_psd_918fcd2d" -verbose -image_format png

Exporting a map:

util_export_asset -map "gm_construct" -verbose -export_images 1 -image_format png -generate_ao 0 -export_animations 0

Exporting a model:

util_export_asset -model "props_2fort/tank001" -verbose -image_format png -generate_ao 0

(Make sure to remove the ".mdl" extension!)

Exporting a Source 2 model:

util_export_asset -model "characters/gman/gman" -verbose -image_format png -generate_ao 0

Batch-exporting all models in a directory and all sub-directories:

util_export_asset -model "props_2fort" -verbose -image_format png -generate_ao 0 -recursive 1


Exporting to Source Engine

You can also use the command to export a model to the Source Engine .mdl format. To do so, simply set the "format" parameter to "mdl":

util_export_asset -model "props_2fort/tank001" -format "mdl"

Most of the parameters listed above will have no effect when using the Source Engine mdl-exporter!

This will automatically generate the QC and SMD files for the model, convert the textures to vtf, convert the materials to vmt, as well as automatically compile the model using studiomdl. Pragma will attempt to locate studiomdl automatically, but you can also specify which game's studiomdl should be used:

util_export_asset -model "props_2fort/tank001" -format "mdl" -game "tf2"

This will use the studiomdl from TF2. The game name has to match the entry from "Pragma/cfg/mounted_games.udm" (You can open the file in a text-editor).

If the model's materials use PBR, the exporter will also automatically apply fake PBR for use in SFM.

All of the model's animations will be included in the Source Engine model as well, however morph targets are currently not supported.

Using Pragma to convert models from Blender to Source

Converting a model from Blender (or other modelling programs) is very simple. All you have to do is export your model from Blender in either the glTF format, or the glb format and copy the exported file to "Pragma/addons/imported/models". Then use the command above and replace the model name with the name of the glTF/glb file (without the extension).


Source 2

The approach for Source 2 assets is exactly the same as for Source 1 assets, with the exception of maps. To export a Source 2 map, follow these steps (using Half-Life: Alyx as an example):

  1. Open the map's vpk-file (steamapps/common/Half-Life Alyx/game/hlvr/maps) in GCFScape
  2. Extract all of the files from the vpk to "Pragma/addons/imported/"
  3. Run the "util_export_asset" command with the asset name pointing to the "vwrld_c"-file. For example, for the map "a5_vault", you should use:
util_export_asset -map "a5_vault/world" -verbose -export_images 1 -image_format png -generate_ao 0



If you want to import a model from Blender (or other modelling programs), all you have to do is export the model in the glTF or glb format and copy the exported file to "Pragma/addons/imported/models". The model should automatically show up in the PFM model catalog and it will automatically get converted (along with the textures) when used.

Source Engine / Source 2

If you want to import a model (or material/texture) from Source or Source 2, you generally don't have to do anything. All of your installed Source Engine games (assuming they're installed via Steam) should be automatically detected and mounted by Pragma. In the rare event that this doesn't work, you can try adding the mount path for the game to "Pragma/cfg/mounted_games.udm".

Alternatively you can also simply extract the asset files to "Pragma/addons/imported/models" and "Pragma/addons/imported/materials" respectively.

File Types

TODO: This is a stub






UDM (Unified Data Model)

Property Types

ASCII-Name Size in bytes C++ Type Notes ASCII Value format
Trivial Types        
nil 0 void   nil
int8 1 int8_t   ?
uint8 1 uint8_t   ?
int16 2 int16_t   ?
uint16 2 uint16_t   ?
int32 4 int32_t   ?
uint32 4 uint32_t   ?
int64 8 int64_t   ?
uint64 8 uint64_t   ?
float 4 float   ?
double 8 double   ?
bool 1 bool   true/1 or false/0
vec2 8 glm::vec2   [x,y]
vec3 12 glm::vec3   [x,y,z]
vec4 16 glm::vec4   [x,y,z,w]
quat 16 glm::quat   [w,x,y,z]
ang 12 EulerAngles Angles in degrees, rotation order: y-p-r [p,y,r]
srgba 4 uint8_t[4] SRGB color with alpha ?
hdr 6 uint16_t[3]   ?
transform 28 umath::Transform Translation +Rotation [[tx,ty,tz][qw,qx,qy,qz]]
stransform 40 umath::ScaledTransform Translation +Rotation +Scale [[tx,ty,tz][qw,qx,qy,qz],[sx,sy,sz]]
mat4 64 glm::mat4   [[00,01,02,03][10,11,12,13][20,21,22,23][30,31,32,33]]
mat3x4 48 glm::mat3x4   [[00,01,02,03][10,11,12,13][20,21,22,23]]
Non-trivial types        
string Varying (>=1) std::string Null-terminated; ASCII "text"
utf8 Varying (>=1) ?

UTF8 String

Bytes [0-3]: Blob size as uint32

Remaining bytes: Binary data

Base64 encoded
blob Varying (>=8) udm::Blob

Bytes [0-7]: Blob size as uint64

Remaining bytes: Binary data

Base64 encoded

lz4 Varying (>=16) udm::BlobLz4

Bytes [0-7]: Uncompressed size as uint64

Bytes [8-15]: Compressed size as uint64_t

Remaining bytes: LZ4 compressed data

Starts with integer representing uncompressed size, then a semicolon, then the compressed data as Base 64 encoded data string

element Varying (>=4) udm::Element   ?
array Varying (>=5) udm::Array   ?



Field Type Value Notes
identifier char[3] "UDMB"  
version uint32 1  

Immediately after the header follows the root property.



Every element starts with a type, which determines how the following data should be interpreted:

Field Type Value Notes
type uint32_t Type enum  

The type corresponds to the type id column of the Property Types table.


Trivial Types

Trivial types have a constant size


Non-trivial Types

Non-trivial types have varying sizes and special rules associated with them depending on the type.


Strings are ASCII encoded and start with a single byte describing its length:

Field Size in bytes Type Value
length 1 uint8_t [0,255]
longLength 4/0 uint32_t/void  
string length char[length]  

A length of 255 is a special case for long strings! In this case a uint32 (4 byte) follows describing the actual length of the string! That also means that strings cannot be longer than 4,294,967,295 characters.

Immediately after the length follow length number of characters.



Field Type Notes
size uint64_t Size of the buffer
data uint8_t[size] Buffer data


Field Type Notes
compressedSize uint64_t Size of the buffer
uncompressedSize uint64_t Size of the buffer after decompression
compressedData uint8_t[compressedSize] LZ4-compressed data

LZ4 compressed.

Field Type Notes
size uint64_t Total size of the element (including children)
numberOfProperties uint32_t Number of child properties for this element
keyNames std::string[numberOfProperties] Array of key-names for all properties (as null-terminated strings)
properties Property[numberOfProperties] Array of child properties


Field Type Notes
valueType Type Type of the items contained in this array
size uint32_t Number of items in this array
totalSizeInBytes uint64_t/void The combined size of all children in the array.

The "totalSizeInBytes" field only exists if "valueType" is a non-trivial type! For arrays of trivial types, the field can be considered to be of type void!
For trivial array types, the total size can be calculated with size *sizeof(valueType).







Name Type Notes
mass float  
flags.loop bool  


Asset Types


Import +mount



After import: import

After conversion: converted


Asset type File location Supported formats
Model models pmdl, pmdl_b, mdl, vmdl_c, glTF, glb, wmd
Material materials pmat, pmat_b, vmt, vmat_c, wmi
Texture materials dds, ktx, vtf, vtex_c, png, tga, jpg, bmp, psd, gif, hdr, pic
Map maps pmap, pmap_b, bsp, vmf, vmap_c, wld
Particle particles pptsys, pptsys_b
Navigation file maps pnav, pnav_b
Sound file sounds wav, ogg, mp3
Configuration file cfg, scripts, data txt, udm
Savegame   psav, psav_b
Shader shaders gls, spv
PFM project file projects


SFM session file elements/sessions


Green formats are Pragma's primary formats, which are based on Pragma's UDM format. The _b variant denotes the binary version, without the suffix the ASCII version. Either version can be losslessly converted to the other using the "udm_convert" console command.

Red formats are not directly supported, but can be imported, in which case they are automatically converted to the equivalent Pragma format.

Striked-through formats are legacy formats, which may or may not still be supported, but should be avoided.

Bold formats are recommended over alternatives.




All 3D meshes are

animations, etc.



The pmap format contains level information, such as entities, BSP data, lightmap information, etc. It does not contain any level geometry, which is instead stored in separate model files located in "models/maps/<mapName>/...".

AI navigation data is also stored in a separate file in the pnav format. It is not generated automatically, but can be generated using the "nav_generate" console command. If a pnav file exists, it will automatically be loaded on map load.


Pragma supports a wide variety of texture types, however for performance and compatibility reasons, dds with BCn compression is recommended. Using image formats without GPU-supported texture compression may come with a severe performance penalty.

Textures are usually used in conjunction with materials.


Location: materials

Supported formats: pmat, pmat_b, vmt, wmi

Materials in Pragma have the file extension "pmat" and "pmat_b". Vmt materials are also supported, but should only be used for import purposes. Occasionally you may also see "wmi" materials, which is a legacy format and should be avoided.

Material files can be opened and edited in a text-editor (with the exception of "pmat_b"). Every material has a single base block,


Navigation files contain nav meshes required for AI to properly navigate on maps. Without a nav-mesh file, NPCs may run into walls and get stuck on obstacles frequently.

A nav-mesh file can be generated using the "nav_generate" console command after loading the map for which to generate it for.


Location: particles

Supported formats: pptsys, pptsys_b

Sound Files




Configuration Files