Mesh with shadow returns different Vector3.Project result in onBeforeDrawObservable

Hi everyone,

I have a piece of work that is using onBeforeDrawObservable of the mesh to check if mesh is inside/outside viewport. It’s been working great until I start to add shadow to mesh.

In this playground Mesh with no shadow when I log the Vector3.Project result in observable, the result is stable no matter where mesh is located (inside or outside of viewport). For example:

...
position e {_isDirty: true, _x: 798.9455910326021, _y: 576.1805893373077, _z: 0.9860939636044204}
position e {_isDirty: true, _x: 798.9455910326021, _y: 576.1805893373077, _z: 0.9860939636044204}
position e {_isDirty: true, _x: 798.9455910326021, _y: 576.1805893373077, _z: 0.9860939636044204}
position e {_isDirty: true, _x: 798.9455910326021, _y: 576.1805893373077, _z: 0.9860939636044204}
...

However when I add shadow to the mesh in this playground Mesh with shadow on, when mesh or/and shadow are inside viewport, Vector3.Project value starts to alternate between 2 different values. For example:

...
position e {_isDirty: true, _x: 375.00002564673196, _y: 776.0707440406622, _z: 0.002290388183970621}
position e {_isDirty: true, _x: 798.9455910326021, _y: 576.1805893373077, _z: 0.9860939636044204}
position e {_isDirty: true, _x: 375.00002564673196, _y: 776.0707440406622, _z: 0.002290388183970621}
position e {_isDirty: true, _x: 798.9455910326021, _y: 576.1805893373077, _z: 0.9860939636044204}
...

It seems that it’s alternating between position of Mesh and shadow? Once mesh and shadow are both outside of viewport, Vector3.Project value starts to be stable value again.

I wonder how I can get correct Vector3.Project value that won’t be affected by shadow postition inside onBeforeDrawObservable?


Updates

Both methods mentioned in the marked solution worked. I chose onBeforeRenderObservable methoed in the project. Thanks!

onBeforeDrawObservable is called each time a mesh (submesh in fact) is drawn. When shadows are visible, the mesh is drawn twice, once in the shadow map and once in the regular rendering pass.

You can check that the current render pass is not the shadow render pass by checking:

if (engine.currentRenderPassId !== shadowGenerator.getShadowMap().renderPassId)
    console.log('position', position)

You can also use onBeforeRenderObservable instead of onBeforeDrawObservable as the former is only called during the regular render pass.

2 Likes