Categories
General

HTML5 Canvas 3D particles

Yesterday I met Renaun Erickson from Adobe, who told me that he took my basic 3D engine, compiled it with the Flash CS5 beta into an iPhone app, and demoed it the very next day at the 360 Flex conference at Adobe!

HTML5 Canvas 3D particles

It gave me a few ideas about how to optimise it so perhaps I’ll try that soon. But first, I wanted to see whether I could port it to javascript and HTML5 canvas. It turns out that I could, but this time it’s more like 11 lines.*

var scale = fov/(fov+z3d); 
var x2d = (x3d * scale) + HALF_WIDTH;	
var y2d = (y3d * scale)  + HALF_HEIGHT;

By now you’ll recognise this code to convert the 3D x y and z position into 2D x and y, the difference here is that I’m offsetting the coordinate system so that it’s in the middle, which puts the vanishing point in the centre of the screen. (In the Flash version, I just moved the whole container for the particles into the middle.)

 
particles.sort(compareZPos);

function compareZPos(a, b)
{
	return (b.pos.z-a.pos.z)
}	

This is the bit that sorts the array relative to the z position of each particle, so that when we then go through and draw them all, it starts from the back to the front.

And here’s the bit that draws the image onto the canvas :

	c.drawImage(img,x2d-scale, y2d-scale, scale*2, scale*2);

I’m thinking about making all of this stuff into a slightly better explained tutorial, is this something you’d be interested in? In the meantime, check it out and let me know what you think. In particular I’d like to hear from any javascript experts with any optimisation tips.

HTML5 Canvas 3D Particles

* I know it’s not 11 lines, OK? And perhaps it’d be more apt to call it a 3D lawnmower engine πŸ™‚

21 replies on “HTML5 Canvas 3D particles”

that’s cool now i can do a benchmark test between html5 and flash. it looks like they both perform the same, until i resize my firefox (hit “control +” a bunch of times). Then the HTML5 is sluggish, but Flash scales gracefully.

oh, and the particle fountain in 10 lines of code is way cool too.

There are a couple of differences between the Flash and HTML5 versions, firstly, the Flash version actually blurs the trails effect and applies a colour transformation. Secondly, the Flash version uses a vector gradient circle for the particle image, whereas the HTML5 version uses a png. So actually Flash is working quite a bit harder; it’s not a very fair comparison.

Hi,

Pretty much the same optimisations we know from Flash apply to JS as well, inline code to avoid function calls, local variables, etc..

But just as with Flash the real bottleneck is rendering.
The fastest way with canvas would be context.putImageData which is similar to BitmapData.copyPixels (doesn’t seem to retain transparency though).
I did some comparisons with Chrome and Safari – Firefox is currently way behind unfortunately.
Turns out Flash is a lot faster than canvas on Windows – but slower on Macs (little surprise). I’ll publish the results somewhere.

Cheers, Dan

Cool, that’s helpful, thanks Dan. I hadn’t heard of putImageData, so I’ll check that out. I won’t be inlining right now, the whole point of this code is that it’s a learning example so it’d kinda defeat the object if I obfuscate the hell out of it :-). Like I said before, don’t forget that the Flash version is working a lot harder with several blur filters, so it’s not a like-for-like comparison.

For the records: I think I was wrong with putImageData being always faster than drawImage, seems to depend on the image dimensions. Last time I did tests with small images and putImageData won. When comparing with larger images though drawImage is clearly faster.

Cheers, D

Comparison here:

//spielzeugz.de/html5/compare

Please let me know if you spot any flaws in the comparison, maybe I’m overlooking something.
But I think it’s as fair as it gets. In Flash I left out optimisations that aren’t available in JS, namely Vector or a linked list instead of an Array and a Particle class with statically typed members. Also all bitmaps are smooth (no such option with canvas, can’t turn off anti-aliasing).

Hot topic obviously – but I’m not interested in bashing JS, both technologies have pros and cons. I just wanted to see if might be an alternative for games.

Cheers, Dan

ps: Code is not for learning purposes πŸ˜‰

