Pragma Filmmaker

Getting Started

SFM to PFM Workflow

Rendering

Material Editor

Actors and Components

Lighting

Expressions and Drivers

External Render Tool

Troubleshooting Getting Started

Filmmaker

The Pragma Filmmaker (PFM) is an addon for the Pragma Engine and is shipped with all Pragma installations by default. See here for information on how to install Pragma. Click here for more information on the Engine itself.

PFM is currently in a very early beta stage, it is not a viable replacement for SFM yet. You can use it for rendering, however the editing capabilities are currently very limited.

The primary goal of this project is an open-, highly moddable alternative to the , with new features and quality of life changes. The project is still in an early state and is funded by Patreon supporters. Some of the current features include:

Support for various Source Engine and Source 2 assets, such as: maps, models, materials, textures, sound-script files and particle systems Support for loading SFM projects/sessions Can automatically locate assets of installed Source Engine / Source 2 games (as well as workshop addons and games) Raytraced rendering with Cycles (the same renderer used by Blender) External rendering tool for rendering in the background Extensive modding support with Lua Support for physically based rendering Audio support for spatial audio* (WIP)

Open source (Source Code available on GitHub) Written in Lua to maximize moddability Import and export capabilities for easy interoperability with Blender etc.

Here's a comparison render between SFM and PFM:

Media

For information on how to load and render your SFM animations with PFM, check out this article. SFM to PFM Workflow

Here are some rough guidelines on how to import and render your SFM project with the Pragma Filmmaker:

1.) Get your SFM project ready

In most cases your SFM project should just work, however there are a few restrictions to keep in mind:

PFM does currently not support IK rigs. If your animation uses any IK rigs, you have to follow these steps in SFM first:

1.) Make sure all transforms for all actors are unlocked:

2.) Detach all rigs from all actors that have one: 3.) Save the session. The animations should now appear in PFM properly.

Also keep in mind that some features (like motion blur) are not yet implemented in PFM and will not work.

2.) Launch PFM and import the Project

You can launch PFM by launching Pragma, clicking "New Game" and changing the game mode to "Filmmaker".

PFM currently doesn't change the map when importing a SFM session, so you will have to select the map in the "New Game" menu before clicking "Start Game"! If you're loading a map for the first time, Pragma will have to convert the map and all of its assets first, which may take several minutes. This only has to be done once for every map/asset, so loading should be faster next time.

Once the Filmmaker has been loaded, select "File -> Import..." from the menu bar and select your SFM project, then press "Open". This will once again start a conversion process, which may take several minutes (Pragma may appear frozen during this time). After the project has been imported, you can save it in PFM's internal format (".pfm"), which can be loaded a lot faster.

If your SFM session file is located in one of the default sub-directories in "steam/steamapps/common/SourceFilmmaker/game/", your SFM session file should be listed in the import file explorer automatically. If the file is located in a custom location (e.g. "SourceFilmmaker/game/custom/elements/"), you will have to open "Pragma/cfg/mounted_games.txt", locate the "sfm" entry and add your path to the "game_paths" list in the same format as the existing ones. If this doesn't work, you can just copy the session file to one of the default sub-directories (e.g. "SourceFilmmaker/game/usermod/elements/").

Here's an example video on how to load a map / a project:

(The video is from an older video of Pragma / PFM, but the basic approach is still the same.)

For information on how to render your animation with Pragma, check out this article. Rendering

To render your scene, switch to the "Cycles-Renderer" tab above the viewport and you should see a window similar to this one (but with a black viewport):

This is where you can render your scene with the Cycles path-tracing rendering engine. This is the same renderer used by Blender to create highly realistic images.

Cycles is not a real-time renderer, which means rendering an image takes time. The amount of time required, depends on the complexity of the scene, your hardware, the specified sample count and various other factors, and can take anything between several seconds and minutes.

If you want to get a quick preview render, click the "Render Preview" button. This will render an image with a very low sample count and low resolution, which will give you a rough idea of what the final render will look like. To render your final image(s), press the "Render Image(s)" button.

