DEV Community

Cover image for A Git-Friendly Particle VFX Workflow for Three.js and PixiJS
Hiroshi TK
Hiroshi TK

Posted on

A Git-Friendly Particle VFX Workflow for Three.js and PixiJS

Git is great at tracking code.

It is less pleasant when important parts of your game are hidden inside opaque editor files.

That becomes noticeable when you start building a serious VFX library.

An explosion changes.

What changed?

Was it the texture?

The particle lifetime?

The emission shape?

The velocity curve?

The blend mode?

If your effect is stored as readable data, answering those questions becomes much easier.

VFX Works Surprisingly Well as Text

A particle system is mostly structured configuration.

Conceptually, an effect might contain something like this:

{
  "name": "impact",
  "duration": 0.5,
  "emission": {
    "count": 18
  },
  "lifetime": {
    "min": 0.2,
    "max": 0.5
  }
}
Enter fullscreen mode Exit fullscreen mode

Real effects obviously contain more information, but the important point is that most of it can be represented cleanly as data.

Once the source is JSON, normal development tools start working on your visual effects.

You get:

  • Git history
  • Diffs
  • Branches
  • Pull requests
  • Code review
  • Merge tooling
  • Search
  • Scripts
  • CI validation

That is useful even if nobody on the team ever edits the JSON manually.

Reviewing Visual Changes

Suppose someone changes a fire effect.

A Git diff might show that particle lifetime changed from 1.2 seconds to 0.8 seconds and the emission rate changed from 30 to 45.

You still need to preview the effect visually, but the diff gives you useful context.

That is much better than this:

fire_effect.asset changed
Enter fullscreen mode Exit fullscreen mode

with no idea what happened inside it.

Keep Authoring and Runtime Separate

There is another useful pattern here.

Do not make your game load the entire editor project.

Instead, export a runtime bundle.

For example:

vfx-project/
  particle-data/
  source-assets/
  editor-settings/

game/
  public/
    vfx/
      manifest.json
      effects/
      textures/
Enter fullscreen mode Exit fullscreen mode

The first directory exists for authoring.

The second exists for shipping.

This keeps unnecessary editor data out of the production build and gives you an explicit point where validation can happen.

Validation Belongs in the Build Pipeline

Visual tools often encourage a dangerous assumption:

"If it previews correctly, it must be valid."

That is not always true.

An effect might reference a missing texture.

A feature could work in one renderer but not another.

A malformed value might only fail on a specific device.

A command-line validation step catches some of these problems before the game starts.

This is where tools such as NixieFX fit naturally into a web development workflow. A browser-based editor is useful for visual iteration, while CLI-oriented validation and export make it easier to connect particle assets to the rest of your build process.

Conceptually, your package.json could include something like this:

{
  "scripts": {
    "vfx:validate": "your-vfx-tool validate",
    "vfx:export": "your-vfx-tool export",
    "build": "npm run vfx:validate && npm run vfx:export && vite build"
  }
}
Enter fullscreen mode Exit fullscreen mode

Now broken effects can fail a build instead of becoming a runtime surprise.

Why This Helps Three.js Projects

Three.js is deliberately flexible.

That is one of its biggest strengths.

It also means a lot of systems are yours to build.

Scenes, loaders, UI architecture, asset pipelines, animation structure, game logic, and VFX can all be arranged differently depending on the project.

For particle effects, I prefer keeping the Three.js integration fairly thin.

Something like:

effects.play("laser-hit", {
  position: hitPoint
});
Enter fullscreen mode Exit fullscreen mode

The actual particle configuration should live elsewhere.

This prevents effect tuning from spreading through gameplay classes.

The Same Applies to PixiJS

PixiJS games often have similar problems.

You might start with a few sprites:

const spark = new Sprite(texture);
Enter fullscreen mode Exit fullscreen mode

Then add ten.

Then add pooling.

Then lifetime handling.

Then interpolation.

Then random velocity.

Then easing.

At some point, you have accidentally built a particle runtime.

There is nothing wrong with doing that if the game needs something custom.

But if particles are simply one part of the game's presentation, an external authoring format and reusable runtime can save a lot of maintenance.

Text Assets Also Work Better With Automation

Once effects are files, you can operate on them using scripts.

You can check:

  • Whether every effect has a unique ID
  • Whether referenced textures exist
  • Whether file names follow conventions
  • Whether an effect targets the correct renderer
  • Whether unused assets remain in the project

You can also generate reports or migrate old formats.

That becomes much harder when all the data is locked behind an editor-specific binary format.

Visual Tools and Developer Tools Do Not Have to Compete

There is sometimes an assumption that visual editing and developer-friendly workflows are opposites.

They are not.

The ideal setup looks something like this:

visual editor
     |
     v
readable source files
     |
     v
validation
     |
     v
export
     |
     v
game runtime
Enter fullscreen mode Exit fullscreen mode

Artists get a visual interface.

Developers get text files and automation.

Git gets something it can understand.

Your game gets a clean runtime bundle.

For web development, that is a much better compromise than hiding the entire VFX pipeline inside application code.

Top comments (0)