Texture.CreateFromBase64String doesn't seem to work for IOS devices initially

Hi everyone,

I have a SVG image with base64 embedded assets (fonts and images) which I want to use as a texture.
I use the Texture.CreateFromBase64String function for this use case.

However the very first call of Texture.CreateFromBase64String doesn’t seem to work on IOS devices.
The SVG is not (or only partly) shown on the texture. => https://playground.babylonjs.com/#U8FUEJ#3
image
…in this example (of an iPad Pro 12) only the texts are missing, on some other IOS devices the whole SVG is not displayed.

When calling CreateFromBase64String a second time it works => https://playground.babylonjs.com/#U8FUEJ#2
image

It also works already on the first call when reloading the tab.
If no base64 assets are embedded in the SVG there is also no problem as well.

@Cedric, could you have a look into it ?

1 Like

Let me take a look.

1 Like

I can repro on MacOS/Safari as well where I get a black texture only. I’m investigating for a fix.

3 Likes

nothing found so far. It’s like the image is not yet ready to be rendered/loaded by gl.texImage2D. I cheked a few things like the view box, tried to check if image is ready but had no luck :confused:

it this true as well ? HTMLImageElement.complete - Web APIs | MDN

Yes, image complete returns true :frowning:

Did I tell you already how much I love Safari ???

If you had a setTimeout(…, 0) or defer one frame before loading is it enough ?

@sebavan Yes, I already tried timeouts of 10 seconds, didn’t work.
Also I completely share your love for Safari :upside_down_face:

I guess you could create an issue on the webkit bug tracker as unfortunately it sounds to be mostly on their side :frowning:

After spending some more time with this issue I want to share my new findings with you.
I reevaluated some different approaches for drawing SVGs on textures and saw, that the very same issue also occurs for DynamicTextures.

Originally we solved our use case with DynamicTextures which seemed to have some (different) problems in IOS V14 and below, see forum post.
Seems like the issue mentioned in this forum post can be solved by using a different base64 conversion (btoa instead of createObjectUrl) but that’s a different story.

Anyway here is the updated PG example which shows 4 different planes with SVGs on it.

  • yellow: solved with Dynamic Texture / no embedded fonts => works
  • red: solved with CreateFromBase64Sring / no embedded fonts => works
  • blue: solved with Dynamic Texture / embedded fonts => doesn’t work
  • green: solved with CreateFromBase64Sring / embedded fonts => doesn’t work
    …so the problem are the base64 embedded fonts for both DynamicTexture and CreateFromBase64String

The fixes for DynamicTexture and CreateFromBase64String are the same:

  • reload the page
  • or call dedicated function twice

So I tried to find what part exactly has to be done twice in order to make it work.
=> It’s the image loading process.
After the image has been loaded once, set the image source again (with the exact same value) and wait for another onload callback.
This can be seen in the previously mentioned playground example in line 89.

Another thing worth mentioning is that adding the “erronous image” to the HTML page is working.
You can try it in line 100.
So the image itself doesn’t seem to be broken, it must be related to the usage inside the texture.

It looks like a weird issue with Safari and embedded fonts. You could try to use it against a 2d canvas just to see if you can repro there to open a webkit issue.

Safari + SVG + embedded/custom fonts, always a fun combo to work with :upside_down_face:
Sorry for not contributing anything helpful here but that had to get out :wink:

1 Like

I would suggest a correction :slight_smile:

Safari + SVG + embedded/custom fonts, always a fun combo to work with

1 Like

@sebavan I tried to load the SVGs on a plain HTML Canvas Element and it really can be reproduced there as well!
https://playground.babylonjs.com/#U8FUEJ#77

This guy seemed to have the same problem.
He solved it with a timeout after image.onload and it seems to work for our use case too, even though it’s not the nicest solution and I’m not sure which timeout values are required.

The onload event can’t be accessed when using CreateFromBase64String, that’s why the first timeout tests didn’t work.
Anyway at least now we got something to implement a workaround.

3 Likes

FYI, I checked the Webkit Bugtracker and there are already 2 issues which tackle this topic:

The first one is already from 2010, so I doubt that there is high priority on it.

3 Likes