<InstancedMesh>
The component <InstancedMesh> is wrapping the Three.js object InstancedMesh and provides instanced rendering support. Use <InstancedMesh> if you have to render a large number of objects with the same geometry and material but with different world transformations and colors. The usage of <InstancedMesh> will help you to reduce the number of draw calls and thus improve the overall rendering performance in your application.
<script lang="ts"> import { Canvas } from '@threlte/core' import Scene from './Scene.svelte'</script>
<div> <Canvas> <Scene /> </Canvas></div>
<style> div { height: 100%; }</style><script lang="ts"> import { T, useTask } from '@threlte/core' import { Instance, InstancedMesh } from '@threlte/extras'
let dn = $state(Date.now()) useTask(() => (dn = Date.now()))</script>
<InstancedMesh> <T.SphereGeometry args={[0.5]} /> <T.MeshStandardMaterial color="white" />
<Instance position.x={-2} position.y={Math.sin(dn / 1000 + 40)} /> <Instance position.x={-1} position.y={Math.sin(dn / 1000 + 10)} /> <Instance position.x={0} position.y={Math.sin(dn / 1000 + 5)} /> <Instance position.x={1} position.y={Math.sin(dn / 1000 + 200)} /> <Instance position.x={2} position.y={Math.sin(dn / 1000 + 550)} /></InstancedMesh>
<T.DirectionalLight position.y={10} position.z={5}/>
<T.AmbientLight intensity={0.1} />An <InstancedMesh> is used in conjunction with the <Instance> component:
<InstancedMesh> <T.BoxGeometry /> <T.MeshStandardMaterial />
<Instance /> <Instance /></InstancedMesh>It’s also possible to nest other objects in an <InstancedMesh> component:
<InstancedMesh> <T.BoxGeometry /> <T.MeshStandardMaterial />
<Instance /> <Instance />
<GLTF /></InstancedMesh>Provide an id to use multiple <InstancedMesh> components:
<InstancedMesh id="tree"> <T is={treeGeometry} /> <T.MeshStandardMaterial map={treeTexture} />
<InstancedMesh id="leaf"> <T is={leafGeometry} /> <T.MeshStandardMaterial map={leafTexture} />
<T.Group position.x={1}> <Instance id="tree" /> // Instance of InstancedMesh with id="tree" <Instance id="leaf" /> // Instance of InstancedMesh with id="leaf" </T.Group>
<T.Group position.x={-2}> <Instance id="tree" /> <Instance id="leaf" /> </T.Group> </InstancedMesh></InstancedMesh>Instance count
Section titled “Instance count”Use the property limit to set the maximum amount of <Instance> components (defaults to 1000). The property limit will be used to initialize the internally used Float32Array. Use the property range to optionally limit the amount of drawn instances.
<InstancedMesh limit={10000} range={100}> <T.BoxGeometry /> <T.MeshStandardMaterial />
<Instance /> <Instance /></InstancedMesh>Events
Section titled “Events”Mouse around in the example below.
<script lang="ts"> import Scene from './Scene.svelte' import { Canvas } from '@threlte/core' import { Checkbox, Pane } from 'svelte-tweakpane-ui'
let paused = $state(false)</script>
<Pane position="fixed" title="Instanced Colors"> <Checkbox bind:value={paused} label="paused" /></Pane>
<Canvas> <Scene {paused} /></Canvas>import { Color } from 'three'import { Tween } from 'svelte/motion'import { cubicOut } from 'svelte/easing'
export default class { y = new Tween(0, { easing: cubicOut, duration: 250 }) scale = $derived(this.y.current + 1) startColor = new Color() endColor = new Color() color = $derived(this.startColor.clone().lerpHSL(this.endColor, this.y.current)) constructor( startColor: Color, endColor: Color, public x: number, public z: number ) { this.startColor.set(startColor) this.endColor.set(endColor) }}<script lang="ts"> import BallInstance from './BallInstance.svelte' import { Color } from 'three' import { DirectionalLight } from 'three' import { Instance, InstancedMesh, interactivity } from '@threlte/extras' import { T, useTask, useThrelte } from '@threlte/core'
let { paused = false }: { paused?: boolean } = $props()
const width = 10 const limit = width * width const gap = 2.5 const offset = (width * gap) / 2
const startColor = new Color('blue') const endColor = new Color('yellow') const instances: BallInstance[] = [] for (let i = 0; i < limit; i += 1) { const x = (i % width) * gap - offset const z = Math.floor(i / width) * gap - offset instances.push(new BallInstance(startColor, endColor, x, z)) }
const { size } = useThrelte() const zoom = $derived($size.width / (1.5 * gap * width))
interactivity({ filter(items) { // only report the first intersection return items.slice(0, 1) } })
const light = new DirectionalLight() const lightRadius = 10 const lightHeight = 5
let time = 0 const { start, stop } = useTask( (delta) => { time += delta const x = lightRadius * Math.cos(time) const z = lightRadius * Math.sin(time) light.position.set(x, lightHeight, z) light.lookAt(0, 0, 0) }, { autoStart: false } )
$effect(() => { if (!paused) { start() } return () => { stop() } })</script>
<T.OrthographicCamera position={[width, width, width]} {zoom} makeDefault oncreate={(ref) => { ref.lookAt(0, 0, 0) }}/>
<InstancedMesh {limit} range={limit}> <T.SphereGeometry /> <T.MeshToonMaterial />
{#each instances as instance} <Instance rotation.x={0.5 * Math.PI} position.x={instance.x} position.y={instance.y.current} scale={instance.scale} position.z={instance.z} color={instance.color} onpointerenter={() => { instance.y.set(1) }} onpointerleave={() => { instance.y.set(0) }} /> {/each}</InstancedMesh>
<T is={light} />Instances also support interactivity events.
<InstancedMesh> <T.BoxGeometry /> <T.MeshStandardMaterial />
<Instance onclick={onClick} /></InstancedMesh>Nesting
Section titled “Nesting”Instances can be nested in other objects and all parent transformations apply as usual:
<InstancedMesh> <T.BoxGeometry /> <T.MeshStandardMaterial />
<T.Group rotation.z={DEG2RAD * 180}> <Instance />
<T.Group position.y={2}> <Instance /> </T.Group> </T.Group></InstancedMesh>Component Signature
Section titled “Component Signature”
<InstancedMesh> extends
<
T
.
InstancedMesh
>
and supports all its props, snippets, bindings and events.