Search public documentation:


Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 Home > Particles & Effects > Particles Systems > VFX Optimization in UE3 > VFX Optimization: Getting Results
UE3 Home > FX Artists > VFX Optimization in UE3 > VFX Optimization: Getting Results

VFX Optimization: Getting Results

Core Systems in Cascade - GPU/Game Thread/Render Thread

Cascade creates robust particle systems which have dynamic costs spread across three core engine systems in UE3. Game Thread, Render Thread, and GPU.

  • Particle simulation times (Tick) are calculated on the Game Thread (gamethread)
  • Particle data finalization (Packing Geometry, Draw calls) are calculated on the Render Thread
  • Particle visuals (Shader complexity, overdraw) are calculated on the GPU

All of these systems calculate parallel to each other, so slowdown on any single system can mean bottlenecks in the rendering process, which equates to low framerate. It is important to consider all 3 processes when creating particle systems in Cascade.

It is also important to note that Cascade runs Particle evaluation on the Game Thread, which is the same location gameplay calculations are done. Particle counts are critical to keeping framerate within reasonable range.

Overdraw - GPU

If you are a seasoned effects artist, or if you have only been an effects artist for 2 weeks you have already heard about Overdraw.

In its simplest form, overdraw can be described as:

Overdraw = Pixel shader cost = Number of layers * avg number of pixels affected by a layer * avg number of instructions for a layer

Essentially, when you add a material to the surface of a sprite, that material has a cost in instruction count, which UE3 displays in the content browser and material editor. For translucent objects this instruction cost adds up as translucency stacks up, creating overdraw. The more layers of translucency, the higher the cost. You can easily see this cost in the shader complexity mode. Bright Red = 300 instructions, pink = 600 instructions, and white = 900 instructions. Press F5 to view shader complexity on PC.

Shader complexity outputs an approximation of what the cost of a system will be, however it is also dependent upon the scene since translucency is calculated against opaque objects which also have a cost.

Checking the usage of your effects is critical. An effect which may be called in any given scenario (weapon impact) will generally need to be lighter than an effect you can custom build to match a specific scenario, since it will be drawn in fluctuating cost scenarios.

Some steps that can be taken to get overdraw impact under control are:

  1. Reduce emission rates
  2. Reduce material instruction count
  3. Reduce particle scale (fill less of the screen)
  4. Create LODs for near/far particle emissions to reduce cost at different view distances
  5. Check for emitters placed in a line stacking against each other (static placed effects)

LODs - Level of Detail - GPU/Game Thread

LODs in Cascade provide users the ability to control modules and behavior based upon the distance from the player to the emitter. Any attribute in a particle system can be modified to make use of the LOD system.

Refer to the Particle System Level of Detail (LOD) section of the Cascade User Guide for more technical information on setting up LODs

It is important to keep in mind when creating LODs, there are memory costs associated with unshared modules. Sharing as many modules across LODs as possible reduces memory footprint. Only create unique module settings for the attributes you wish to modify.

The preview modes in Cascade and the editors perspective view behave in different ways. In order to get proper viewing in Cascade make certain the editor preview mode is disabled. (circled in the image below)


Cascade allows for a switch between LODs and displays the LOD specified. Be certain to disable the Editor LOD view mode in order to see Cascade update correctly.

Enabling the editor preview grants the ability to fly through the scene and see the particle systems switch between LODs as you move around. (circled in the image above)

It is important to measure the scene and get a realistic idea of just how many units are needed to see effects in the proper state. In the case of ambient particle systems it is possible to emit 0.00 particles and reduce tick time when the particle systems might not be visible. Measuring distance can be done by holding down the middle mouse button and dragging in any orthographic view (front, side, top.)

LOD Distance Check Time

This feature dictates how often the game checks the distance of the player, to the emitter placed in the scene to determine which LOD to use. LOD Distance Check Time works when the LOD Method is set to automatic.

Automatic essentially lets the game determine the LOD as you play. If you increase the LOD Distance Check Time, the amount of time between checks will increase. LOD DistanceCheckTime is calculated in seconds, so consider your player's max movement speed when setting this. If you set LOD Distance Check Time to a value of 0.00 the distance is checked every frame, which may equate to lower performance.

LOD Method - Game Thread

Appropriately setting the LOD Method can be vital to performance and visuals.

Automatic - the game will set the LOD based on the distance parameters defined in the effect, using the LOD Distance Check Time settings. Typically used on ambient effects which loop and are not called by game code.

Direct Set - the LOD is determined (typically by game code) when the effect is spawned and stays at the LOD defined. Typically used in burst effects like explosions or impacts.

Activate Automatic - The LOD is defined when the effect is spawned, based upon the distance parameters defined in the LOD. Typically used on burst effects called by kismet etc. which require LODs to never shift once spawned.

