# Sharing one material across multiple objects using onBeforeRender()

**URL:** <https://discourse.threejs.org/t/sharing-one-material-across-multiple-objects-using-onbeforerender/12640>\
**Category:** Questions\
**Tags:** textures, materials\
**Created:** [February 10, 2020, 3:49pm UTC](https://discourse.threejs.org/t/sharing-one-material-across-multiple-objects-using-onbeforerender/12640 "2020-02-10T15:49:07Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![ECI-YC](https://avatars.discourse-cdn.com/v4/letter/e/439d5e/32.png) [@ECI-YC](https://discourse.threejs.org/u/ECI-YC)\
**Post date:** [February 10, 2020, 3:49pm UTC](https://discourse.threejs.org/t/sharing-one-material-across-multiple-objects-using-onbeforerender/12640/1 "2020-02-10T15:49:07Z")

</div>

Title says it all - I want to set up one copy of MeshStandardMaterial and assign it to a number of objects, then let each object set its own color, textures, etc before being drawn. I figure this is a little tidier than doing all my setup for each and every material, as I’m injecting shader code like [BPCEM](https://threejs.org/examples/#webgl_materials_envmaps_parallax) and I worry that my myriad materials won’t share the same shader code unless I force them to.

Doesn’t seem to work!

What I’m seeing is every object with the material takes on the properties set by whichever one is drawn last (closest to the camera). My hunch is I’m probably misunderstanding the purpose of onBeforeRender(), and that it doesn’t work in-between draw calls because then the GPU would have to start drawing, stop drawing, start drawing, stop drawing, etc. If that’s the case, makes sense, all good.

But if what I’m trying to do is possible, can anyone point me in the right direction? Also, would this save performance vs one material per object?

---

<div class="post-metadata">

**Author:** ![Mugen87](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/mugen87/32/5645_2.png) [@Mugen87](https://discourse.threejs.org/u/Mugen87)\
**Post date:** [February 11, 2020, 9:48am UTC](https://discourse.threejs.org/t/sharing-one-material-across-multiple-objects-using-onbeforerender/12640/2 "2020-02-11T09:48:05Z")

</div>

What you are trying to do is not yet possible. At least with built-in materials. More details in this thread:

> <https://github.com/mrdoob/three.js/issues/9870>
>
> Description of the problem
> onBeforeRender was added as a solution for #9662
> Unfortunately, because of the way setProgram works in THREE.WebGLRenderer, uniform changes...

However, if you are using `ShaderMaterial`, it is possible via `uniformsNeedUpdate` to force a uniform update in `onBeforeRender()`.

I’m not sure it’s worth to add this option for `MeshStandardMaterial` since the benefits are minor. `three.js` always tries to determine if it’s possible to share shader programs across materials. Because of this feature, you don’t save state changes by using `uniformsNeedUpdate` and thus don’t have a better performance. You only save a bit of RAM, that’s all.

---

<div class="post-metadata">

**Author:** ![Fyrestar](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/fyrestar/32/52793_2.png) [@Fyrestar](https://discourse.threejs.org/u/Fyrestar)\
**Post date:** [February 11, 2020, 10:17am UTC](https://discourse.threejs.org/t/sharing-one-material-across-multiple-objects-using-onbeforerender/12640/3 "2020-02-11T10:17:23Z")

</div>

You might give this plugin a try

> [@Chainable onBeforeCompile + Uniforms per Mesh](https://discourse.threejs.org/t/chainable-onbeforecompile-uniforms-access-per-mesh/8905):
>
> This little code will patch all material classes to have a chainable onBeforeCompile pattern, so when you assign a callback to onBeforeCompile it will be pushed into a plugins array property on the material instead overriding it. Assign null to reset or use removePlugin to remove a specific. Also addPlugin (same as assining) and hasPlugin is available. It doesn’t break the API and works without core modification, so WebGLPrograms.js will get a combined string of all functions. You can also set…

The uniforms per mesh part allows you to change uniforms for each mesh individually.

---

<div class="post-metadata">

**Author:** ![mch](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/mch/32/21493_2.png) [@mch](https://discourse.threejs.org/u/mch)\
**Post date:** [October 11, 2021, 10:23am UTC](https://discourse.threejs.org/t/sharing-one-material-across-multiple-objects-using-onbeforerender/12640/4 "2021-10-11T10:23:32Z")

</div>

> [@Mugen87](#):
>
> However, if you are using `ShaderMaterial` , it is possible via `uniformsNeedUpdate` to force a uniform update in `onBeforeRender()` .

I’m facing the same request as the original post : I have hundreds of Points objects that share the same material but I would like to update one uniform value per Point object.

Do you have an example code for `uniformsNeedUpdate` and `onBeforeRender()` please ?

---

<div class="post-metadata">

**Author:** ![Mugen87](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/mugen87/32/5645_2.png) [@Mugen87](https://discourse.threejs.org/u/Mugen87)\
**Post date:** [October 11, 2021, 10:49am UTC](https://discourse.threejs.org/t/sharing-one-material-across-multiple-objects-using-onbeforerender/12640/5 "2021-10-11T10:49:10Z")

</div>

> [@mch](#):
>
> Do you have an example code for `uniformsNeedUpdate` and `onBeforeRender()` please ?

Yes, the `Lensflare` class uses the flag in its `onBeforeRender()` implementation.

> <https://github.com/mrdoob/three.js/blob/cf2905626a3d23fa0a1445f236064157c742b03f/examples/jsm/objects/Lensflare.js#L248>

---

<div class="post-metadata">

**Author:** ![davcri](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/davcri/32/15926_2.png) [@davcri](https://discourse.threejs.org/u/davcri)\
**Post date:** [April 21, 2023, 8:38am UTC](https://discourse.threejs.org/t/sharing-one-material-across-multiple-objects-using-onbeforerender/12640/6 "2023-04-21T08:38:54Z")

</div>

> `three.js` always tries to determine if it’s possible to share shader programs across materials

Sorry for commenting an old post, but I was wondering: how does this work exactly?  
PS: thanks for providing all these useful insights 🙂
