Particle System Improvements

Here’s a little something that I’ve been doing on the side.

The fire effect has been created with a new Particle System node that includes tons of customization controls. For example, you can define shapes for the particle emitter from several mathematical shapes like cylinder (the one in the video), cones, spheres, etc.

In addition, some particle properties like size and color can be interpolated using starting and ending values. The interpolation method is fixed for the moment, but it will be customizable in the near future to use different integration curves.

At the moment, the particle system is implemented entirely in CPU, meaning no point sprites or any other optimization techniques are used, which lead to performance issues as particle count gets bigger (the effect in the video has a particle count of 50).

The particle system in the video above is configured on a Lua script as follow

   type = 'crimild::ParticleSystem',
   maxParticles = 50,
   particleLifetime = 2.0,
   particleSpeed = 0.75,
   particleStartSize = 0.5,
   particleEndSize = 0.15,
   particleStartColor = { 1.0, 0.9, 0.1, 1.0 },
   particleEndColor = { 1.0, 0.0, 0.0, 0.5 },
   emitter = {
      type = 'cylinder',
      height = 0.1,
      radius = 0.2,
   precomputeParticles = true,
   useWorldSpace = true,
   texture = 'assets/textures/fire.tga',

Even when the new system is quite easy to configure, it still requires a lot of try and error to get something nice on screen. Maybe it’s time to start thinking about a scene editor…


Crimild v4.1.0

A new year. A new version.

In the past few months I’ve been working hard on a small iOS game called “Le Voyage”. If you haven’t heard about it, you can check it out on its official website and download it for free. No ads guarantee.

“Le Voyage” has been a great opportunity to improve Crimild’s iOS support, particularly regarding rendering and simulation. Enhanced image effects, performance tweaks, a more robust scene builder, more tools for debugging and handling platform specifics, and a lot of bug fixing. Go to GitHub to get the full release notes.

Here’s the trailer for “Le Voyage”, where you can see the latest version in action. Enjoy!

Deferred(ish) Rendering

During the past few weeks I’ve been reviewing a lot of the rendering pipeline. One of the things I started working on is the new Deferred Render pass.

In short, Deferred Rendering (DR) is performed by first rendering the visible scene into a deep frame buffer (usually known as the G-Buffer), storing specific sets of data like positions, normals, colors, material properties, etc. Lighting calculations are then performed in a separate pass, computing the lighting equation only for the visible pixels. Here’s a great introduction to Deferred Rendering in general.

The main benefit of DR is that it makes possible the use of a high number of light sources, since there is no need to compute lighting for those pixels that are actually occluded by others. But I personally like it because it provides much more data to work with when applying screen effects like SSAO or Glow.

Since this is my first approach to Deferred Rendering, I didn’t want to complicate too much the layout of the G-Buffer:

G-Buffer LayoutA lot of space is wasted, I know. But then again, this is the first approach.

The following video shows the updated Lightcycle demo using deferred rendering and a glow effect. The video also shows the output for each buffer separately, for debug purposes

I also gave it a try to SSAO, which can be seen in the next couple of images, but I’m not comfortable with the results



Without SSAO

Without SSAO

As much as I like DR, making it the default render pass seems difficult in the near future. It requires a lot of memory and it’s dependent on the host platform to support multiple render targets (MRT), which is not standard. For example, GLES 3 does support MRT, but most mobile devices still have GLES2-based graphic cards.

Next steps are to compute lighting using light shapes and add some more screen effects. Stay tuned.