WebGL VS Canvas 2D hardware acceleration - javascript

These days, I need to draw many images on a canvas. The canvas size is 800x600px, and I have many images of 256x256px(some is smaller) to draw on it, these small images will compose a complete image on the canvas. I have two ways to implement this.
First, if I use canvas 2D context, that is context = canvas.getContext('2d'), then I can just use context.drawimage() method to put every image on the proper location of the canvas.
Another way, I use WebGL to draw these images on the canvas. On this way, for every small image, I need to draw a rectangle. The size of the rectangle is the same as this small image. Besides, the rectangle is on the proper location of the canvas. Then I use the image as texture to fill it.
Then, I compare the performance of these two methods. Both of their fps will reach 60, and the animation(When I click or move by the mouse, canvas will redraw many times) looks very smooth. So I compare their CPU usage. I expect that when I use WebGL, the CPU will use less because GPU will assure many work of drawing. But the result is, the CPU usage looks almost the same. I try to optimize my WebGL code, and I think it's good enough. By google, I found that browser such as Chrome, Firefox will enable Hardware acceleration by default. So I try to close the hardware acceleration. Then the CPU usage of the first method becomes much higher. So, my question is, since canvas 2D use GPU to accelerate, is it necessary for me to use WebGL just for 2D rendering? What is different between canvas 2D GPU acceleration and WebGL? They both use GPU. Maybe there is any other method to lower the CPU usage of the second method? Any answer will be appreciate!

Canvas 2D is still supported more places than WebGL so if you don't need any other functionality then going with Canvas 2D would mean your page will work on those browsers that have canvas but not WebGL (like old android devices). Of course it will be slow on those devices and might fail for other reasons like running out of memory if you have a lot of images.
Theoretically WebGL can be faster because the default for canvas 2d is that the drawingbuffer is preserved whereas for WebGL it's not. That means if you turn anti-aliasing off on WebGL the browser has the option to double buffer. Something it can't do with canvas2d. Another optimization is in WebGL you can turn off alpha which means the browser has the option to turn off blending when compositing your WebGL with the page, again something it doesn't have the option to do with canvas 2d. (there are plans to be able to turn off alpha for canvas 2d but as of 2017/6 it's not widely supported)
But, by option I mean just that. It's up to the browser to decide whether or not to make those optimizations.
Otherwise if you don't pick those optimizations it's possible the 2 will be the same speed. I haven't personally found that to be the case. I've tried to do some drawImage only things with canvas 2d and didn't get a smooth framerate were as I did with WebGL. It made no sense to be but I assumed there was something going on inside the browser I was un-aware off.
I guess that brings up the final difference. WebGL is low-level and well known. There's not much the browser can do to mess it up. Or to put it another way you're 100% in control.
With Canvas2D on the other hand it's up to the browser what to do and which optimizations to make. They might changes on each release. I know for Chrome at one point any canvas under 256x256 was NOT hardware accelerated. Another example would be what the canvas does when drawing an image. In WebGL you make the texture. You decide how complicated your shader is. In Canvas you have no idea what it's doing. Maybe it's using a complicated shader that supports all the various canvas globalCompositeOperation, masking, and other features. Maybe for memory management it splits images into chucks and renders them in pieces. For each browser as well as each version of the same browser what it decides to do is up to that team, where as with WebGL it's pretty much 100% up to you. There's not much they can do in the middle to mess up WebGL.
FYI: Here's an article detailing how to write a WebGL version of the canvas2d drawImage function and it's followed by an article on how to implement the canvas2d matrix stack.

Related

Google Chrome hardware acceleration making game run slow

