Cge-2d-particle-emitter now supports GPU-based particle

I just done reviving my 5-year-old 2D particle system and add supports for GPU particles. The APIs for the new particle system is similar to the old one so one can just swap the class to the new system and it “just work” :slight_smile:

screenshot, render 1 million particles on screen & FPS is still stable at 60

A few things:

  • The new particle system makes use of Transform Feedback and some OpenGL 3+ stuff, so an OpenGL 3.3+ compatible graphics card is required. This also mean it will not work on mobile, as CGE still uses GLES2 for mobile devices. The old particle system is still available for those who wants to target low-end systems.
  • Due to the way new system handles lifecycles, if ReleaseWhenDone field is true, particle emitter will immediately remove itself once EmissionTime = 0.
  • It is implemented by calling OpenGL APIs directly, so if CGE caches OpenGL states somewhere then there’s chance it will mess up rendering (I haven’t noticed anything weird so far).
1 Like

ReleaseWhenDone field now behave similarly to old particle system’s, which makes GPU-based particle system 100% compatible with the old one.

Edit: Just notice a blending bug that affect the old particle system. Fixed now in latest commits.

Oh fantastic. I will test it and make a news post in the upcoming week. Thank you!

As for OpenGLES 3, you can test it already. For Android (and other systems that could initialize OpenGLES using EGL – which means everything except iOS), just edit src/window/castlewindow_egl.inc and change there

const
  ContextAttribs: array [0..2] of EGLint =
  ( EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE);

to use number 3 instead of 2 :slight_smile:

This change will be enough for all systems except iOS. On iOS the OpenGLES context is initialized using iOS API, it is in tools/build-tool/data/ios/xcode_project/cge_project_name/OpenGLController.m . There’s a line with initWithAPI:kEAGLRenderingAPIOpenGLES2 – likely you can just change it to initWithAPI:kEAGLRenderingAPIOpenGLES3.

I did not test it. But as far as I know, our usage of OpenGLES 2 should be also all valid in OpenGLES 3.

CGE doesn’t ship with GLES3 header (so does Free Pascal) so a GLES3 header is necessary. And yes I am aware that GLES2 is compatible with GLES3 so current engine code should work fine with GLES3 :slight_smile:

Edit: btw when rebuilding castle-editor via Restart Editor menu the compiler cannot see castleconf.inc used by custom components. It is fine if I build the project with build tool.

Your own code should not use, and not need, castleconf.inc. The idea is that it is only necessary for CGE code, to set some things we like when coding CGE. Applications/components based on CGE should not need castleconf.inc.

I need it mainly for explicitly calling OpenGL header (CastleGL). I can check the target manually, but include CastleGL would be better since there’re platforms (Nintendo Switch) that doesn’t have a FPC target.

On Nintendo Switch, we define CASTLE_NINTENDO_SWITCH symbol.

I’d say that for custom components, it is better to manually do define CastleGL macro, replicating part of castleconf.inc:

{ Whether we use OpenGL ES or normal OpenGL.
  OpenGL ES is generally for mobile devices.
  For testing, you can also use OpenGL ES on normal desktop OSes
  (under Debian, install libegl1-mesa-dev and libgles2-mesa-dev).
  Put "CastleGL" in uses clause to include the appropriate OpenGL API. }
{ $define OpenGLES}
{$ifdef ANDROID} {$define OpenGLES} {$endif}
{$ifdef iOS} {$define OpenGLES} {$endif}

{ NX supports OpenGL and OpenGLES (that's public information,
  https://wccftech.com/nintendo-switch-supports-vulkan/ ).
  Our rendering matches better OpenGLES on NX. }
{$ifdef CASTLE_NINTENDO_SWITCH} {$define OpenGLES} {$endif}

{$ifdef OpenGLES}
  {$ifdef CASTLE_NINTENDO_SWITCH}
    {$define CastleGL := CastleInternalNxGLES20}
  {$else}
    {$define CastleGL := CastleGLES20}
  {$endif}
{$else}
  {$define CastleGL := GL, GLExt}
{$endif}

While it means a duplication of code, it also means you don’t rely on castleconf.inc which I treat as somewhat internal – it may even change Pascal syntax (depending on engine needs, e.g. at some point I added there {$ifdef FPC} {$modeswitch advancedrecords} {$endif}).