Open yaustar opened 3 years ago
The issue seems to be around these 2 lines in image-element.js
when assigning a new material
to the element: https://github.com/playcanvas/engine/blob/master/src/framework/components/element/image-element.js#L986
...
// if this is not the default material then clear color and opacity overrides
if (this._hasUserMaterial()) {
this._renderable.deleteParameter('material_opacity');
this._renderable.deleteParameter('material_emissive');
}
...
The material that you are setting is a clone from the StandardMaterial, so even though it is technically a "user material" (not the default one), it still requires those 2 parameters. A temporary workaround is to manually re-set those values after you set the element's material, but please note that the following code uses private APIs.
...
this.entity.element._image._renderable.setParameter('material_opacity', 1);
this.entity.element._image._renderable.setParameter('material_emissive', [1, 1, 1]);
A slightly better client-side workaround is to trigger a call that also resets those values, such as:
...
this.entity.element.opacity = 0;
this.entity.element.opacity = 1;
this.entity.element.color = new pc.Color(0, 0, 0);
this.entity.element.color = new pc.Color(1, 1, 1);
Or:
...
var texture = this.entity.element.texture;
this.entity.element.texture = null;
this.entity.element.texture = texture;
There are multiple other references to those two parameters (material_opacity
and material_emissive
), so I'll dig deeper in order to find a more elegant approach on the engine side. I'll keep this thread updated.
As mentioned in AliMoe's post, the default UI material that the code is cloning from defines non-default emissive and opacity values (on _createBaseImageMaterial
). The reason this was done is so that the shader compiler doesn't optimise those values out. When you do this.entity.element.opacity
or .color
, you are not setting the material
parameters, but
rather the meshInstance
's (which overrides the material's).
So actually the best way to deal with this is to set the opacity and emissive parameters directly on the cloned material, like so:
...
material.emissive.set(1, 1, 1);
material.opacity = 1;
material.update();
This will avoid having to deal with custom mesh instances overrides, and resetting to different values before setting to the values you actually want. We're still looking into a better engine-side fix.
Did reach a conclusion or fix for this in the end?
From the duplicate ticket:
Repro: https://playcanvas.com/editor/scene/1331078
Launch the project and the image element will not be shown
This is due to when a material is set on the element, two parameters are deleted: https://github.com/playcanvas/engine/blob/dev/src/framework/components/element/image-element.js#L980
After talking to @jpauloruschel, we think that the best route to go here is in this check, also check if the material has the same parameters used in the default image element material (material_emissive and material_opacity) and if so, set those parameters on the renderable. If not, then delete the parameters.
Workaround for now is to dirty the color and opacity values:
// Dirty the element to reapply values to parameters to the renderable mesh var tempColor = this.entity.element.color.clone(); this.entity.element.color = new pc.Color(tempColor.r, tempColor.g + 0.01, tempColor.b); this.entity.element.color = tempColor; var tempOpacity = this.entity.element.opacity; this.entity.element.opacity = 0; this.entity.element.opacity = tempOpacity;
Repro: https://playcanvas.com/editor/project/836052 Forum: https://forum.playcanvas.com/t/ui-elements-are-not-being-rendered-after-cloning-material/22214