So I have been working on a game in HTML5 canvas and noticed that the games lags and performs much slower when hardware acceleration is turned on in Google Chrome then when it is turned off. You can try for yourself here
From doing some profiling I see that the problem lies in drawImage.
More specifically drawing one canvas onto another. I do a lot of this.
Hardware Acceleration on.
Hardware Acceleration off.
Is there something fundamental I am missing with one canvas to another? Why would the difference be that profound?
If I remember correctly, in-DOM canvases are loaded into GPU memory in Chrome, and off-DOM canvases may not be. So each drawImage from an off-screen canvas to an on-screen canvas results in loading the content of the canvas onto the GPU as a texture, followed by a copy of that memory on-GPU onto the on-screen canvas. The cost of sending a new texture through to the GPU can be quite high. Loading textures is high-throughput, but also high-latency, on most GPUs.
Someone from the Chrome team will have to chime in with a definitive answer, but that fits my experience with canvases in Chrome.

Canvas Pixel Manipulation Poor Performance

I am writing a web visualization tool which involves displaying a processed image ~30 times a second.
I have been using the standard canvas tag and using functions such as getImageData/putImageData to perform some pixel manipulation along with drawing circles, squares and paths using beginPath() and bezierCurveTo(), stroke(), etc
Everything is working great but I am getting horrible performance even with hardware acceleration.
Is canvas inherently slow at these types of operations?
I have been researching into using WebGL/THREE.JS for performance, but all I need is to do pixel manipulation with some basic shape drawing. Is WebGL overkill for this? Is there a better alternative?
Ideally I believe I want something that wraps the canvas API but displays it using the WebGLRenderer for performance.

What is the real benefit of using canvas for games?

I'm currently reading up on the canvas, but I'm finding it hard to find practical benefits of using canvas, when a lot can be done using simple css overlays/JavaScript (+ jquery lib).
This is probably because I don't know the FULL practicalities of using canvas.
Looking at this game:
http://www.pirateslovedaisies.com/
Could someone help explain how and why canvas is being used as opposed to just css?
This is a 4k js/canvas demo I wrote to experiment with the 2d context (here is a video if your browser doesn't work). I tested it only on chrome, opera, firefox, safari and nexus one browser.
Note that no external resources are loaded (i.e. the texture and the raytraced envmap are built dynamically), so this is just a single self-contained 4096 bytes HTML file.
You can do something like that with DIVs?
But indeed I agree that the game you linked IMO could be done also with DIVs; apparently there are no transformations - not even in the falling daisy loading scene - and the action areas for the pirates are just circles. Not sure but could be that even shooting only happens at fixed angles.
Canvas could have been used instead for:
Drawing general sloped lines and polygons (the map could be created dinamically from a compact description or could have been generated randomly). Shooting could be done at any angle...
Procedural image creation (e.g. textures or special pixel effects)
Gradients, texture mapping
General 2d matrix transforms
Of course a game using an image+DIVs approach is probably way easier to make (a lot of photoshop and simple xy animation).
Creating tons of HTML elements is extremely slow and memory-hungry. The canvas object is made for graphics operations and thus optimized for it. Besides that.. how would you draw a curve with plain HTML/CSS? ;)
Using <canvas> you have a per-pixel control of what's shown on the screen. You don't have to deal with specific browser CSS or DOM compatibility.
Also, that's actually a pretty similar programming model to 2D non-browser games, like those created using SDL o DirectDraw.
Here's a game I wrote in a few hours using Canvas; note that the scaling of the tiles, the anti-aliasing of the lines, is perfect. This would not be the case with image tiles that were being resized by the browser.
Click the tiles to rotate them in an attempt to make all connections. Click the row of buttons at the top for a new board of a different size; click the row of buttons below that for a new board with different numbers of connections.
The game concept is not mine, only the implementation.

HTML5 <canvas>: Performance implications of drawImage()

