Creating particle effects

Particle effects. What a great thing. You can have thousands of little billboards that get computed interactively based on the information you give about the desired particle behavior. The particle effects system has been completely redesigned for Ultimate 3D 2.0 and has been improved a little in Ultimate 3D 2.1. It is really flexible. First, there are many settings you can change to define the properties of the particles such as origin, velocity, acceleration, size and color. Second, you can add gravity emitters that work realistically. You could actually use the particle effects system with the gravity emitters to make a solar system simulator :D. Finally, you can set up modifiers that change the behavior of particles whenever they are in the area you set up for them. These could be used, for example, to create a room that reflects the particles when they hit one of the walls, changing their color. Additionally, every single particle in Ultimate 3D can have an unlimited size. And using particle effects is quite easy, so do not miss the following tutorial ;) .


Creating a particle system and setting up basic properties

Creating a particle system is probably the easiest thing one could imagine. You do not have to set up any variables; all you have to do is put CreateParticleSystem() into the creation event of an object. But it is obvious that that can not be all. You have to tell Ultimate 3D what you want the particle system to look like somehow. For this reason, you have to call a couple of other functions after the call to CreateParticleSystem(). There are also two variables, which can be set up at any time. The first one is texture, which defines the index of the used texture. The second one is optional and is called aspect_ratio. You can use this if you do not want quadratic particles. The height of the particles always equals their size, the width is the size multiplied by aspect_ratio. The other options are set through functions. The first two functions define the number of particles that will be created each step, and the lifetime of the particles. The following functions will always have some of the same parameters, one with a minimal value and one with a maximal value. Ultimate 3D will choose a random value in the range from the minimal value to the maximal value whenever it needs this value. This way everything gets a bit random and every particle gets an individual behavior. So here are the two functions:

This function sets up the number of particles the particle system will create.

SetParticleCount(
MinimumParticleCount,
MaximumParticleCount,
MaximumTotalParticleCount
)

MinimumParticleCount, MaximumParticleCount
The number of particles that are to be created per step.

MaximumTotalParticleCount
The maximum number of particles that can exist at the same time. If the absolute number of particles gets close to this value, Ultimate 3D will stop creating particles until enough particles have exceeded their lifetime. Usually a good value for this is (MaximumLifetime+MinimumLifetime)/2*(MaximumParticleCount+MinimumParticleCount)/2 .


This function sets up the lifetime of the particles of the particle system the function is called by. The lifetime is the time that passes from their creation until they get destroyed (in steps).

SetParticleLifetime(
MinimumParticleLifetime,
MaximumParticleLifetime
)

MinimumParticleLifetime, MaximumParticleLifetime
The lifetime of the particles that are to be set up.


Now it gets a little bit more complicated. You've got to define where the particles get created. If you want to you can simply leave out this step. Then all particles will be created at the same position. But that'd be kind of boring. To define the origin you have to give a transformation and a real value. Imagine you have a model of a sphere with a radius of one. If you apply the transformation you enter into the next function to this sphere model, the model will show you the areas particles can be created in. The second real value will be used as scaling for a second sphere that uses the same transformation. This is the other border that limits the area particles may get created in. The following graphic illustrates this.

Illustration not available

The first sphere gets transformed using the transformation you enter into the next function. Then the second sphere gets transformed using the same transformation and scaled by the given second sphere radius. Then the area between these two spheres is the origin of the particles. Here's the function to set up these properties:

This function sets up the particle origin. The position of the origin is not set up by this function since it often has to be changed very frequently. For this reason you have to set up the variables x, y, and z for every particle system.

SetParticleOrigin(
SecondSphereRadius,
RotationX, RotationY, RotationZ,
ScalingX, ScalingY, ScalingZ
)

SecondSphereRadius
The radius of the second sphere which is the second border for the origin of the particles. If you put 0 for this parameter, the particle origin will be an exact sphere.

RotationX, RotationY, RotationZ
The rotation that is to be used as transformation for the two spheres. Usually you do not need this parameter, since rotating the origin only makes sense if you do not enter the same value for all three scaling parameters.

ScalingX, ScalingY, ScalingZ
The scaling that is to be applied to the two spheres.


