What can't be safely changed when freezing materials

Playing around with freezing materials and seeing some weirdness when freezing materials and using video texture. I created a PG that switches between a webcam video texture and a default texture. If I freeze the materials, then the webcam texture is upside down, but if I don’t, then it is correct. I even tried unfreezing right before swapping the texture and refreezing after swapping and it made no difference.

Why is freeze preventing the texture from flipping correctly in this case and where do I need to unfreeze in order to prevent it?

cc @sebavan

We have an open issue to improve support for frozen materials:

I added your PG to the list.

As a workaround, you can either freeze again after a certain delay, to give the system time to compile the new effect:

const toggleVideo = async (scene) => {
    baseAvatar.material.unfreeze();
    if (!videoState) {
        await enableWebcam(scene);
    } else {
        disableWebcam();
    }

    window.setTimeout(() => {
        baseAvatar.material.freeze();
    }, 100);
}

Or to avoid depending on an arbitrary timeout value, you can detect when things are ready to be frozen again:

const toggleVideo = async (scene) => {
    baseAvatar.material.unfreeze();
    if (!videoState) {
        await enableWebcam(scene);
    } else {
        disableWebcam();
    }
    const e1 = baseAvatar.subMeshes[0].effect;

    const freezeWhenReady = () => {
        const e2 = baseAvatar.subMeshes[0].effect;
        if (e2 !== e1 && e2.isReady()) {
            baseAvatar.material.freeze();
        } else {
            window.setTimeout(freezeWhenReady, 0);
        }
    };

    freezeWhenReady();
}
2 Likes

Thank you for the workaround.

1 Like

@Evgeni_Popov What specifically needs the material to be unfrozen? Adjusting the UVs? Adding a video texture?

I don’t really have a list of what does and doesn’t work in frozen mode. A list would certainly help, but we would probably forget some cases as it’s possible to change a lot of things wrt a material…

Setting a new texture should work, even if it’s a video (what does not work in your example is the vScale=-1 part, not the texture itself).

@Evgeni_Popov I’m running into a situation in our production code where e1 is never not equal to e2. I’m guessing this occurs when a material update is not required or maybe has already happened by the time I get e1? Can I use onCompiled or a dirty flag to tell when the material has been updated?

You have the onEffectCreatedObservable which will tell you when an effect is “created” for a material. However, “created” here can mean “retrieved from cache”, if the effect we need already exists. Perhaps you can try to take advantage of this observable?

That didn’t work any better. I just ended up limiting the loop to 1 sec and that works well.