playcanvas / playcanvas/engine

Material asset miss texture asset after v1.40.5+ engine

Open
#3,185 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

area: assets
Dominant language
JavaScript
Stars
16.8k
Forks
2k
Avg merge
4h 32m
Merged PRs (30d)
222

Description

Description

This happen with the following conditions:

  1. material asset refer texture asset and cubemap asset.
  2. texture asset with negative asset id
  3. cubemap asset loaded after the refered texture asset.

When you load the material asset, the material will miss texture.
Here is a screenshot:

image

Here is the test project and the code snippet:

https://playcanvas.com/project/700222/overview

var textureAsset = new pc.Asset('t', 'texture', { url: 'https://raw.githubusercontent.com/nidorx/matcaps/master/64/28292A_D3DAE5_A3ACB8_818183-64px.png' });
var cubemapAsset = pc.app.assets.list().find(a => a.type === 'cubemap' && !a.loaded);
var materialAsset = new pc.Asset('m', 'material', null, { diffuseMap: textureAsset.id, cubeMap: cubemapAsset.id });
var onLoaded = () => {
    if (textureAsset.loaded && cubemapAsset.loaded && materialAsset.loaded) {
        console.log('texture: ', textureAsset.resource);
        console.log('material.difuseMap', materialAsset.resource.diffuseMap);
        console.log('material.cubeMap', materialAsset.resource.cubeMap);
    }
}

textureAsset.ready(onLoaded);
cubemapAsset.ready(onLoaded);
materialAsset.ready(onLoaded);
pc.app.assets.add(textureAsset);
pc.app.assets.add(materialAsset);
pc.app.assets.load(materialAsset);
Reason

In #3074 , @raytranuk remove the following code:

    _assignTexture(parameterName, materialAsset, texture) {
-        materialAsset.data[parameterName] = texture;
        materialAsset.resource[parameterName] = texture;
    }

In JsonStandardMaterialParser:

 // initialize material values from the input data
 for (const key in data) {
    const type = standardMaterialParameterTypes[key];
    const value = data[key];

    // .......
+    if (type === 'texture') {
+        if (value instanceof Texture) {
+            material[key] = value;
+        } else if (!(material[key] instanceof Texture && typeof(value) === 'number' && value > 0)) {
+            material[key] = null;
+        }
+    }

    // ......
}

The engine will check materialAsset.data's texture type and it may override the texture field to null if the texture asset id is negative.

In MaterialHandler,

_onCubemapLoad(parameterName, materialAsset, cubemapAsset) {
    this._assignCubemap(parameterName, materialAsset, cubemapAsset.resources);
    this._parser.initialize(materialAsset.resource, materialAsset.data);
}

when the cubemap asset loaded, it will call JsonStandardMaterialParser#initialize again, and if the cubemap asset is loaded after the texture asset, it will set the texture field to null.

Maybe this will affect engine user only (like me 😭 ).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/resources/material.js and src/resources/parser/material/json-standard-material.js, then reproduce the failure using the linked project or the JavaScript snippet. Trace material initialization when the cubemap loads after the texture, and consider the issue complete when the material retains its texture and cubemap resources in that order.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
computer-graphics
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.