# How can I use DataTexture for BatchedMesh to access per-instance data in shader?

**URL:** <https://discourse.threejs.org/t/how-can-i-use-datatexture-for-batchedmesh-to-access-per-instance-data-in-shader/72996>\
**Category:** Questions\
**Tags:** batchedmesh, instancedbuffergeometry\
**Created:** [October 19, 2024, 4:40pm UTC](https://discourse.threejs.org/t/how-can-i-use-datatexture-for-batchedmesh-to-access-per-instance-data-in-shader/72996 "2024-10-19T16:40:34Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![ingun37](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/ingun37/32/27390_2.png) [@ingun37](https://discourse.threejs.org/u/ingun37)\
**Post date:** [October 19, 2024, 4:40pm UTC](https://discourse.threejs.org/t/how-can-i-use-datatexture-for-batchedmesh-to-access-per-instance-data-in-shader/72996/1 "2024-10-19T16:40:34Z")

</div>

I was using `InstancedMesh` with custom `InstancedBufferAttribute`s. Then I got to have many of such `InstancedMesh`s that use the same material, so I tried to use `BatchedMesh` to draw them at once. But I was getting some internal errors so I checked the ThreeJS code and then I found a big difference between `InstancedMesh` and `BatchedMesh` which was that **`InstancedMesh` use `InstancedBufferAttribute` while `BatchedMesh` use `DataTexture` to manage per-instance data ([this part](https://github.com/mrdoob/three.js/blob/37d6f280a5cd642e801469bb048f52300d31258e/src/objects/BatchedMesh.js#L192-L194))**. Does it mean `BatchedMesh` doesn’t use `drawArraysInstanced` internally therefore I can’t use `InstancedBufferAttribute`? If so, do I need to use DataTexture as well to achieve the same thing?

---

<div class="post-metadata">

**Author:** ![agargaro](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/agargaro/32/35529_2.png) [@agargaro](https://discourse.threejs.org/u/agargaro)\
**Post date:** [October 19, 2024, 6:00pm UTC](https://discourse.threejs.org/t/how-can-i-use-datatexture-for-batchedmesh-to-access-per-instance-data-in-shader/72996/2 "2024-10-19T18:00:48Z")

</div>

BatchedMesh uses [multidraw](https://github.com/mrdoob/three.js/blob/2976aa1545e41a213510151908b5f26349dac12e/src/renderers/webgl/WebGLIndexedBufferRenderer.js#L43).

Yes, you should use DataTexture.

Do you need help? (I’m using DataTexture also for my [InstancedMesh2 library](https://github.com/agargaro/instanced-mesh)).

---

<div class="post-metadata">

**Author:** ![ingun37](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/ingun37/32/27390_2.png) [@ingun37](https://discourse.threejs.org/u/ingun37)\
**Post date:** [October 20, 2024, 1:17am UTC](https://discourse.threejs.org/t/how-can-i-use-datatexture-for-batchedmesh-to-access-per-instance-data-in-shader/72996/3 "2024-10-20T01:17:34Z")

</div>

Yes I do! How do I access per-instance data using DataTexture? Meanwhile I’ll try to figure out myself by looking at the yours and THreeJS’s code

---

<div class="post-metadata">

**Author:** ![agargaro](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/agargaro/32/35529_2.png) [@agargaro](https://discourse.threejs.org/u/agargaro)\
**Post date:** [October 20, 2024, 9:53am UTC](https://discourse.threejs.org/t/how-can-i-use-datatexture-for-batchedmesh-to-access-per-instance-data-in-shader/72996/4 "2024-10-20T09:53:02Z")

</div>

### Create DataTexture:

You can find utility methods for creating `DataTexture` here:

> <https://github.com/agargaro/instanced-mesh/blob/31f1d8731be5ae60da7ba9c791b7034fa44d4611/src/utils/createTexture.ts>

Like with `BatchedMesh`, create textures with equal width and height, because creating a texture width = N and height = 1, might fail.

### Get Instance index in the shader

I recommend this site to check the shaders of three.js:

> **[three-shaderlib-skim](https://ycw.github.io/three-shaderlib-skim/dist/)**

You should check these two parts

```javascript
#include <batching_pars_vertex>
...
#include <batching_vertex>

```

You can get the instance ID in this way:

```javascript
getIndirectIndex( gl_DrawID )

```

### Get instance data

You can find utility methods for get data from texture here:

> <https://github.com/agargaro/instanced-mesh/blob/31f1d8731be5ae60da7ba9c791b7034fa44d4611/src/shaders/chunks/get_from_texture.glsl.ts>

Obviously pay attention to the types and declare the texture uniform in your shader.

I hope I haven’t forgotten anything 🙂

---

<div class="post-metadata">

**Author:** ![ingun37](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/ingun37/32/27390_2.png) [@ingun37](https://discourse.threejs.org/u/ingun37)\
**Post date:** [October 21, 2024, 9:58am UTC](https://discourse.threejs.org/t/how-can-i-use-datatexture-for-batchedmesh-to-access-per-instance-data-in-shader/72996/5 "2024-10-21T09:58:49Z")

</div>

I managed to use BatchedMesh instead of InstancedMesh, but the result performance was, even with dramatic decrease in the number of draw calls, not as good as expected. So I did some researching and It seems like, to benefit from both multi-drawing and instancing, you should use [multiDrawElementsInstancedWEBGL](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_multi_draw/multiDrawElementsInstancedWEBGL) or [multiDrawArraysInstancedWEBGL](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_multi_draw/multiDrawArraysInstancedWEBGL). But my debugger said it was using [multiDrawElementsWEBGL](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_multi_draw/multiDrawElementsWEBGL). So I checked the ThreeJS code and there was indeed a code that [use the multiDrawElementsInstancedWEBGL](https://github.com/mrdoob/three.js/blob/48e6e2ee4e769013b911a079a433aecc2686d5b2/src/renderers/webgl/WebGLIndexedBufferRenderer.js#L73) but the code seemed unreachable. Because [\_multiDrawInstances has to be not null](https://github.com/mrdoob/three.js/blob/48e6e2ee4e769013b911a079a433aecc2686d5b2/src/renderers/WebGLRenderer.js#L863-L867) but there’s no code in ThreeJS that sets it with any value.

Is ThreeJS is still under development on using both MultiDraw and Instancing? cc @donmccurdy @agargaro

---

<div class="post-metadata">

**Author:** ![agargaro](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/agargaro/32/35529_2.png) [@agargaro](https://discourse.threejs.org/u/agargaro)\
**Post date:** [October 21, 2024, 11:11am UTC](https://discourse.threejs.org/t/how-can-i-use-datatexture-for-batchedmesh-to-access-per-instance-data-in-shader/72996/6 "2024-10-21T11:11:22Z")

</div>

It’s possible to use those commands but it’s not recommended because they don’t work on firefox.

> <https://github.com/mrdoob/three.js/pull/29655>
>
> \*\*Description\*\*
> 
> Deprecates the now-unreferenced instanced multidraw rendering… paths from #28103, which was superseded by #28404, and does not implement a fallback for Firefox. Instancing is since emulated by appending instances into the multidraw arguments themselves and using indirection for sorting/visibility, which has a fallback implemented for Firefox.

I created an example (not cleaned) that use multidrawInstanced to handle InstancedMesh LODs with a single drawCall, but I don’t think I’ll ever use it:

> **[three.js bug drawcall & triangles info - StackBlitz](https://stackblitz.com/edit/three-ezinstancedthree-js-bug-drawcall-triangles-infomes?file=src%2Fmain.ts)**
>
> A Vite TypeScript project based on @three.ez/main, @three.ez/instanced-mesh, three, @types/three, typescript and vite

If individual frustum culling by instance might be useful to you, you might take a look at the library I linked to earlier.