When rendering an image for a new project or a new map for the first time, Pragma may appear frozen for a few minutes, this is because some additional asset conversions are required for the Cycles-renderer. Subsequent renders should not take as long.

The render options to the right can be used to change the resolution of your render, sample count, number of frames, etc. You can leave most of these options on their defaults in most cases, but here are some of the more important options:

Device Type: You can render with either your CPU or your GPU. This option only affects rendering speed, the end-result is the same. If you have a modern GPU, you may want to consider switching to GPU rendering. Samples per Pixel: The higher the sample count, the higher quality your render will be, at the cost of rendering time. If you notice weird discolorations in your final render, or if you're using advanced render features (like subsurface scattering), you'll likely have to increase this value to get good results. Resolution: The resolution of the render. You can choose between the presets, or hold the alt-key and click into the field to enter manual values (e.g. "1000x1200"). Higher resolutions will result in longer rendering times. Sky override: This defines the background sky image if you're rendering an outdoor scene (or an indoor scene with windows). The choice of sky is important and can have a tremendous impact on your scene, choose it carefully! Both equirectangular HDR and PNG images are supported, but it's important that the images have a 16-bit color depth (HDR colors). You can also leave this field empty to use the map's skybox for the sky instead. Sky Strength: The intensity of the light emitted by the sky image. Max transparency bounces: This field is usually not important unless you have a lot of overlapping transparent objects in your scene. If you notice black spots around transparent objects, try increasing this value. Light intensity factor: Controls the global light intensity of the scene (excluding lighting caused by the sky). Number of frames to render: If you intend to render an image sequence, set this value to the number of frames you wish to render. Output Format: The image format that the frames will be saved as once rendering is complete. If set to HDR, no tone-mapping will be applied and the image will be saved with the original 16-bit colors. Enable camera frustum culling: If enabled, objects that are outside of the visible area of the camera are not included in the render. This can improve rendering times, but may also cause incorrect lighting in some scenes (especially indoor scenes). Tone mapping: The tone-mapping algorithm to use to transform the HDR colors to sRGB space. Some tone-mappers have additional parameters to tweak the result.

Once rendering is complete, the image will automatically get saved to your harddrive. You can press the "Open Output Folder" to navigate to it in the system explorer.

In general it is not recommended to render a large sequence of images or images with a large sample count / high resolution directly in Pragma, but to use the external render tool instead. Please see that section for details.

VR / 360 Scenes

To render VR or 360 images, change the "Camera type" to "Panorama". This opens two new render options:

Panorama Range: The horizontal view range in degrees for your scene. The vertical range is always 180 degrees. Stereo: Enable this to render images for VR. This will render the image twice, once for the left eye and once for the right, which will also double rendering times. Material Editor

The material editor allows you to change the material properties used to render your models, which can drastically change the way they look in the final render. There are two ways to access it:

Method #1

1. Open the "Model Catalog" from the "Windows" menu and find the model of which you want to edit a material. 2. Right-click the icon. 1. If you see "Import asset" in the list, click that option. This means it's an external asset, which needs to be converted to Pragma first. 2. If you see "Load" in the list, click that option. This means the asset hasn't been loaded yet.

3. Right-click the icon again and select "Edit Material" from the list. 4. Select the material you wish to edit.

Method #2

1. Open the "Material Catalog" from the "Windows" menu and find the material you wish to edit. 2. Right-click the icon. 1. If you see "Import asset" in the list, click that option. This means it's an external asset, which needs to be converted to Pragma first. 2. If you see "Load" in the list, click that option. This means the asset hasn't been loaded yet.

3. Right-click the icon again and select "Edit Material" from the list.

Both methods will open the material editor, the only difference being that with method #2 you will get a sphere in the material editor preview viewport instead of an actual model. In most cases you should prefer method #1.

You should be seeing a window like this: The left column contains all of the available material properties, the right column contains a live preview. Any changes to the material properties will immediately update the preview window.

The options below the preview viewport have no effect on the material itself.

Any changes you make to the material will be kept for this session, even if you close the material editor. If you close Pragma without pressing the "Save" button, however, the changes will be lost.

Textures