I was wondering if there were any performance differences in using drawImage() on a dynamically created canvas (i.e. document.createElement("canvas")) versus a canvas already created in the DOM (i.e. tags on a HTML page).
My thinking is that the "slow" part of drawImage() occurs when it actually has to display visuals to the user, though I could be wrong (can't find too much information on this).
Would it be substantially more expensive to draw a group of objects to a canvas in memory followed by a final draw to the "main" canvas than just drawing straight to the latter? I feel like it'd be better to have multiple canvases, at least for organizational purposes.
Related: Does the size of the canvas impact performance if you're only drawing to a subsection of it?
Talking about Chrome and Firefox I could not find any difference between static and dynamic canvas elements. Mainly the amount of pixels drawImage() handles makes it slow + the current globalCompositeOperation (copy, source-over are fastest). However, the browser has to render the full page, so it is a bad idea to place a stretched (background) image below the canvas.
There is a difference between the canvas attributes width/height and its style width/height attributes. You may have a 300*200 pixels canvas with a style size set to 100%. Then internal drawing speed is same what ever the browsers window size is. Of course display quality is a concern.
You may want to separate drawing (lines, boxes, arcs etc) from blitting (drawImage) and find out what consumes more time in your application. As long there is no need for multiple canvas (image processing, blending videos, etc.) try to avoid drawImage(). Your code - not elements - should help you to deal with 'organizational purposes'.
A fullscreen drawImage() on a 1 GHZ Netbook with 1024x600 pixels takes about 10msec. Doing it twice means there is no way to achieve a display rate of 50Hz. Things getting worse if you target iPhone or Android smartphones.
There is no need to do good-old-double-buffering with canvas, it's already implemented. You are free to update only relevant (dirty) subparts of your canvas element whenever you want and gain essential msecs.
Instead of using multiple canvas there is an option to do all invisible operations on a huge one in different sections - drawImage() with target and source the same. It is easier then to see what is happening while debugging.

Redraw lots of objects on Canvas HTML

Is there a quick and efficient way to move lots of objects in canvas? Basically if there are around 1000 objects and I want to move all of them at once to emulate scrolling, it is very slow to redraw every single object by calling drawImage() 1000+ times.
Is there anyway to optimize this? I have an example link of the problem (and that's only with 100 objects): http://craftyjs.com/isometric/
Since canvas doesn't provide fast low level bitmap copying it's hard to do stuff in multiple layers and scroll for example the whole background at once and then only render the edges.
So what can you do? In short, nothing. Especially not when scrolling, sure you can do tricks with multiple canvases when you have a more or less static background but for moving objects there are hardly any performance improving tricks.
So, you've go to wait for Hardware Acceleration shipping in all majors browsers, I know this sounds ridiculous but I'm too waiting for that :/
The problem is that the canvas was never designed for game stuff. It was designed as, well, basically some kind of on the fly drawing thing, guess the designers had Photoshop clones in mind, but definitely not games, let alone the fact that there's no fast clear operation proves that, there's not even optimization in place when clearing the whole canvas with the same color.
If the images are already composited, not moving relative to one another, and defined by a rectangular region, then using canvas.drawImage() with a canvas as the first parameter and drawing to a sub-region should be significantly faster than re-drawing all the objects.
You could also just layer multiple canvases and slide the top canvas with the objects in HTML to scroll them.
Edit: Having really looked at your example, it seems to me that it should be implemented similar to Google Maps: create tiles of canvases and slide them left/right on the HTML page; once a canvas has been slid off the screen entirely (for example, off the left edge), move it to the other side (to the right edge) and re-use it for drawing. With this you will only need to re-draw whatever objects overlap the canvases that are moving on the edges.
You can draw all objects on a second, off-screen canvas and then only blit the whole canvas (drawImage() accepts canvas element).
However, if you're targeting desktop browsers, then this shouldn't be necessary. I've implemented tile engine (source) that simply redraws whole scene and naive implementation turned out to be pretty fast.
What I did to solve this problem was I had 10 squares on my screen and I wanted to animate them on a white background. So I drew a white rectangle over the canvas to clear the canvas so the animation would work. Does that make sense?
#Ivo By the way I read on http://www.w3.org/TR/html5/the-canvas-element.html that canvas was made for applications like games because it was a solution to get rid of the dependency on a external engine. Canvas is built in so it's kind of like a flash player built into your browser powered by JavaScript. I think it's fascinating.
You can use tiled rendering.
http://www.gamesfrommars.fr/demojsv2/ (better viewed with Chrome)

Categories

Resources