The next two functions set up the particle velocity and the particle acceleration (acceleration is the change of the velocity per step). This is pretty easy. The only thing you have to keep in mind about these functions is that the longitude has to be in the range from -90 to 90 because otherwise a method Ultimate 3D uses to achieve a regular spread of the particles will not work correctly.

This function sets up the initial velocity of the particles that are created by the particle system.

SetParticleVelocity(
MinLongitude, MinLatitude,
MinVelocity,
MaxLongitude, MaxLatitude,
MaxVelocity
)

MinLongitude, MinLatitude, MaxLongitude, MaxLatitude
The direction of the movement given in degrees. The values for longitude should be in the range of -90 to 90.

MinVelocity, MaxVelocity
The speed of the movement per step.


This function sets up the initial acceleration of the particles that are created by the particle system.

SetParticleAcceleration(
MinLongitude, MinLatitude,
MinAcceleration,
MaxLongitude, MaxLatitude,
MaxAcceleration
)

MinLongitude, MinLatitude, MaxLongitude, MaxLatitude
The direction of the movement change given in degrees. The values for longitude should be in the range of -90 to 90.

MinAcceleration, MaxAcceleration
The amount of movement change per step.


Next you can set up something that's called initial center repulsion. It happens quite often that all particles are supposed to move away from the origin of the particle system. One example for this would be a particle system for explosions. That's what you need the initial center repulsion for. When a new particle gets created the initial center repulsion factor gets multiplied by the difference of the position of the particle and the position of the particle system. Then the result gets added to the initial velocity of the particle ( InitialVelocity+=(ParticlePosition-ParticleSystemPosition)*RepulsionFactor). The repulsion factor gets set up individually for every axis. Here's the function:

This sets up the initial center repulsion factor:

SetInitialCenterRepulsion(
RepulsionFactorX, RepulsionFactorY, RepulsionFactorZ
)

RepulsionFactorX, RepulsionFactorY, RepulsionFactorZ
The repulsion factor along each axis. To get a description of what the repulsion factor is have a look at the text above.


Next you can set up the color and the size of the particles. For each of them you can set up a range of possible initial values and a range of possible final values. The final values will be used by the particle at the end of its lifetime. Here are the functions that are available to set up these values:

This function sets up a range of possible initial color values for the particles.

SetInitialParticleColor(
MinimumR, MinimumG, MinimumB, MinimumA,
MaximumR, MaximumG, MaximumB, MaximumA
)

MinimumR, MinimumG, MinimumB, MinimumA
The minimum color values for the initial color of the particle. These values have to be in the range from 0 to 255. MinimumA gives the minimum amount of opacity (0 for no opacity (fully transparent), 255 for fully opaque).

MaximumR, MaximumG, MaximumB, MaximumA
The maximum color values for the initial color of the particle. These values have to lie in the range from 0 to 255 as well.


This function sets up a range of possible final color values for the particles.

SetFinalParticleColor(
MinimumR, MinimumG, MinimumB, MinimumA,
MaximumR, MaximumG, MaximumB, MaximumA
)

MinimumR, MinimumG, MinimumB, MinimumA, MaximumR, MaximumG, MaximumB, MaximumA
These parameters have the same meaning as for
SetInitialParticleColor(...) but this time they refer to the final particle color.


This function sets up a range of possible initial and final particle sizes. The size values are given in world space so they get interpreted in the same way as the parameters you can set up for billboards.

SetParticleSize(
MinInitialSize, MaxInitialSize,
MinFinalSize, MaxFinalSize
)

MinInitialSize, MaxInitialSize
The range of possible initial sizes for the particles.

MinFinalSize, MaxFinalSize
The range of possible sizes the particles may have at the end of their lifetime.


Finally you can specify a rotation for the particles. Making the particles rotate makes the particle system look a lot more chaotic and this greatly adds to its natural look.

This function specifies the intial particle rotation and their rotation speed.

SetParticleRotation(
MinInitialRotation, MaxInitialRotation,
MinRotationSpeed, MaxRotationSpeed
)

MinInitialRotation, MaxInitialRotation
The range of possible initial rotations for the particles in degrees. A rotation of zero means, that the top of the texture is at the top of the particle. Bigger rotations make the particles rotate in screen space in clockwise direction.

