GitPedia

Instanced mesh

Enhanced InstancedMesh with frustum culling, fast raycasting (using a BVH), sorting, visibility, LOD, skinning and more.

From agargaroยทUpdated June 3, 2026ยทView on GitHubยท

Simplify your three.js application development with three.ez! three.ez/batched-mesh-extensions - BatchedMesh extension methods and enhancements for better performance and usability The project is written primarily in TypeScript, distributed under the MIT License license, first published in 2024. Key topics include: bvh, frustum-culling, instancedmesh2, instances, lod.

Latest release: r3
<div align="center"> <h1>Three.ez - InstancedMesh2</h1> <p> <em>Simplify your <b>three.js</b> application development with <b>three.ez</b>!</em> <br><br> <b><a href="https://github.com/agargaro/batched-mesh-extensions">three.ez/batched-mesh-extensions</a></b> - <code>BatchedMesh</code> extension methods and enhancements for better performance and usability </p>

<img src="public/banner.png" alt="banner" /> <br>

Discord
npm
Stars
BundlePhobia
Quality Gate Status
DeepScan grade

</div>

InstancedMesh2 is an alternative version of InstancedMesh with enhanced features for performance and usability.

ts
const myInstancedMesh = new InstancedMesh2(geometry, material); myInstancedMesh.addInstances(count, (obj, index) => { obj.position.x = index; });

๐Ÿง‘โ€๐Ÿ’ป Live Examples

Vanilla

Using three.ez/main

Using other libraries

โ” Need help?

Join us on Discord or open an issue on GitHub.

โญ Like it?

If you like this project, please leave a star. Thank you! โค๏ธ

๐Ÿ“š Documentation

The documentation is available here.

โฌ‡๏ธ Installation

You can install it via npm using the following command:

bash
npm install @three.ez/instanced-mesh

Or you can import it from CDN:

html
<script type="importmap"> { "imports": { "three": "https://cdn.jsdelivr.net/npm/three/build/three.module.js", "three/addons/": "https://cdn.jsdelivr.net/npm/three/examples/jsm/", "@three.ez/instanced-mesh": "https://cdn.jsdelivr.net/npm/@three.ez/instanced-mesh/build/index.js", "bvh.js": "https://cdn.jsdelivr.net/npm/bvh.js/build/index.js" } } </script>

๐Ÿš€ Features

Dynamic capacity

Manage a dynamic number of instances, automatically expanding the data buffers as needed to accommodate additional instances. <br>

If not specified, capacity is 1000. <br>

ts
const myInstancedMesh = new InstancedMesh2(geometry, material, { capacity: count }); myInstancedMesh.addInstances(count, (obj, index) => { ... }); // add instances and expand buffer if necessary myInstancedMesh.removeInstances(id0, id1, ...); myInstancedMesh.clearInstances(); // remove all instances

Object3D-like instances

It's possible to create an array of InstancedEntity (Object3D-like) in order to easily manipulate instances, using more memory.

ts
const myInstancedMesh = new InstancedMesh2(geometry, material, { createEntities: true }); myInstancedMesh.instances[0].customData = {}; myInstancedMesh.instances[0].position.random(); myInstancedMesh.instances[0].rotateX(Math.PI); myInstancedMesh.instances[0].updateMatrix(); // necessary after transformations

Per-instance frustum culling

Avoiding rendering objects outside the camera frustum can drastically improve performance (especially for complex geometries). <br>
Frustum culling by default is performed by iterating all instances, but it is possible to speed up this process by creating a spatial indexing data structure (BVH). <br>

By default perObjectFrustumCulled is true.

Spatial indexing (dynamic BVH)

To speed up raycasting and frustum culling, a spatial indexing data structure can be created to contain the boundingBoxes of all instances. <br>
This works very well if the instances are mostly static (updating a BVH can be expensive) and scattered in world space. <br>

Setting a margin makes BVH updating faster, but may make raycasting and frustum culling slightly slower.

ts
myInstancedMesh.computeBVH({ margin: 0 }); // margin is optional

Sorting

Sorting can be used to decrease overdraw and render transparent objects. <br>

It's possible to improve sort performance adding a customSort, like built-in createRadixSort.

By default sortObjects is false. <br>

ts
import { createRadixSort } from '@three.ez/instanced-mesh'; myInstancedMesh.sortObjects = true; myInstancedMesh.customSort = createRadixSort(myInstancedMesh);

Per-instance visibility

Set the visibility status of each instance.

ts
myInstancedMesh.setVisibilityAt(index, false); myInstancedMesh.instances[0].visible = false; // if instances array is created

Per-instance opacity

Set the opacity of each instance. It's recommended to enable instances sorting and disable the depthWriting of the material.

ts
myInstancedMesh.setOpacityAt(index, 0.5); myInstancedMesh.instances[0].opacity = 0.5; // if instances array is created

Per-instance uniforms

Assign unique shader uniforms to each instance, working with every materials.

ts
myInstancedMesh.initUniformsPerInstance({ fragment: { metalness: 'float', roughness: 'float', emissive: 'vec3' } }); myInstancedMesh.setUniformAt(index, 'metalness', 0.5); myInstancedMesh.instances[0].setUniform('emissive', new Color('white')); // if instances array is created

Level of Detail (LOD)

Improve rendering performance by dynamically adjusting the detail level of instances based on their distance from the camera. <br>
Use simplified geometries for distant objects to optimize resources.

ts
myInstancedMesh.addLOD(geometryMid, material, 50); myInstancedMesh.addLOD(geometryLow, material, 200);

Shadow LOD

Optimize shadow rendering by reducing the detail level of instances casting shadows based on their distance from the camera.

ts
myInstancedMesh.addShadowLOD(geometryMid); myInstancedMesh.addShadowLOD(geometryLow, 100);

Skinning

Apply skeletal animations to instances for more complex and dynamic movements.

ts
myInstancedMesh.initSkeleton(skeleton); mixer.update(time); myInstancedMesh.setBonesAt(index);

Raycasting tips

If you are not using a BVH, you can set the raycastOnlyFrustum property to true to avoid iterating over all instances.

It's recommended to use three-mesh-bvh to create a geometry BVH.

๐Ÿค Special thanks to

๐Ÿ“– References

Contributors

Showing top 11 contributors by commit count.

View all contributors on GitHub โ†’

This article is auto-generated from agargaro/instanced-mesh via the GitHub API.Last fetched: 6/14/2026