Hi, I know this has been covered before, but I can’t get any of the examples to work. I have a bunch of meshes and I’m trying to smoothly fade out all but one (the parent of the entity the script is attached to). My code here complains that I shouldn’t used a function within a loop. I’m not sure how to do this. Any advice gratefully received . Thank You!
//fade out layers that are not used
Hotspot.prototype.fadeOutUnusedLayers = function ()
{
console.log("FADING LAYERS");
aplha=1;
for(x=0;x<this.explode_layers.length > 0;x++)
{
//only fade out OTHER layers, not this one
if(this.explode_layers[x]!=this.entity.parent)
{
var data = {
opacity: 1
};
var material = this.explode_layers[x].model.material;
this.app
.tween(data)
.to({opacity: 0.0}, 1.0, pc.Linear)
.on('update', function () {
// alpha is called opacity in Playcanvas
material.opacity = data.opacity;
material.update();
})
.start();
}
}
};
Hi, yes I saw that project and I’ve tried to replicate it using just a basic switch to change the opacity to 0.5 but nothing happens (no errors etc). All the materials have blend mode alpha set.Here is the code:
//fade out layers that are not used
Hotspot.prototype.fadeOutUnusedLayers = function ()
{
console.log("FADING LAYERS");
aplha=1;
this.explode_layers=this.app.root.findByTag("explode_layer");
for(x=0;x<this.explode_layers.length > 0;x++)
{
//only fade out OTHER layers, not this one
if(this.explode_layers[x]!=this.entity.parent)
{
var meshInstances = this.explode_layers[x].model.meshInstances;
for(var i = 0; i < meshInstances.length; ++i)
{
meshInstances[i].setParameter("material_opacity", 0.5);
}
console.log("FADING LAYER " +x);
}
}
};
Can you try setting the initial opacity of your materials in something different than 1.0? Much like the example project does, that will force the engine to include the opacity shader chunk, in case that missing is the issue.
Edit: removed part of the photo to not show the product, in case that’s not allowed for you.
Thanks. Well, I’ve been trying this but I still cant get anything at all to work using the tween library. I want to use the tween library because its supposedly easier to manage(!?)
Here is what I have, but nothing happens…
I cant believe its taken me all day on this and Im still no closer to fading out a model. I’d hoped this would be a simple one liner like myEntity.fadeAlpha(1.0,0,1.0). It seems like a massive waste of energy.
Hotspot.prototype.fadeOutUnusedLayers = function ()
{
console.log("FADING LAYERS");
this.explode_layers=this.app.root.findByTag("explode_layer");
//aplha=1;
for(x=0;x<this.explode_layers.length > 0;x++)
{
//only fade out OTHER layers, not this one
if(this.explode_layers[x]!=this.entity.parent)
{
var data = {
opacity: 1
};
var material = this.explode_layers[x].model.material;
this.doFadeOut(data,material);
}
}
};
Hotspot.prototype.doFadeOut = function (data,material)
{
this.app
.tween(data)
.to({opacity: 0.0}, 1.0, pc.Linear)
.on('update', function () {
// alpha is called opacity in Playcanvas
material.opacity = data.opacity;
material.update();
})
.start();
};
Looks right, though I can’t test right now. I’ll try later to update the standard fade in out example to use a tween.
In the meantime I would try to debug the data.opacity value inside the tween update method. Try and see if the issue is with the tween or the material.
Thanks, I noticed that additionally when I set the alpha it doesn’t affect the existing shadows of the model (I would expect them to share the same alpha value). Do I need to do this separately somehow?
Of course, this is fairly trivial when the object has only one material. I’ve always thought it odd that PlayCanvas doesn’t have an object level dissolve as is common in many 3D rendering applications.
I ended up writing a script to serve that function. But my 3D animation experience still leaves me thinking this should be an application level function.
So the tween project I’ve posted will work with no change for models with multiple materials, since it loops through the available mesh instances.
Though you will still have to prepare each material to include the opacity shader chunk. On that subject agreed, that could be simplified. Try posting a feature request about it in the engine repo.
Ah - I just ran the project and didn’t look closely at the script.
Yes, you need to deal not only with making sure the materials have the opacity shader chunk, but you need to consider what the original material opacity was. If your object has windows at 60% opacity, fully fading in the object would mean restoring the window to 60% opacity, not 100%.
The following is (I think) the current version of my objectFade.js. You apply it to the entity and then typically would manipulate the object’s opacity via a tween.
//// Version 4.0
//// Provides a way to set opacity for all materials on a specific object independly of other objects using a single variable.
//// Children must have a different name than the name of the main parent entity that this script is attached to.
//// Usage: Add this script to an entity that has a model component.
//// Initial Opacity is the object opacity that will be used when the object is first loaded.
//// Object Opacity is the opacity of the object after the initial load. This can be changed either in Editor of by using a script (such as with a tween).
//// Both of the above two values are values that are multiplied by the object meshInstance's material opacity value.
//// This allows the script to proportionally fade and restore surfaces that start with partial transparency.
//// Example tween:
// this.tween = this.someEntity.tween(this.someEntity.script.objectFade).to({opacity: 0}, 1, pc.SineInOut)
// //.yoyo(true).repeat(10) // unremark to fade up and down five times
// .delay(0);
// this.tween.start();
//// Directly set opacity like this:
// this.someentity.script.objectFade.opacity = 0.75;
var objectFade = pc.createScript('objectFade');
objectFade.attributes.add('initialOpacity', {
title: 'Initial Opacity',
type: 'number',
default: 1
});
objectFade.attributes.add('opacity', {
title: 'Object Opacity',
type: 'number',
default: 1
});
// Determines if the child objects will inherit the opacity setting or not.
objectFade.attributes.add('inherit', {
title: 'Inherit Opacity',
type: 'boolean',
default: true
});
// Forces all materials to have the "Alpha to Coverage" setting as true. This will apply to all children objects/materials if "Inherit Opacity" is true.
objectFade.attributes.add('alpha2cover', {
title: 'Alpha to Coverage',
type: 'boolean',
default: true
});
// initialize code called once per entity
objectFade.prototype.initialize = function() {
//this.initialOpacity = 0.999;
this.previousOpacity = undefined;
this.opacityFactor = undefined;
this.miStep = 0;
this.chiStep = 0;
this.toggle = false;
this.rootName = undefined;
};
objectFade.prototype.objectFade = function () {
};
// update code called every frame
objectFade.prototype.update = function(dt) {
// Ensures that all the meshInstance materials have some transparency and a blendType
if(this.entity.model.meshInstances[0].parameters.material_opacity === undefined){
for (this.miStep = 0; this.miStep < this.entity.model.meshInstances.length; ++this.miStep){
this.opacityFactor =this.entity.model.meshInstances[this.miStep].material.opacity;
this.entity.model.meshInstances[this.miStep].material.opacity = (this.opacityFactor * 0.999999);
this.entity.model.meshInstances[this.miStep].material.blendType = pc.BLEND_NORMAL;
this.entity.model.meshInstances[this.miStep].material.update();
this.previousOpacity = this.initialOpacity;
this.opacity = this.initialOpacity;
this.entity.model.meshInstances[this.miStep].setParameter('material_opacity', (this.opacity * this.opacityFactor));
}
if(this.inherit === true){
this.entity.forEach(function (node) {
if(node.model && node.name !== this.entity.name){
//console.log('all children', node.name);
var meshInstances = node.model.meshInstances;
for (this.miStep = 0; this.miStep < meshInstances.length; this.miStep++){
var material = meshInstances[this.miStep].material;
if( ! material) continue;
//console.log('material', material.name);
this.opacityFactor = material.opacity;
material.opacity = (this.opacityFactor * 0.999999);
if(this.alpha2cover === true){
material.alphaToCoverage = true;
}
material.blendType = pc.BLEND_NORMAL;
material.update();
this.opacity = this.initialOpacity;
node.model.meshInstances[this.miStep].setParameter('material_opacity', (this.opacity * this.opacityFactor));
}
}
}, this);
}
}
if(this.previousOpacity === this.opacity){
//do nothing
}else{
this.miStep = 0;
for (this.miStep = 0; this.miStep < this.entity.model.meshInstances.length; ++this.miStep){
this.opacityFactor = this.entity.model.meshInstances[this.miStep].material.opacity;
this.entity.model.meshInstances[this.miStep].setParameter('material_opacity', (this.opacity * this.opacityFactor));
}
if (this.inherit === true){
this.entity.forEach(function (node2) {
if(node2.model && node2.name !== this.entity.name){
//console.log('all children', node2.name);
var meshInstances2 = node2.model.meshInstances;
for (this.miStep = 0; this.miStep < meshInstances2.length; this.miStep++){
var material2 = meshInstances2[this.miStep].material;
if( ! material2) continue;
//console.log('material2', material2.name);
this.opacityFactor = material2.opacity;
node2.model.meshInstances[this.miStep].setParameter('material_opacity', (this.opacity * this.opacityFactor));
}
}
}, this);
}
}
this.previousOpacity = this.opacity;
};