# Proper way to update an assigned (PBR) material

**URL:** <https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451>\
**Category:** Questions\
**Tags:** material\
**Created:** [January 17, 2023, 10:23am UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451 "2023-01-17T10:23:10Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![paleRider](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/palerider/32/7774_2.png) [@paleRider](https://forum.babylonjs.com/u/paleRider)\
**Post date:** [January 17, 2023, 10:23am UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/1 "2023-01-17T10:23:10Z")

</div>

Good morning:

In my scene, I need to update a specific material, that comes within a GLTF I’ve just imported.

The case is that, if I traverse the different channels, updating each one at a time, a visible artifact (blink-like) happens in the 3d model. Under this strategy, maybe the **atomicMaterialsUpdate** API can help here, but sadly I can’t find any example of use of PG about.

This said, I thought a complementary (better) approach would be to have a fully-updated backup material, and swap it with the active one by means of a unique assignation, but sadly `scene.getMaterialByName("myMateriaNameHerel")=baclupMaterial` throw an “_ **invalid assignment left-hand side** _” exception.

I’ve reviewed de **Scene** and **Material** APIs, but none of them seems to fit my needs, so any help on would be really very appreciated.

Thanks in advance for your time.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [January 17, 2023, 10:51am UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/2 "2023-01-17T10:51:23Z")

</div>

There should be no blinking if you are using WebGL2, because we are using parallel shader compilation and don’t update the current material (effect) until the new effect is compiled when you change some properties of the material that lead to the creation of a new effect.

Would you be able to setup a repro in the Playground so that we can better help?

Regarding `atomicMaterialsUpdate`, here’s the doc:

> **[Material | Babylon.js Documentation](https://doc.babylonjs.com/typedoc/classes/BABYLON.Material#atomicMaterialsUpdate)**
>
> Base class for the main features of a material in Babylon.js \[API\]

However, I don’t think it will help with your problem at hand.

> [@paleRider](#):
>
> scene.getMaterialByName(“myMateriaNameHerel”)

What you want to do is update the `mesh.material` property of all the meshes for which you want to change the material.

---

<div class="post-metadata">

**Author:** ![paleRider](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/palerider/32/7774_2.png) [@paleRider](https://forum.babylonjs.com/u/paleRider)\
**Post date:** [January 17, 2023, 11:10am UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/3 "2023-01-17T11:10:49Z")

</div>

Hi @Evgeni_Popov:

I see, it’s then a misunderstanding here. I supposed it would exist a way to update the material and automatically have it propagated along all meshes using it.

Thanks for your time.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [January 17, 2023, 11:57am UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/4 "2023-01-17T11:57:14Z")

</div>

> [@paleRider](#):
>
> I supposed it would exist a way to update the material and automatically have it propagated along all meshes using it.

If you update an existing material, then yes it will be propagated to all meshes that use this material as you don’t change the `material` property. But if you create a new material, then you will have to loop over all the meshes to change it.

---

<div class="post-metadata">

**Author:** ![paleRider](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/palerider/32/7774_2.png) [@paleRider](https://forum.babylonjs.com/u/paleRider)\
**Post date:** [January 17, 2023, 12:57pm UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/5 "2023-01-17T12:57:15Z")

</div>

Hi there, @Evgeni_Popov:

Ok, taking this [PG](https://playground.babylonjs.com/#R2XMCV#5) as example, the central point here is that, in the aim to go the more efficient way (I mean with a whole-material-update API callI), I was hoping to be able to use the **offendingMaterialUpdate** method (lines 49 to 58), but instead it’s necessary the **workingMaterialUpdate** one.

BTW, as you can see, in order to “dispose” the PBR channels attached to a texture, I’ve assigned them straightforward to “null”, but maybe that is not the more convenient way, isn’t it?

Thanks for your time.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [January 17, 2023, 1:28pm UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/6 "2023-01-17T13:28:59Z")

</div>

You can implement the `offendingUpdateMaterial` function like this:

> **[Babylon.js Playground](https://playground.babylonjs.com/#R2XMCV%236)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

> [@paleRider](#):
>
> BTW, as you can see, in order to “dispose” the PBR channels attached to a texture, I’ve assigned them straightforward to “null”, but maybe that is not the more convenient way, isn’t it?

This is the right way to do it!

---

<div class="post-metadata">

**Author:** ![paleRider](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/palerider/32/7774_2.png) [@paleRider](https://forum.babylonjs.com/u/paleRider)\
**Post date:** [January 17, 2023, 2:42pm UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/7 "2023-01-17T14:42:06Z")

</div>

Thanks again, @Evgeni_Popov, for the immediate response:

As a final request, regarding both your brand-new version of **offendigUpdateMaterial** and my **workingUpdateMaterial** , what would you recommend to use?

I’ve carried out a very simplistic (and maybe misleading) test with the help of console.time (of course, very rough tool) and obtaining an average (throught 10 executions) of:

- **workingUpdateMaterial** : ~1ms
- (no longer) **offendingUpdateMaterial** : ~3ms

> **[Babylon.js Playground](https://playground.babylonjs.com/#R2XMCV%239)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

Despite the much more speed in the **workingUpdateMaterial** , are there any others considerations you can foresee that discourage its use?

Thanks for your time.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [January 17, 2023, 6:37pm UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/8 "2023-01-17T18:37:25Z")

</div>

Updating an existing material is probably better as it will save a little bit of memory. But I would not worry about the timings, as I don’t think you will be using those functions so many times in the course of your program?

---

<div class="post-metadata">

**Author:** ![paleRider](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/palerider/32/7774_2.png) [@paleRider](https://forum.babylonjs.com/u/paleRider)\
**Post date:** [January 18, 2023, 7:02am UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/9 "2023-01-18T07:02:23Z")

</div>

Thanks, @Evgeni_Popov:

Bringing the things just a little further, trying to update the PBR channels by means of their attached textures, something is not working here, as I get an exception raised from `uniformBuffers.updateColor4ForUniform`:

> **[Babylon.js Playground](https://playground.babylonjs.com/#R2XMCV%2313)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

What is happening here?

Again, thank you very much for your time and advices.

P.S: Please note that it fails with both methods: **updatetextredMaterialFromAux** and **updateTexturedMaterial**.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [January 18, 2023, 10:03am UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/10 "2023-01-18T10:03:52Z")

</div>

You forgot the `new` keyword on line 99:

```auto
    mat.albedoColor = BABYLON.Color3(1.0, 1.0, 1.0);

```

---

<div class="post-metadata">

**Author:** ![paleRider](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/palerider/32/7774_2.png) [@paleRider](https://forum.babylonjs.com/u/paleRider)\
**Post date:** [February 28, 2023, 1:32pm UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/11 "2023-02-28T13:32:55Z")

</div>

Hi there, @Evgeni_Popov:

I’ve opted for re-living this thread, as my question is indeed closely related to the subject.

You said that no blinking should happen when updating channel textures of a PBR material, isn’t it? But the case is that, I’m experimenting such a behavior, as you can see in [this PG](https://playground.babylonjs.com/#R2XMCV#25).

So, I wonder is there any “swap” technique more appropriate to implement this. In order to avoid or soften that not very aesthetic behavior, I mean.

Thanks for your time.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [February 28, 2023, 2:54pm UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/12 "2023-02-28T14:54:34Z")

</div>

You should wait for both the textures to be loaded and the effect to be ready. `Scene.executeWhenReady` will help you for the effect part:

> **[Babylon.js Playground](https://playground.babylonjs.com/#R2XMCV%2326)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

You should use `texture.onLoadedObservable` instead of using a timeout to detect that a texture is loaded, but the timeout way is easier for a PG!

---

<div class="post-metadata">

**Author:** ![paleRider](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/palerider/32/7774_2.png) [@paleRider](https://forum.babylonjs.com/u/paleRider)\
**Post date:** [February 28, 2023, 7:06pm UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/13 "2023-02-28T19:06:00Z")

</div>

Hi, @Evgeni_Popov; and as always, thanks for your immediate response.

The case with the suggested `texture.onLoadedObservable` is that it seems to not being defined, as you can see in this new version of the [PG](https://playground.babylonjs.com/#R2XMCV#32).

What am I doing wrong there?

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [February 28, 2023, 7:55pm UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/14 "2023-02-28T19:55:39Z")

</div>

Sorry, it is named `onLoadObservable`.

---

<div class="post-metadata">

**Author:** ![paleRider](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/palerider/32/7774_2.png) [@paleRider](https://forum.babylonjs.com/u/paleRider)\
**Post date:** [March 1, 2023, 8:49am UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/15 "2023-03-01T08:49:20Z")

</div>

Thanks, @Evgeni_Popov:

It worked like a charm.

Anyway, I see now in the docs that the `Texture` class constructor let as also provide, as its sixth parameter, an `onLoad` callback.

So I think it could be a more appropriate (compact) way to implement all this, avoiding the use of observables.

In such a case, what are the “recommended” values I must have here for the parameters: `noMipmapOrOptions` and `samplingMode`?

Thanks for your time.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [March 1, 2023, 10:23am UTC](https://forum.babylonjs.com/t/proper-way-to-update-an-assigned-pbr-material/37451/16 "2023-03-01T10:23:54Z")

</div>

You generally want mipmaps as it improves the rendering and performances, so `noMipmap=false` and `samplingMode = BABYLON.Constants.TEXTURE_TRILINEAR_SAMPLINGMODE` (those are the default values for these parameters).
