Niagara ribbons hair

Hi,
I’m wondering how could I generate ribbons from an other emitter that look like hair / grass strand on the surface of a skeletal mesh for example.

I have a first emitter that spawns particles on the surface of the mesh and a second emitter that creates the ribbon for each particle.

However I have to use add velocity to make them look like strands and use a spawn rate. It makes it move a lot and feels glitchy.
What I would like to use is a spawn burst instantaneous with infinite lifetime.

I imagine I need to place and offset particles of the ribbons using RibbonID and execution index, but that seems fairly hard. So I was wondering if there was an easier solution or if there is someone who already did that that could give some hints?

Thanks!

I would have done exactly what you are discribing here.
You can probably do it even without the source emitter, but having the source emitter makes it easier.
You don’t necessarily need to spawn from the source emitter, but rather just use the positions coming from those particles via AttributeReader.

So something like this:

  • Spawn source particles on SkelMesh
  • Spawn ribbon particles as burst (amount = nr of source particles * nr of particles per ribbon/strand)
  • Divide the ribbon particles into individual ribbons by giving them a RibbonID (every ‘nr of particles per ribbon/strand’ you up the RibbonID by 1) & also a custom index/ribbon (0->‘nr of particles per ribbon/strand’)
  • Seutp the RibbonLinkOrder (0->1) for each Ribbon (custom index / ‘nr of particle sper ribbon’)
  • Now setup the positions. Sample the source particle positions and snap your ribbon particles to those. ParticleID of source particle = RibbonID of ribbon particle.
  • Offset the ribbon particles e.g. Sampled normal of source particle * strand/ribbon-length * RibbonLinkOrder
  • Add any movement to this on top, e.g. gravity.

You could also take a look at the Niagara chain example, which has spring forces etc. to control movement. Might be useful for your usecase. Might be some issues with CPU vs. GPU particles though as there is still no official GPU ribbon solution.

1 Like

Hey,
That is very good information, thanks a lot!

Just one question, about the Ribbon ID, it’s a Niagara Id with 2 components.
Index and Acquire Tag.
If I understand this right, Index is an ID per strand? Can’t we just use the same as source particle ID?
As for the acquire tag, it is a unique ID per ribbon particle right?

When you say:

Divide the ribbon particles into individual ribbons by giving them a RibbonID (every ‘nr of particles per ribbon/strand’ you up the RibbonID by 1) & also a custom index/ribbon (0->‘nr of particles per ribbon/strand’)

So the RibbonID != Source Particle ID?
The index would be: every ‘nr of particles per ribbon/strand’ you up the RibbonID by 1
How can you keep a reference of that variable accessible between particles so you know the current number?

And Acquire Tag: a custom index/ribbon (0->‘nr of particles per ribbon/strand’)
Again, how do you generate this unique custom index?
The range is between 0 and number of particles per strand so it’s not a unique ID per strand link for the whole emitter?

Sorry for all the questions, I am very confused about ribbons and how they work!

Heya,

I’m honeslty not sure what Acquire Tag is actually for. I usually use Index (which is what I actually ment with RibbonID). Index is what I use.

Ribbon.Index = SourceParticle ID. You can directly match up the RibbonID(Index) with the SourceParticle ID (UniqueID? Execution Index, whichever goes from 0->nr of particles).

Each particle only knows information about themselves (except for when using an AttributeReader), but that’s enough information in this case. Just add an Int particle parameter to keep track of this index.

So, let’s say you have 10 particles per ribbon/strand and 10 source particles. That means we spawn 100 ribbon particles. Now, to get the RibbonID seutp, we basically want the first 10 particles to be ribbon/strand 0, the next 10 particles to be ribbon/strand 1 etc.
So you just do something like this:

2 Likes

Ho yeah!
Got it working, thank you so much!

UnrealEditor_I5CY5PiXiX
With some animation…

2 Likes

Nice work! That looks super cool :slight_smile:

You can even do cool things like make the particles bend away from the player with this. It’s very convenient to have this as Niagara particles as manipulating them is easy!

Couldn’t resist :sweat_smile:

Animation

3 Likes

Ha! Awesome :slight_smile: Exactly what I meant!
This very much reminds me of the returnal vfx:

1 Like

Yeah I had that thought as well!
I wonder how they were able to use ribbon and distance field at the same time since one is CPU only and the other one is GPU only :thinking:

Yeah, they probably have their own solution for it. It would be possible to create your own GPU Ribbons, but that’s rather tricky.
Another solution would be, to use GPU particles to write their position into a render target, then sample those (in BP for exapmle) and feed that data into your CPU system. But none of that will be super cheap, I assume, as it always has to shuffle data around between GPU & CPU. Might be worth taking the perf hit though, depending on how important it is :slight_smile:

Hey guys bit of a long time since you visited this but I was wondering if you remember how you got them to be seperate strands, I have got a niagara setup that can spawn multiple ribbons constrained to each other but an issue im running into is that the end of the previous ribbon wants to connect to the start of the next ribbon, or they are getting tangled trying to connect to each other

I was just wondering if you guys had some insight on how to make sure they are seperate ribbons

I realized this bug too. My band-aid fix is to reduce the size or opacity of the start and end particles of each strand of ribbon to be zero.

1 Like