Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
WebGL: 80.000 particles (minimal.be)
252 points by _ZeD_ on April 7, 2015 | hide | past | favorite | 77 comments


Here's a much cooler version by Nop Jiarathanakul. Nop's version has shape targeting, which is especially cool. Check out the running horse.

http://www.iamnop.com/particles/


On my currently laptop I only pull about 5fps when viewing this. Indeed cool, but the OPs (albeit more simple) runs at a solid 60fps


Runs at 60fps on latest Chrome for me. I'm on a retina macbook pro 15".


3fps here on what should be a beefy i7 with a relatively recent integrated GPU. Anyone want to comment on what the bottleneck is?


CPU has little to do with it, since most of the heavy lifting is done by the GPU. Maybe that integrated chip isn't enough.


It does depend whether the particles are drawn using shaders or the simpler canvas drawing commands. Without shaders, it would be very CPU intensive. However this site has definitely taken the shader approach.


yeah iamnop crashes my firefox


Runs at near-60 FPS in Firefox for me. Using Linux and Firefox 37.


Firefox 31 from the debian wheezy package


Close to 60fps in Chrome 41 on my 2014 MBP.


Big difference between this one (which is great) and OP's is that OP's done all the WebGL himself whereas Nop's uses Three.js


here's one with 1 million particles done in vanilla WebGL

http://www.iamnop.com/particles-mrt/

