This is an old revision of the document!


Using the ParticleSystem

Gorilla3D provides an integrated particle system for rendering complex and individual particle effects.

A particle effect is produced by a so-called emitter represented by the basic TGorillaParticleEmitter class. Extend this class to build your own effect. Gorilla3D already supplies some of the most popular effects, like: fire, smoke, rain, snow, waterfall, eruption, explosion.

It is possible to manipulate each particle by the so-called influencers. The framework already provides a lot of the basic influencer types, like: linear movement, spiral movement, gravity, wind, particle color, trailed movement, traktor movement and physics.

Features

  • Randomizable particle properties by presets
  • Cachable particles
  • Count limitation
  • Auto emittance
  • Interactive emmittance
  • Endless or limited emmittance
  • Physically based particle collision detection with other scene objects (not with particles!)

Example

Fire effect

Form1.pas
procedure TForm1.FormCreate(Sender: TObject);
var LParticles := TGorillaFireParticleEmitter;
    LParticleMat : TParticleMaterialSource;
begin
  LParticles := TGorillaFireParticleEmitter.Create(FGorilla);
  LParticles .Camera := FCamera;
 
  // a fire effect contains multiple parts: a front and back flame and smoke
  LParticleMat := LParticles.Back.MaterialSource as TParticleMaterialSource;
  LParticleMat.Texture.LoadFromFile('fire2.png');
 
  LParticles.LoadTexture('fire.png');
  LParticles.Smoke.LoadTexture('smoke.png');
  LParticles.Scale.Point := Point3D(5, 5, 5);
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // on some constellations you will need an interval to update the viewport
  FGorilla.Invalidate();
end;

Smoke effect with wind influencer

Form1.pas
procedure TForm1.FormCreate(Sender: TObject);
var LParticles := TGorillaSmokeParticleEmitter;
    LParticleMat : TParticleMaterialSource;
    LWind : TGorillaWindParticleInfluencer;
begin
  LParticles := TGorillaSmokeParticleEmitter.Create(FGorilla);
  LParticles.Camera := FCamera;
 
  // load smoke texture atlas
  LParticles.LoadTexture('smoke.png');
 
  // randomize particle size and growth
  LParticles.ParticleSize   := TParticlePreset.Create(16, 16, 1, false);
  LParticles.ParticleGrowth := TParticlePreset.Create(4, 8, 1, false);
 
  LWind := TGorillaWindParticleInfluencer.Create(LParticles);
  LWind.Origin := TPoint3D.Create(5, 0, 0);
  LWind.Size   := TPoint3D.Create(5, 3, 3);
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // on some constellations you will need an interval to update the viewport
  FGorilla.Invalidate();
end;

Eruption effect with color influencer

Form1.pas
procedure TForm1.FormCreate(Sender: TObject);
var LParticles : TGorillaEruptionParticleEmitter;
    LColorInfl : TGorillaColoredParticleInfluencer;
begin
  LParticles := TGorillaEruptionParticleEmitter.Create(FGorilla);
  LParticles.Camera := FCamera;
 
  LColorInfl := TGorillaColoredParticleInfluencer.Create(LParticles);
  LColorInfl.StartColor := TAlphaColorF.Create(0, 0, 1, 1);
  LColorInfl.EndColor := TAlphaColorF.Create(0, 0, 0, 0);
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // on some constellations you will need an interval to update the viewport
  FGorilla.Invalidate();
end;

Rain effect

Form1.pas
procedure TForm1.FormCreate(Sender: TObject);
var LParticles : TGorillaRainParticleEmitter;
begin
  LParticles := TGorillaRainParticleEmitter.Create(FGorilla);
  LParticles.Camera := FCamera;
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // on some constellations you will need an interval to update the viewport
  FGorilla.Invalidate();
end;

Snow effect

Form1.pas
procedure TForm1.FormCreate(Sender: TObject);
var LParticles : TGorillaSnowParticleEmitter;
begin
  LParticles := TGorillaSnowParticleEmitter.Create(FGorilla);
  LParticles.Camera := FCamera;
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // on some constellations you will need an interval to update the viewport
  FGorilla.Invalidate();
