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: 0.9.15 (2021-05-31)


Legacy Versions




This is a standalone (non-steam) version of Pragma. No installation is required, just extract it somewhere and run the "run.bat".

This version does not come with an auto-updater, which means you will have to re-download Pragma whenever there's a new update!
$10 Patrons also get early access to new features and updates!


Source Code

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

Detailed instructions on how to build Pragma will follow.


Version 0.9.15 [2021-05-30]







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.


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:



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