MinRotationSpeed, MaxRotationSpeed
The range of possible rotation speeds for the particles in degrees. The rotation speed will be added to the rotation of a particle once per step.


Now that you know how to set up the properties of your particle system, it's time to make it become alive. To do this you have to put a function call into the step event of the object you've created for your particle system, but this time it's not Step(). The reason for this is that the step function of particle systems does take one parameter and does not need to be called in every single step, because it takes quite a bit of computing time depending on the number of particles, gravity emitters and modifiers. It makes no sense to perform a step for a complex particle system if it is not visible currently. Here's the function:

This function performs a step of the given length for the particle system the function is called by.

ParticleSystemStep(
StepLength
)

StepLength
The length of the step you want to perform. One could also call this a time factor. If you put one for this, one step will be performed for every call to this function. If you put 0.5, everything will run at half speed, and if you put 2, everything will run twice as fast. Note that a big time factor can lead to imprecise calculations, especially when using modifiers and gravity emitters.


Finally you have to put a call to Destroy() into the destroy event of the particle system object, otherwise the particle system will still be visible after destroying the object it was associated with.

If you want to get very shiny particle effects with a volumetric effect you may want to use additive blending for the particle effects system. Additive blending means that every particle adds to the color on the screen instead of covering it. Without additive blending five particles in a row seen from the front, look exactly the same as a single particle, since the particle at the front covers the other four particles. With additive blending the colors of the particles are added together, leading to a very bright spot (brighter than a single particle). Enabling additive blending is easy.

This function enables or disables additive blending for the object it is called by.

SwitchAdditiveBlending(
UseAdditiveBlending
)

UseAdditiveBlending
If this parameter is true additive blending will be used for this object, if it is false it will not be used.

This function does not only work for particle systems, but also for model, terrain and primitive objects. Though you should use it for these object types only if they are partially transparent. Otherwise the results may not be desirable due to the z-buffering.


Gravity emitters

Gravity emitters are really cool. They can make particles move on paths that are quite frequent but never the same. Gravity emitters can also emit "negative" gravity, so they push away particles which is useful for many different kinds of effects. The gravity emitters use real physics so even if you do not know anything about Newton's theory of gravity, this will lead to some feeling of natural behavior. Note that gravity emitters aren't meant to be used to make gravity that comes always from the same direction. This can be achieved more easily by setting up a constant acceleration.

Using gravity emitters is really easy. You just have to set up their position in world space and the intensity of the gravity they should emit. The rest is done automatically. Gravity emitters should be used carefully since they have to be applied to every single particle which takes a bit computing time. Ultimate 3D sets a limit of 32 gravity emitters per particle system. Here's the function you have to use to create gravity emitters:

This function adds a new gravity emitter to the particle system the function is called by and returns its ID, which can be used to modify it afterwards.

AddGravityEmitter(
PositionX, PositionY, PositionZ,
GravityEmitterMass
)

PositionX, PositionY, PositionZ
The position of the gravity emitter given in world space.

GravityEmitterMass
The mass of the gravity emitter. A good value for this parameter depends on the distances in your particle system, so you should find one by playing around with it.


This function can be used to modify or remove a gravity emitter you have created before.

SetGravityEmitter(
GravityEmitterID,
PositionX, PositionY, PositionZ,
GravityEmitterMass
)

GravityEmitterID
The ID of the gravity emitter you want to modify. This is the value
AddGravityEmitter(...) returned when creating the gravity emitter.

PositionX, PositionY, PositionZ
The new position of the gravity emitter given in world space.

GravityEmitterMass
The new mass of the gravity emitter. If you enter 0 for this parameter the gravity emitter will be removed.


Particle modifiers

Often particles need to change when they get into some particular area. For example if you make a particle system to add some spray to a waterfall, the particles have to stream upwards after they hit the surface of the water. Things like this can be done easily using particle modifiers. Particle modifiers change particles whenever the particles are in the area you have defined for them. They can change any property of the particles (lifetime, velocity, acceleration, color and size). This makes the particle systems really flexible and lively.

Setting up the properties of particle modifiers is quite similar to setting up the properties of the particle system. Everything is done through function calls and many properties are similar to those you can set up for the particle systems. But before setting up properties for particle modifiers you have to create them. To do this you have to call AddModifier(). This function will return the ID of the modifier which has to be saved to a variable, to be able to set up any properties for the modifier. Here are the functions you need to set up the properties of the modifier:

