I’ve had this idea for a quite time now (few years I guess), but haven’t released it because it felt so stupid. Yes, just good old fashioned stupid, simple, idea. But it has some extremely good benefits that cannot be ignored.
If you check out my programming experiments from the past 10 years you’ll see a lot of particles. For some reason I keep on coming back to them. Always looking for ways to get more of them to the screen. But also trying to find new ways to render them, not just how they move, but also what sort of pixels I can draw to/with them.
Today I would like to introduce a new way of rendering particles.
But first, let’s describe a perfect particle.
– 1. Absolute minimum amount of vertices and indices, because every draw call costs
– 2. No blending needed. Say NO to performance killer alpha blending or “all lights on”-addition blending or whatever slow drawing process there might be.
– 3. No CPU z-sorting required, meaning the z-sort should happen in GPU (not just set off, we need it)
– 4. Antialiased.
The conventional way of creating particles is not like this. You would create a quad, face that quad to camera, draw a texture to it and use alpha blending on it, maybe z-sort on cpu or use additive blend and perhaps remove the z-sorting or do it later in fragment shader.
This is ok for some cases, but a lot of effects has to be ruled out or performance will be dropped dramatically. And when it comes to particles more is more.
Flipping Triangle Particle
Our brain has a sensory memory. As it states on that Wikipedia page, it allows individuals to retain impressions of sensory information after the original stimulus has ceased. And it seems our brain is blending this information together.
You can easily test this phenomena by just swinging your hand. When you do this, it looks like fingers form trails. In reality this all happens in your mind. Fingers doesn’t get blurry just because they are moved :)
This phenomena only applies if change between frames is fast enough, but luckily 60fps (16.6ms) is enough to combine two frames perfectly.
So how about we create a particle by exploiting the imperfections of our brain! It’s realtime graphics we’re creating here after all, not still images.
The idea is very simple. We create a triangle and store a flipped version of it to vertex data. So every vertice has a two stages.
TriVertices = float3(Math.Sin(angler*2 + Math.PIf), Math.Cos(angler*2 + Math.PIf), 0);
TriVertices = float3(Math.Sin(angler + Math.PIf), Math.Cos(angler + Math.PIf), 0);
TriVertices = float3(Math.Sin(angler*3 + Math.PIf), Math.Cos(angler*3 + Math.PIf), 0);
TriVerticesFlip = float3(Math.Sin(angler*2), Math.Cos(angler*2), 0);
TriVerticesFlip = float3(Math.Sin(angler), Math.Cos(angler), 0);
TriVerticesFlip = float3(Math.Sin(angler*3), Math.Cos(angler*3), 0);
Then we make an uniform that changes between 0 and 1 in every frame. This flips the particle in GPU in every frame.
Guess it goes without saying this is very cheap for GPU. What happens is that you’ll get a hexacon and 50% alpha spikes around it. This doesn’t look like much when it’s scaled up, but once you scale it down enough the end result is a nice antialiased dot.
Oh and the benefits:
– It’s only 3 vertices and 3 indices. Fast as it possible can be.
– You can draw nice dot cloud shadowmap with it, instead of quad shaped ugly crap you would get with normal particles.
– Self shadowing? check.
– Want to have reflections on it? done.
– How about deferred lighting? Sure, no blending needed.
– GPU handles the z-sorting. =win
– Again no blending, so particles can have any color, including black.
There are few set backs though. It needs to run 60fps or you’ll start to see the flipping. Particles aren’t very nice when they are too large. Other then those it’s pretty perfect and opens new doors what can be done visually with particles.
Here’s little something I’ve playing around with this summer:
It’s far from perfect yet, but you’ll see the particle in action. I’ll post realtime builds a bit later. Better build a demo with this shiz first.
So in case you need a lot of little dots to fill your screen this is one way to do it and rather fast and good for deferred lightening.
For those looking for less artistic example of this particle in practice here’s an experiment I did back in 2013 with it.
http://www.simppa.fi/experimental/webgl/uno/spin_particle/1million/ It takes a little while on WebGl to push all million particles to GPU, but once it’s done, depending on your hardware, it should demonstrate quite well.