Cannot create property '_needNormals'

Hi:

My project currently use two engine and two scenes,a vue-router is used, to switch canvas and it’s related engine. in each scene there is a disc with mirror texture near the floor, I add mesh to the scene and add it to the mirror. It works fine when staying on one engine(canvas).

The engine runs at background and related to a canvas element which is not in the body. When the vue component mounted, I use engine.registerView(canvas, this.camera, true) to mount it to the new canvas, and engine.unRegisterView(canvas) before unmount.

When I change to another canvas(engine) it works fine, but when I add a mesh(my class automatically add a PBRMaterial to it and add it to mirror renderlist), it throws error like below, and the canvas become static:

Uncaught TypeError: Cannot create property '_needNormals' on string '#define SM_LIGHTTYPE_DIRECTIONALLIGHT
#define SM_FLOAT 1
#define SM_ESM 0
#define SM_DEPTHTEXTURE 1
#define SM_NORMALBIAS 0
#define SM_DIRECTIONINLIGHTDATA 1
#define SM_USEDISTANCE 0
#define SM_SOFTTRANSPARENTSHADOW 0
#define SM_DEPTHCLAMP 1
#define NUM_BONE_INFLUENCERS 0'
    at PBRMaterial._prepareDefines (pbrBaseMaterial.ts:1525:17)
    at PBRMaterial._prepareEffect (pbrBaseMaterial.ts:1236:14)
    at PBRMaterial.isReadyForSubMesh (pbrBaseMaterial.ts:1173:27)
    at Mesh.render (mesh.ts:1962:31)
    at SubMesh.render (subMesh.ts:427:29)
    at RenderingGroup._RenderSorted (renderingGroup.ts:275:21)
    at RenderingGroup._renderOpaqueSorted (renderingGroup.ts:205:31)
    at RenderingGroup.render (renderingGroup.ts:144:18)
    at RenderingManager.render (renderingManager.ts:217:28)
    at MirrorTexture._renderToTarget (renderTargetTexture.ts:1234:36)
Uncaught TypeError: Cannot create property '_needNormals' on string '#define SM_LIGHTTYPE_DIRECTIONALLIGHT
#define SM_FLOAT 1
#define SM_ESM 0
#define SM_DEPTHTEXTURE 1
#define SM_NORMALBIAS 0
#define SM_DIRECTIONINLIGHTDATA 1
#define SM_USEDISTANCE 0
#define SM_SOFTTRANSPARENTSHADOW 0
#define SM_DEPTHCLAMP 1
#define NUM_BONE_INFLUENCERS 0'
    at PBRMaterial._prepareDefines (pbrBaseMaterial.ts:1525:17)
    at PBRMaterial._prepareEffect (pbrBaseMaterial.ts:1236:14)
    at PBRMaterial.isReadyForSubMesh (pbrBaseMaterial.ts:1173:27)
    at Mesh.render (mesh.ts:1962:31)
    at SubMesh.render (subMesh.ts:427:29)
    at RenderingGroup._RenderSorted (renderingGroup.ts:275:21)
    at RenderingGroup._renderOpaqueSorted (renderingGroup.ts:205:31)
    at RenderingGroup.render (renderingGroup.ts:144:18)
    at RenderingManager.render (renderingManager.ts:217:28)
    at Scene._renderForCamera (scene.ts:3630:32)

when I turn off the mirror, only the second error is reproduced.

Can I know how to fix it, or how can I catch the problem?

and this is my containerManager class, when an assetContainer is passed to the constructor, it works like this:

   for (const mesh of container.meshes) {
            mesh.receiveShadows = true;
            mesh.visibility = 0;
            mesh.alwaysSelectAsActiveMesh = true;
            if (USE_MIRROR) {
                this.mgr.mirrorRenderList.push(mesh); // this is the renderlist the mirrorTexture used.
            }
            if (mesh.material && mesh.material.name == GLTF_DEFAULT_MATERIAL_NAME) {
                mesh.material = this.mgr.defaultMat; // this is the shared PBRMaterial
            }
            mesh.metadata = {
                ...mesh.metadata,
                type: 'soulNode',
                mgr: this,
            };
            mesh.overlayColor = Color3.Green();
            mesh.overlayAlpha = 0.1;
        }

Unfortunately, it will be difficult to help without a repro…

It seems the problem is related to the shadow shader: are you using the ShadowDepthWrapper class to wrap an existing PBR material for shadow rendering? If yes, you could try to create the ShadowDepthWrapper instance(s) with a small delay (using a setTimeout call) and see if that helps.

Hi:
I’m sorry for not providing a reproduce because the PG seems not sufficient for two engines.
But relax, my problem only happens during my project’s refactoring stage.

I tried the ShadowDepthWrapper method but seems no use.

And later I tried to reuse the former engine like:

let engine:Engine;
if (EngineStore.lastCreatedEngine) {
    engine = EngineStore.lastCreatedEngine;
}
else {
    engine = new Engine(nullCanvas,false, {blablabla})
}

The errors are gone, but the render result is glitched: it contains contents in the scene I last used (the last scene is not detached?).

Hope I provided some clue :slight_smile:

Can you refactor to have a single engine but register two views, one for each canvas? Why do you need to have two engine instances?

that is why I said relax it only happens during refactoring :slight_smile: during the refactor both new and old codes are used.
It will be fine when the full refactor is finished (then all views will use a single engine, like before the refactor).