# Instancing a mesh with shaderMaterials

**URL:** <https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782>\
**Category:** Questions\
**Tags:** material, shader\
**Created:** [May 12, 2020, 4:41pm UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782 "2020-05-12T16:41:51Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![lasse](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/lasse/32/8398_2.png) [@lasse](https://forum.babylonjs.com/u/lasse)\
**Post date:** [May 12, 2020, 4:41pm UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782/1 "2020-05-12T16:41:51Z")

</div>

Hi ya all, I wanted to use instances for every possible mesh in my scene and encountered some problems on the way. If you have a Mesh with a custom shader instancing isn’t working flawless, i already found some post and got that i have to adjust the custom shader, but i can’t figure out how. Here is the cutom vertexShader used in this case:

```
// Precision
	+ 'precision highp float;\r\n'
	// Attributes
	+ 'attribute vec3 position;\r\n'
	+ 'attribute vec2 uv;\r\n'
	// Uniforms
	+ 'uniform mat4 world;\r\n'
    + '#include<instancesDeclaration>\r\n'
	+ 'uniform mat4 worldViewProjection;\r\n'
	// Varying
	+ 'varying vec2 vUV;\r\n'
	// MAIN
	+ 'void main(void) {\r\n'
    + '#include<instancesVertex>\r\n'
	+ ' vec4 p = vec4(position, 1.0);\r\n'
	+ ' gl_Position = worldViewProjection * finalWorld * p;\r\n'
	+ ' vUV = uv;\r\n'
	+ '}\r\n';

```

I basically just added the two includes and multiplied worldViewProjection by finalWorld, but i have no idea where this value comes from.  
And the fragmentShader:

```
// Precision
+ 'precision highp float;\r\n'
// Varying
+ 'varying vec2 vUV;\r\n'
// Uniforms - Diffuse
+ 'uniform sampler2D diffuseTexture;\r\n'
// MAIN
+ 'void main(void) {\r\n'
+ ' gl_FragColor = texture2D(diffuseTexture, vUV);\r\n'
+ '}\r\n';

```

And here the shaderMaterial gets created:

```
const material = new ShaderMaterial(
	mesh.name + '-material',
	scene,
	{
		vertexElement: 'custom',
		fragmentElement: 'custom'
	},
	{
		attributes: ['position', 'uv', 'normal', 'world0', 'world1', 'world2', 'world3'],
		uniforms: ['world', 'worldViewProjection'],
		needAlphaBlending: true,
		defines: ['#define INSTANCES']
	}
);
material.alphaMode = Engine.ALPHA_MULTIPLY;

```

In the final creation i just extended the attributes and added the defines statement.  
It seems better than before, cause at least the plane materials get rendered at diffrent positions, but their aren’t the correct ones. I have to say i’m really not that common with shader programming and have no good understanding, what is going on there

---

<div class="post-metadata">

**Author:** ![Deltakosh](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/deltakosh/32/26635_2.png) [@Deltakosh](https://forum.babylonjs.com/u/Deltakosh)\
**Post date:** [May 12, 2020, 4:58pm UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782/2 "2020-05-12T16:58:32Z")

</div>

Hello, maybe you could be more interested by NME? [https://doc.babylonjs.com/how\_to/node\_material](https://doc.babylonjs.com/how_to/node_material)

Else you need to do more in your ShaderMaterial:

> [@How to set custom attribute on ShaderMaterial for use with instances and clones at the same time?](https://forum.babylonjs.com/t/how-to-set-custom-attribute-on-shadermaterial-for-use-with-instances-and-clones-at-the-same-time/9448):
>
> Hi, I have a custom shader for my ShaderMaterial, and want to be able to use that material on meshes that are instanced, but also on simple clones. For that material I need to set some parameters, that are unique to each instance/clone. Here’s an example: [https://playground.babylonjs.com/#026IT4](https://playground.babylonjs.com/#026IT4) When using instances everything works as expected (with instancedBuffers and a shader attribute), but how can I set the same attribute for the normal mesh, when no instances are used? (and with the s…

---

<div class="post-metadata">

**Author:** ![lasse](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/lasse/32/8398_2.png) [@lasse](https://forum.babylonjs.com/u/lasse)\
**Post date:** [May 12, 2020, 7:42pm UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782/3 "2020-05-12T19:42:52Z")

</div>

First of all thanks for the quick response, was not excepting it to be this fast 🙂 and much thanks for this link, had not seen this before, it is a geniuos tool. It will take me some time to fully understand this, so i have one quick question, how easy is it to still set a texture on my custom NodeMaterial. Basically what i want to accomplish is to have a texture with black/white and set the white as alpha so it only renders the black part. I don’t need a guide on how to accomplish that exactly, but can you tell me if it’s possible without spending serveral days designing the nodeMaterial. Sorry for my maybe uneducated question.

---

<div class="post-metadata">

**Author:** ![Deltakosh](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/deltakosh/32/26635_2.png) [@Deltakosh](https://forum.babylonjs.com/u/Deltakosh)\
**Post date:** [May 12, 2020, 8:49pm UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782/4 "2020-05-12T20:49:50Z")

</div>

It will be dead fast to do with NME 🙂

---

<div class="post-metadata">

**Author:** ![lasse](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/lasse/32/8398_2.png) [@lasse](https://forum.babylonjs.com/u/lasse)\
**Post date:** [June 3, 2020, 5:37pm UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782/5 "2020-06-03T17:37:51Z")

</div>

Hi, there. I didn’t get it to work right away and had a few other things with higher prio, but today i finished it (it is very basic, but i’m still learning that 3d stuff) and it is still not working. I looked in the sources and noticed, that there is no setTexture function on the NodeMaterial class. Is this really the case, that it is not possible to set a texture for a NodeMaterial?

---

<div class="post-metadata">

**Author:** ![sebavan](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/sebavan/32/57_2.png) [@sebavan](https://forum.babylonjs.com/u/sebavan)\
**Post date:** [June 3, 2020, 5:48pm UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782/6 "2020-06-03T17:48:18Z")

</div>

You can use smthg like this :  
`let block = nodeMaterial.getInputBlockByPredicate((b) => b.name === "foo"); block.texture = bar;`

---

<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:** [June 3, 2020, 5:50pm UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782/7 "2020-06-03T17:50:15Z")

</div>

Have a look at the nme programming doc:

[https://doc.babylonjs.com/how\_to/node\_material](https://doc.babylonjs.com/how_to/node_material)

Texture blocks have a `texture` property that you can set:

* * *

Once a graph is built inside a NodeMaterial, you can use the following API to get a specific node by name:

```auto
let block = nodeMaterial.getBlockByName("MyBlock");

```

You can also get a block using a predicate:

```auto
let block = nodeMaterial.getBlockByPredicate((b) => b.getClassName() === "AddBlock" && b.name === "foo");

```

Or you can also use this API to get an InputNode and use it to setup its value if the node is set manual value:

```auto
let block = nodeMaterial.getInputBlockByPredicate((b) => b.name === "foo");
block.value = 10;

```

Note that while this API generically works for all input blocks, not all input blocks have a “value” attribute. **For example texture blocks would have block.texture instead of block.value**. Be sure to check the [API documentation](https://doc.babylonjs.com/api/classes/babylon.nodematerial) for detail.

---

<div class="post-metadata">

**Author:** ![lasse](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/lasse/32/8398_2.png) [@lasse](https://forum.babylonjs.com/u/lasse)\
**Post date:** [June 4, 2020, 7:28am UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782/8 "2020-06-04T07:28:53Z")

</div>

Thanks, that did the trick, didn’t got that. Ended up with using getTextureBlocks(), cause my material has only one and i didn’t have to rely on that name. But somehow the whole thing is still not working, when i create instances. It applies different positions for the instances, but just not the correct ones (without instances it get’s drawn in the correct place). Here is a link to my material [https://nme.babylonjs.com/#8PFDX7#16](https://nme.babylonjs.com/#8PFDX7#16). And another question right away, can i clone this material, after loading it via url, it returns null if i call clone() on it.

> const material = await NodeMaterial.ParseFromSnippetAsync(‘8PFDX7#16’, scene);  
> material.clone(‘new-name’); // this is null

---

<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:** [June 4, 2020, 12:53pm UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782/9 "2020-06-04T12:53:36Z")

</div>

You need to use the **Instances** block to be able to use a node material with instances:

 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/2X/9/9a2d252f10558b9ce82b4068a58b46fba97dfa2e.png)

I think you will need to provide a PG for the cloning problem as cloning should work.

---

<div class="post-metadata">

**Author:** ![lasse](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/lasse/32/8398_2.png) [@lasse](https://forum.babylonjs.com/u/lasse)\
**Post date:** [June 4, 2020, 1:00pm UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782/10 "2020-06-04T13:00:59Z")

</div>

aww, damn it, i put the wrong version in the link, corrected it now (@Evgeni_Popov it is the same that you propably already saw). I will work out a playground and put it here in a few hours

---

<div class="post-metadata">

**Author:** ![lasse](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/lasse/32/8398_2.png) [@lasse](https://forum.babylonjs.com/u/lasse)\
**Post date:** [June 4, 2020, 4:13pm UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782/11 "2020-06-04T16:13:58Z")

</div>

Ok, here is a playground for my positioning Problem: [Babylon.js Playground](https://playground.babylonjs.com/#9CLVFV). This was surprisingly easier to reproduce, than the cloning, which works, flawless in the playground. Anyway, if you don’t apply the node material, or outline the creation of the instance the position is as expected, but it somehow alters both positions, that of the original and the position of the instance

---

<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:** [June 4, 2020, 4:35pm UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782/12 "2020-06-04T16:35:20Z")

</div>

This will be corrected by:

> <https://github.com/BabylonJS/Babylon.js/pull/8312>

---

<div class="post-metadata">

**Author:** ![lasse](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/lasse/32/8398_2.png) [@lasse](https://forum.babylonjs.com/u/lasse)\
**Post date:** [June 4, 2020, 5:18pm UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782/13 "2020-06-04T17:18:02Z")

</div>

thank you so mouch for your time and effort, looking forward to using the awesome NME-Editor more often in the future

---

<div class="post-metadata">

**Author:** ![peterimg](https://avatars.discourse-cdn.com/v4/letter/p/50afbb/32.png) [@peterimg](https://forum.babylonjs.com/u/peterimg)\
**Post date:** [November 16, 2020, 4:48pm UTC](https://forum.babylonjs.com/t/instancing-a-mesh-with-shadermaterials/10782/14 "2020-11-16T16:48:38Z")

</div>

That image saved my day 🙂 Thanks. Instances block 🙂
