@react-three/fiber 10.0.0-canary.604355a → 10.0.0-canary.9806389

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as three_webgpu from 'three/webgpu';
2
- import { RenderTarget, WebGPURenderer, CanvasTarget, Node, ShaderNodeObject, Euler as Euler$2, Color as Color$2, ColorRepresentation as ColorRepresentation$1, Layers as Layers$1, Raycaster, Intersection as Intersection$1, BufferGeometry, Matrix4 as Matrix4$1, Quaternion as Quaternion$1, Vector2 as Vector2$1, Vector3 as Vector3$1, Vector4 as Vector4$1, Matrix3 as Matrix3$1, Loader as Loader$1, ColorSpace, Texture as Texture$1, CubeTexture, Scene, Object3D, Frustum, OrthographicCamera } from 'three/webgpu';
2
+ import { RenderTarget, WebGPURenderer, Node, StorageTexture, Data3DTexture, CanvasTarget, ShaderNodeObject, Euler as Euler$2, Color as Color$2, ColorRepresentation as ColorRepresentation$1, Layers as Layers$1, Raycaster, Intersection as Intersection$1, BufferGeometry, Matrix4 as Matrix4$1, Quaternion as Quaternion$1, Vector2 as Vector2$1, Vector3 as Vector3$1, Vector4 as Vector4$1, Matrix3 as Matrix3$1, Loader as Loader$1, ColorSpace, Texture as Texture$1, CubeTexture, Scene, Object3D, Frustum, OrthographicCamera } from 'three/webgpu';
3
3
  import * as THREE$1 from 'three';
4
4
  import { WebGLRenderTarget, WebGLRenderer, Color as Color$1, ColorRepresentation, Euler as Euler$1, Loader, RenderTargetOptions as RenderTargetOptions$1 } from 'three';
5
5
  import { WebGLRendererParameters } from 'three/src/renderers/WebGLRenderer.js';
