TileSprite not Displaying on Mobile Browsers

I am currently making a 2D Shooter in Phaser3. I am using the Tilesprite class for my scrolling background. It works brilliantly on desktop, but when testing on some mobile browsers the Tilesprite does not render to the screen. The background is just black, but the other sprites for my characters, bullets, enemies, etc. show up normally and the game runs totally fine otherwise.

This occurs in both Safari and Firefox for iOS and Chrome for Android, although for some reason Firefox on Android seemed to display it just fine. I didn’t get any error messages, and my game has a loading screen that waits for the assets to be loaded before starting the game, so it shouldn’t be an issue of a large file just not being ready yet. Additionally, the behavior is the same for accessing the game via both localhost or from Itch.

Thank you so much for your help!

Make sure the TileSprite isn’t too large.

According to all of the documentation I have found, it shouldn’t be, but using a smaller one does resolve the issue. The original image was 4800x270, which comes in well under 2 megapixels. The documentation that I could find for Safari and Chrome claims that there is no single dimensional maximum, merely a cap on the size in megapixels. The lowest bound I could find is 3MP for a lower-end iOS device, which I am not even testing on but should be more than enough for my image.

Is it possible that somehow Phaser is increasing the file size at an intermediate step? I am using pixelArt mode with a resolution of 480x270 and scaling my game’s viewport to fit my screen. Is it possible that Phaser is loading the image and then writing it to an offscreen image/canvas that is the proper scale when accounting for my displaySize? E.g., if my display size is 1920x1080, then Phaser is attempting to create a source image of my tilesprite that is 19200x1080 somewhere?

Assuming you’re using WebGL - the limit depends on the tile sprite’s size, too, not only the texture’s size. If you make a 1920x1080 tile sprite, Phaser will internally create a texture of that size. This allows it to circumvent other WebGL limitations that would make tiling textures impossible (natively, you can only tile a texture if its size is a power of two). You can call game.renderer.getMaxTextureSize() to get the maximum texture dimensions supported by the device (both for the real texture and the internal texture for the tile sprite).

The canvas renderer shouldn’t be as fussy with large textures and tile sprites, but they can still cause serious performance issues. I can’t say whether they could make the sprite not appear at all because I’ve almost never used the canvas renderer.

Well that would explain it, getMaxTextureSize() returns 4096. Furthermore, the tileSprite docs mention that textures will be scaled up to powers of 2, so inside Phaser it must have been creating a canvas of size 8192x512 or larger if I’m understanding properly.

I think Phaser should emit a warning of sorts when assets fail to load because of prior restraints as in this case, especially since it is using a separate type of constraint for maximum size than browsers. (The texture loading on the weaker Android device in the non-native Firefox but not in the native Chrome on the same Device or in either the native or non-native browser on the more powerful iOS device makes it seem like a browser issue, not a Phaser issue.)

It’s interesting why you got no error. WebGL should complain by itself if you try to create a texture that’s too large. On my desktop browser, I get WebGL: INVALID_VALUE: texImage2D: width or height out of range, but admittedly I haven’t tried it on a mobile browser.

I didn’t think of that being a potential issue, debugging on mobile is quite bad so my setup is somewhat hacked together. I will have to test when I have access to my PC again. Right now I’m using Eruda so I can have a JS console directly on my mobile devices. It works well for most things, but it’s possible it is swallowing some warnings/errors here and there.