AdvancedDynamicTexture renders differently using parseFromSnippetAsync or parseFromURLAsync

In this playground I create a simple mesh and load a GUI onto it using parseFromSnippetAsync, it works perfectly.

Whereas in my real code I have to use parseFromURLAsync. Everything else is the same but it fails to work if I use .parseFromURLAsync(‘./assets/ui/MainMenu-guiTexture.json’, true) with an error saying it needs to be a POT texture.

If I use .parseFromURLAsync(‘./assets/ui/MainMenu-guiTexture.json’, false) then it loads but doesn’t render the layout correctly, see image below.

What is going on here?

Could you provide a PG where you use parseFromURLAsync?

It works for me in this PG:

As I said it works in the playground as that uses a snippet.

It’s the loading from a url that doesn’t work.

I’ll have to see if I can host my json file somewhere and read that in via a playground instead of using the snippet

This link may help - https://doc.babylonjs.com/toolsAndResources/thePlayground/externalPGAssets/v

My PG is using parseFromURLAsync:

const guiSnippet = {
    "id": "9ZL1UP",
    "version": 0,
    "description": "",
    "jsonPayload": "A LOT OF CODE - SEE PG",
    "name": "",
    "snippetIdentifier": "9ZL1UP-0",
    "tags": "",
    "date": "2025-10-28T09:12:48.433Z"
};

vrTexture
    .parseFromURLAsync("data:text/plain;base64," + btoa(JSON.parse(guiSnippet.jsonPayload).gui), true)
    .then(() => {});

Passing a data uri is/should not be different from passing a “real” url.

Maybe your missing my point.
It is parsing it from my url but it renders it differently. That’s the bug.
It should be no different, yet it is.

MainMenu-guiTexture.zip (2.1 KB)

CORS policies seem to prevent me some exactly mirroring the code in a playground. So other than the screen shot I’m not sure how to show that it doesn’t work

If I set the gui editor size to 512 x 1024, a POT size, then it displays as it does in my application. So I’m guessing that is the error. It’s imposing a POT size whereas the playground does not.

So yes switch to a size of 512 x 1024 fixed all the layout issues. But it does mean the UI has to be a certain size only which is a bit limiting.

I put your file in one of my github repo and it still works for me for a size of 500 x 800 (at least the display is the same than in https://playground.babylonjs.com/#O06SZ5#12):

Do you pass true as the second parameter to parseFromURLAsync in your project?

If I pass true I get an error saying not POT and it doesn’t render.

So the screenshot is from passing false.

I’m testing in Chrome and running in a tethered Rift S

So, it looks like your system is running WebGL1, as non-POT support is a requirement of WebGL2. Can you check if my PG works for you (check which engine is being used by looking at the browser console)?

Ok yes that’s working for me too, and I can see my app is using webgl 1, so why is my application not using WebGL 2….

“dependencies”: {

"@babylonjs/core": "^8.25.1",

"@babylonjs/gui": "^8.25.1",

"@babylonjs/loaders": "^8.25.1",

"react": "^19.1.1",

"react-dom": "^19.1.1"

},

let engine;

try {

  engine = new Engine(canvasRef.current, true, { preserveDrawingBuffer: true, stencil: true });

  globalEngine = engine; *// Store globally*

  console.log('Babylon.js engine initialized');

}

WebGL2 should be used by default if it is supported. Only if disableWebGL2Support: true is added to the options when building the engine will WebGL2 support not be tested.

So I don’t understand why it doesn’t work in your project if my PG works on your device… Or could it be that canvasRef.current does not support WebGL2 for some reasons?

Try logging canvasRef.getContext(“webgl2”) and see what value is returned (do this before calling new Engine()).

I’ve added some stuff to force it to prefer webgl 2 and that now does seem to be working now. Thanks for all the help.

1 Like