It’s an interesting test, that’s for sure! The Flash seems mostly OK, although I don’t think the big bitmap needs smoothing and you should probably lock it before you apply the colour transform. I’ve run out of time to check it out more πŸ™‚

But I think it’s important to point out that you’re making Flash work the same way that HTML5 canvas does. With HTML5 canvas we have to draw bitmaps into the canvas because that’s the only option we have, but if I were to do this in Flash, I’d simply move a load of movieclips around with cacheAsBitmap set to true. Although whether that would be more performant remains to be seen. πŸ™‚

heh, you did a pretty good job of making JS look bad… the Flash version works in both of my browsers, the JS version fails in both of my browsers (IE doesn’t run at all, Firefox runs it with bugs)

Set everything to smooth just to be fair. Agree with transform after lock, difference is really minor though. πŸ˜‰

But you’re totally right, with MovieClips the comparison gets tricky. Animating MCs with vector art in Flash is faster than canvas too, but there’s nothing equivalent to MCs in canvas. You could compare it to the drawing API but that’s moot, it’s not how you do things in Flash.
But however you look at it – for realworld use it seems Flash is performing better for now, at least on Win.

On a sidenote, one big bitmap (aka blitting) is a lot faster than MCs on stage, that’s for sure. Just needs more planning, only makes sense for games really.
cacheAsBitmap in my experience is all but useless unless the content never changes. Better alternative might be to draw states into separate BitmapDatas and swap them.

Cheers, Dan

I am yet to be convinced that the blitting technique is faster than lots of cacheAsBitmap display objects (or even Bitmaps) on stage. Of course the display objects mustn’t scale animate or rotate, but you could create your own manual conversion of movieclip frames to bitmaps. Sigh. I guess more benchmarks are in order (yawn) πŸ™‚

Hi Seb,

I like the cool stuff you do πŸ™‚ Here are some observations running from my machine, a quad core Q8400 2.6GHz running Windows 7.

Canvas Version
Chrome 4 – ~17% CPU
Firefox 3.5.8 ~ 7% CPU
Opera 10.50 – ~3% CPU
All use roughly 40MB of memory

Flash version runs on all at about 40% CPU and 60MB memory with the exception of chrome which uses about 160Mb ram.

As you have mentioned, it may not be a fair comparison in terms different implementations (maybe one could try gradient fills in canvas), in addition different browsers and platform may yield different performances.
However, the performance with 3% CPU on opera was impressive.

I also noticed Flash seems to be using multiple cores to render while browsers like Firefox and Opera seems to run single threaded. Its interesting to note that the new Firefox 3.6 ships with worker threading support, and browsers supporting direct hardware acceleration in the near future gives some hope for the future of canvas.

Cheers,
Joshua

Really interesting, thanks Joshua. And yes I should just re-state that the Flash version is doing considerably more work, I was thinking that perhaps I should make an identical Flash version but on reflection, I’m not sure these comparisons are very relevant.

Flash does indeed use multi-core for rendering. It splits up the screen into horizontal strips, one for each core.

[…] interaktives Partikelsystem von sebleedelisle findet ihr […]

I want to try it in IE9 preview…but I just get the not supported in IE message. any chance you can change that for the IE9 preview?

Hi Daniel, do you know how to get it to work in IE9? The “not supported” message is just enclosed with the canvas tags, there’s no more clever browser detection than that.

Is it possible to run the particles and instead of click and rotate, that it rotates as the mouse moves while it runs? I know thats crazy, but based upon that, you could really have the beginning of a great 3d interface for a website if the objects were clickable. I found this really cool site with some different experiments. Some of them are similar. This one is cool…
//www.dhteumeuleu.com/wanna-tell-her/

Thanks for the great work. Keep it up!

-Eric

Hi,

This is really cool. I had played around with the demo and thought it would be a great idea to put as a logo animation at my site. Though i have used drupal heads instead of the ball.

-Aj

Perfect post!

Thanks a lot!

BTW – it is easily portable to GWT 2.2 – I just did it… πŸ˜‰
For those of us who do not want to code in JavaScript! *smile*

Comments are closed.