end;

Mouse interaction

Form1.pas
var 
  FParticles : TGorillaParticleEmitter;
 
procedure TForm1.FormCreate(Sender: TObject);
var LParticleMat : TParticleMaterialSource;
    LVPreset   : TParticleVectorPreset;
    LColorInfl : TGorillaColoredParticleInfluencer;
begin
  // create the particle material shader
  LParticleMat := TParticleMaterialSource.Create(FGorilla);
  LParticleMat.Parent := FGorilla;
  LParticleMat.UseTexture := false;
  LParticleMat.IsTextureAtlas := false;
 
  // create particle emitter for spraying effect
  FParticles := TGorillaParticleEmitter.Create(FGorilla);
  FParticles.Parent := FGorilla;
 
  // connect particle shader and emitter
  LParticleMat.Emitter := FParticles;
 
  // limit number of particles
  FParticles.EmitParticles := 100;
  FParticles.MaxParticles  := 10000;
 
  // disable auto emittance, becaus we want only to emit on mouse click
  FParticles.AutoEmit := false;
 
  // enable particle caching
  FParticles.Reuse := true;
 
  // randomize particle properties
  // 1) random position of particles
  LVPreset := TParticleVectorPreset.Create(0, 0, 1000, Point3D(1, 1, 1), [axX, axY, axZ]);
  FParticles.ParticlePosition := LVPreset ;
 
  // 2) random velocity of particles
  LVPreset := TParticleVectorPreset.Create(5, 10, 1000, Point3D(1, 2, 1), [axX, axY, axZ]);
  LVPreset.RangeY.Negative := false;
  FParticles.ParticleVelocity := LVPreset;
 
  // 3) the rest of properties
  FParticles.ParticleSize     := TParticlePreset.Create(2, 3, 1, false);
  FParticles.ParticleAngle    := TParticlePreset.Create(0, 360, 1, false);
  FParticles.ParticleWeight   := TParticlePreset.Create(1, 1, 1, false);
  FParticles.ParticleGrowth   := TParticlePreset.Create(0, 0, 1, false);
  FParticles.ParticleLifeTime := TParticlePreset.Create(500, 5000, 1000, false);
 
  // create a color influencer for a starting and end color
  LColorInfl:= TGorillaColoredParticleInfluencer.Create(FParticles);
  LColorInfl.StartColor := TAlphaColorF.Create(0, 1, 0, 1);
  LColorInfl.EndColor := TAlphaColorF.Create(0, 0, 1, 0);
end;
 
var 
  FLatest : TPointF;
  FMouseMove : Boolean = false;
  FClickPt : TPoint3D; 
 
procedure TForm1.DoOnViewportMouseUp(ASender : TObject; AButton : TMouseButton;
  AShift : TShiftState; X, Y : Single);
begin
  FMouseMove := false;
end;
 
procedure TForm1.DoOnViewportMouseDown(ASender : TObject; AButton : TMouseButton;
  AShift : TShiftState; X, Y : Single);
var I : Integer;
begin
  if (ssLeft in AShift) then
  begin
    FMouseMove := true;
    FLatest := PointF(X, Y);
 
    // emit particles at mouse position
    FClickPt := FGorilla.ScreenToWorld(Point(round(X), round(Y)));
    for I := 0 to (FParticles.EmitParticles - 1) do
      FParticles.EmitParticle(FClickPt);
  end;
end;
 
procedure TForm1.DoOnViewportMouseMove(ASender : TObject; AShiftState : TShiftState;
  X, Y : Single);
var lDiff   : TPointF;
    I       : Integer;
    lOrigin : TPoint3D;
begin
  if (ssLeft in AShiftState) then
  begin
    // emit particles at mouse position
    FClickPt := FGorilla.ScreenToWorld(Point(round(X), round(Y)));
    for I := 0 to (FParticles.EmitParticles - 1) do
      FParticles.EmitParticle(FClickPt);
  end;
 
  if FMouseMove then
  begin
    FLatest := PointF(X, Y);
  end;
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // on some constellations you will need an interval to update the viewport
  FGorilla.Invalidate();
end;

Next step: Physics