Getting started with Kanzi Particles

This guide walks through setting up Kanzi Particles in Kanzi Studio, from an empty project to a working emitter with custom emission logic, a collider, event generation, and a subemitter.

Each section builds on the previous one. If you already have a project and just want to add custom shader logic, skip to Writing custom compute materials.

Tip

Fastest path to particles on screen. If you just need a standard shape emitter (box, sphere, disc, torus, or point), drop the matching prefab into your ParticleSystem and tune the published properties on the prefab root. No manual material import, no property-type imports, no GLSL. See Starting with templates.

Continue with this page when you want to build an emitter from the materials by hand — useful for learning how the pieces fit together, or for cases the prefabs don’t cover (custom emission shape, non-standard material slots).

Note

Kanzi Particles and its underlying Kanzi branch are under active development. You can encounter transient compiler errors, UI glitches, or workflow rough edges. These are known and being fixed before release. The Known issue callouts in this document flag the bigger ones.

Smoke test: your first emitter

Create a new Kanzi Studio project

  1. Launch Kanzi Studio.

  2. In the Quick Start window, click New.

  3. Choose the Kanzi Studio project template. (The Application template generates a C++ scaffold; you do not need that for this walkthrough.)

  4. In the right-hand panel:

    • Project Name: FirstSparks (or whatever you like).

    • Location: the default C:\KanziWorkspace\Projects is fine.

    • Create folder: leave checked.

    • Materials: choose Add materials later. The particle rendering materials used in this tutorial come from the asset package, so there is no need to generate any defaults.

  5. Click Create.

_images/new-project-dialog.png _images/empty-project.png

Set the target graphics API

By default new projects target OpenGL ES 3.0, which does not support compute shaders. Kanzi Particles runs all of its emission, simulation, and collision on the GPU via compute, so you need OpenGL ES 3.1 or higher.

  1. From the main menu, select Project → Properties.

  2. In the Properties panel, scroll to the Profile group and set Target Graphics API to OpenGL ES 3.1 (or higher).

_images/target-graphics-api.png

If you skip this step, the plugin loads, but any emitter, affector, or collider that references a compute material fails to run.

Add the Kanzi Particles DLL

  1. In Kanzi Studio, open the Library panel.

  2. Locate the Kanzi Engine Plugins category.

  3. Right-click Kanzi Engine Plugins and select the option to add a plugin.

  4. Browse to kzparticles.dll. In a Kanzi installation it is at <KanziWorkspace>/Engine/plugins/particles/lib/win64/vs2022_Release_DLL/kzparticles.dll (use vs2022_Debug_DLL for the debug build). If you build the plugin from source, it is in the same lib/win64/vs2022_<configuration>_DLL/ folder of the plugin repository.

Once added, the plugin appears in the Library under Kanzi Engine Plugins → kzparticles → your chosen build configuration (for example, VS2022 Release).

_images/library-kzparticles.png

After the plugin loads, four new node types become available when you right-click a node in the Node Tree and select Create:

  • Particle System: root node for a single system of particles; contains emitters, affectors, and colliders.

  • Particle Emitter: emits particles according to material shaders.

  • Particle Affector: applies forces to particles.

  • Particle Collider: bounces particles off surfaces.

_images/create-menu.png

Add a Particle System and Emitter

  1. In the Node Tree, right-click the Scene node and select Create → Particle System. Kanzi Studio prompts for a name: enter ParticleSystem and confirm.

  2. Right-click the new ParticleSystem node and select Create → Particle Emitter. Name it ParticleEmitter and confirm.

_images/create-emitter-menu.png

In the Preview pane, you should already see a small cluster of coloured particles emitting from the centre of the scene. The emitter ships with sensible defaults for all of its materials so there is something on screen right away.

