WARNING : This site is outdated and the PopcornFX team will no longer answer your questions here.
For all support questions please go to our Discord server
1 like 0 dislike
350 views

Hi Guys

New to PopcornFX but not new to particle fx

I`m having a problem using LifeRatio properly in my effect. I am spawning particles from a rectangle mesh and I then want to fade out their velocities and alpha based on the individual particles 1-life. It looks like the Evolver script is only sampling one particle as the all fade off at the same time. 

Also my gravity seems to stop working too. Is that because Im setting velocity?

Cheers
Ed

Layer info:
Duration = 0.1
spawn count = 200

In my SpawnerScript I have :

function void    Eval()
{

    Life = rand(1,2.0);
    Size = rand(0,1.5);
    Position = Shape_0.samplePosition();
    Rotation = rand(-60,60);
    ScalarRotationSpeed = (rand(-pi,pi))*0.5;    
    float3 ColorDiffuse = float3(1,1,1)*rand(0.2,0.75);
    float ColorAlpha = rand(0,0.5);
    Color = float4 (ColorDiffuse.rgb, ColorAlpha);

    Velocity = float3 (rand(-1,1),rand(-1,1),rand(0,5));
}

and I have an Evolver script after a Physics and Rotation evolvers

function void    Eval()
{

    Velocity.xyz =  (Velocity.xyz * (1-LifeRatio));
    ScalarRotationSpeed = ScalarRotationSpeed * (1-LifeRatio);
    Color = Color * float4(1,1,1,1-LifeRatio);   
}

by Dryrainstudios (170 points)

1 Answer

1 like 0 dislike
 
Best answer

Hi,

All the problems you're seeing come from the same thing:
you're trying to manually damp everything, in a way that heavily depends on the framerate.
Unless you have a very low framerate of, say, 5 frames per second, you're not going to see anything and all the values will very quickly plummet to zero.

The velocity, rotation speed, and color will all become zero after only a few frames.
 

How to fix this?

 


Using existing evolvers

If I read your script correctly, you'd like the velocity do become smaller and reach zero when the particle dies, as for all other fields.

for 'Velocity', usually this is done with the 'Drag' property of the physics evolver. setting a nonzero drag will cause the particle to slow down smoothly over its lifetime.

for 'ScalarRotationSpeed', you have the 'damper' evolver that does what 'drag' does in the physics evolver.
It'll take the field and smoothly decrease its value towards zero.

for 'Color', you can use a field evolver that'll give you a color curve where you'll be able to do the same thing. just take the 'w' channel of the curve, make it start from 1 at t=0, and end at 0 at t=1

 


Using scripts

If you do not want to use existing evolvers, the easiest and most readable way to do this is by using an initial value, and linear scaling based on 1-LifeRatio, like in your original script.

You'll need to create three extra fields: 'float BaseRotationSpeed', 'float4 BaseColor', and 'float BaseSpeed':

function void    Eval()
{
    Life = rand(1,2.0);
    Size = rand(0,1.5);
    Position = Shape_0.samplePosition();
    Rotation = rand(-60,60);
    BaseRotationSpeed = rand(-pi,pi)*0.5; // Not ScalarRotationSpeed
    float3 ColorDiffuse = float3(1,1,1)*rand(0.2,0.75);
    float ColorAlpha = rand(0,0.5);
    BaseColor = float4(ColorDiffuse.rgb, ColorAlpha); // Not Color
    Velocity = rand(float3(-1,-1,0),float3(1,1,5));
    BaseSpeed = length(Velocity);
}

You'll notice 'ScalarRotationSpeed' and 'Color' are not set in the spawn script. This is because we'll overwrite them each frame in the evolve script with a new value that does not depend on their previous value, so there's no point in initializing them (they'll be default-initialized to zero), but you can initialize them if you want, it won't make a difference, except more computations when spawning the particle.

Then, the evolve script:

function void    Eval()
{
    Velocity = safe_normalize(Velocity) * (BaseSpeed * (1-LifeRatio));
    ScalarRotationSpeed = BaseRotationSpeed * (1-LifeRatio);
    Color = BaseColor * float4(1,1,1,1-LifeRatio);
}

This should work properly for ScalarRotationSpeed and Color, but still isn't ideal for Velocity, the physics evolver will try to fight the values you force in the script by re-applying the gravity each frame, and the script will fight those values by forcing the length of the velocity vector to a hard value based on the LifeRatio.

This method also consumes more memory per-particle, as you now have to store an extra float4 field, and two extra float fields, giving you a memory overhead of 24 bytes per particle.

For the color, if you just want to change the alpha and force it to be zero at the particle birth and 1 when it dies, you can also do this, without the need for a 'BaseColor' field:

    Color = Color.rgb0 + (1 - LifeRatio).000x;

This will take the rgb components of the existing color unchanged, will clear its alpha, and will replace it by an alpha whose value is '1 - LifeRatio'

or, (the same thing but done in a different way):

    Color = float4(Color.rgb, (1 - LifeRatio));

This will construct a new RGBA color from the unchanged RGB of the previous color, and a new alpha of '1 - LifeRatio'

 


Using scripts, version 2

You can also do non-linear damping by hand, without storing a 'Base' value for each field (this is what the evolver damper is doing behind the scenes), like this:

function void    Eval()
{
    float velDampSpeed = 2.0;
    float rotDampSpeed = 1.0;
    float colDampSpeed = 1.0;
    Velocity *= exp(-dt * velDampSpeed);
    ScalarRotationSpeed *= exp(-dt * rotDampSpeed);
    Color *= float4(1,1,1, exp(-dt * colDampSpeed));
}

This is a way to get mathematically perfectly smooth damping, no matter what the framerate is.
It uses a very nice property of the exponential function, which is that it's its own derivative.
The formula used above 'x = x * exp(-dt * k)' is called exponential decay.

Calling the 'exp' function will be slightly more expensive than the other methods above though.
You can also change the damping speeds by tweaking the values '*DampSpeed'

 

by Julien (35.3k points)
Cheers Julien,
Thanks for that very full and thorough explanation.
I think i will try the ramps/curves first it just didnt feel like it was per particle when I was trying it
Cheers
...