views:

37

answers:

2

I'm working on a game and having some performance problems drawing one canvas onto another with drawImage. According to Chrome's Profiler, I'm spending 60% of my time in just this one drawImage call and 10% in the clearRect above it...

The source canvas is about 3000x3000 for now (which is pretty small, I'd say) and the destination canvas is 1024x768.

I figured that instead of drawing all of the tiles; walls and so on and so forth each loop (which gives me around 15fps), that it would probably be faster to draw them all once onto an off-screen canvas and then draw that onto my main canvas, then draw entities etc. on top. That gives me ~30fps but... is this the best I'm going to get with software rendering?

My render loop is basically:

ctx.clearRect(0, 0, 1024, 768);

ctx.beginPath();
ctx.drawImage(map, cam.position.i, cam.position.j, 1024, 768, 0, 0, 1024, 768);
ctx.closePath();

ctx.save();
ctx.translate(-cam.position.i, -cam.position.j);
// draw entities, etc.
ctx.restore();

I can't really think what to do, other than start using WebGL (to take advantage of its hardware acceleration) or wait for vendors to implement hardware acceleration for the 2d context. I'd rather not do either of those, though, so any input would be appreciated.

A: 

It might be faster to use getImageData for each of your "sprites" and keep references to the imageData arrays in your Javascript and use putImageData to render to your target canvas.

You can still render your sprites using an invisible source canvas and the getImageData on each of the tiles/sprites. It would use more memory but might be faster than drawImage with a source and destination canvas.

kanaka
+1  A: 

Wow, that is a large offscreen canvas. The storage just for the buffer is about 36MB.

I'd be tempted to use smaller offscreen tiles, e.g. 1024x124 and draw the visible ones on your main canvas. To save memory you could only initially create the visible tiles and then generate other ones as they become visible. (And you could dispose of, or even better recycle ones that are no longer visible).

I don't believe the answer suggesting that you use putImageData will give better performance, as the experience of the questioner here indicates: why-is-putimagedata-so-slow

andrewmu