Jose Moreno Profile picture
Coffee, math and game lover. Senior Technical Artist at @remedygames. Prev. Metroid Dread @nintendo @mercurysteam, @sabergames, @labcave and @calendulagame.

Oct 12, 2022, 17 tweets

Before getting into the fluid simulation thing we are going to talk about "programming" in a simulation stage and why do this. #ue5 #niagara

Let's suppose we have a scratch pad like the one in the first picture. As we know, this scratch pad runs for every cell in the Grid2D. But, what is it exactly "running"?

Every scratch pad, when we are in "GPU mode", is translated to HLSL code. Fortunately, Niagara can show us this translation. If you select your emitter (and you are in the "Generated Code tab") you should be able to choose "Particle GPUCompute Script".

At a single glance at the code (exactly where our scratch pad is defined) you'll see easily the correspondence between the scratch pad nodes and the HLSL code.

Let's see another example. We are going to "code" a simple blur effect. The algorithm is easy: in each step, take a cell and the adjacent ones, add up them and divide by the number of cells. After that, set the new value of the cell as the computed one.

Here a scratch pad that implements the algorithm. If we zoom in we can see the nodes used: basically a bunch of "GetPreviousFloatValue" node. No doubt: this is a hell. Both for read and edit.

We can see the blur effect in the next gif. It works as expected: in each frame we blur a bit the previous data in the Grid2D.

Only for completeness: the scratch pad used in the setup of the Grid2D.

If we take a look at the HLSL code of the Blur scratch pad generated, we'll see some repetitive structure. Furthermore, if we have some programming background, we know that we could code this as something like the second picture: a simple loop.

This the "why" part. Happily, the "how" part is built in Niagara and it is the node "Custom HLSL". In this node, we can write any custom HLSL routine, and even better, we can make use of functions owned by Niagara.

In the "old days", you had to dig in the engine code to know these Niagara functions (seem to remember) but nowadays it's simple as (right-) click in your object and select "Data Interface Function HLSL...". If you "Copy All" and paste in text editor you'd see the second picture.

Ok, having all this information, we're prepared to write the blur effect in a HLSL node. If you code it as the first picture you should see a generated code similar to the second and third picture. After code your node, Niagara do some "minor" modifications.

A very (very) similar way of doing this is the following. In the case we use "SetFloatValue" function (the same as the node) to update the value of the cell. In this case, you have to pass the "Context" through the "Custom HLSL" node creating a Niagara map at begin and at end.

Just one thing more about this node: the "out" variables created must not be declarated.

I'll end this thread talking about "Iterate a Simulation Stage". In some cases, like in a blur effect, we would like to repeat a whole simulation stage to make things happen faster. This is not (always) the same as duplicate a scratch pad.

Repetition can be achieved changing the "Num Iterations" parameter in the Simulation Stage parameters. In each iteration, some variables like Grid2D, write its new values and the old ones are available in nodes like "GetPreviousFloat" node. This not happen stacking scratch pads.

This is a good place to end this thread. In the next one, we'll start the fluid simulation implementation.

Share this Scrolly Tale with your friends.

A Scrolly Tale is a new way to read Twitter threads with a more visually immersive experience.
Discover more beautiful Scrolly Tales like this.

Keep scrolling