instanceCullingIndex
instanceCullingIndex(culler : ComputeInstanceCulling) : Node<uint>TSL function that returns the culled instance ID for the current draw call.
Unlike instanceIndex which gives the draw index (0 to survivorCount),
this returns the actual original instance ID from the culled set.
Use this in custom material nodes when you need to access per-instance data from the original instance arrays, such as:
- Per-instance random values (via hash)
- Animation offsets
- Custom attribute lookups
Example: Per-instance rotation with stable IDs
Example: Custom per-instance data lookup
import { instanceCullingIndex } from '@three-blocks/core';
import { storage, vec3 } from 'three/tsl';
// Custom per-instance colors stored in a storage buffer
const colorBuffer = new THREE.StorageBufferAttribute(colors, 3);
const colorStorage = storage(colorBuffer, 'vec3', instanceCount);
// Look up color using original instance ID
const originalId = instanceCullingIndex(culler);
material.colorNode = colorStorage.element(originalId);
Parameters
The GPU instance culler.
Returns
Node<uint> — The culled instance ID node.Example
import { ComputeInstanceCulling, instanceCulling, instanceCullingIndex } from '@three-blocks/core';
import { Fn, hash, time, rotate, positionLocal, normalLocal, transformNormalToView } from 'three/tsl';
import * as THREE from 'three/webgpu';
const mesh = new THREE.InstancedMesh(geometry, material, 10000);
const culler = new ComputeInstanceCulling(mesh, renderer);
// Get the original instance ID (stable across culling changes)
const originalId = instanceCullingIndex(culler);
// Create per-instance rotation that persists when instances are culled/unculled
const randomOffset = hash(originalId).mul(Math.PI * 2);
const angle = time.mul(0.5).add(randomOffset);
// Apply rotation before instance transform, then cull
material.positionNode = Fn(() => {
positionLocal.assign(rotate(positionLocal, angle));
normalLocal.assign(rotate(normalLocal, angle));
instanceCulling(culler).toStack();
return positionLocal;
})();
material.normalNode = transformNormalToView(normalLocal).normalize();