With the ParticleEmitter selected, the Properties panel shows the material slots grouped by pipeline stage:

  • Affector → Self Affect Material: applies forces local to this emitter.

  • Emission → Maximum Amount, Emission Material, Emission Count Material: how many particles, how they are initialised.

  • Events → Event Generate Material: conditions under which a particle generates an event (death, hit, and so on).

  • Rendering → Particle Material, Particle Mesh, Sorting Type: how particles are drawn.

You will replace the default materials with asset-package materials in the next section, and with your own custom shaders via Writing custom compute materials.

_images/default-emitter-properties.png

Adding the asset package

Building materials and shaders by hand for every project is tedious. The ParticlesAssetPackage ships with ready-made emitter shapes, affectors, colliders, emission counts, event generators, and rendering materials that you can drop into any project.

Add the asset package as a source

Asset package sources are configured globally in Kanzi Studio, not per-project. If you have added ParticlesAssetPackage in a previous session, it is already in the list and you can skip this step.

Note

If the asset package was added previously but the contents look stale (for example, materials you expect to see are missing), the source may be cached. Try clicking refresh on the asset source, or remove and re-add the source to pull the current contents.

  1. Open the Asset Packages tab.

  2. Click the + Add Asset Source button at the top of the panel.

    _images/add-asset-source.png
  3. In the Select Asset Source folder picker, navigate to <KanziWorkspace>/Engine/plugins/particles/assets/ParticlesAssetPackage/ and click Select Folder.

    _images/select-asset-source-folder.png

The left-hand list of sources now shows a ParticlesAssetPackage entry alongside any pre-installed sources (for example, Asset Toolkit and Factory Content). Selecting it shows the available materials, material types, property types, and prefabs as thumbnails.

Import an emitter material

  1. Copy the Shaders/Particles directory from <KanziWorkspace>/Engine/plugins/particles/assets/ParticlesAssetPackage into the Shaders directory of your Kanzi Studio project.

    Note

    This works around a known issue: Kanzi Studio imports the shader include files without their Particles directory, so without this copy the imported shader fails to compile with #include - Could not process include directive for header name: Particles/emitter.glsl. Do this once per project, before you import materials or prefabs from the asset package. See Kanzi Studio: imported shaders cannot find their include files.

  2. In Asset Packages, select ParticlesAssetPackage from the list of sources on the left. The main area shows all exported assets as a flat thumbnail grid. Use the search box at the top to narrow down the list.

  3. Find the Emitter_Disc thumbnail, right-click it, and select Import Asset Package.

_images/import-emitter-disc.png

The material, its material type, and all its required property types are copied into your project. You can find them under Materials, Material Types, and Property Types in the library. In Resource Files → Shaders, the imported Emitter_Disc.comp.glsl sits next to the Particles directory that you copied:

_images/shaders-after-manual-fix.png

Assign the material to the emitter node

  1. Select the Particle Emitter in the node tree.

  2. In the Properties panel, under the Emission group, locate the Emission Material property.

  3. Click the property value and select the Emitter_Disc material you just imported.

_images/assign-emission-material.png

Add emission property types to the node

The emission shader exposes several uniforms (radius, lifetime, initial velocity, and so on). To control them in Kanzi Studio you must add the matching property types to the emitter node.

  1. Select the Particle Emitter.

  2. In Properties, click + Add Property.

  3. In the Add Properties dialog, select the All tab and type emission in the search box. The available properties list narrows to the Emission category.

    _images/add-emission-properties.png
  4. Add the following properties:

    • Emission.OuterRadius

    • Emission.InnerRadius

    • Emission.Volume

    • Emission.Lifetime

    • Emission.InitialVelocityStrength

    • Emission.Scale

  5. Set Emission.Volume to true. With Volume off (the default), Emitter_Disc spawns particles on the inner and outer rims of the disc; with Volume on, it fills the disc area between InnerRadius and OuterRadius.