Fixed vs. Non Fixed Bounds - Game Thread

Bounds are one of the ways in which the engine determines visibility of an effect. These invisible coordinates tell the engine if an effect is in view or out of view. If a corner of your bounds is visible the engine will calculate any components of the effect necessary.

Bounds are costly the check and update each frame, therefore it is a good idea to set your bounds to be fixed and determine how large bounds need to be. In some cases you might want your bounds to be rather large if you need to see every piece of debris flying out of an explosion. If you wish to keep costs low, tightening bounds to core components can increase performance, at the risk of effects popping off when the bounds go out of view.

There are some considerations for fixed vs. non-fixed bounds to keep in mind.

Fast moving effects such as rocket trails, tracers, or anything attached to a projectile etc. should not have fixed bounds set, or have the fixed bounds set so large that the emitter cannot fly outside of the bounds.

When setting bounds be aware of local vs. world space coordinates defined in your system. If an emitter is rotated the opposite direction of your bounds orientation, it is possible for elements of the effect to fly out of your bounds and elements popping out of view can occur.

Draw Calls - Render Thread

Draw calls within particle systems can be tricky to track at times. There are several combined factors to keep in mind when determining draw call costs.

Particle emission is 1 draw call per emitter, regardless of screen orientation.

Mesh emission is 1 draw call per mesh emitted. So if you have 2 emitters in your effect, each emitting 10 meshes, you have a total cost of 20 draw calls associated with that particle system.

Material passes also determine draw call costs. The more passes in your material, the more draw calls in your effect.

For Instance:

  • Particle System A consists of: 1 emitter, spawning 12 sprites, using a material with 1 Pass, the entire system costs 1 draw.
  • Particle System B consists of: 1 emitter, spawning 12 sprites, using a material with 2 Passes, the entire system costs 2 draws.
  • Particle System C consists of: 1 emitter spawning 12 meshes, using a material with 2 Passes, the entire system costs 24 draws. (2 passes per call * 12 meshes since each mesh is a single draw call = 24 draws)
  • Particle System D consists of: 1 emitter spawning 6 meshes, using a material with 2 Passes, and 1 emitter spawning 10 sprites with 1 pass the entire system costs 13 draws. ( 2 passes per call * 6 meshes since each mesh is a single draw call = 12 draws, 1pass * 10 sprites = 1 draw call)

Material Attributes which contribute passes include:

Translucent material = 1 pass base

  • +2 for distortion
  • +1 for bUseLitTranslucencyDepthPass
  • +1 for bUseLitTranslucencyPostRenderDepthPass
  • +2 for bUsedWithFogVolumes

Opaque / masked material = 2 passes base

Draw calls for a particular scene can be viewed using the command DumpParticleFrameRenderingStats. This command outputs a spreadsheet which lists draw call costs in detail.

Impact from draw calls increases proportionally to the number of views being rendered. This means that in split-screen, the effects are multiplied. See the VFX Optimization: SplitScreen page for more detailed information on optimizing effects for splitscreen.

It is important to keep these costs in mind when constructing your effects, and when optimizing effects. If your render thread is high due to draw calls, and the environment is within budget this is the place to start looking.

Mesh Emission - Game Thread/Render Thread

Mesh emission is one of the more powerful features of Cascade, and is a feature which can be accidentally abused. Keep in mind when using meshes the figures listed above relating to draw calls. the emission rate equates to the number of draw calls. It is also a good idea to keep the vert count on your meshes low.

In some cases a single mesh emission can be used to fake a large volume of objects without the cost of calculating the positions all of the sprites which would be needed to create a volume of debris for instance.

Collisions - Game Thread

Typically there is a high cost associated with doing particle collision in UE3 so they should be used only when needed.

In some cases collisions can be made cheaper by specifying which objects in the world to collide against using the Collision Actor module. This is typically done when spawning effects through a Kismet action, or script where an emiterActor is placed in the world and it is possible to define specific objects in the scene to collide with through the instanceParameters of the actor. See the Per Actor Particle Collision page for instructions on setting up this type of collision.

Several settings can be used to minimize collision costs these include:

  1. MaxCollisions: keep this value as low as possible
  2. Collision Completion Option: set this to HaltCollisions/Freeze to stop doing collision checks against the scene once MaxCollisions is reached.
  3. The Damping Factor determines the bounce of objects following collision, lower values may result in objects coming to rest faster (lower Max Collisions value.)

Spawn Per Unit - GPU/Game Thread

Spawn Per Unit is a feature in Cascade which is helpful for filling in gaps when particle systems are moving. While this feature is handy for creating great looking trails of particles it is important to balance visual with performance limitations when using Spawn Per Unit.

