Topic: Metaballs, Canvas, low fps (Page 1 of 1) Pages that link to <a href="" title="Pages that link to Topic: Metaballs, Canvas, low fps (Page 1 of 1)" rel="nofollow" >Topic: Metaballs, Canvas, low fps <span class="small">(Page 1 of 1)</span>\

Obsessive-Compulsive (I) Inmate

From: Cracow, Poland
Insane since: Jan 2009

IP logged posted posted 01-06-2009 00:59 Edit Quote


I have a concept of fancy animated preloader.

Take a look at this (it's static, generated image):

Now imagine that those balls are satellites and turns around the center one. Every ball represents one image that is currently preloading. When some image is ready then corresponding ball smoothly falls back into center and thus makes center ball bigger. Preloading process ends when last satellite falls into centre. I hope it's clear despite my poor language skills

But of course I run into performance issues, for example try to mouse over arena:

In document.title you will get speed of one frame rendering and rounded fps number. And let me tell you this upfront - it's low... Good fps (around 10-12 on Pentium M 1.7GHz) is only possible in Chrome.

I've tried every reasonable metaballs/metasurfaces optimization technique I've found on the internet. At the moment I'm using only one - I divided canvas into 5x5 blocks and first I'm checking if I should bother calculating individual pixels or not - that improved speed a lot, but other techniques gave very miserable effect so I gave up with them.

The major bottleneck is drawing on canvas - I'm doing it with context.fillRect() and it's painfully slow. I was thinking about Canvas's ImageData but I can't get it to work in any browser (not even Opera) - I don't know if it's me or if it's not implemented yet because I can't find any working demo of ImageData.

Should I gave up or maybe you know about some fast implementation of metaballs with Canvas? I don't want to do it with datauris (at least just yet).

Ehm... I could talk about various strategies, problems and my test results for long, but I'll stop now, because maybe you just have some working example or you know about some nice technique. If not then I'll try to elaborate on this problem more. Or maybe I should gave up because it's not possible today?


I just found this forum, so hello everyone!
It's surprises me that forum like this still exists - I thought that last ones extinct about 3 years ago

Kamil Trebunia //

Paranoid (IV) Inmate

From: Norway
Insane since: Jun 2002

IP logged posted posted 01-06-2009 02:42 Edit Quote

128x128 is an awful lot of pixels to draw and compute manually.

Personnaly if I were aiming for such resolution, I'd go for either data:URI or an image & globalCompositeOperation based approach. The first is trivial : just do some adaptive subsampling and generate a BMP8. The later is not so complex : use drawImage to draw the sprites of the iso-surfaces, draw a mostly black rectangle on top of everything, and do some recursive glow to get the glow and blending back.

Never had any pb with ImageData. FYI it works fine in FF3, Opera 9.5+, and IIRC Safari 4.

Hope that helps,

Kyle the Feared
Obsessive-Compulsive (I) Inmate

Insane since: Jan 2009

IP logged posted posted 01-07-2009 01:17 Edit Quote

I can't offer much help with the data:URI or much else, but I know the imageData approach would be a lot faster.

Here's a quick example to help you out if you're wanting to try that route:


<canvas id="canvas" width="128" height="128"></canvas>

var context = document.getElementById('canvas').getContext('2d');

var imgData = context.getImageData(0, 0, context.canvas.width, context.canvas.height);

var r = Math.floor(Math.random() * 255);
var g = Math.floor(Math.random() * 255);
var b = Math.floor(Math.random() * 255);
var a = Math.floor(Math.random() * 255);

var data =;
var len = data.length;
var index = 0;

while (index < len) {
 data[index++] = r;
 data[index++] = g;
 data[index++] = b;
 data[index++] = a;

context.putImageData(imgData, 0, 0);


The pixels for the ImageData are just stored as one big array of rgba values, so to plot a pixel with x-y coordinates you'll basically have to convert from a 2 dimensional array to a 1 dimensional.

It should give adequate speeds for what you're currently doing, but the browser support is somewhat limited.

Paranoid (IV) Inmate

From: Norway
Insane since: Jun 2002

IP logged posted posted 01-07-2009 11:02 Edit Quote

As you obviously figured already by doing adaptive subsampling, such effect is a perfect candidate to render/process at lower resolution then strecth & blur. I really doubt you need to process 128x128 pixels.

side note: Man! I wish Canvas ( and SVG ) had an indexed color mode. That would allow for a some funky and almost free gradients, saturation & exposure effects and require to set a single byte instead of 3-4 or have a two pass method using a data:URI generation then drawImage()

Obsessive-Compulsive (I) Inmate

Insane since: Mar 2009

IP logged posted posted 03-21-2009 01:44 Edit Quote

I'm a newbie to using <CANVAS>, but I think radial gradients in larger rectangles might work well. You'd just set the gradient colors so that the gradient is a white radial gradient whose alpha decreases as it goes outward. Now, there'd be the flaw of how the balls look when they merge:

But that could be solved by placing a third, temporary radial gradient between the two merging ones, and then getting rid of it when the two are sufficiently merged.


Nervous Wreck (II) Inmate

Insane since: May 2011

IP logged posted posted 05-31-2011 11:08 Edit Quote
Edit TP: spam removed

Post Reply
Your User Name:
Your Password:
Login Options: Remember Me On This Computer
Your Text:
Options: Show Signature
Enable Slimies
Enable Linkwords

« BackwardsOnwards »

Show Forum Drop Down Menu