The asset-package defaults (OuterRadius=1, InnerRadius=0, Lifetime=1, InitialVelocityStrength=1, Scale=1) give you visible particles out of the box. InitialVelocityStrength is the initial speed of each particle; raise it (for example, to 4) for a livelier spray. Sliders appear in the Emission group of the Properties panel for each one. Emission lists every property Emitter_Disc reads.

_images/emission-property-sliders.png

Import and assign an emission count material

By default an emitter uses a built-in emission count material that emits 100 particles per second. To control the rate yourself, replace it with one from the asset package.

  1. In Asset Packages → ParticlesAssetPackage, type count in the search box. Select EmissionCount_Schedule and import it (right-click → Import Asset Package).

    _images/import-emission-count.png
  2. Select the Particle Emitter.

  3. In the Emission group of the Properties panel, set Emission Count Material to EmissionCount_Schedule.

  4. Add the Emission.Rate property to the emitter node and set it to the rate you want in particles per second (for example, 500). The material default is 10.

With the other schedule properties at their defaults (Emission.OnDuration = Emission.OffDuration = 0), EmissionCount_Schedule emits a steady stream at Emission.Rate.

_images/emission-count-result.png

Tip

Maximum Amount caps live particles. The emitter’s Maximum Amount property (default 5000) is the hard upper limit on how many particles can be alive at once. If Rate × Lifetime exceeds Maximum Amount, emission stalls once the cap is reached and particles visibly pop in as older ones die. For smooth emission, keep Maximum Amount ≥ Rate × Lifetime. You can also create a binding that computes this automatically: set Maximum Amount to {./Emission.Rate} * {./Emission.Lifetime}. See Sizing MaximumAmount.

Writing your own compute materials

The asset package covers common cases, but custom behaviour requires writing your own compute shader for the relevant slot (emission, emission count, affector, collider, event generator).

For the authoring workflow (GLSL include structure, declaring uniforms and wiring them up to asset-package property types, and hooking a custom material into an existing node slot) see Writing custom compute materials.

Writing a collider

A collider tests each particle for penetration into a surface and reports a hit point, normal, and parametric hit time. The collider template handles the physical response (reflect velocity, apply bounce/friction, advance remaining sub-step time): your shader only answers the geometric question.

Collider shader template

#version 450 core
#include "Particles/collider.glsl"

// Uniforms here.

HitInfo Collide(vec3 position, vec3 prevPosition)
{
    HitInfo info;
    info.hit  = false;
    info.tHit = 0.0;

    // The collider node's world transform is available via getColliderTransform().

    // If this particle has penetrated your surface, fill in:
    //   info.hit      = true
    //   info.position = contact point on the surface
    //   info.normal   = outward surface normal (unit length)
    //   info.tHit     = [0..1] parametric hit time along prevPosition → position

    return info;
}

Hook it up

  1. Right-click Particle System → Create → Particle Collider.

  2. In the Library → Material Types, duplicate an existing collider material type (for example, Collider_Sphere) and rename the copy. Replace its Compute Shader with your collider shader.

  3. Create a material instance and assign it to the collider node’s Collider Material property.

  4. The collider node has built-in Bounce (default 0.5) and Friction (default 0.1) properties: no need to add them manually. The collider template feeds these into the response calculation automatically.

Reference colliders in the asset package: Collider_Plane, Collider_Sphere, Collider_Box, Collider_Cylinder, Collider_Capsule, Collider_Cone.

Other emission count options

Earlier you used EmissionCount_Schedule for a steady stream. The same material also produces other time-based patterns through its Emission.OnDuration, Emission.OffDuration and Emission.ImpulseAtCycleStart properties:

  • One burst at start: Emission.ImpulseAtCycleStart = N, Emission.Rate = 0, Emission.OffDuration = a large value (for example, 1e10).

  • Recurring burst: Emission.ImpulseAtCycleStart = N, Emission.Rate = 0, Emission.OnDuration = 0, Emission.OffDuration = the interval in seconds.

  • Stream that switches on and off: Emission.Rate, Emission.OnDuration and Emission.OffDuration.