(it's a little unstable since it uses WEBGL_draw_buffers)


CAUTION iamnop.com link plays quite loud music from start (for me).


cool stuff, here's the sauce https://github.com/nopjia/webgl-particles



80k particles isn't an awful lot, unfortunately. I can hit well into the millions on desktop GPU's, so I would assume 2-300k would be well achieveable

EDIT: Seems that http://threejs.org/examples/#webgl_buffergeometry_particles has 500k.


Particles can be misleading too because if they're simply propagated by some PDE on a regular mesh (or even no mesh) it is an embarrassingly parallel problem. But if they're interacting particles then you need neighbor lists and predictor corrector methods to propagate them which is considerably more difficult to implement and parallelize.


But the original post isn't interacting either, it's just an integration with gravity, that happens to be rendered by WebGL.


Yeah that's what I'm saying, if this demo has been 80,000 interacting particles it would be extremely impressive.


Not really. Back in 2002 we did the first game jam where the engine concept was "100,000 guys". That was 13 years ago:

http://www.indiegamejam.com/igj0/

Those guys all interacted with each other and the environment (though the engine was designed to do the interactions in slices, where 1/N of the guys would be checked each frame, but N was not high, like 4 or 5 maybe?)


Just 2 days ago I ran across my all my written notes from GDC 2002 (the only GDC I've gone to; I went by myself for fun) with that specific session, and I had your name written down. (I just thought that was a funny coincidence.) It was very memorable, especially the one with the Doom guy doing the Robotron thing with the camera zooming out. Late last year, Casey Muratori also mentioned it on his handmade hero webcast.


In particle simulations interactions can happen at a distance, so at every time step all particles need to be checked with all other nearby particles to get their distances and compute the force of their interaction. It looks like your simulation is a hard-sphere type interaction where you're only checking to see if two particles bump into each other and is considerably faster to compute.


No, it's not really different from a hard-sphere type interaction. It's the same thing. But that doesn't matter in this context, because in the system we built, our problem was harder/more-general because we were simulating 'guys', meaning you can program an arbitrary interaction into your guys (is guy type X near guy type Y, if so what happens?), and those 'guys' also interacted with a 2D height field terrain.

Keep in mind this was all on computers from the year 2002, which were pretty damn slow compared to computers today. Today you could do a lot of guys.


> though the engine was designed to do the interactions in slices, where 1/N of the guys would be checked each frame, but N was not high, like 4 or 5 maybe?

I'm assuming they all still moved, and the checking was just for change-of-independent-behaviour-pattern?


Yes, everyone moved every frame. If I remember correctly, they would get linearly extrapolated until next time the update for that guy ran. I think there was also an option to do the terrain interaction every frame, to avoid any perception of guys sinking into the terrain slightly.


This three.js demo doesn't seem have dynamically updating particles though, it's essentially rendering static geometry (as far as I can glance from the source).


I think this is a few years old. I remember seeing it before.


I did some emscripten/WebGL performance tests a while ago which went into the hundred-thousands particles for 3D-shape-particles at 60fps, but this depends very much on the target hardware, less on the browser or operating system.

Both tests use simple 3D shape particles (5-vertex diamonds) and hardware-instanced rendering (instanced_arrays extension), the first updates particle positions on the CPU, the second on the GPU (fragment shader writes particle position to offscreen render target, which is then sampled in vertex shader to displace particle positions).

The first (CPU updates) goes up to around 450k particles on my Windows7 desktop machine before consistently dropping below 16ms per frame, the second (GPU updates) goes to about 800k particles before dropping below 60fps:

http://floooh.github.io/oryol/Instancing.html

http://floooh.github.io/oryol/GPUParticles.html

These numbers are not much different then using desktop GL (2.1 with extensions). The real advantages for this type of scenario would come from updating persistently mapped buffers which are not available in WebGL.

What's impressive is the raw math performance of asm.js, the particle update loop is simple glm code (https://github.com/g-truc/glm) without any fancy optimizations.


>What's impressive is the raw math performance of asm.js

I continue to be staggered at how well asm.js performs, and really glad Chrome has taken on optimising for it as well as Firefox.


Running the instancing demo on an iPhone6+ I can get to 150k particles before dropping below 60fps. There's an obvious speed up about three seconds in where I guess the JITter decides to get serious.

So, even though there's no official support for asm.js on mobile safari. It still works surprisingly well!


Try it without instancing. I was working on a rendering approach and initially went with instanced rendering. I was reading about how badly some GPU's handle that, so switched it off and saw a pretty decent perf gain. Basically trading some startup time to mass create the attribute buffers in exchange for better ongoing perf.


Not what you mean, but here's the same demo without instancing and lots of drawcalls, but careful, it will grind your browser to a halt pretty quickly:

http://floooh.github.io/oryol/DrawCallPerf.html

This is one uniform update and one draw call per particle in a loop.

Unfortunately draw call overhead on WebGL is really bad compared to desktop GL. On my Windows7/nvidia setup I can go up to about 75k draw calls before frame rate drops below 60fps, on other platforms it's worse. So in this particular (very simple) scenario, hardware instancing actually pays off.

For quad particle systems it is indeed usually better to just directly write the vertices to a dynamic buffer instead of instancing, but I don't have a demo (yet) for this particular case :)


Yeah, definitely keep draw calls low. I'm not surprised to see instancing beating that.

I'd be curious to see your comparison over non instanced/single draw call though. I threw the adapter code I wrote for my instanced version up here if it helps: http://pastebin.com/1gjvreBs


I was expecting the particles to be done as a pure shader implementation, but when I looked at the source that's not the case. While a vertex shader is used to display the particles, the "physics" is done in a JavaScript loop.


This also surprised me. You can do the exact same thing, but with millions of particles, if you store and process them on the GPU. The first example of that technique being used in WebGL is probably by Mr.doob [1]. Since then, there have been many iterations, some of which are basically a cooler version of the linked demo [2]. (And simpler, judging from the source!)

[1]: https://www.chromeexperiments.com/experiment/magic-dust

[2]: https://www.chromeexperiments.com/experiment/one-million-par...


Exactly, there's not much optimisation in there. In fact, it was my first try with WebGL.


Ive made something similar to this a while ago.

https://www.chromeexperiments.com/experiment/one-million-par...

It does its calculations on the GPU so it can handle a million particles easily. You can also pause it to explore it in 3D.


This same page appear on HN almost 3 year ago : https://news.ycombinator.com/item?id=4008040.

Interesting how this all WebGL stuff is still so "hacky" and not yet commonly used all around .


I don't think WebGL is hacky if you approach it right.

We have 100,000 users who have created +180,000 scenes using advanced WebGL and it is really stable: http://clara.io.

Here is a new demo scene I've been working on. PBR materials (w/ clear coat), area lights, HDR, bloom, DOF and FXAA:

https://clara.io/view/d3b82831-d56b-462f-b30c-500ea1c7f870/w...

And you can edit any part of the mesh or materials or animation or lighting in our editor.


Just for the lols i visited the link on my phone... It worked! All the blurs and reflections all of it worked. Hats off to your team. Frame rates though were laggy but i'm still impressed.


It's really cool but please to not link to the "real time" tab? It almost hung my browser :) (FF37, shitty old netbook)


So sorry... We'll all make an effort to keep the internet slow while you're browsing on your shitty netbook.


I love WebGL and 3D graphics and particles, and love seeing WebGL becoming ubiquitous (when I first played with it I had to download a nightly of Firefox). But it's really hard to come up with a business use case that justifies using WebGL in say, a marketing product, or an online marketplace.


Maybe because it isn't available everywhere, specially in mobile platforms?


It is available on all new Android and iOS devices. And it mostly works (although less so iOS devices.)


As if everyone just would dump their devices and buy new ones for WebGL.

Not everyone is using iOS 8 and Chrome blacklists lots of Android handsets, and lets not forget about other mobile OSes.

I also assume you also checked Android Auto and TVs regarding WebGL support.


> As if everyone just would dump their devices and buy new ones for WebGL.

That just happens every three years, and we don't have to do anything about that.


Maybe in your country, on my country people buy handsets full price with pre-paid cards and use them until they die.


Maybe in your country, in my country people repair their handsets when they die and pass them on from generation to generation as family heirlooms.


I find playing with this very relaxing. +1!


That is so cool. There's a great demo of orbitals and the like that can be picked up from this. I would have loved if a physics teacher showed me something like this when I was in school.


I made a test a while back to see how Canvas performs with particles : http://codepen.io/sakri/full/ntLAv . If I select the "per pixel" method, on my old laptop I get 60fps with 80,000 particles. I wasn't very impressed :D (although I'm sure the code could be improved)


By drawing circles rapidly around the particles, you can herd them into a tiny blob. Move your mouse into the blob for a colourful explosion.


This is always the first thing I do with one of these. It's so satisfying. On this one, if you make big, fast circles so the blob is moving as little as possible, then you let go, you can get the whole blob to just drift off to the side and stop (it disappears), so when you mousedown again somewhere else, you get a big stream of them all coming from the same general area.

I could play with this for hours. :)


I've looked over the code and I can't figure out what makes the particles brighter. Some of it is when the particles overlap, they appear brighter, but if you don't touch the screen, all the particles fade out to black. Anyone know how that is done?


The particles are drawn as line segments, with lengths proportional to their velocity. As the velocity approaches zero, each line segment covers a smaller and smaller fraction of a pixel. Because the lines are drawn with antialiasing (at least in Chrome) this causes them to fade into transparency as the pixel coverage approaches zero.


The particles are rendered with additive blending:

gl.enable(gl.BLEND); ... gl.blendFunc(gl.SRC_ALPHA, gl.ONE);

It basically means that the particle color is added on top of the already rendered particles (with the alpha value used to modulate the particle color, which is a bit strange, it would be more usual to use gl.ONE for both parameters). The more particles overlap, the brighter that pixels becomes.

Details are explained here: https://www.opengl.org/wiki/Blending#Blend_Equations


Plus what teraflop writes about particle velocity being proportional to their line length. The 'overbrightening effect' should be caused by the blending however.


The standard particles example in three.js has 500.000 particles.

A description like "80k dynamic interactive physics based particles" would do this one more justice.

(There's a dynamic particles demo in the threejs examples too, though it doesn't say how many there are...)


Since these particles aren't dynamic, they are much easier to render at high volume. You create the vertex buffers once and you're done. Dynamic particles are a lot more complicated, since the buffer needs to be updated constantly.

If anyone has some good articles about how to render a large number of dynamic particles, where the simulation happens on the CPU (i.e. it's not all shader trickery), using modernish OpenGL (no fixed function stuff), please share. I'm eager to learn more about it, but haven't found good resources. It's a blocking issue towards my goal of creating a bullet hell shoot-em-up game.


Unfortunately dynamic buffer updates is one of the tricky parts to do right in OpenGL since you need to assume what the driver does under the hood, and the best technique depends on what GL version you're targeting, and what GL extensions are available.

I found this blog post very useful: http://hacksoflife.blogspot.de/2012/04/beyond-glmapbuffer.ht...

If you can afford to target bleeding edge OpenGL, the AZDO slides contain the current state of the art (there's a whole section about dynamic buffer updates somewhere in there): http://www.slideshare.net/CassEveritt/approaching-zero-drive...

On WebGL, the established tricks like buffer orphaning don't work, and direct mapping isn't available. It seems best to simply do a bufferSubData and not care about double buffering etc (https://groups.google.com/forum/#!searchin/webgl-dev-list/fl...)


The developer could improve this page by adding a demo mode that shows the particles moving randomly around the screen. The demo mode could be shown after a couple seconds of user inactivity.


Cool. I wonder what the governing equation for the particles is...

Also, If I open developer console in Chrome (docked at the bottom), it seems the mouse position is off like 100 pixels or so.


The particles are attracted by the position of the mouse, each having a slightly different (randomized) attraction factor.

If a particle ever reaches the exact mouse coordinates, its position is randomly generated anywhere on the screen.

When rendering the particles, it simply draws a line between the previous and the new position. So when a particle is transported to a random place, it create the rays that appear around the cursor.

There's no real complexity in the maths involved, but I remember spending quite some time tweaking the random ranges to get something nice.


Have you seen this VR demo: http://youtu.be/fAhzW4blqvM ? It looks similar enough that I bet it's inspired by yours.

Yours is a very fun demo. I tried modifying it to move more work to the GPU. I had the CPU only update a subset of the particles each frame and the GPU would interpolate a curve to fill in the missing frame updates. It sorta worked. It was N-times faster and could do more particles. But, the interpolated curves were progressively less responsive and fun.


Okay, thanks for sharing. But still, I'm wondering why the orbits of the particles always end up being roughly the same size.


we need a remake of this now https://www.youtube.com/watch?v=E_87pSWYhKo

'attack of the killer swarm' one of the first round of games out of experimental gameplay project


Smoothest WebGL I've ever used on my iPhone. Well done whoever created this!


It's this guy (https://twitter.com/boblemarin). I know him, and he is pretty damn good.


:)


Loving the fact that this runs so smoothly on my old netbook.


Works perfectly on my macbook pro 15" retina from 2012.


Works fine on my Lenovo T530 with Fedora 21


Why the hate?


Definitely minimal on my Firefox


I had the same problem - then I realised you need to click/drag the mouse.


would be cool if you could somehow output this to audio




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: