7 ms·
Are you currently prerendering to a separate canvas? Drawing it to a different (hidden) canvas, grabbing the image data, and just pushing that to the actual ca
by de90 14y ago
Are you currently prerendering to a separate canvas? Drawing it to a different (hidden) canvas, grabbing the image data, and just pushing that to the actual canvas might be a bit performance boost.
- gren 14y agoThis is what I do except I use drawImage. You think using getImageData and putImageData is more performant that drawImage(canvas, 0, 0) ? BTW i'm not sure it will works for combining images together with special composite operation.
- leeoniya 14y agodrawImage is usually faster. i think it's also more useful if you need alpha composition (overlays). http://jsperf.com/canvas-drawimage-vs-putimagedata/11 http://jsperf.com/canvas-drawimage-vs-putimagedata/11 also read this about imageData caching and explanations of the different opts. loop unrolling helps a bit, forget the typed array stuff for now, it wont work anywhere for some time. http://hacks.mozilla.org/2011/12/faster-canvas-pixel-manipulation-with-typed-arrays/ http://hacks.mozilla.org/2011/12/faster-canvas-pixel-manipul...
- gren 14y agoThanks!
- ajuc 14y agoI have 3 canvas elements, bottom with static backgroud, middle with scrolling terrain, and upper with sprites. I clear the whole middle canvas each frame, and only redraw parts of the other canvas elements. But I don't use hidden canvases, just .drawImage each visible tile of terrain into the middle canvas each frame. I'll try to draw to hidden canvas, and see the difference, thanks for suggestion.
- JackC 14y agoHuh. I've never worked with canvas, but is it possible that moving the middle canvas itself would be faster than clearing and redrawing it every frame? Like you have two canvases side by side in a div with overflow hidden, move both canvases each frame, and when one of them is totally off screen, move it to the other side and draw new terrain. Or are you hoping to avoid animating the canvases themselves?
- ajuc 14y agoI've just tested. The fastest I get (37% time in drawing according to chrome profile, and ~45 fps) is when I draw everything moving to one, visible canvas, that I clear at the start of each frame, and everything static (background) is on another canvas, that isn't changed when it's not needed. When I draw everything moving to off screen canvas, and then drawImage this off screen canvas into visible canvas, I get 48% of time in draw function, and ~35 fps. It is indeed faster to draw everything to off screen canvas, than to on screen one (when I commented out copying off screen canvas to on screen canvas, and left only drawing sprites and tiles to off screen canvas - I got steady 60 fps, but obviously nothing is visible then :)). And copying whole canvas to the visible one is still slower, than drawing the sprites and tiles on the visible canvas in the first place. But thanks for ideas.
- de90 14y agoAre you redrawing every time to the invisible canvas, or are you saving the data, and just pushing that to the screen? I'm not entirely sure if this is plausible for you situation, but take the event of a game like mario. The ground on the bottom can be drawn one time grabbing each tile from a tile sheet, and then you can save that bitmap data, so you cut out having to 'pick out' each tile, and just push that data to the screen. Any chance you have an example of what you're doing for your sprite\tile layer? I believe it can be a bit fast this way, but we may just not be on the same page.
- ajuc 14y agoI have 4096x4096 tiles 64x64 pixels each. I can't draw that to off screen canvas at once. I only draw tiles that are visible, and terain is mostly empty (some platform in the air), than I don't draw anything obviously. My fastest code: for (var y=y1; y>=y0; --y) { var resultY = (0.5+ (level.topLeft.y - camera.position.y + camera.screen.height / 2 + level.cellHeight + y * level.cellHeight-level.cellHeight) )|0; // fast clip to int for (var x=x1; x>=x0; --x) { var tileImageNo = level.layers[z].cells.valueAt([x, y])-1; if (tileImageNo==null || tileImageNo<=0) { //nothing to do } else { ctxOnScreenCanvas.drawImage( tiles[tileImageNo], (0.5+ (level.topLeft.x - camera.position.x + camera.screen.width / 2 + level.cellWidth + x * level.cellWidth- level.cellWidth) )|0, // fast clip to int resultY ); } } } I've also tried drawing to OffScreenCanvas in the loop, and then drawing that canvas to screen, but it was slower. I could try drawing to off screen canvas only when player moves out off current off screen canvas, but that will trade small delay each turn into big delay every N turns, and that's even worse. But I'll try that. EDIT: cuting out not important code.