phaserjs / phaser-ce

Phaser CE is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
http://phaser.io
MIT License
1.35k stars 491 forks source link

The WebGL is slower than Canvas in my game on IOS ? #356

Open JanusSpark opened 7 years ago

JanusSpark commented 7 years ago

I've changed nothing except the game config 'renderer' in Phaser.AUTO or Phaser.CANVAS But it's very slow in Phaser.AUTO and it's renderType is 2 on my iphone. But it shows very well on android. When I change Phaser.AUTO to Phaser.CANVAS it shows pretty good. I used to use Pixi.js.It didn't show like this. I don't know why ? Have you ever meet this scene ? It is really confused me. My phaser-ce is 2.8.6

samme commented 7 years ago

WebGL performance can vary by device and by game.

Make sure you turn off game.debug: https://phaser.io/tutorials/advanced-rendering-tutorial/part5.

JanusSpark commented 7 years ago

Yes. I'm sure about that. This my code now image

hyena3300 commented 7 years ago

By any chance you have text on the screen? If so then I think it's related to this issue.

https://github.com/photonstorm/phaser-ce/issues/198

If you remove the text on your screen then your performance on device should go up.

JanusSpark commented 7 years ago

I do have some text on it.But when I remove the text it isn't working better than before.

goldfire commented 7 years ago

We are having this same issue and are quite confused by it. We are getting <10fps with a relatively simple game on an iPhone 7, but switching it to CANVAS makes it run at a smooth 60fps. It is really too bad that Phaser's PIXI diverged so much from the current PIXI as I suspect an up-to-date version of PIXI would solve these problems.

samme commented 7 years ago

Have you checked the draw counts?

photonstorm commented 7 years ago

I would disable multiTexture too, the shaders required for it are a lot more complex and likely to cause branch misprediction, which isn't great on mobile. Desktop has the grunt to benefit more than it costs.

goldfire commented 7 years ago

@photonstorm Yeah, we actually already disabled multiTexture and are still facing the same issues.

goldfire commented 7 years ago

Our draws peak out at ~39 with ~419 calls using WebGL, but it is practically unplayable on an iPhone 7. In canvas mode it has ~102 draws with ~317 calls and runs at a smooth 60fps. We don't necessarily need to use WebGL mode, but the ability to use shaders was something that is important for our plans and I can't see any reason why WebGL should be performing this poorly compared to Canvas.

okaybenji commented 7 years ago

@samme Can you comment on why this issue was closed?

samme commented 7 years ago

Guess I was too hasty.

okaybenji commented 7 years ago

Ok, thanks for reopening 👍

gaurav-dixitv commented 7 years ago

@goldfire Did you find anything that might be causing this? Honestly, >100 draw calls seem a bit too much for mobile web. Do you have loads of display objects? From what I can see, PIXI (Phaser) seems to upload entire buffers on every render (and this also entails calculating the new transform for every object, on the CPU :/ I wonder why this was not done using model matrices on the GPU) frame. So since your draw calls for CANVAS and WEBGL are comparable, I am thinking you are uploading too much every frame.

goldfire commented 7 years ago

@gaurav-dixitv Unfortunately, no, we haven't made much progress here. Honestly, it isn't that complex of a scene, and I don't see why that would be too many draws. We developed a canvas game with a different engine that has 300+ and runs at a smooth 60fps on mobile. Our new game is quite a bit simpler and we assumed we'd get significantly better performance with the batching in pixi/phaser. We have noticed that updating the transforms is fairly heavy. Any idea if this still happens with killed entities by chance? There's generally only a few dozen entities on the screen at once, but there are up to a few thousand killed entities waiting to be recycled in groups.

gaurav-dixitv commented 7 years ago

@goldfire Kill() will set this.visible to false. And by the looks of things, PIXI.DisplayObjectContainer.prototype.updateTransform() and PIXI.Sprite.prototype._renderWebGL() return if !this.visible. So you are neither updating transforms nor uploading them to the GPU every frame. Does profiling point to anything in particular? For a few dozen entities, this does not seem reasonable :/

Shots in the dark:

  1. Maybe you have too many shader programs and you useProgram() to switch between them in a render call ?
  2. Using PIXI.scaleModes.LINEAR? For a POT texture, this defaults to LINEAR_MIPMAP_LINEAR, which is expensive.

I think profiling should really help here!

goldfire commented 7 years ago

Well, that is the real problem. We've done quite a bit of profiling in Chrome and it runs quite well on desktop. iOS is where the performance drops off a cliff, but Safari's remote profiler is essentially worthless as far as we can tell, so we are having a hard time even pinpointing where the issue might be.

We disabled the only custom shader we are using and it made no difference in performance. We haven't directly set the scale mode, which looks like it defaults to linear. Setting antialias on the game to false sets all of the textures to use PIXI.scaleModes.NEAREST, but due to the style of our graphics it makes the game look quite bad. Making this change also resulted in roughly the exact same FPS on our test iPhone.

willieZhao commented 6 years ago

@goldfire Hi buddy, we are now facing this problem too. Since we have to use Spine, we have to also use Phaser with WebGL. So may I know what is your team's final solution? Do we need to abandon WebGL? Or how we can improve the performance for it?

goldfire commented 6 years ago

@willieZhao In our case, the solution was to completely eliminate parent/child relationships in the code, which were preventing the sprite batching from working. We were also using a hue shifting filter that broke batching, so we over-wrote the built-in batch shader with our own custom version that had our custom filters included in it. These two changes took us from several hundred draw calls to around 5 or 6 and massively improved the performance of the game.

AhmedElyamani commented 6 years ago

@goldfire Hello, I'm also facing the same problem. Would you please explain what it means to "eliminate parent/child relationships in the code" ?

goldfire commented 6 years ago

@AhmedElyamani We just never use .addChild() on anything. This adds a bit of complexity in some areas as we now have to update positions, rotations, etc of everything independently, but overall it wasn't too big of a pain and resulted in massive performance gains with the batching.

monteiz commented 3 years ago

I believe this issue shouldn't be closed, because in mobile devices performances are still very bad.

Or maybe there are techniques that I am not aware of?

Please help.

monteiz commented 3 years ago

@samme thanks for re-opening this issue. I believe that instead of introducing new features, we should make an real effort to make WEBGL working with the same performance as canvas even on mobile, because Spine, lights, 3D features, only work with that, and games are going in that directions, and also in directions of mobile devices. So basically the entire Phaser risks to become obsolete soon.

samme commented 3 years ago

For Phaser CE I think this issue will remain until someone good at WebGL gives a lot of attention to it.

For better WebGL performance, you should always:

monteiz commented 3 years ago

@samme thanks for your tips and support

Regarding Phaser 3, if you have some tips on the same topic or a document/blog post I can read about it, please share it.