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!)
Shader / Material
The particle emitter expects a pointsprite compatible material source to be applied. Gorilla3D therefor provides the TGorillaParticleMaterialSource as default material. It supports rendering a single texture, texture-atlas (for animated particles) and colored particles on pointsprite basis.
Have a look at Materials
Of course you can write your own shader if those features do not suit your needs.
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