For each material there are multiple texture slots available: Albedo Map, Normal Map, RMA Map, etc. Pragma (and Cycles) uses a standardized PBR model with the metallic workflow.

If you want to change the texture for one of the slots, all you have to do is open the file path in the system explorer and simply drag-and-drop the image file into the respective slot (make sure Pragma is running in windowed mode!). To clear a texture slot, simply right-click on it and choose "Clear".

Some textures are affected by the material properties. For instance, if you assign an emission texture, it will not actually have an effect, unless the "Emission Factor" property is > 0.

RMA Map

A RMA-map is a special texture that holds PBR components in the rgb-channels:

Red: Ambient Occlusion Green: Roughness Blue: Metalness

If you don't have PBR-textures, you can clear the texture slot and control the PBR-properties with the sliders instead.

If you don't have a RMA-map, but you have the PBR-textures as separate image files, you can easily them to a RMA-map with the material editor. To do so, follow these steps:

1. Right-click on the RMA texture slot 2. Click "Compose RMA" 3. A new window should pop up. Drag and drop your image files to the respective texture slots. If you don't have one of the textures, right-click on the respective slot and click "Clear". 1. If you don't have an ambient occlusion map, and you've opened the material editor with method #1, you can also right-click on the ambient occlusion map slot and click "Generate ambient occlusion", which will automatically generate an ambient occlusion map for the model. This may take a few seconds to complete! 2. If you have specular workflow textures (i.e. a specular map and a glossiness map), you can click the "Workflow" button to switch to the specular workflow. This will automatically convert the specular workflow textures to the metallic workflow.

4. Click "Compose RMA" to generate the RMA texture Material Properties

Texture Factors

The slider controls (Metalness/Roughness/Emission Factor/etc.) are multipliers for their respective textures. For instance a metalness factor of 0 effectively means that the metalness map will be ignored and the material will be fully non-metallic, a metalness factor of 1 means the metalness texture controls the metalness entirely. There are some special rules:

If no emission map is specified, the emission factor will have no effect. Same applies for the ambient occlusion map. If no metalness map is specified, the metalness factor will control the metalness entirely. Same applies for the roughness map.

Transparency

The material's transparency is determined by the alpha-channel of the albedo map, however transparency is ignored by default.

To enable transparency, set the "Alpha Mode" to either "Mask" or "Blend":

Opaque: The alpha channel will be ignored and transparency is disabled. Mask: Any alpha channel values above the alpha cutoff threshold will be treated as full opaque, and any values below it as fully transparent. Blend: The alpha channel values will be treated as smooth blend values.

Subsurface Scattering

Subsurface scattering can have a big impact on the quality of your render (especially if characters are involved) and is easy to set up.

To enable subsurface scattering, simply choose one of the presets (e.g. "Skin 01") from the preset list. Generally you shouldn't have to change the method or factor, but you may have to tweak the "Scatter Color" to match the skin color of your character more closely.

Subsurface scattering is not yet implemented for the real-time renderer, which means you will only see its effects when rendering with Cycles.

Cycles Preview

The viewport shows a real-time preview of the model with the current material properties, but in some cases you may want to see a preview of what it will look like when rendering with Cycles as well. To do so, simply click on "Render Mode" to switch to "Raytracing" and click the "Render Preview" button. It may take a few seconds for the render to complete. Actors and Components

This article refers to PFM v0.4.3 and newer and may not be representative of older versions.

Actors in PFM are entities (i.e. game

objects) that are part of your animation, not including map entities or other entities that exist independently of your project. An actor can be anything from a camera to a light source, prop or particle system. An articulated actor is an actor with a skeletal rig or morph targets (i.e. flexes/flex controllers).

In the PFM interface you can find a list of all actors in the currently selected film clip in the "Actor Editor" window.

Creating an actor

To create a new actor, click the gear icon at the top of the actor editor: Choosing "New Actor" will create an empty actor without any components, the other options will automatically add the required components for the chosen option. Components are explained in the following section:

Components

Contrary to SFM, there are no concrete actor types in PFM. Instead, every actor has a list of components associated with it which define the behavior/function of that actor. For instance, if you create a camera in SFM, that actor is a camera entity. If you create a camera in PFM, that actor is an entity with a camera component. The key difference is that components in PFM can be freely added or removed to/from an actor.

