PopcornFX DEV. NOTE #3

PopcornFS - screenshot - particles

Using the execution rate to optimize your effects

 

Visual effects can be tricky to optimize. Sometimes you will need a specific behavior which is very costly performance wise and removing some pieces of this behavior for optimization purpose just destroys the whole effect. How can you optimize those effects?
Since PopcornFX 1.12, we introduced custom update rate that allows the artists to change how often a specific script will be updated.
By default, PopcornFX executes the spawn script when a particle is created to initialize the particle data and then executes the evolvers each frame for each particle:

So let’s imagine that one of your effect uses a piece of script which is very costly and that you cannot simplify and optimize more. The costly lines in a script will appear redder than the others:

In this script for example, the first line which samples the turbulence appears in orange. This means that it takes more time to execute than the other lines of this script. The issue is that if we remove the turbulence sampling here, the effect will behave completely differently.

The solution would be to sample the turbulence only once every 2, 4 or 8 frames and behave as if the turbulence value did not change otherwise. To do that, we need to store the latest turbulence value sampled in a particle field:

And then extract the costly lines of the initial script in a separate script:

You can then modify the update rate of this script by clicking the “1” next to the script name:

Let’s try a ¼ update rate (so the script will run once every 4 frames):

The effect will indeed behave just a little bit differently, but in most cases you won’t be able to see the difference. Furthermore, if you have enough particles in your effect, the script will actually run every frame but just for a quarter of the particles, which will avoid a performance spike every 4 frames.

As you can see, there are not more spikes on the quarter update rate than in the full update rate and the CPU execution time has gone from 4.1ms to 1.5ms by changing the turbulence sampling script update rate to ¼.

A simple approach

We’ve showed you the previous method in order to have an idea on how you can use that in general, if you need a more specific use of this take a look at the following example:

You can add a “VelocityField” field for your particles in which you are going to store the result of the turbulence sampling. This field will be used by the physics evolver to add some “wind” to the particles (you need to set the name of your newly created field in the “VelocityFieldField” of the physics evolver).

Then in the evolver field that we set to ¼ rate, we type in:
VelocityField = Turb_1.sample(Position);
And compile! (PS: don’t forget to put the drag to 1, or anything else rather than keeping it 0. This determines how much the wind is applied to the particles.)

You can also use the ½, ¼, ⅛ rates depending on different situations like scene.intersect functions, and anything that is performance expensive.

Going further

In this case, we only sample the turbulence once and behave as if it returned the same value for the frames that did not update the turbulence sampling script. This might be improved by interpolating between the previously sampled and the latest sampled turbulence in a full rate update script to fake a continuous turbulence.


Conclusion

This is just a basic example for one usage of the update rates, but if you want more insight on how to use this feature properly in your effects, we provide some more advanced samples in the “ReleaseHighlights” pack, which you can download in the project explorer when you launch the PopcornFX editor:


 

Paul Baron
Graphics programmer at PopcornFX,
&
Abdel Kader Wawi
Project manager / Technical artist at PopcornFX,