The asset package has one other emission count material, EmissionCount_FromEvents, which emits N particles per event received from another emitter. Subemitters use it; see Subemitters below. See Emission for the full catalog.

Generating events

An emitter can generate events for notable moments in a particle’s life: death, collision, or custom conditions. These events drive subemitters.

On-death events

  1. In Asset Packages → ParticlesAssetPackage, search for lifetime and import Event_Lifetime.

  2. Select the emitter node.

  3. Set its Event Generate Material property to Event_Lifetime. Its defaults (Events.LifetimeMin = Events.LifetimeMax = 1) fire an event on death.

Each frame, every particle that died this frame writes an event into the emitter’s event buffer. On its own this does nothing visible: events only take effect when another emitter consumes them.

Probabilistic events

Add the Events.Probability property to Event_Lifetime to fire for only a fraction of dying particles (0.0 = never, 1.0 = every particle). The roll is population-level (per-particle deterministic), so a steady fraction fires rather than flickering frame to frame. Useful when you do not want a 1:1 ratio between parent and sub-emitted particles.

See Events and subemitters for the full generator catalog.

Subemitters

A subemitter is a second Particle Emitter that reads events from a source emitter and spawns one or more particles per event. Canonical use case: sparks or puffs spawning where particles die. Full recipe is in Events and subemitters; a short walkthrough follows.

Add a second emitter node

  1. Right-click Particle System → Create → Particle Emitter. Name it SubEmitter to distinguish it from the first one.

  2. Assign it a Particle Material for rendering, so that its particles look different from the source emitter’s (for example, import ParticlesColorOverLife from the asset package).

Import event-driven emission materials

From the asset package (search for event), import:

  • EmissionCount_FromEvents (emits one particle per event; to emit N, add Emission.ParticlesPerEvent to the subemitter node and set it to N).

  • Emitter_FromEvents (a simple emission material that spawns each particle at the hit/death position of the source particle).

Wire up the subemitter

  1. Select the SubEmitter node.

  2. Set Emission Count Material to EmissionCount_FromEvents.

  3. Set Emission Material to Emitter_FromEvents.

  4. Add the Emission.SourceEventBuffer and Emission.SourceParticleDataBuffer properties to the subemitter. Leave their values empty: you set them with bindings in the next two steps, not from the property drop-downs.

  5. In the Properties, click + Add Binding. In the Binding Editor, set Property to Emission.SourceEventBuffer, enter this expression, and click Save:

    {@../ParticleEmitter/ParticleEmitter.EventBuffer}
    
  6. Add a second binding the same way, with Property set to Emission.SourceParticleDataBuffer and this expression:

    {@../ParticleEmitter/ParticleEmitter.ParticleDataBuffer}
    

The first binding gives the subemitter the events from the source emitter, and the second gives it the source particles, so that it knows where each event happened. Each frame, the subemitter spawns one particle per event: at the position of the source particle that generated the event.

For more about these bindings, see Events and subemitters.

Play and tune

Press Play. You should see the original emitter plus a stream of subparticles appearing wherever a source particle dies. Adjust:

  • Events.Probability on the source: fewer events, fewer sub-particles.

  • Subemitter lifetime, scale, and rendering material: to make the secondary particles look distinct.

What’s next?

  • Browse the demo scene in the asset package: open ParticlesAssetPackage.proj.kzm in Kanzi Studio and look at the exhibits under Screens → Screen. It contains working examples of most emitters, affectors, and colliders. Open the project from a copy of the plugin directory, not from your Kanzi installation. See Kanzi Studio: opening the asset package changes the installation.

  • Run the demo scene outside Kanzi Studio on Windows or Android with the example application. See Running the example application.

  • Read Particle system anatomy for the node and material-slot model.

  • Check Shaders/Particles/particle_data_buffer.glsl for the complete list of per-particle accessors (getPosition, getVelocity, getNormalizedLifetime, and so on).