playcanvas / playcanvas/engine
Material asset miss texture asset after v1.40.5+ engine
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 16.8k
- Forks
- 2k
- Avg merge
- 4h 32m
- Merged PRs (30d)
- 222
Description
Description
This happen with the following conditions:
- material asset refer texture asset and cubemap asset.
- texture asset with negative asset id
- cubemap asset loaded after the refered texture asset.
When you load the material asset, the material will miss texture.
Here is a screenshot:

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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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