There are a few tricks to controlling emission

  1. Keep the Unit Scalar to a value as high as possible, and balance it with the emission rate to get the fill you need, without making the effect too heavy
  2. Try and use lower instruction count materials if you know you are going to have high emission rates using Spawn Per Unit
  3. Adjust the Max Frame Distance to limit how many particles can be emitted. If the emitter goes above this Max Frame Distance Spawn Per Unit will cease emission until it returns below the distance. This prevents the emitter from dumping large amounts of sprites into the scene.

Memory Costs

Cascade offers the ability to display large amount s of valuable information relative to particle system creation. It is often helpful to turn these displays on to get a good idea of just how many particles your system is allocating, and how many particles your system is emitting.

Particle Allocation determines how many particles it is possible for the emitter to place in the world at any given time, this plays a large part in determining how much memory your particle system will consume. You can see a memory estimation by enabling the particle memory overlay in the View drop down menu in Cascade.

By adjusting settings it is possible to see memory cost increase and decrease.

Several ways to reduce memory footprint include:

  1. Reduce the number of modules in a system to the essential modules required for a given behavior
  2. For looping effects reduce Loop Time/Duration (allocates fewer particles per loop)
  3. Reduce Lifetime (fewer particles overall)
  4. Share as many modules as possible

Cascade features the ability to share modules from one emitter to the next. Using this feature has two benefits. First, if you wish the edit values across multiple emitters it is possible to edit 1 module and update all other settings. Second, sharing modules reduces memory footprint since the cooked version sees the module cost as 1 instance of the module.

A more recent addition to the Cooker evaluates all modules in a particle system and determines identical modules, then shares modules to automatically reduce memory footprint at cook time.

Tick Time - Game Thread

Tick Time represents the amount of time spent updating particle systems in the scene. Tick Time can be viewed with the stat particles command which lists out all relative information required to assess particle evaluation costs.

There are many methods which can be used to reduce Tick costs.

Tick Time is directly influenced by the number of active emitterActors in your scene, the more active emitters in the scene the higher Tick Time will be. Emitters should only be set to autoActivate if they are required to loop when the level starts.

If large amounts of sprites/explosions/burst effects are visible on level load in the editor, these effects are automatically evaluated at run time and can cause visible hitching when a level is loaded.

A Particle Parameter can be used in an effect to allow for position offsets once the effect is placed in the world. By using a particle parameter it is possible to reduce emitter counts, which reduces tick cost overall. Particle Parameters can be setup by selecting particleParameter from the distribution list in the module for the individual setting.

It is possible to stream out and disable emitterActors when they are not in view, or if they are associated with an area of a level which is no longer in memory. Streaming emitterActors with level geometry is a good practice to reduce tick overhead. In some cases where atmospheric effects are heavy kismet actions can be used to toggle atmosphere off and on during combat sequences to lower tick time and overdraw.

Particle Systems loaded into memory, but out of view (say on the floor above you) can also be toggled with kismet actions and streaming volumes to reduce evaluation costs.

In some cases a mesh effect can be a good replacement for a particle system. A placed static mesh does not have an evaluation cost on the Game Thread, in many cases it is more beneficial to place a static mesh as a replacement for a particle system. This includes vista effects, fog effects etc.

Particle counts play directly into evaluation cost. The more particles in a scene, and the longer they live, the more evaluation is required. Limiting lifespan to the duration required for the effect is good practice all around.

Enabling LODs in particle systems allows for lower particle emissions when a system is not within optimal viewing range. It may help to think of your effect in terms of a hero state, and an acceptable level of lower quality for longer viewing distances. Tightening LODs to required distances can go a long way to lowering evaluation costs in a scene without dramatically losing visual quality.

Check your effects for expensive evaluation costs which can be lowered such as Collisions, non-fixed bounds, and spawn per unit counts which are too high. Setting bounds to a fixed state can increase performance significantly and should be used whenever possible.

Non Directional Lighting Costs - Game Thread

Non Directional lighting adds depth and realism to particle effects by doing a trace within the world to determine lighting information around emitters spawned into the scene. Non Directional Lighting comes at a Game Thread evaluation cost. Non directional lighting is often used for weapon effects, impact effects, character effects, ambient fog effects, and Binked cinematic effects .

Another option for matching particle color to a light environment would be to utilize a Particle Parameter to control color and alpha per actor. By using a particle parameter on a placed ambient effect which never moves, several costs are eliminated.

  1. Cost to store a unique color variant of an effect in memory
  2. Cost to load a unique color variant at run-time
  3. Cost to create each color variant in Cascade
  4. Cost to light the effect to match the environment with Non Directional Lighting on the Game Thread

It is recommended to use Non Directional Lighting in as many cases as performance allows, it can be helpful to setup your effects with a Particle Parameter in mind should you be required to use this method due to performance restrictions.

Back to VFX Optimization