The most impressive bit of this is that it it keeps under 20% CPU on my Mid-2010 MBP [Chrome 19].
It's hard not to imagine another cyclical shift towards browser centric development, away from rich client apps, when you have Chrome pulling off tricks like this. Things that would've seemed impossible in 2008, the last time everything was moving to the browser.
Give Apple/ARM/Intel/Samsung a few more cycles in mobile [more RAM, if nothing else!] and you might need to reconsider the disadvantages of native apps in favor of all the advantages that centrally hosted applications offer [no Apple fee, no pirating, continuous deployment, cross-platform, etc, etc.].
I long for a vibrant open-source project that builds quality widgets and elements for people to use inside this framework. Let's not pretend jQuery mobile et. al. are anywhere close.
CPU utilization is the wrong metric. Your CPU is mostly idle because it's feeding a tiny set of commands to the GPU each frame, and then idling waiting for user input and/or vsync. The GPU is running full-tilt, but unfortunately there's no good OS-level tool to show that.
One of the reason CPU utilization is so low is that this is a demo. Most of the "logic" is just a straightforward computation of the mouse position, and the particle coordinates are all figured out from that in the shader engines. Real apps and games have real data that needs to be crunched.
(Edit: I just checked the source, the particle positions are actually computed in Javascript, the shaders are just straight rendering. And I don't see anything particularly clever about the implementation, it's just a bunch of array accesses. V8 is doing an amazing job on this.)
But broadly, you're right: the need for highly optimized native code to drive a modern GPU has mostly disappeared. A javascript interpreter (well, V8) is more than good enough.
The particle positions are indeed computed in Javascript, and even if the version you tried only had 30000 of them, the "real 80000" version [ http://minimal.be/lab/fluGL/index80000.html ] does not raise my CPU usage that much.
A more clever way to code that animation would be to pass the mouse position to the GL shaders that would compute themselves the particle positions, and I think modern GPUs are very optimized for that kind of stuff.
Please don't be too rude, cause it was my first WebGL experiment.
Apologies if I seemed rude, it's really very nice. But yes: a shader absolutely could compute a particle position based on a previous value (and other state, and inputs like mouse position, etc...) as a mapping between, say, a 1D texture and a 1D output framebuffer that gets used as the next frame's source texture. Honestly, given the apparent performance this is what I had assumed was happening.
Having the GPU compute position updates into a texture would indeed be orders of magnitude faster, but it would require the vertex shader to read from a texture to get the results. Unfortunately, vertex texturing is an extension that is not required in the WebGL standard and not supported on a significant percentage of machines. It's almost a shame that vertex texturing makes really fun demos really easy to make. Every time I see a VT demo, there are dozen of comments crying "Doesn't work for me. WebGL is broken!"
No need to read the texture in the vertex shader. Render to a buffer object and use that as your vertex array. But broadly yes: that's the problem with OpenGL support, and WebGL in particular is still very bleeding edge.
I'd be pretty surprised if vertex texture fetch wasn't supported though. It works on basically all hardware from the PVR SGX on up. Unified shaders are pervasive on both phones and desktops. I did find this, though, which implies that for a while that the browsers weren't properly exposing support:
FBOs are absolutely part of ES2, and thus presumably an official part of WebGL. I've used them in embedded contexts, but never in a browser. And as always, this is on the bleeding edge of what the drivers are prepared for, so dragons may lurk. But at least in principle it should work.
I've seen talk of CPU-less render-to-vertexbuffer dating back to 2004, but I've never dug into how to actually do it until now. From what I can dig out, it requires PBOs which are not available in ES2. I guess copying back and forth over the bus via gl.bufferData(ARRAY_BUFFER, gl.readPixels(...), gl.STREAM_DRAW)) is still better than doing the math in JS. I might have to try combining the glReadPixels with the mapped buffer extension that is available on the iPhone P:
It's actually 30,000 particles, not 80,000. See the source: "numLines = 30000".
If you set a breakpoint at that line (28), then you can edit the variable in the console to whatever you want. You can make it smaller without setting the breakpoint, but any higher results in a "attempt to access out of range vertices" error.
I can get it to ~40,000 on my iMac's 6970m 2GB without noticeable slowdown (this is w/ Chrome 20 dev.)
UPDATE: It turns out the slowdown at 40,000 was due to the Web Inspector being open (I have no idea why!) It's actually still pretty damn smooth at a MILLION particles! Crazy!
It's not nearly as efficient as this demo, but it's at least a game. There are at least a dozen areas I could fix up to prevent the GC from going nuts if I was so inclined, but it works fine for most people.
That demo gets about 19 fps on my machine, whereas the WebGL demo appears to be getting close to 60, so that seems to be scaling pretty similarly. Also keep in mind that the demo you linked to uses Alchemy, which is C/C++ compiled to AVM2, so for WebGL to be getting roughly equivalent performance is pretty damned impressive.
"On my OsX toy the difference between flash on browser and standalone is insane. 200 000-300 000 particles is pretty much the maximum until it won’t run smooth anymore. I wonder if this is memory related thing? or what? Who knows? Someone from Adobe might… Well anyways. Here’s the same thing exploding 1.4 million particles in 1920×1200 resolution with smooth 60fps."
Interesting behavior.
On that other JS demo mentioned in a sibling comment my puny 9400m runs at a steady 30fps at 100k with 7~10% CPU on Safari. The same goes for some non-browser pyopencl [0], which uses about 10% CPU. I seem to be hitting a sort of bottleneck here as ramping either up to 200k or using the Flash realtime demo brings FPS down to about the same level. The Flash one though, uses between 20 and 60% CPU and mostly hovers around 30%. Whatever that means.
Probably not. The author of this WebGL app is updating the particles on the CPU which probably explains the low particle count.
Now-a-days it's pretty much standard to use two floating-point off screen textures to store, update, and draw the particles completely on the GPU. This way, you can get 1M+ particles easy.
While looking pretty, the demo actually is fairly unoptimized. Each draw loop the vertex buffer is rewritten after iterating over and updating each particle's velocity.
you can do the same in JS if you have such simple particles as well (ie rendering by just writing a few bytes). http://mrdoob.com/lab/javascript/strangeattractor/ does 300k as well (though it's borked right now since he has to update his stats code).
if you don't let the particles catch up w/ your mouse (and trace circles around them) the gather up in one place and turn white, resulting in some spectacular 'explosions'
Chrome blacklists most opengl drivers on linux (except the proprietary nvidia one) since old mesa based drivers don't work too well with webgl. You can change this in about:flags, "override software rendering list" (and restart)
Very small bug I thought I'd mention: If you resize the browser window the center of the particles no longer tracks the mouse pointer location but rather appears to be offset by an amount depending on the resize that happened. W7/C19
For what it's worth, I wrote a simplistic Osmos clone last year using 2D canvas drawing (not WebGL). It's fairly inefficient, but anyone's welcome to hack on it and make something cool with it.
Works great using Firefox on my Ubuntu laptop with only integrated graphics too. Although I had to click the NoScript placeholder to allow the WebGL to execute.
Works absolutely flawlessly in Chrome, impressive stuff. Can't wait to see a company like Blizzard release a HTML5 MMO in a few years time (it'll definitely happen). Imagine a game like Diablo 3 in HTML5? Wow.
When I wrote that experiment (nearly one year ago), I started with 80000 but finally went for 30000 because it was smoother on my laptop. I just forgot to change the title when posting (it was a long ago, and I wasn't expecting it to get much attention).
any idea why i get the JS error "requestAnimationFrame is not defined" when I run the HTML page on my local system. Same browser (firefox 12)) renders the online-like just fine.
As i understand this method is part of the browser's JS api. So, why is it not defined if I run it "locally"?
thanks; i missed the import. I only remember that the method also exists in the JS api itself. did not think that there might be a wrapper around with the same name :-)
Much of the code comes from a WebGL tutorial (context and shaders creation, and the shaders code). I added the interactive parts, the particles and tweaked the shaders.
It's hard not to imagine another cyclical shift towards browser centric development, away from rich client apps, when you have Chrome pulling off tricks like this. Things that would've seemed impossible in 2008, the last time everything was moving to the browser.
Give Apple/ARM/Intel/Samsung a few more cycles in mobile [more RAM, if nothing else!] and you might need to reconsider the disadvantages of native apps in favor of all the advantages that centrally hosted applications offer [no Apple fee, no pirating, continuous deployment, cross-platform, etc, etc.].
I long for a vibrant open-source project that builds quality widgets and elements for people to use inside this framework. Let's not pretend jQuery mobile et. al. are anywhere close.