Jump to content

Game works better in Canvas than in WebGL


jmdev
 Share

Recommended Posts

Hi, I've recently created a game (http://deeeep.io) and while I was finishing it, I realized that the FPS were lower than they should. Later, I tried changing the render mode from AUTO (which used WebGL) to Canvas, and now the game works a lot better (60FPS). So I've changed it from AUTO to Canvas until I find a solution.

I've read a lot of posts that say that WebGL should run faster, so I think I'm doing something that in WebGL mode slow performance.

 

Does anyone know what things does one has to avoid in WebGL to improve perfomance?

Link to comment
Share on other sites

21 minutes ago, tips4design said:

99% of time it's because you are displaying text instead of bitmapText.

Yes, I am using Text. So the performance impact in WebGL mode is that big? :( Text is a very easy to use and convenient class. As I've just read, BitmapText creates sprites for each character, which are taken from a bitmap file I have to create. If I want to be able to display Chinese characters, for example, does that mean that I need to create a image file containing every Chinese character?

 

Also, if it works fine in Canvas mode, is there any reason for which it should be better to use WebGL? If not, I can just leave it how it is, right? (Using text in Canvas mode)

Link to comment
Share on other sites

14 hours ago, tips4design said:

It works fine on your PC. On mobile devices or other low-end devices that have a GPU, moving the canvas-drawing stress from the CPU to the GPU really makes a difference.

Also, when you can find many bitmap fonts online that you can use. 

At least it works much better in Canvas in low-end and mobile devices than in WebGL as it was working before. To use bitmap fonts I guess I should only accept languages that use alphabet, as ideographic languages like Chinese have huge bitmap files (4MB or more) and I want to be as international as possible :S

Link to comment
Share on other sites

6 hours ago, jmdev said:

At least it works much better in Canvas in low-end and mobile devices than in WebGL as it was working before. To use bitmap fonts I guess I should only accept languages that use alphabet, as ideographic languages like Chinese have huge bitmap files (4MB or more) and I want to be as international as possible :S

When using WebGL, the problem is that that a texture for each letter is created and uploaded the the GPU each frame I think, which is much worse than uploading once a larger GPU. So yeah, having to use Chinese might be a problem.

Link to comment
Share on other sites

On 11/2/2016 at 4:23 PM, tips4design said:

99% of time it's because you are displaying text instead of bitmapText.

Shit. I was using game.debug.text on every update frame and it was cutting my FPS in half in webgl. 

I don't think Phaser.Text, is the problem, I think the culprit is often debugging text and calling it every frame. Kind of absurd that such a small thing would choke the renderer. Really happy to have figured it out tonight though as this issue was driving me crazy. I can now go back to being a webgl enthusiast. 

Link to comment
Share on other sites

I now that WebGL is teased at the highend, fast rendering stuff.. but it really isn't at least for the usecase of pixelgraphics.
WebGL is fast in doing calculations and stuff, drawing shapes. But rendering Pixelgraphics is different.

With that said at first. If you are writing a game that supports average PCs / Mac / Linux you should consider droppping WebGL and using Canvas.
(I am only talking about desktops here, mobile is different but the webGL support is also still lacking)

WebGL is pretty slow compared to Canvas when using phaser (not due to phaser, due to using what it is for).
This can also seen on every integrated graphics, which most non-gaming-pc people have. At least the Iris Pro 550 / 580 (fastes yet, 580 is scored higher than a dedicated Geforce 940M) are still performing a lot better in Canvas then in WebGL. This can also be seen on the latest 620 series ob intel kaby lake.
Most machines use an integrated solution especially in asian countries. (older ones).

WebGL 2.0 is behind the corner with full support in Microsoft Edge and via flag on Chromium. I don't investigated tests on this.
So if you are looking for a solution that most people can play - Canvas is the way to go.
You are loosing the nice filters, but if they are not essential; drop 'em.

WebGL has huge potential and it would be great to see the performance every one talks about. But you have to focus on real numbers and on average System-
running an i5 / i7 with HD 6000; HD500; Iris 500; HD 600 - Canvas is up to 30% faster. (System were actually tested).

Please notice: I am looking on overall OS not only Windows. 


regards

Link to comment
Share on other sites

I agree - webgl performance just isn't what it should be on your average working-man's PC. 

It is hard to have a side by side comparison simply by switching from webgl to canvas mode and vice versa, because there are some scenarios in which one will perform better than the other, but it depends entirely on your code. For example, in theory, webgl should be super fast if you fit everything into a single texture. Canvas doesn't gain much in speed by limiting the number and size of texture atlases. I did some tests once and discovered that the bottleneck for # of sprites is a much smaller number on canvas. i.e. you can have 1000 sprites in webgl @60fps but those 1000 sprites in canvas will slow the game down to 30 FPS.  I don't remember when i did those tests but a lot has changed since then in Phaser, and Chrome's webgl implementation. 

But in general, I've found canvas is much more widely supported. I think my solution will ultimately be to offer both modes and allow the player to change rendering modes via the menu. Of course, the defaults I will set intelligently. IF you're running Firefox, canvas, definitely. If you're on an older mac, canvas definitely. But a newer PC with 3rd party GPU, should be able to take advantage of webgl. 

 

Link to comment
Share on other sites

  • 7 months later...

I've also noticed a significant improvement when switching from WebGL to Canvas for mobiles. I was able to go from ~8 FPS to a solid 55+. This was totally against my intuition.

Here's a must read for anyone looking to jack up their FPS. https://phaser.io/tutorials/advanced-rendering-tutorial/index

Also, there appears to be an ongoing issue with Phaser texts that you should be aware of if you use a lot of text objects. https://github.com/photonstorm/phaser-ce/issues/198 The simplest solution for now, is just to use bitmap texts instead.

Link to comment
Share on other sites

  • 7 months later...

Funny how I keep going back to this question even in 2018. Been doing a lot of testing and pondering wether I should make canvas the default on my new game, as opposed to webgl. At the end of the day it really comes down to "depends on the computer," so I want to give the user the choice. I've done that on previous games but learned that is too much of a responsibility to put on the user. e.g. seeing kids playing at 5FPS and ignoring the prompts to switch to canvas mode... I might just make canvas the default. 

Link to comment
Share on other sites

  • 9 months later...

Hi guys,

I'll reuse this topic for posting my question regarding the never ending battle between Canvas2d & WebGL rendering.
Let me first describe my situation, i'm building a simple match3 genre game for desktop and mobile devices. I was trying the game on my desktop PC and on my Nexus 5X phone, and the game is working flawlessly on 60 FPS on average with WebGL rendering. Next day I was coding the game on my laptop, and when I tried it out, the movement was not smooth. I've checked the FPS count and saw that the game is running just on 40FPS on average with WebGL, even if in Idle mode (nothing moving on the screen). I'm rendering the game in 1920x1080 resolution, and having around 12 Draw Calls, antialias and transparency enabled. I was wondering what the heck is going on here, and after reading a few articles, I've tried to change the rendering context from WebGL to Canvas2D and sudenlly the game is back on 60FPS.
Investigating browsers Graphics Feature Status (chrome://gpu) showed that Canvas, WebGL, and WebGL2 are Hardware Accelerated. Because I was using Phaser.AUTO configuration and WebGL is supported and enabled, the system picked WebGL renderer even though Canvas2D is performing better.

After a while I even figure out (better wording would be I've remembered :) ) , that my laptop has two graphic cards, one integrated (Intel something) and external NVIDIA GeForce GTX 950M). And I figured out that Chrome is using integrated card for rendering. I've changed that to GeForce to be default graphics processor, and sudenlly the game is working on 60FPS with Canvas2D and WebGL renderer. Quite surprising. I've came to conclusion that the performance is appearently heavely dependent on GPU card/chip.
My question is, is it possible to change the renderer type during game run.  So in cases when both renderers are supported, I would run the game with WebGL, and as soon as I get information about FPS and see that it's running under 50 FPS for example, I would switch to Canvas2D, check FPS one more time, and then pick the better renderer. Would that be possible? Obviously I did not  yet try out that, but I'll dig into it over the next few days. 
I would really appreciate any kind of tips you could give me here, what would be the fastest approach and least stressfull  for the player (so that the game still runs smooth during the switch) to do it.

 

Link to comment
Share on other sites

I figured out the solution. 
If anyone will need to change the rendering type during game run, you need to do the following (WebGL --> Canvas2D):
anywhere in the game add and call this:
 

this.game.renderType = Phaser.CANVAS;
this.game.setUpRenderer();

Afterwards I've overridden the setUpRenderer() method, and did following modifications at the end of the method:
 

if (this.renderType !== Phaser.HEADLESS) {
  this.stage.smoothed = this.antialias;

  // remove old Canvas element from DOM
  let canvas = document.getElementsByTagName('canvas')[0];
  if (canvas) {
     canvas.parentNode.removeChild(canvas);
  }
  // add new Canvas element to DOM
  Phaser.Canvas.addToDOM(this.canvas, this.parent, false);
  Phaser.DOM.getOffset(this.canvas, this.offset);
  // re-enable input events, so they're listening to new Canvas
  this.input.boot(this.config);
  
  // assures that the new Canvas is at the correct position and in correct size
  let  bounds = this.scale.getParentBounds(this.scale._parentBounds);
  this.scale.onResize.call(this.scale.onResizeContext, this.scale, bounds);
  this.scale.updateLayout();
  this.scale.signalSizeChange();
}

 

After a few tests, everything works as it should. This should now enable me switching between renderer types.

 

 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...