This function sets up the area that's affected by the particle modifier. This works in the same way as setting up the particle origin (see SetParticleOrigin(...) ). Whenever a particle is in this area it gets modified:

SetModifierEffectedArea(
ModifierID,
SecondSphereRadius,
PositionX, PositionY, PositionZ,
RotationX, RotationY, RotationZ,
ScalingX, ScalingY, ScalingZ
)

ModifierID
The ID of the modifier you want to change.

SecondSphereRadius
The radius of the second sphere which is the second border for the affected area.

PositionX/Y/Z, RotationX/Y/Z, ScalingX/Y/Z
The transformation of the two spheres that are the borders of the affected area.


This function sets up a modifier that will change the life time of a particle when it's in the area of that modifier. So if you set this to one, a particle would never die while it's in the affected area, because its lifetime gets increased (and decreased) by one in every single step.

SetModifierLifetimeChange(
ModifierID,
LifetimeChange
)

ModifierID
The ID of the modifier you want to change.

LifetimeChange
The change of the lifetime per step.


The next two functions set up how the modifier changes the velocity and the acceleration of the particles that are in its affected area. Both take a factor and a summand. Whenever a particle is in the affected area, its velocity or acceleration gets changed using the following formula: Value=Value*Factor+Summand. In this formula "Value" refers to the velocity or the acceleration. So by setting up a velocity factor which is a bit lower than 1, you could implement friction. By setting up a negative velocity factor you can reflect particles. Here are the functions for setting up these properties:

This function sets up the velocity modifier of the particles in the affected area:

SetModifierVelocityChange(
ModifierID,
VelocityFactorX, VelocityFactorY, VelocityFactorZ,
VelocitySummandX, VelocitySummandY, VelocitySummandZ
)

ModifierID
The ID of the modifier you want to change.

VelocityFactorX, VelocityFactorY, VelocityFactorZ
The factor that the velocity of the particle is to be multiplied by in every step while it's in the affected area of the modifier. It can be set up individually for every single axis.

VelocitySummandX, VelocitySummandY, VelocitySummandZ
The summand that the velocity of the particle is to be added to in every step while it's in the affected area of the modifier. It can be set up individually for every single axis.


This function sets up the acceleration modifier of the particles in the affected area:

SetModifierAccelerationChange(
ModifierID,
AccelerationFactorX, AccelerationFactorY, AccelerationFactorZ,
AccelerationSummandX, AccelerationSummandY, AccelerationSummandZ
)

ModifierID
The ID of the modifier you want to change.

AccelerationFactorX, AccelerationFactorY, AccelerationFactorZ
The factor that is to be multiplied by the acceleration of every particle in every step while it's in the affected area of the modifier. It can be set up individually for every single axis.

AccelerationSummandX, AccelerationSummandY, AccelerationSummandZ
The summand that is to be added to the acceleration of every particle in every step while it's in the affected area of the modifier. It can be set up individually for every single axis.


Next you can set up a new final color and a new final size for the particles that enter the area of the particle modifier. Since you change only the new final values, there's no rapid change. Instead there will be a smooth interpolation. Here are the functions:

This function sets up a range of possible colors that may be used as new final color for particles that enter the area of the given particle modifier.

SetModifierNewFinalColor(
ModifierID,
MinimumR, MinimumG, MinimumB, MinimumA,
MaximumR, MaximumG, MaximumB, MaximumA
)

ModifierID
The ID of the modifier you want to change.

MinimumR/G/B/A, MaximumR/G/B/A
The range of possible colors that may be set up as the new final color for particles that enter the area of the modifier. The values for these parameters should lie in the range of 0 to 255.


This function changes the final size for particles that enter the area of the modifier.

SetModifierNewFinalSize(
ModifierID,
MinimumNewFinalSize, MaximumNewFinalSize
)

ModifierID
The ID of the modifier you want to change.

MinimumNewFinalSize, MaximumNewFinalSize
The range of possible new final sizes given in world space.



© Christoph Peters. Some rights reserved.

Creative Commons License XHTML 1.0 Transitional