Update uniforms in onBeforeRenderObservable call back

Hi All,

I was trying to create a render buffer where I can for example, just write some data for each mesh. For this, I use a MultiRenderTarget.
Now in onBeforeRender of the renderTarget, I assign a unique custom shader material for each mesh, and restore the original material back later in onAfterRender.
Then using onBeforeRenderObservable callback available on a mesh, I assign some uniforms to the custom material.

All of this works fine.
But I wanted to optimize this, and rather than creating a custom material for each mesh, I want to have a single custom material, and just change the uniforms before rendering the mesh.
However this doesn’t really work.
So my question is, how can I tell babyloneJS to update/refresh uniforms of a material before rendering the mesh.

Thanks

You can use the material.onBindObservable for that: the observer is called with the mesh currently processed.

Thanks for your reply!

I tried that, but it dosent work.
it appears that this callback is called once per material bind, and so in the callback I always get the same mesh, because the material is shared for all meshes.
The onBeforeRenderObservable was called with each mesh, but then the issue is that uniforms are not updating.
Like this::

let beforeRender = (mesh:BABYLON.Mesh) => {
maskData.x = (mesh as any).matid;

        (mesh.material as any).setVector4('maskData', maskData);

}

The idea is to create one instance of the material per set of parameters so onBind would work as expected. Think as the material as holding the parameter and pointing to a shader. So even if you have several materials, you should still be able to only have one shader.

It is actually exactly how most scene works today. each new config of a metarial makes us create a new one :slight_smile:

You must have a problem somewhere, you do get the right mesh in the callback:

The ground and sphere share the same shader material, and I change the color in the onBindObservable observer depending on the mesh.

2 Likes

Arh, I got it working now.

I was setting the data like this::
this.maskMaterial_.setVector4(‘maskData’, maskData);

But the way you did
this.maskMaterial_.getEffect().setVector4(‘maskData’, maskData);

I am new to BabyloneJS, so not sure whats the difference.

But many thanks for your reply and solution!!