Example: You create an actor X and add a camera component to it, which turns that actor into a camera. If you add another component to actor X, for instance a light source component, then actor X is both a camera and a light source at the same time. If you then remove the camera component from the actor, it ceases to be a camera, but remains to be a light source (This should ring a bell if you're familiar with entity-component-systems.). This allows you to flexibly change or enhance the behavior of an actor. Some other examples:

You can add a "retarget" component to an actor to change its model to another, even if the new model has different proportions or a different rig, while keeping the animation intact. You can add a "physics" component to make an actor move in a physically accurate manner (e.g. dropping on the ground). You can then add a "gravity" component to change the actor's gravity (e.g. make it fall upwards instead). etc.

If you have some programming experience, you can also create custom components with Lua, and then add those components to your actors. Custom components can also add new animatable properties. See here for details.

You can find a list of components an actor has in the "Actor Editor":

To avoid cluttering the interface, not all of the actor's components are listed by default. Right-click on "Components" and choose "Add Component" to see which ones of the actor's current components are hidden. By clicking one of the components it will be added to the interface (along with its properties, if it has any). You should only do this if you intend to modify the properties of one of the components.

The option "Create new Component" allows you to add an entirely new component to the actor:

This list includes all components known by the engine, many of which may not be suited for use in PFM!

Custom Lua-based components will also appear in this list automatically.

If you select one or more components from the actor component list, you will get a set of properties on the right-hand side of the editor: Most of these properties can be animated (with the exception of strings and a few other types).

Creating custom components

To create a new Lua-based component for use in PFM, follow these steps:

1. Create a new addon in the "addons" directory 2. Within that directory create the path and file "lua/entities/components//client/client.lua" "component_name" has to be lower-case and must not contain any special characters (aside from '_') or spaces! If the component is specific to PFM only, you should use the "pfm_" prefix for the component name.

3. Open the "client.lua" in a text-editor and paste the following contents into it (and make sure to follow the comments):

-- Replace "CustomComponent" with a name of your choice (make sure it doesn't exist yet)

local Component = util.register_class("ents.CustomComponent",BaseEntityComponent)

-- Register properties for this component. These will be editable (and animatable) in PFM

Component:RegisterMember(

"ExampleProperty", -- Property name

udm.TYPE_FLOAT, -- Property type

1.0, -- Default value

{

min = 0.0, -- Min value (hint for the UI)

max = 10.0 -- Max value (hint for the UI)

}

) function Component:Initialize()

BaseEntityComponent.Initialize(self)

print("Initializing component of type '" .. self:GetComponentName() .. "'...")

-- Do something when this component has been added to an entity/actor

end

function Component:OnRemove()

print("Removing component of type '" .. self:GetComponentName() .. "'...")

-- Do some cleanup?

end

-- Register the component. "component_name" has to match the name of the directory in

"entities/components/"!

-- "COMPONENT_CUSTOM" should also reflect this name!

-- e.g. if your component name is "apple_tree", "COMPONENT_CUSTOM" should be

"COMPONENT_APPLE_TREE"

ents.COMPONENT_CUSTOM = ents.register_component("component_name",Component)

The next time you start PFM, your component should appear in the component list automatically and you can add it to your actors.

Below is an example of the pfm_sky component, which enables animating the sky orientation and strength when rendering with raytracing:

util.register_class("ents.PFMSky",BaseEntityComponent)

local Component = ents.PFMSky

Component:RegisterMember("Strength",udm.TYPE_FLOAT,1.0,{

min = 0.0,

max = 10.0

})

Component:RegisterMember("Transparent",udm.TYPE_BOOLEAN,false)

Component:RegisterMember("SkyTexture",udm.TYPE_STRING,"",{

specializationType = ents.ComponentInfo.MemberInfo.SPECIALIZATION_TYPE_FILE,

metaData = {

rootPath = "materials/skies/",

basePath = "skies/",

extensions = {"hdr"},

stripExtension = true

} })

function Component:Initialize()

BaseEntityComponent.Initialize(self)

self.m_callbacks = {}

table.insert(self.m_callbacks,ents.add_component_creation_listener("unirender",function(c)

table.insert(self.m_callbacks,c:AddEventCallback(ents.UnirenderComponent.EVENT_INITIALIZE_SCENE,function(scene,renderSettings)

scene:SetSkyAngles(self:GetEntity():GetAngles())

scene:SetSkyStrength(self:GetStrength())

local tex = self:GetSkyTexture()

if(#tex > 0) then scene:SetSky(tex) end

scene:SetSkyTransparent(self:GetTransparent())

end))

end)) end function Component:OnRemove()

util.remove(self.m_callbacks) end ents.COMPONENT_PFM_SKY = ents.register_component("pfm_sky",Component) Lighting

PFM supports four light source types:

Sun Lights (aka directional light or environmental light) Point Lights (aka omni light) Spot Lights HDRI lighting

To create a light source, open the actor editor and click the gear icon, then select "New spot light", "New point light" or "New sun light" respectively. The light source will appear in front of the camera, so make sure you're not standing right in front of a wall or an object, otherwise the light may appear behind it.

When creating a light source (or any other actor), make sure a film clip is selected in the timeline window first! The light source will only be valid for that particular film clip.

To change the properties of the light source, select it in the actor editor. The available properties depend on the light source type and will appear in the righthand window of the actor editor.

PFM uses Pragma's renderer for rendering your scene in real-time in the viewport, however the final render is processed using the Cycles path-tracing renderer. Due to the different rendering method between the two, the lighting in your scene may look quite a bit different (especially with outdoor scenes). For this reason it's recommended to render a preview image of your scene from time to time to ensure the lighting in the final render matches your expectations.

Point Light

Point light sources are omnidirectional lights, which means they emit the same amount of light in all directions from a point in space.

Intensity

The intensity of the light source in Lumen or Candela (depending on the specified unit type). Intensity Unit

The intensity unit field specifies the base unit that the intensity value represents, which can be either Lumen or Candela. If you're unsure which value to choose, you can just use the Lumen intensity value printed on the side of most light bulb packages.

Radius

The maximum radius of the light source in meters.

This property is currently ignored when rendering with Cycles!

Spot Light

Spot lights emit light as a cone in a particular direction.

Intensity

The intensity of the light source in Lumen or Candela (depending on the specified unit type).

If you're specifying the light intensity for a spot light in Lumen, beware that the perceived light intensity will depend on the outer cone angle of the light source, i.e. a smaller cone angle will create a brighter light. If you want to have consistent light intensities regardless of the angle, use Candela instead!

Intensity Unit

The intensity unit field specifies the base unit that the intensity value represents, which can be either Lumen or Candela. If you're unsure which value to choose, you can just use the Lumen intensity value printed on the side of most light bulb packages.

Radius

The maximum radius of the light source in meters.

This property is currently ignored when rendering with Cycles! Outer Cone Angle

The angle (in degrees) of the cone in which light should be emitted. The angle mustn't exceed 180 degrees.

Inner Cone Angle

The difference between the outer and inner cone angles determines the smoothness towards the edges of the cone. The smaller the inner cone (relative to the outer cone), the smoother the light falloff will appear. This value should always be lower than the outer cone angle.

Sun Light

A sun light source does not have an origin in space and emits the same light everywhere from the same direction.

Intensity

Contrary to point and spot lights, the intensity of a sun light source is measured in Lux (Lumen per square meter). This means that the value doesn't actually represent the amount of light emitted by the light source, but rather the amount of light received by a surface that is being lit by this light source.

HDRI Lighting

HDRI lighting is special in that it's not a conventional light source, but rather based on a HDR panorama image. This type of lighting can have a substantial effect on your scene, but only works for outdoor scenes and you can only specify one HDRI image for your entire scene.

HDRI Lighting currently only works when rendering with Cycles and has no visible effect in PFM's viewport.

To specify a HDRI image, open the Cycles render settings and click the "Sky Override" field. You can then press "..." to select your HDRI image file. Pragma already ships with several HDRI skies you can choose from, but you can also get additional skies from websites like https://hdri- skies.com/ or https://hdrihaven.com. Expressions and Drivers

This article refers to PFM v0.4.3 and newer and may not be representative of older versions.

Math Expressions

Any animatable actor property (color, radius, position, etc.) can be animated with a math expression (Similar to SFM's expression operators). The implementation is based on the high-performance exprtk library, which includes support for:

Logical operators (and/or/not/etc.) Conditions (if/ternary/etc.) Loops (for/while/etc.) Vectors

Examples

As a basic example, let's say you want to animate the position of your actor, so you move it to [0,30,0] at timestamp 0, [0,50,20] at timestamp 1 and [30,0,-20] at timestamp 2. You can then apply the math expression value *2 to the property, which will double the values, meaning your actor will move from [0,60,0] to [0,100,40] and then to [60,0,-40] instead.

Here are some other basic examples:

var newValue[3] := {0,value[1],0}; return [newValue]; : Returns [0,value.y,0], which means the actor will only move on the y-axis. var newValue[3] := {time *100,0,0}; return [newValue]; : The channel value will be ignored, and the actor will move on the x-axis depending on how much time has passed since the start of the animation. var f := time /duration; var newValue[3] := {sin(f *pi *2) *100,0,cos(f *pi *2) *100}; return [newValue]; The channel value will be ignored, and the actor will move in a circular motion depending on the time passed.

Inputs

These are the variables available for use with math expressions:

value: The current value time: The current time in seconds timeIndex: The index into the times array of the channel for the current timestamp. startOffset: The channel's start offset in seconds. timescale: The channel's time scale. duration: The duration of the channel (i.e. max time value in the times array).

Constants:

pi epsilon inf

Base Functions

All built-in exprtk functions float noise(float v1,float v2,float v3) : Perlin noise. float[X] value_at(float time) : Returns the value at the specified timestamp. The return value is either float , float[3 ] or float[4] , depending on the channel value type. float sqr(float v) : returns v *v float ramp(float x,float a,float b) : returns (a == b) ? a : (x -a) /(b -a) float cramp(float v1,float v2,float v3) : returns clamp(ramp(v1,v2,v3),0,1) float lerp(float x,float a,float b) : returns a +(b -a) *x float clerp(float 1,float v2,float v3) : returns clamp(lerp(v1,v2,v3),v2,v3) float elerp(float v1,float v2,float v3) : returns ramp(3 *v1 *v1 -2 *v1 *v1 *v1,v2,v3) float rescale(float x,float xa,float xb,float ya,float yb) : returns lerp(ramp(x,xa,xb),ya,yb) float crescale(float v1,float v2,float v3,float v4,float v5) : returns clamp(rescale(v1,v2,v3,v4,v5),v4,v5) print(...) : For debugging purposes, prints the specified arguments to the console.

Quaternion Functions

q_from_axis_angle(float[3] axis,float angle,float[4] out) q_forward(float[4] quat,float[3] out) q_right(float[4] quat,float[3] out) q_up(float[4] quat,float[3] out) q_slerp(float[4] q0,float[4] q1,float factor,float[4] out) q_lerp(float[4] q0,float[4] q1,float factor,float[4] out) q_dot(float[4] q0,float[4] q1) q_mul(float[4] q0,float[4] q1,float[4] out) q_inverse(float[4] quatInOut) float q_length(float[4] quat)

Contrary to SFM's expression operators, PFM's math expressions cannot reference anything outside of the animation channel for the property it's assigned to. To create dependencies between properties, you need to use animation drivers instead.

Animation Drivers

Animation drivers are similar to math expressions, with a few key differences:

Lua expression instead of a math expression Can be used to create dependencies between arbitrary properties (this is their primary purpose) Similar to Blender's driver system Slower to compute than math expressions, use sparingly

Since animation drivers are Lua-based, that means you have the entire Lua API available, making them much more powerful tools compared to math expressions. Their purpose is to animate a property programmatically with dependencies to other properties. To do so, animation drivers can have input variables, which can be references to actors, components or component properties.

Examples

Animation drivers cannot be created through PFM yet, so the following are Lua-based examples. These may seem a little daunting, but once the system is integrated into the interface, drivers will be much easier to use.

Changing the color of a light source depending on its distance to an actor (red = actor is close, green = actor is far away):

local actorId = "327b5bb8-74ae-400e-bbf7-61a2ad2020d3" -- Id of the actor for whom we check

the distance

local expr = [[

local dist = trLight:GetDistance(trActor)

return Color.Red:Lerp(Color.Lime,math.clamp((dist -120) /150.0,0.0,1.0)):ToVector()

]]

lightSource:AddDriver(

ents.COMPONENT_COLOR,"color",

game.ValueDriverDescriptor(expr,{

-- 'trActor' variable referencing the transform component of the actor

["trActor"] = "pragma:game/entity/ec/transform?entity_uuid=" .. actorId,

-- 'trLight' variable referencing the transform component of the light

["trLight"] = "pragma:game/entity/ec/transform" })

)

Making an actor always face the camera:

local camId = "6f964743-faa6-4b2b-b781-41a258e2f7d1" -- Id of the camera actor

local expr = [[

local angToCamera = self:GetAngles(trCam)

return EulerAngles(0,angToCamera.y,0)

]]

actor:AddDriver(

ents.COMPONENT_TRANSFORM,"angles",

game.ValueDriverDescriptor(expr,{

-- 'trCam' variable referencing the transform component of the camera actor

["trCam"] = "pragma:game/entity/ec/transform?entity_uuid=" .. camId

})

)

External Render Tool

While it's possible to render images directly in the Filmmaker, it is not recommended for final renders or animations. You can use the external render tool instead, which has the following advantages:

It's much faster than rendering directly in Pragma (since more GPU resources are available if Pragma is not running) You don't have to keep Pragma running in the background during the render process You can keep working on projects without affecting the rendering If Pragma crashes, the render will continue You can use both your CPU and GPU simultaneously when rendering animations You can cancel it any time, frames that have already been rendered will not be lost (except for the current one)

To use the external rendering tool, follow these instructions:

1. Launch PFM like usual and load your project 2. Switch to the "Render" tab 3. Instead of clicking "Render Image(s)" to render your images, click the "Create render job(s)" button

Once the render jobs have been generated, an explorer window should open with a bunch of ".prt"- files, a "cache" directory (which contain all of the information needed to render your images), as well as a "render.bat". To start the render, simply double-click the .bat-file, which should open a black console window. Pragma is no longer required at this point and can be closed.

The images will be rendered one after another and placed in the same directory as the ".prt"-files. Once all images have been rendered you can remove all of the .prt-files, as well as the "cache" directory, as they are no longer required. Troubleshooting

PFM crashes since a recent update

If you can still get to the main menu, try running "clear_cache", then restart the Engine. If it still crashes, you can report your problem on the Discord server.

My SFM project doesn't appear in the project browser

If you want to import a SFM project file, make sure to choose "File -> Import..." from the menu bar instead of "File -> Open...". If your project still doesn't appear, and it is located in a custom user directory ("SourceFilmmaker/game//..."), you will have to open the "cfg/mounted_games.txt" file, locate the "sfm" entry and add the custom user path to the "game_paths" section.

The animations from my SFM project don't play correctly

PFM does currently not support IK rigs. If your SFM project uses IK rigs, you will have to detach them in SFM before loading it in PFM for the time being:

PFM freezes when loading a project

Importing a project for the first time can take several minutes or more, during which Pragma may appear frozen. This is normal and should only be the case the first time you load the project.

I can't move in the viewport

To move in the viewport, make sure the "Work Camera" is selected instead of the scene camera. Then right click into the viewport, hold the right mouse button down and move with WASD and the mouse.

I get a black viewport after opening a project

Make sure you've loaded the right map before loading the project, PFM is currently not able to switch to the project's map automatically.

I get visual artifacts on a model in the viewport / when rendering with Cycles

If you get artifacts like the ones above, it means your model is most likely using a method called "fake PBR". This is used in some models to create a PBR-like effect in Source (which doesn't support actual PBR), but is incompatible with Pragma and Cycles.