@@ -149,6 +149,8 @@ interface IntersectionEvent<TSourceEvent> extends Intersection {
149
149
  unprojectedPoint: THREE$1.Vector3
150
150
  /** Normalized event coordinates */
151
151
  pointer: THREE$1.Vector2
152
+ /** pointerId of the original event for multiple pointer events */
153
+ pointerId: number
152
154
  /** Delta between first click and this event */
153
155
  delta: number
154
156
  /** The ray that pierced it */
@@ -225,6 +227,18 @@ interface EventHandlers {
225
227
  type FilterFunction = (items: THREE$1.Intersection[], state: RootState) => THREE$1.Intersection[]
226
228
  type ComputeFunction = (event: DomEvent, root: RootState, previous?: RootState) => void
227
229
 
230
+ /** Configuration for XR pointer registration (controllers/hands) */
231
+ interface XRPointerConfig {
232
+ /** Ray origin (updated each frame by XR system) */
233
+ ray: THREE$1.Ray
234
+ /** Optional: custom compute function for this pointer */
235
+ compute?: (state: RootState) => void
236
+ /** Pointer type identifier */
237
+ type: 'controller' | 'hand' | 'gaze'
238
+ /** Which hand (for controller/hand types) */
239
+ handedness?: 'left' | 'right'
240
+ }
241
+
228
242
  interface EventManager<TTarget> {
229
243
  /** Determines if the event layer is active */
230
244
  enabled: boolean
@@ -244,8 +258,21 @@ interface EventManager<TTarget> {
244
258
  disconnect?: () => void
245
259
  /** Triggers a onPointerMove with the last known event. This can be useful to enable raycasting without
246
260
  * explicit user interaction, for instance when the camera moves a hoverable object underneath the cursor.
261
+ * @param pointerId - Optional pointer ID to update specific pointer only
247
262
  */
248
- update?: () => void
263
+ update?: (pointerId?: number) => void
264
+ /** Defer pointer move raycasting to frame start (default: true) */
265
+ frameTimedRaycasts?: boolean
266
+ /** Always fire raycaster immediately on scroll events (default: true) */
267
+ alwaysFireOnScroll?: boolean
268
+ /** Automatically re-raycast every frame to detect hover changes from moving objects/camera (default: false) */
269
+ updateOnFrame?: boolean
270
+ /** Flush deferred pointer raycasts. Called by scheduler at frame start (input phase). */
271
+ flush?: () => void
272
+ /** Register an XR pointer (controller/hand). Returns assigned pointerId */
273
+ registerPointer?: (config: XRPointerConfig) => number
274
+ /** Unregister an XR pointer */
275
+ unregisterPointer?: (pointerId: number) => void
249
276
  }
250
277
 
251
278
  interface PointerCaptureTarget {
@@ -487,6 +514,68 @@ interface SchedulerApi {
487
514
  subscribeJobState(id: string, listener: () => void): () => void
488
515
  }
489
516
 
517
+ //* Buffer Types (useBuffers) ========================================
518
+
519
+ /**
520
+ * Buffer-like types for GPU compute and storage operations.
521
+ * Includes raw CPU arrays, Three.js buffer attributes, and TSL buffer nodes.
522
+ *
523
+ * @example
524
+ * ```tsx
525
+ * const { positions, velocities } = useBuffers(() => ({
526
+ * positions: instancedArray(count, 'vec3'), // StorageBufferNode
527
+ * velocities: new Float32Array(count * 3), // TypedArray
528
+ * }), 'particles')
529
+ * ```
530
+ */
531
+ type BufferLike =
532
+ | Float32Array
533
+ | Uint32Array
534
+ | Int32Array
535
+ | Float64Array
536
+ | Uint8Array
537
+ | Int8Array
538
+ | Uint16Array
539
+ | Int16Array
540
+ | THREE$1.BufferAttribute // Base class for all buffer attributes
541
+ | Node // TSL buffer nodes (instancedArray, storage)
542
+
543
+ /** Flat record of buffer-like values (no nested scopes) */
544
+ type BufferRecord = Record<string, BufferLike>
545
+
546
+ /**
547
+ * Buffer store that can contain both root-level buffers and scoped buffer objects.
548
+ * Structure: { positions: Float32Array, particles: { vel: StorageBufferNode } }
549
+ */
550
+ type BufferStore = Record<string, BufferLike | BufferRecord>
551
+
552
+ //* Storage Types (useGPUStorage) ========================================
553
+
554
+ /**
555
+ * GPU storage types for texture-based storage operations.
556
+ * Includes Three.js storage textures and TSL storage texture nodes.
557
+ *
558
+ * @example
559
+ * ```tsx
560
+ * const { heightMap } = useGPUStorage(() => ({
561
+ * heightMap: new StorageTexture(512, 512),
562
+ * }), 'terrain')
563
+ * ```
564
+ */
565
+ type StorageLike =
566
+ | StorageTexture // GPU storage texture
567
+ | Data3DTexture // 3D texture (can be used as storage)
568
+ | Node // TSL storage texture nodes (storageTexture)
569
+
570
+ /** Flat record of storage-like values (no nested scopes) */
571
+ type StorageRecord = Record<string, StorageLike>
572
+
573
+ /**
574
+ * Storage store that can contain both root-level storage and scoped storage objects.
575
+ * Structure: { heightMap: StorageTexture, terrain: { normal: StorageTextureNode } }
576
+ */
577
+ type StorageStore = Record<string, StorageLike | StorageRecord>
578
+
490
579
  //* Renderer Types ========================================
491
580
 
492
581
  /** Default renderer type - union of WebGL and WebGPU renderers */
@@ -500,6 +589,18 @@ type Subscription = {
500
589
  store: RootStore
501
590
  }
502
591
 
592
+ /** Per-pointer state for multi-touch and XR support */
593
+ type PointerState = {
594
+ /** Objects currently hovered by this pointer */
595
+ hovered: Map<string, ThreeEvent<DomEvent>>
596
+ /** Objects capturing this pointer */
597
+ captured: Map<THREE$1.Object3D, PointerCaptureTarget>
598
+ /** Initial click position [x, y] */
599
+ initialClick: [x: number, y: number]
600
+ /** Objects hit on initial click */
601
+ initialHits: THREE$1.Object3D[]
602
+ }
603
+
503
604
  type Dpr = number | [min: number, max: number]
504
605
 
505
606
  interface Size {
@@ -541,12 +642,21 @@ interface Performance {
541
642
 
542
643
  interface InternalState {
543
644
  interaction: THREE$1.Object3D[]
544
- hovered: Map<string, ThreeEvent<DomEvent>>
545
645
  subscribers: Subscription[]
646
+ /** Per-pointer state (hover, capture, click tracking) - replaces hovered, capturedMap, initialClick, initialHits */
647
+ pointerMap: Map<number, PointerState>
648
+ /** Pointers needing raycast this frame (used with frameTimedRaycasts) */
649
+ pointerDirty: Map<number, DomEvent>
650
+ /** Last event received (for events.update() compatibility) */
651
+ lastEvent: React$1.RefObject<DomEvent | null>
652
+ /** @deprecated Use pointerMap.get(pointerId).hovered instead */
653
+ hovered: Map<string, ThreeEvent<DomEvent>>
654
+ /** @deprecated Use pointerMap.get(pointerId).captured instead */
546
655
  capturedMap: Map<number, Map<THREE$1.Object3D, PointerCaptureTarget>>
656
+ /** @deprecated Use pointerMap.get(pointerId).initialClick instead */
547
657
  initialClick: [x: number, y: number]
658
+ /** @deprecated Use pointerMap.get(pointerId).initialHits instead */
548
659
  initialHits: THREE$1.Object3D[]
549
- lastEvent: React$1.RefObject<DomEvent | null>
550
660
  /** Visibility event registry (onFramed, onOccluded, onVisible) */
551
661
  visibilityRegistry: Map<string, VisibilityEntry>
552
662
  /** Whether occlusion queries are enabled (WebGPU only) */
@@ -687,11 +797,17 @@ interface RootState {
687
797
  uniforms: UniformStore
688
798
  /** Global TSL nodes - root-level nodes + scoped sub-objects. Use useNodes() hook */
689
799
  nodes: Record<string, any>
690
- /** Global TSL texture nodes - use useTextures() hook for operations */
691
- textures: Map<string, any>
692
- /** WebGPU PostProcessing instance - use usePostProcessing() hook */
693
- postProcessing: any | null // THREE.PostProcessing when available
694
- /** Global TSL pass nodes for post-processing - use usePostProcessing() hook */
800
+ /** Global TSL buffer nodes - root-level buffers + scoped sub-objects. Use useBuffers() hook */
801
+ buffers: BufferStore
802
+ /** Global GPU storage (textures, etc.) - root-level storage + scoped sub-objects. Use useGPUStorage() hook */
803
+ gpuStorage: StorageStore
804
+ /** Global Texture registry (key Texture, usually keyed by URL) - use useTextures() hook for access + lifecycle */
805
+ textures: Map<string, THREE$1.Texture>
806
+ /** Internal: refcount per texture key, driven by mounted useTexture consumers (registry enrollment is on by default) */
807
+ _textureRefs: Map<string, number>
808
+ /** WebGPU RenderPipeline instance - use useRenderPipeline() hook */
809
+ renderPipeline: any | null // THREE.PostProcessing (will be THREE.RenderPipeline in future Three.js release)
810
+ /** Global TSL pass nodes for render pipeline - use useRenderPipeline() hook */
695
811
  passes: Record<string, any>
696
812
  /** Internal version counter for HMR - incremented by rebuildNodes/rebuildUniforms to bust memoization */
697
813
  _hmrVersion: number
@@ -741,6 +857,20 @@ interface Renderer {
741
857
  render: (scene: THREE$1.Scene, camera: THREE$1.Camera) => any
742
858
  }
743
859
 
860
+ //* Color Management Config ==============================
861
+
862
+ /**
863
+ * Color management configuration shared by both WebGL and WebGPU renderers.
864
+ */
865
+ interface ColorManagementConfig {
866
+ /**
867
+ * Color space assigned to 8-bit input textures (color maps).
868
+ * Defaults to sRGB. Most textures are authored in sRGB.
869
+ * @default THREE.SRGBColorSpace
870
+ */
871
+ textureColorSpace?: THREE$1.ColorSpace
872
+ }
873
+
744
874
  //* WebGL Renderer Props ==============================
745
875
 
746
876
  type DefaultGLProps = Omit<THREE$1.WebGLRendererParameters, 'canvas'> & {
@@ -751,7 +881,7 @@ type GLProps =
751
881
  | Renderer
752
882
  | ((defaultProps: DefaultGLProps) => Renderer)
753
883
  | ((defaultProps: DefaultGLProps) => Promise<Renderer>)
754
- | Partial<Properties<THREE$1.WebGLRenderer> | THREE$1.WebGLRendererParameters>
884
+ | (Partial<Properties<THREE$1.WebGLRenderer> | THREE$1.WebGLRendererParameters> & ColorManagementConfig)
755
885
 
756
886
  //* WebGPU Renderer Props ==============================
757
887
 
@@ -777,9 +907,9 @@ interface CanvasSchedulerConfig {
777
907
  }
778
908
 
779
909
  /**
780
- * Extended renderer configuration for multi-canvas support.
910
+ * Extended renderer configuration for multi-canvas support and color management.
781
911
  */
782
- interface RendererConfigExtended {
912
+ interface RendererConfigExtended extends ColorManagementConfig {
783
913
  /** Share renderer from another canvas (WebGPU only) */
784
914
  primaryCanvas?: string
785
915
  /** Canvas-level scheduler options */
@@ -844,8 +974,6 @@ interface RenderProps<TCanvas extends HTMLCanvasElement | OffscreenCanvas$1> {
844
974
  * @see https://threejs.org/docs/#api/en/renderers/WebGLRenderer.shadowMap
845
975
  */
846
976
  shadows?: boolean | 'basic' | 'percentage' | 'soft' | 'variance' | Partial<THREE$1.WebGLShadowMap>
847
- /** Color space assigned to 8-bit input textures (color maps). Defaults to sRGB. Most textures are authored in sRGB. */
848
- textureColorSpace?: THREE$1.ColorSpace
849
977
  /** Creates an orthographic camera */
850
978
  orthographic?: boolean
851
979
  /**
@@ -1098,7 +1226,7 @@ interface CanvasProps
1098
1226
  */
1099
1227
  resize?: Options
1100
1228
  /** The target where events are being subscribed to, default: the div that wraps canvas */
1101
- eventSource?: HTMLElement | React$1.RefObject<HTMLElement>
1229
+ eventSource?: HTMLElement | React$1.RefObject<HTMLElement | null>
1102
1230
  /** The event prefix that is cast into canvas pointer x/y events, default: "offset" */
1103
1231
  eventPrefix?: 'offset' | 'client' | 'page' | 'layer' | 'screen'
1104
1232
  /** Enable/disable automatic HMR refresh for TSL nodes and uniforms, default: true in dev */
@@ -1312,6 +1440,7 @@ declare global {
1312
1440
  | three_webgpu.Euler
1313
1441
  | three_webgpu.Quaternion
1314
1442
  | { x: number; y?: number; z?: number; w?: number } // Plain objects converted to vectors
1443
+ | { r: number; g: number; b: number; a?: number } // Plain objects converted to Color
1315
1444
  | Node // TSL nodes like color(), vec3(), float() for type casting
1316
1445
  | UniformNode
1317
1446
 
@@ -1357,34 +1486,34 @@ declare module 'three/tsl' {
1357
1486
  }
1358
1487
 
1359
1488
  /**
1360
- * PostProcessing Types for usePostProcessing hook (WebGPU only)
1489
+ * RenderPipeline Types for useRenderPipeline hook (WebGPU only)
1361
1490
  */
1362
1491
 
1363
1492
 
1364
1493
 
1365
1494
  declare global {
1366
- /** Pass record - stores TSL pass nodes for post-processing */
1495
+ /** Pass record - stores TSL pass nodes for render pipeline */
1367
1496
  type PassRecord = Record<string, any>
1368
1497
 
1369
1498
  /** Setup callback - runs first to configure MRT, create additional passes */
1370
- type PostProcessingSetupCallback = (state: RootState) => PassRecord | void
1499
+ type RenderPipelineSetupCallback = (state: RootState) => PassRecord | void
1371
1500
 
1372
1501
  /** Main callback - runs second to configure outputNode, create effect passes */
1373
- type PostProcessingMainCallback = (state: RootState) => PassRecord | void
1502
+ type RenderPipelineMainCallback = (state: RootState) => PassRecord | void
1374
1503
 
1375
- /** Return type for usePostProcessing hook */
1376
- interface UsePostProcessingReturn {
1504
+ /** Return type for useRenderPipeline hook */
1505
+ interface UseRenderPipelineReturn {
1377
1506
  /** Current passes from state */
1378
1507
  passes: PassRecord
1379
- /** PostProcessing instance (null if not initialized) */
1380
- postProcessing: any | null // THREE.PostProcessing
1508
+ /** RenderPipeline instance (null if not initialized) */
1509
+ renderPipeline: any | null // THREE.PostProcessing (will be THREE.RenderPipeline in future Three.js release)
1381
1510
  /** Clear all passes from state */
1382
1511
  clearPasses: () => void
1383
- /** Reset PostProcessing entirely (clears PP + passes) */
1512
+ /** Reset RenderPipeline entirely (clears PP + passes) */
1384
1513
  reset: () => void
1385
1514
  /** Re-run setup/main callbacks with current closure values */
1386
1515
  rebuild: () => void
1387
- /** True when PostProcessing is configured and ready */
1516
+ /** True when RenderPipeline is configured and ready */
1388
1517
  isReady: boolean
1389
1518
  }
1390
1519
  }
@@ -2004,6 +2133,8 @@ declare function Environment(props: EnvironmentProps): react_jsx_runtime.JSX.Ele
2004
2133
  declare function removeInteractivity(store: RootStore, object: Object3D): void;
2005
2134
  declare function createEvents(store: RootStore): {
2006
2135
  handlePointer: (name: string) => (event: DomEvent) => void;
2136
+ flushDeferredPointers: () => void;
2137
+ processDeferredPointer: (event: DomEvent, pointerId: number) => void;
2007
2138
  };
2008
2139
  /** Default R3F event manager for web */
2009
2140
  declare function createPointerEvents(store: RootStore): EventManager<HTMLElement>;
@@ -2444,11 +2575,16 @@ type UseTextureOptions<Url extends string[] | string | Record<string, string>> =
2444
2575
  /** Callback when texture(s) finish loading */
2445
2576
  onLoad?: (texture: MappedTextureType<Url>) => void;
2446
2577
  /**
2447
- * Cache the texture in R3F's global state for access via useTextures().
2448
- * When true:
2578
+ * Register the texture(s) in R3F's global texture registry for access via useTextures().
2579
+ * When true (the default):
2449
2580
  * - Textures persist until explicitly disposed
2450
- * - Returns existing cached textures if available (preserving modifications like colorSpace)
2451
- * @default false
2581
+ * - On mount, returns existing registered textures if available (preserving modifications like colorSpace)
2582
+ *
2583
+ * Reads are taken once at mount — a mounted `useTexture` does not re-render when the registry
2584
+ * changes. To react to registry swaps, use `useTextures(s => s.get(key))` instead.
2585
+ *
2586
+ * Pass `false` to opt out of registry enrollment entirely.
2587
+ * @default true
2452
2588
  */
2453
2589
  cache?: boolean;
2454
2590
  };
@@ -2472,15 +2608,18 @@ type UseTextureOptions<Url extends string[] | string | Record<string, string>> =
2472
2608
  * normal: '/normal.png'
2473
2609
  * })
2474
2610
  *
2475
- * // With caching - returns same texture object across components
2476
- * // Modifications (colorSpace, wrapS, etc.) are preserved
2477
- * const diffuse = useTexture('/diffuse.png', { cache: true })
2611
+ * // Textures are registered in the global registry by default — the same texture
2612
+ * // object is shared across components and modifications (colorSpace, wrapS, etc.) are preserved
2613
+ * const diffuse = useTexture('/diffuse.png')
2478
2614
  * diffuse.colorSpace = THREE.SRGBColorSpace
2479
2615
  *
2480
2616
  * // Another component gets the SAME texture with colorSpace already set
2481
- * const sameDiffuse = useTexture('/diffuse.png', { cache: true })
2617
+ * const sameDiffuse = useTexture('/diffuse.png')
2618
+ *
2619
+ * // Opt out of registry enrollment for a one-off texture
2620
+ * const scratch = useTexture('/scratch.png', { cache: false })
2482
2621
  *
2483
- * // Access cache directly
2622
+ * // Access the registry directly
2484
2623
  * const { get } = useTextures()
2485
2624
  * const cached = get('/diffuse.png')
2486
2625
  * ```
@@ -2497,63 +2636,80 @@ declare const Texture: ({ children, input, onLoad, cache, }: {
2497
2636
  cache?: boolean;
2498
2637
  }) => react_jsx_runtime.JSX.Element;
2499
2638
 
2500
- type TextureEntry = Texture$1 | {
2501
- value: Texture$1;
2502
- [key: string]: any;
2639
+ /** Accepted shapes for a registry read: a single key, a list of keys, or a name→key map. */
2640
+ type TextureInput = string | string[] | Record<string, string>;
2641
+ /** Result of a `get()` read, mirroring the input shape. */
2642
+ type TextureResult<Input extends TextureInput> = Input extends string ? Texture$1 | undefined : Input extends string[] ? (Texture$1 | undefined)[] : {
2643
+ [K in keyof Input]: Texture$1 | undefined;
2503
2644
  };
2645
+ /** Options for `dispose()`. */
2646
+ interface DisposeOptions {
2647
+ /** Dispose even if the texture still has active references (default false). */
2648
+ force?: boolean;
2649
+ }
2504
2650
  interface UseTexturesReturn {
2505
- /** Map of all textures currently in cache */
2506
- textures: Map<string, TextureEntry>;
2507
- /** Get a specific texture by key (usually URL) */
2508
- get: (key: string) => TextureEntry | undefined;
2509
- /** Check if a texture exists in cache */
2510
- has: (key: string) => boolean;
2511
- /** Add a texture to the cache */
2512
- add: (key: string, value: TextureEntry) => void;
2513
- /** Add multiple textures to the cache */
2514
- addMultiple: (items: Map<string, TextureEntry> | Record<string, TextureEntry>) => void;
2515
- /** Remove a texture from cache (does NOT dispose GPU resources) */
2516
- remove: (key: string) => void;
2517
- /** Remove multiple textures from cache */
2518
- removeMultiple: (keys: string[]) => void;
2519
- /** Dispose a texture's GPU resources and remove from cache */
2520
- dispose: (key: string) => void;
2521
- /** Dispose multiple textures */
2522
- disposeMultiple: (keys: string[]) => void;
2523
- /** Dispose ALL cached textures - use with caution */
2524
- disposeAll: () => void;
2651
+ /** The live registry Map (key Texture). Treat as read-only. */
2652
+ readonly all: Map<string, Texture$1>;
2653
+ /** Read one texture, an array of textures, or a name→texture record (mirrors the input shape). */
2654
+ get<Input extends TextureInput>(input: Input): TextureResult<Input>;
2655
+ /** Check whether a key exists in the registry. */
2656
+ has(key: string): boolean;
2657
+ /**
2658
+ * Register a texture (or a record of textures) that has no URL — e.g. a render
2659
+ * target or procedural texture. URL-loaded textures are registered automatically
2660
+ * by `useTexture` (registry enrollment is on by default).
2661
+ */
2662
+ add(key: string, texture: Texture$1): void;
2663
+ add(record: Record<string, Texture$1>): void;
2664
+ /**
2665
+ * Dispose a texture's GPU resources and remove it from the registry.
2666
+ * Refcount-aware: if the key is still in use by a mounted `useTexture` consumer it is
2667
+ * skipped (with a warning) unless `{ force: true }` is passed.
2668
+ * @returns true if disposed, false if skipped.
2669
+ */
2670
+ dispose(key: string, options?: DisposeOptions): boolean;
2671
+ /** Dispose every texture in the registry and clear it. Use on scene teardown. */
2672
+ disposeAll(): void;
2525
2673
  }
2526
2674
  /**
2527
- * Hook for managing the global texture cache in R3F state.
2675
+ * Reactive Texture registry load once with `useTexture`, reach the textures from anywhere.
2528
2676
  *
2529
- * Textures are stored in a Map with URL/path keys for efficient lookup.
2530
- * Useful for sharing texture references across materials and components.
2677
+ * This is a registry of plain `Texture` objects (not TSL nodes), so the same texture can feed
2678
+ * a material map, a heightmap sampler, or anything else. It does **not** load — pair it with
2679
+ * `useTexture` for loading (registry enrollment is on by default); `useTextures` is for access and lifecycle.
2680
+ *
2681
+ * The returned handle is **reactive**: the calling component re-renders when the registry
2682
+ * changes. Pass a selector to scope the subscription to a single read.
2531
2683
  *
2532
2684
  * @example
2533
2685
  * ```tsx
2534
- * const { textures, add, get, remove, has, dispose } = useTextures()
2686
+ * // Load + register once (anywhere in the tree) registered by default
2687
+ * useTexture({ map: '/diffuse.jpg', normalMap: '/normal.jpg' })
2535
2688
  *
2536
- * // Check if texture is already cached
2537
- * if (!has('/textures/diffuse.png')) {
2538
- * // Load with useTexture and cache: true, or manually add
2539
- * const tex = useTexture('/textures/diffuse.png', { cache: true })
2540
- * }
2689
+ * // Reach them from another component — record form lands straight into a material
2690
+ * const { map, normalMap } = useTextures().get({ map: '/diffuse.jpg', normalMap: '/normal.jpg' })
2691
+ * return <meshStandardMaterial map={map} normalMap={normalMap} />
2541
2692
  *
2542
- * // Access cached texture from anywhere
2543
- * const diffuse = get('/textures/diffuse.png')
2544
- * if (diffuse) material.map = diffuse
2693
+ * // A set of heightmaps at once
2694
+ * const [a, b, c] = useTextures().get(['/h0.png', '/h1.png', '/h2.png'])
2545
2695
  *
2546
- * // Remove from cache only (texture still in GPU memory)
2547
- * remove('/textures/old.png')
2696
+ * // Register a non-URL texture (render target / procedural)
2697
+ * useTextures().add('rt-main', renderTarget.texture)
2548
2698
  *
2549
- * // Fully dispose (frees GPU memory + removes from cache)
2550
- * dispose('/textures/unused.png')
2551
- *
2552
- * // Nuclear option - dispose everything
2553
- * disposeAll()
2699
+ * // Deliberate GPU cleanup (refcount-aware; force to override)
2700
+ * useTextures().dispose('/diffuse.jpg')
2701
+ * useTextures().disposeAll() // scene teardown
2554
2702
  * ```
2703
+ *
2704
+ * @remarks
2705
+ * **Future expansion:** an imperative async loader (e.g. `await useTextures().load('/x.jpg')`) is
2706
+ * intentionally not included yet. It would let non-React code (loading screens, dynamic streaming)
2707
+ * populate the registry without Suspense, at the cost of putting loading back into this hook. It
2708
+ * will be added only if a concrete consumer needs imperative loading; for now, loading lives in
2709
+ * `useTexture`.
2555
2710
  */
2556
2711
  declare function useTextures(): UseTexturesReturn;
2712
+ declare function useTextures<T>(selector: (registry: UseTexturesReturn) => T): T;
2557
2713
 
2558
2714
  /**
2559
2715
  * Creates a render target compatible with the current renderer.
@@ -2583,9 +2739,9 @@ declare function useTextures(): UseTexturesReturn;
2583
2739
  * const fbo = useRenderTarget(512, 256, { samples: 4 })
2584
2740
  * ```
2585
2741
  */
2586
- declare function useRenderTarget(options?: RenderTargetOptions): RenderTarget | WebGLRenderTarget;
2587
- declare function useRenderTarget(size: number, options?: RenderTargetOptions): RenderTarget | WebGLRenderTarget;
2588
- declare function useRenderTarget(width: number, height: number, options?: RenderTargetOptions): RenderTarget | WebGLRenderTarget;
2742
+ declare function useRenderTarget(options?: RenderTargetOptions): RenderTarget;
2743
+ declare function useRenderTarget(size: number, options?: RenderTargetOptions): RenderTarget;
2744
+ declare function useRenderTarget(width: number, height: number, options?: RenderTargetOptions): RenderTarget;
2589
2745
 
2590
2746
  /**
2591
2747
  * Returns the R3F Canvas' Zustand store. Useful for [transient updates](https://github.com/pmndrs/zustand#transient-updates-for-often-occurring-state-changes).
@@ -4250,4 +4406,4 @@ declare function isOnce(value: unknown): value is {
4250
4406
  declare function Canvas(props: CanvasProps): react_jsx_runtime.JSX.Element;
4251
4407
 
4252
4408
  export { Block, Canvas, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, ErrorBoundary, FROM_REF, IsObject, ONCE, Portal, R3F_BUILD_LEGACY, R3F_BUILD_WEBGPU, REACT_INTERNAL_PROPS, RESERVED_PROPS, three_d as ReactThreeFiber, Scheduler, Texture, _roots, act, addAfterEffect, addEffect, addTail, advance, applyProps, attach, buildGraph, calculateDpr, context, createEvents, createPointerEvents, createPortal, createRoot, createStore, detach, diffProps, dispose, createPointerEvents as events, extend, findInitialRoot, flushSync, fromRef, getInstanceProps, getPrimary, getPrimaryIds, getRootState, getScheduler, getUuidPrefix, hasConstructor, hasPrimary, invalidate, invalidateInstance, is, isColorRepresentation, isCopyable, isFromRef, isObject3D, isOnce, isOrthographicCamera, isRef, isRenderer, isTexture, isVectorLike, once, prepare, presetsObj, reconciler, registerPrimary, removeInteractivity, resolve, unmountComponentAtNode, unregisterPrimary, updateCamera, updateFrustum, useBridge, useEnvironment, useFrame, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useMutableCallback, useRenderTarget, useStore, useTexture, useTextures, useThree, waitForPrimary };
4253
- export type { Act, AddPhaseOptions, Args, ArgsProp, AttachFnType, AttachType, BackgroundConfig, BackgroundProp, BaseRendererProps, Bridge, Camera, CameraProps, CanvasProps, CanvasSchedulerConfig, Catalogue, Color, ComputeFunction, ConstructorRepresentation, DefaultGLProps, DefaultRendererProps, Disposable, DomEvent, Dpr, ElementProps, EnvironmentLoaderProps, EnvironmentProps, EquConfig, Euler, EventHandlers, EventManager, EventProps, Events, Extensions, FiberRoot, FilterFunction, FrameCallback, FrameControls, FrameNextCallback, FrameNextControls, FrameNextState, FrameState, FrameTimingState, Frameloop, GLProps, GLTFLike, GeometryProps, GeometryTransformProps, GlobalEffectType, GlobalRenderCallback, HostConfig, InferLoadResult, InjectState, InputLike, Instance, InstanceProps, InternalState, Intersection, IntersectionEvent, IsAllOptional, IsOptional, Layers, LegacyInternalState, LegacyRenderer, LegacyRootState, LoaderInstance, LoaderLike, LoaderResult, MappedTextureType, MathProps, MathRepresentation, MathType, MathTypes, Matrix3, Matrix4, Mutable, MutableOrReadonlyParameters, NodeProps, NonFunctionKeys, ObjectMap, OffscreenCanvas$1 as OffscreenCanvas, Overwrite, Performance, PointerCaptureTarget, PresetsType, PrimaryCanvasEntry, Properties, Quaternion, R3FRenderer, RaycastableRepresentation, ReactProps, ReconcilerRoot, RenderCallback, RenderProps, RenderTargetOptions, Renderer, RendererConfigExtended, RendererFactory, RendererProps, Root, RootOptions, RootState, RootStore, SchedulerApi, SetBlock, Size, Subscription, TSLNodeInput, TextureEntry, ThreeCamera, ThreeElement, ThreeElements, ThreeElementsImpl, ThreeEvent, ThreeExports, ThreeToJSXElements, UnblockProps, UseFrameNextOptions, UseFrameOptions, UseTextureOptions, UseTexturesReturn, Vector2, Vector3, Vector4, VectorRepresentation, Viewport, VisibilityEntry, WebGLDefaultProps, WebGLProps, WebGLShadowConfig, XRManager };
4409
+ export type { Act, AddPhaseOptions, Args, ArgsProp, AttachFnType, AttachType, BackgroundConfig, BackgroundProp, BaseRendererProps, Bridge, BufferLike, BufferRecord, BufferStore, Camera, CameraProps, CanvasProps, CanvasSchedulerConfig, Catalogue, Color, ColorManagementConfig, ComputeFunction, ConstructorRepresentation, DefaultGLProps, DefaultRendererProps, Disposable, DisposeOptions, DomEvent, Dpr, ElementProps, EnvironmentLoaderProps, EnvironmentProps, EquConfig, Euler, EventHandlers, EventManager, EventProps, Events, Extensions, FiberRoot, FilterFunction, FrameCallback, FrameControls, FrameNextCallback, FrameNextControls, FrameNextState, FrameState, FrameTimingState, Frameloop, GLProps, GLTFLike, GeometryProps, GeometryTransformProps, GlobalEffectType, GlobalRenderCallback, HostConfig, InferLoadResult, InjectState, InputLike, Instance, InstanceProps, InternalState, Intersection, IntersectionEvent, IsAllOptional, IsOptional, Layers, LegacyInternalState, LegacyRenderer, LegacyRootState, LoaderInstance, LoaderLike, LoaderResult, MappedTextureType, MathProps, MathRepresentation, MathType, MathTypes, Matrix3, Matrix4, Mutable, MutableOrReadonlyParameters, NodeProps, NonFunctionKeys, ObjectMap, OffscreenCanvas$1 as OffscreenCanvas, Overwrite, Performance, PointerCaptureTarget, PointerState, PresetsType, PrimaryCanvasEntry, Properties, Quaternion, R3FRenderer, RaycastableRepresentation, ReactProps, ReconcilerRoot, RenderCallback, RenderProps, RenderTargetOptions, Renderer, RendererConfigExtended, RendererFactory, RendererProps, Root, RootOptions, RootState, RootStore, SchedulerApi, SetBlock, Size, StorageLike, StorageRecord, StorageStore, Subscription, TSLNodeInput, TextureInput, TextureResult, ThreeCamera, ThreeElement, ThreeElements, ThreeElementsImpl, ThreeEvent, ThreeExports, ThreeToJSXElements, UnblockProps, UseFrameNextOptions, UseFrameOptions, UseTextureOptions, UseTexturesReturn, Vector2, Vector3, Vector4, VectorRepresentation, Viewport, VisibilityEntry, WebGLDefaultProps, WebGLProps, WebGLShadowConfig, XRManager, XRPointerConfig };