import { Node } from 'three/webgpu'; import type { NodeBuilder } from 'three/webgpu'; import type { TSLIntegerNode, TSLMat4Node, TSLNodeFactory, TSLStorageNode, TSLUintNode, TSLVoidNode } from '../types/tsl.js'; export interface InstanceCullingIndexSource { readonly isComputeInstanceCulling: boolean; readonly outIdNode: TSLStorageNode<'uint'>; } export interface InstanceCullingSource extends InstanceCullingIndexSource { readonly refMatNode: TSLStorageNode<'mat4'>; } export type InstanceCullingNodeFactory = TSLNodeFactory<[ culler: InstanceCullingSource ], TSLVoidNode>; /** * TSL Node that applies GPU-culled instance matrix transformations to geometry. * Works like Three.js's instancedMesh() node but uses culled instance IDs. * * This node is used internally by {@link ComputeInstanceCulling} and typically * does not need to be instantiated directly. Use {@link instanceCulling} instead. * * @class InstanceCullingNode * @extends Node * @private */ declare class InstanceCullingNode extends Node<'void'> { static get type(): string; /** * Constructs a new instance culling node. * * @param {import('../Compute/ComputeInstanceCulling.js').ComputeInstanceCulling} culler - The GPU instance culler. */ culler: InstanceCullingSource; constructor(culler: InstanceCullingSource); /** * Setups the node and assigns transformed vertex data to positionLocal and normalLocal. * * @param {import('three/webgpu').NodeBuilder} builder - The current node builder. */ setup(builder: NodeBuilder): undefined; } export default InstanceCullingNode; /** * TSL function for creating an instance culling node that applies GPU-culled * instance transforms to vertex positions and normals. * * This is the main entry point for enabling GPU culling in your material. The node * automatically handles the indirection from draw index to original instance ID. * * **Example: Basic GPU frustum culling** * * ```js * import { ComputeInstanceCulling } from 'three-blocks'; * import * as THREE from 'three/webgpu'; * * // Create instanced mesh with 100,000 instances * const geometry = new THREE.BoxGeometry(1, 1, 1); * const material = new THREE.MeshStandardNodeMaterial(); * const mesh = new THREE.InstancedMesh(geometry, material, 100000); * * // Scatter instances randomly * const matrix = new THREE.Matrix4(); * for (let i = 0; i < 100000; i++) { * matrix.makeTranslation( * (Math.random() - 0.5) * 1000, * (Math.random() - 0.5) * 100, * (Math.random() - 0.5) * 1000 * ); * mesh.setMatrixAt(i, matrix); * } * * // Create GPU culler * const culler = new ComputeInstanceCulling(mesh, renderer); * * // Culling patch is applied automatically to material.setupPosition() * // so you can keep using positionNode normally. * * scene.add(mesh); * ``` * * @function instanceCulling * @short TSL node that applies ComputeInstanceCulling transforms to vertex positions and normals for culled instances. * @category TSL * @tags WebGPU * @tsl * @param {import('../Compute/ComputeInstanceCulling.js').ComputeInstanceCulling} culler - The GPU instance culler. * @returns {InstanceCullingNode} Node that applies culled instance transforms. * @type {import('../types/tsl.js').TSLNodeFactory<[import('../Compute/ComputeInstanceCulling.js').ComputeInstanceCulling], import('../types/tsl.js').TSLVoidNode>} */ export declare const instanceCulling: InstanceCullingNodeFactory; /** * 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** * * ```js * import { ComputeInstanceCulling } from 'three-blocks'; * import { instanceCullingIndex } from 'three-blocks/instance-culling'; * 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 the culler's automatic material hook runs * material.positionNode = Fn(() => { * positionLocal.assign(rotate(positionLocal, angle)); * normalLocal.assign(rotate(normalLocal, angle)); * return positionLocal; * })(); * material.normalNode = transformNormalToView(normalLocal).normalize(); * ``` * * **Example: Custom per-instance data lookup** * * ```js * import { instanceCullingIndex } from 'three-blocks/instance-culling'; * 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); * ``` * * @function instanceCullingIndex * @category TSL * @tags WebGPU * @tsl * @param {import('../Compute/ComputeInstanceCulling.js').ComputeInstanceCulling|null|undefined} culler - The GPU instance culler. * @returns {import('../types/tsl.js').TSLUintNode} The culled instance ID node. */ export declare const instanceCullingIndex: (culler: InstanceCullingIndexSource | null | undefined) => TSLUintNode; /** * Fetch the instance matrix for a culled instance. * * Use this when you need the per-instance matrix in custom nodes without manually * indexing `refMatNode`. * * **Example: Extract world position** * * ```js * import { instanceCullingMatrix } from 'three-blocks/instance-culling'; * import { vec3 } from 'three/tsl'; * * const M = instanceCullingMatrix(culler); * const worldPos = vec3(M[3].x, M[3].y, M[3].z); * ``` * * @function instanceCullingMatrix * @category TSL * @tags WebGPU * @tsl * @param {import('../Compute/ComputeInstanceCulling.js').ComputeInstanceCulling|null|undefined} culler - The GPU instance culler. * @param {import('../types/tsl.js').TSLIntegerNode} [idNode] Optional instance id node. Defaults to culled id. * @returns {import('../types/tsl.js').TSLMat4Node|null} Instance matrix for the culled instance. */ export declare const instanceCullingMatrix: (culler: InstanceCullingSource | null | undefined, idNode?: TSLIntegerNode) => TSLMat4Node | null;