Can't load file produced by SceneSerializer

I added a skybox programmatically, then exported the scene with SceneSerializer. Here’s what got exported (I removed unrelated properties):

"reflectionTexture": {
  "url": "assets/textures/skybox/skybox",
  "files": [
    "assets/textures/skybox/skybox_px.jpg",
    "assets/textures/skybox/skybox_py.jpg",
    "assets/textures/skybox/skybox_pz.jpg",
    "assets/textures/skybox/skybox_nx.jpg",
    "assets/textures/skybox/skybox_ny.jpg",
    "assets/textures/skybox/skybox_nz.jpg"
  ],
  "extensions": [
    "_px.jpg","_py.jpg","_pz.jpg","_nx.jpg","_ny.jpg","_nz.jpg"
  ],
  "name": "assets/textures/skybox/skybox",
  "coordinatesMode": 5,
  "isCube": true
}

Looks fine, and the files exist, but SceneLoader.Load throws:

Error: Cannot load cubemap because files were not defined
    at Engine._Engines_thinEngine_js__WEBPACK_IMPORTED_MODULE_0__.ThinEngine.createCubeTextureBase (engine.cubeTexture.js:187:19)
    at Engine._Engines_thinEngine_js__WEBPACK_IMPORTED_MODULE_0__.ThinEngine.createCubeTexture (engine.cubeTexture.js:209:17)
    at Engine._Engines_thinEngine_js__WEBPACK_IMPORTED_MODULE_6__.ThinEngine.createPrefilteredCubeTexture (dds.js:668:17)
    at CubeTexture._loadTexture (cubeTexture.js:335:51)
    at CubeTexture.updateURL (cubeTexture.js:267:18)
    at new CubeTexture (cubeTexture.js:101:15)
    at Function.CubeTexture.CreateFromPrefilteredData (cubeTexture.js:193:22)
    at loadAssetContainer (babylonFileLoader.js:197:115)
    at Object.load (babylonFileLoader.js:886:29)
    at eval (sceneLoader.js:579:35)

The problem starts from this line (babylonFileLoader.js:197):

var cubeTexture = CubeTexture.CreateFromPrefilteredData((parsedData.environmentTexture.match(/https?:\/\//g) ? "" : rootUrl) + parsedData.environmentTexture, scene, parsedData.environmentTextureForcedExtension);

rootUrl=“assets/scenes/”, and parsedData.environmentTexture=“assets/textures/skybox/skybox”. These get appended, and the resulting path is incorrect.

I do not think you should be using a png based texture for the environment texture. How did you generate the scene ?

I would recommend using an .env file instead: Using An HDR Environment For PBR | Babylon.js Documentation

1 Like

I’m using .jpeg files. The scene was created programmatically:

let scene = new Scene(engine)
scene.createDefaultSkybox(new CubeTexture("assets/textures/skybox/skybox", scene))

console.log(JSON.stringify(SceneSerializer.serialize(scene))
// save JSON to start.babylon file

scene = await SceneLoader.LoadAsync('assets/', 'scenes/start.babylon', engine)

I downloaded the skybox jpeg files manually and saved them into the assets/textures directory. The skybox renders correctly.

So we’re calling CubeTexture.CreateFromPrefilteredData, which in turn calls createCubeTextrure with null files arg, and that function throws when files are null.

I find it odd that this is being used to load the environment texture. The babylon file loader checks for the existence of environmentTexture ( Babylon.js/babylonFileLoader.ts at master · BabylonJS/Babylon.js · GitHub) and not reflection texture. Do you have this key in your exported file?

This is due to the helper placing as well the texture in the environmentTexture :frowning:

here is a PR to workaround this case Fix JPEG environment texture by sebavan · Pull Request #12617 · BabylonJS/Babylon.js · GitHub

1 Like

No, there’s no environmentTexture in the exported file. Maybe because I didn’t call createDefaultEnvironment, only createDefaultSkybox, which uses jpeg textures.

Why update environmentTexture? The createDefaultSkybox helper uses reflectionTexture for non-PBR skyboxes - which is what I’m using.

cause createDefaultSkybox stores it in the environmentTexture by default which creates the bug you see