How to make a procedural fractal lightning bolt in Niagara?

Karton
Sat, 31 May 2025 12:39:49 +0000
Asset Creation

I’m working on a procedural 3D fractal lightning bolt effect in Niagara, targeting GPU compute particles, and I’ve hit a wall with the recursive branching logic. I’d love some advice or alternative approaches!
This is the result I’m looking for (in 3D):

What I’d like:

A 3D lightning bolt that grows via recursive branching (main thicker branch, thinner child branches).

Jagged lines between branch points (not straight lines).

Configurable: depth, branching factor, angles, length reduction, randomness, thickness reduction.

Animated appearance: Segments appear sequentially, have a lifespan.

Realistic scale (e.g., 500m-1km length).

Using a Ribbon Renderer for the visuals.

Very performant: GPU only. (bonus points for lightweight emitters)

I’m using UE5.5
Thing is, I’m rather experienced with unreal… Just not with Niagara. I looked at youtube, epic documentation and general google-fu, but everybody either uses textures for the branching or omits branching altogether.

I know that there is a 3D tree generation in the content examples “advanced niagara” with NeighborGrid3D, but I want my ligning asset to be open-sourced under Creative-Common BY 4.0, so I can’t steal Epic assets, or use the marketplace. Plus, Epic’s implementation looks very tough. (I’m still a beginner at Niagara, remember ?..)

I don’t want to precompute my lightning shapes. How hard could it be to ask the GPU to compute it?

What I’m trying:

ChatGPT and I had an idea with two GPU emitters:

1. Lightning Guide: Invisible “guide” particles. Each guide represents a potential segment.

Root Spawn: A single root guide particle is spawned in Emitter Update.

Guide Particle Logic (Particle Update):

Calculates its own properties (start, end, direction, length, thickness, spawn time for visuals, unique BranchID).

Sets a flag Guide_IsReadyForRibbonGeneration = true for one frame when it becomes active.

The Problem - Recursive branching: My initial thought was for a guide particle (Parent) to directly spawn its child guide particles in its Particle Update. It seems however that there is no way for a particle to decide to spawn particle during its update. I tried a workaround with “Spawn Particles From Other Emitter” listing itself as source, but I can only specify a “spawn rate”, not “spawn 2 particles per particle with a given flag”. Plus, it seems that I can’t tell the parent particle whether children did spawn or not, so I would have to assume the spawning happened after one frame.

Sub-branch Parameters: An HLSL node calculates properties for the new child guides based on the Source (parent) guide’s attributes (position, direction, depth, seed, etc.) and user parameters (angles, randomness). This HLSL also determines if the child should spawn based on probability.

The new child guides get their Guide_SpawnTime offset from the parent, creating the progressive growth.

2. Lightning Ribbon: Visible ribbon particles.

Uses Spawn Particles From Other Emitter in its Emitter Update to pull data from NE_LightningGuide.

An HLSL node in Particle Spawn then calculates the actual jagged position for each of the N ribbon points along the segment.

Animated appearance of ribbon points is handled by calculating an ActualSpawnTime for each point based on its index along the segment and the segment’s draw duration.

My approach looks soooo over-engineered. I’m spending days in implementing what one might consider to be a textbook Niagara use-case.

Question:
How would you implement such fractal lightning? Did I miss a feature that makes the implementation tractable?

Any insights, examples, or pointers would be massively appreciated!

4 posts - 2 participants