Loading playcanvas builds with engine only issue (specularUniform difference)

Once again I am having trouble with loading an editor build in my engine-only app. My models in the custom app look different than the ones in the normal build.
I have been able to narrow the issue down to one property in my material, ‘specularUniform’. It is a different value in my custom loader than in the normal loader (opening index.html from the build), when I simply force that value to be the same, it looks fine.

See the color difference below:

I’ll explain my loader code here,
First of all I set all the assets to not ‘preload’, I want to control this myself, then I download files from my server and turn them into blob urls and set those urls to the asset.file.url for each asset.

for (const assetId in buildData.assets) {
  const asset = buildData.assets[assetId];
  if (asset.type !== 'script') buildData.assets[assetId].preload = false;
  if (asset.file) {
    let responseType = '';
    if (asset.type === 'model') responseType = 'application/json';
    if (asset.type === 'texture') responseType = 'arraybuffer';
    // Loading from local files for debug
    const promise = new Promise((resolve, reject) => {
      axios.get(`/playcanvas_build/${asset.file.url}`, {
        responseType,
      }).then((result) => {
        const data = result.data;
        let assetBlob;
        if (asset.type === 'model') assetBlob = new Blob([JSON.stringify(data)], {
          type: 'application/json'
        });
        if (asset.type === 'texture') assetBlob = bytesToB64Blob(new Uint8Array(data));
        else assetBlob = new Blob([data]);
        const assetUrl = URL.createObjectURL(assetBlob);
        buildData.assets[assetId].file.url = assetUrl;

        resolve();
      });
    });
    loadPromises.push(promise);
  }
}

Then following the start script of normal builds, I run app.configure with the build json file url and create a scene from my scene json. Then I only preload the texture files by directly loading it with the resource manager, otherwise it adds ?t=... which breaks blob urls.

app.configure(buildUrl, async (err) => {
if (err) return console.error(err);

// Create the scene entry
const sceneBlobData = JSON.stringify(sceneData);
const blob = new Blob([sceneBlobData], {
  type: 'application/json',
});
const url = URL.createObjectURL(blob);

pc.app.scenes.add('CustomBuild', url);
const scene = pc.app.scenes.find('CustomBuild');

// Go through all the texture assets and load them manually
// (bypassing the app.assets.load method)
const assets = app.assets._assets;
const textureLoads = [];

for (let index = 0; index < assets.length; index++) {
  const asset = assets[index];
  if (asset.type === 'texture') {
    const promise = new Promise((resolve) => {
      const file = asset.file;

      // _opened and _loaded copied from Playcanvas source
      const _opened = function (resource) {
        if (resource instanceof Array) {
          asset.resources = resource;
        } else {
          asset.resource = resource;
        }
        app.loader.patch(asset, app.assets);
        app.assets.fire('load', asset);
        app.assets.fire(`load:${asset.id}`, asset);
        if (file && file.url) app.assets.fire(`load:url:${file.url}`, asset);
        asset.fire('load', asset);
        resolve();
      };

      const _loaded = function (err, resource, extra) {
        asset.loaded = true;
        asset.loading = false;
        if (err) {
          app.assets.fire('error', err, asset);
          app.assets.fire(`error:${asset.id}`, err, asset);
          asset.fire('error', err, asset);
        } else {
          _opened(resource);
        }
      };

      // Load through the ResourceLoader directly
      app.loader.load(asset.file.url, asset.type, _loaded, asset);
    });

    textureLoads.push(promise);
  }
}
await Promise.all(textureLoads);

// Finally, add the scene hierarchy to the app
app.loadSceneHierarchy(scene.url, () => {
  resolve();
  console.log(app.assets);
});

After this I simply start the app.
Does anyone know why the specularUniform can be different in the different builds? :slight_smile:
If you need more information please let me know!

Update: it doesn’t seem to be the specularUniform value. This was solved by running material.update() after the skybox got added.
I currently can not find any differences between the materials or scene settings.
Correct colors:


Incorrect colors:

Any thoughts? :slight_smile:

1 Like

Hi @Ivolutio,

Not sure what’s the issue is, it isn’t easy to debug like this. Though looking the two screenshots I would tell the 2nd one receives more light, quite a difference. Are you sure that all lighting settings (both your light entity and scene settings) are fully identical?

Yeah. The scenes are identical (checked with yaustars tool), also the scene’s skybox, exposure, ambient light, etc. seems to be the same. I’ve been checking a lot of properties with a text compare tool and everything is the same :confused:

It kinda looks like the scene exposure/gamma setting is higher :thinking:

1 Like

Yeah that would make sense, but they are the same, unfortunately :stuck_out_tongue:
I guess I’ll start from zero and retry recreating the scene loader. I can’t share the source of this code, so unless you have any other ideas to check, I’ll just have to go step by step again. :slight_smile:

Check this, just in case:

1 Like

Unfortunately that doesn’t change anything. It is already ‘1’ and setting it to pc.GAMMA_SRGB doesnt change it (GAMMA_NONE does, but of course thats too dark).
afbeelding