@react-three/tsl 10.0.0-canary.87166dc → 10.0.0-canary.88b1ca7
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.cjs +221 -95
- package/dist/index.d.cts +307 -66
- package/dist/index.d.mts +307 -66
- package/dist/index.d.ts +307 -66
- package/dist/index.mjs +222 -96
- package/package.json +2 -2
- package/readme.md +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { RootState, useStore } from '@react-three/fiber/extension';
|
|
2
2
|
import * as three_webgpu from 'three/webgpu';
|
|
3
3
|
import { Node, StorageTexture, Storage3DTexture, StorageArrayTexture, Data3DTexture, RenderPipeline, Vector2, Vector3, Vector4, Color, Matrix2, Matrix3, Matrix4 } from 'three/webgpu';
|
|
4
|
+
import { Fn } from 'three/tsl';
|
|
4
5
|
|
|
5
6
|
//* Buffer Types (useBuffers) ========================================
|
|
6
7
|
|
|
@@ -57,6 +58,40 @@ type NodeRecord<T extends NodeLike = NodeLike> = Record<string, T>
|
|
|
57
58
|
*/
|
|
58
59
|
type NodeStore = Record<string, NodeLike | NodeRecord>
|
|
59
60
|
|
|
61
|
+
/** What `Fn()` returns (its members are what matters here, not its signature). */
|
|
62
|
+
type FnNodeLike = ReturnType<typeof Fn>
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* What an unregistered node read is: `useNodes().wobble`, `useNodes('fx').blur`, a creator's
|
|
66
|
+
* `nodes.wobble`, `state.nodes.wobble` in `useFrame`.
|
|
67
|
+
*
|
|
68
|
+
* Why it is loose: the read goes through a string name, and TypeScript cannot know what the entry
|
|
69
|
+
* under that name holds: a float, a vec3, a texture sample, or an `Fn()` to call. three's types
|
|
70
|
+
* only give operator methods to a node whose node type is known, and only an `Fn()` can be called,
|
|
71
|
+
* so the broad `NodeLike` allowed neither and every read needed a cast.
|
|
72
|
+
*
|
|
73
|
+
* So this has every member that any of three's nodes or an `Fn()` has, each typed `any`, and can
|
|
74
|
+
* be called. `nodes.wobble.mul(2)`, `material.colorNode = nodes.wobble` and `nodes.rimLightFn()`
|
|
75
|
+
* compile, and a misspelt member is still an error. It is a deliberate simplification: results of
|
|
76
|
+
* its own methods and calls are `any`.
|
|
77
|
+
*
|
|
78
|
+
* A single `as` gives it an exact type: `nodes.wobble as Node<'vec3'>`, `nodes.fn as typeof fn`.
|
|
79
|
+
* For exact types without casts, register the nodes (`nodes` / `nodeScopes` in `Register`) or pass
|
|
80
|
+
* a schema to the reader: `useNodes<{ blur: Node<'vec4'> }>('fx')`, `nodes.scope<Schema>('fx')`.
|
|
81
|
+
*/
|
|
82
|
+
interface LooseNode extends TSLLooseMembers<Node<TSLNodeTypeName> | FnNodeLike> {
|
|
83
|
+
(...args: any[]): any
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* A root entry of an unregistered node map: a node (its members) or a scope of nodes (any other
|
|
88
|
+
* name), since the type cannot tell which a name holds.
|
|
89
|
+
*/
|
|
90
|
+
type LooseNodeEntry = LooseNode & { readonly [name: string]: LooseNode }
|
|
91
|
+
|
|
92
|
+
/** An unregistered node map read: `state.nodes`, `useNodes()`. */
|
|
93
|
+
type LooseNodeStore = Record<string, LooseNodeEntry>
|
|
94
|
+
|
|
60
95
|
//* Storage Types (useGPUStorage) ========================================
|
|
61
96
|
|
|
62
97
|
/**
|
|
@@ -93,17 +128,23 @@ type StorageStore = Record<string, StorageLike | StorageRecord>
|
|
|
93
128
|
*/
|
|
94
129
|
interface TSLRootState {
|
|
95
130
|
/**
|
|
96
|
-
* TSL uniform nodes - root-level uniforms + scoped sub-objects. Use useUniforms().
|
|
97
|
-
*
|
|
98
|
-
* needs no cast.
|
|
131
|
+
* TSL uniform nodes - root-level uniforms + scoped sub-objects. Use useUniforms(). Each read is a
|
|
132
|
+
* `LooseUniformNode`, usable without casts, or typed by name once you register them (see
|
|
133
|
+
* `Register`), so `useFrame(({ uniforms }) => uniforms.uTime.value)` needs no cast either way.
|
|
99
134
|
*/
|
|
100
135
|
uniforms: AppUniforms
|
|
101
|
-
/**
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
136
|
+
/**
|
|
137
|
+
* TSL nodes - root-level nodes + scoped sub-objects. Use useNodes(). Each read is a `LooseNode`,
|
|
138
|
+
* usable without casts, or typed by name once you register your nodes (see `Register`).
|
|
139
|
+
*/
|
|
140
|
+
nodes: AppNodes
|
|
141
|
+
/** Buffers - root-level buffers + scoped sub-objects. Use useBuffers(). Typed by name once registered */
|
|
142
|
+
buffers: AppBuffers
|
|
143
|
+
/**
|
|
144
|
+
* GPU storage (textures, etc.) - root-level storage + scoped sub-objects. Use useGPUStorage().
|
|
145
|
+
* Typed by name once registered
|
|
146
|
+
*/
|
|
147
|
+
gpuStorage: AppGPUStorage
|
|
107
148
|
/** Internal: bumped by hot reloads and rebuilds to re-run creators */
|
|
108
149
|
_hmrVersion: number
|
|
109
150
|
/** The canvas's RenderPipeline, once useRenderPipeline created one. Per canvas, not shared. */
|
|
@@ -233,6 +274,69 @@ declare global {
|
|
|
233
274
|
*/
|
|
234
275
|
type UniformStore = Record<string, UniformNode | UniformRecord>
|
|
235
276
|
|
|
277
|
+
//* Loose reads ==============================
|
|
278
|
+
|
|
279
|
+
/** Every shader node type three's TSL declarations type separately. */
|
|
280
|
+
type TSLNodeTypeName =
|
|
281
|
+
| 'float'
|
|
282
|
+
| 'int'
|
|
283
|
+
| 'uint'
|
|
284
|
+
| 'bool'
|
|
285
|
+
| 'vec2'
|
|
286
|
+
| 'vec3'
|
|
287
|
+
| 'vec4'
|
|
288
|
+
| 'ivec2'
|
|
289
|
+
| 'ivec3'
|
|
290
|
+
| 'ivec4'
|
|
291
|
+
| 'uvec2'
|
|
292
|
+
| 'uvec3'
|
|
293
|
+
| 'uvec4'
|
|
294
|
+
| 'bvec2'
|
|
295
|
+
| 'bvec3'
|
|
296
|
+
| 'bvec4'
|
|
297
|
+
| 'color'
|
|
298
|
+
| 'mat2'
|
|
299
|
+
| 'mat3'
|
|
300
|
+
| 'mat4'
|
|
301
|
+
|
|
302
|
+
/** Every member of every constituent of `T`, each typed `any`. */
|
|
303
|
+
type TSLLooseMembers<T> = { [K in T extends unknown ? keyof T : never]: any }
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* What an unregistered uniform read is: `useUniforms().uTime`, `useUniforms('fx').blur`,
|
|
307
|
+
* `useUniform('uTime')`, a creator's `uniforms.uTime`, `state.uniforms.uTime` in `useFrame`.
|
|
308
|
+
*
|
|
309
|
+
* Why it is loose: the read goes through a string name, and TypeScript cannot know what a
|
|
310
|
+
* runtime entry under that name holds. three's types only give the operator methods (`.mul`,
|
|
311
|
+
* `.add`, swizzles, `.toVar()`, ...) to a node whose node type is known, so `UniformNode<unknown>`
|
|
312
|
+
* had none of them and every read needed a cast.
|
|
313
|
+
*
|
|
314
|
+
* So this has every member that any of three's uniform nodes has (float, vec3, color, mat4, ...),
|
|
315
|
+
* each typed `any`. Every operator, TSL function and material slot accepts it, and a misspelt member
|
|
316
|
+
* (`.valeu`) is still an error. It is a deliberate simplification: results of its own methods are
|
|
317
|
+
* `any`, and nothing checks that `cross()` gets a vec3.
|
|
318
|
+
*
|
|
319
|
+
* It converts to an exact type with a single `as`, since every member is `any`:
|
|
320
|
+
* `uniforms.uColor as UniformNode<'color', Color>`, or `as Node<'vec3'>`. A node typed as a float
|
|
321
|
+
* uniform would cover the operators with exact result types, but three's node types are not
|
|
322
|
+
* comparable to one another, so it could only be cast through `unknown`.
|
|
323
|
+
*
|
|
324
|
+
* Exact types without casts: register the uniforms (`Register` in `@react-three/tsl`, which also
|
|
325
|
+
* catches typos in the name), or pass a schema to the reader (`useUniforms<{ blur: number }>('fx')`,
|
|
326
|
+
* `useUniform<Color>('uColor')`, `uniforms.scope<{ uHealth: UniformNode<'float', number> }>('player')`).
|
|
327
|
+
*/
|
|
328
|
+
interface LooseUniformNode extends TSLLooseMembers<three_webgpu.UniformNode<TSLNodeTypeName, any>> {}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* A root entry of an unregistered uniform map: a uniform (its members) or a scope of uniforms (any
|
|
332
|
+
* other name), since the type cannot tell which a name holds. `uniforms.uTime.mul(2)` and
|
|
333
|
+
* `uniforms.player.uHealth` both read.
|
|
334
|
+
*/
|
|
335
|
+
type LooseUniformEntry = LooseUniformNode & { readonly [name: string]: LooseUniformNode }
|
|
336
|
+
|
|
337
|
+
/** An unregistered uniform map read: `state.uniforms`, `useUniforms()`. */
|
|
338
|
+
type LooseUniformStore = Record<string, LooseUniformEntry>
|
|
339
|
+
|
|
236
340
|
/**
|
|
237
341
|
* Helper to safely access a uniform node from the store.
|
|
238
342
|
* Use this when accessing state.uniforms to get proper typing.
|
|
@@ -314,13 +418,18 @@ declare global {
|
|
|
314
418
|
/**
|
|
315
419
|
* State passed to pipeline callbacks after the active pipeline has been created.
|
|
316
420
|
*
|
|
421
|
+
* The same state `useNodes` / `useLocalNodes` creators get: `uniforms`, `nodes`, `buffers`,
|
|
422
|
+
* `gpuStorage` and `textures` are the wrapped views, entries staged earlier in the render
|
|
423
|
+
* included. Reads through them are tracked, so a read resource that appears, is replaced or is
|
|
424
|
+
* removed re-runs the callbacks.
|
|
425
|
+
*
|
|
317
426
|
* `passes.scenePass` is required here: the hook installs the default scene pass before either
|
|
318
427
|
* callback runs, so callbacks can use it without a guard or a cast.
|
|
319
428
|
*
|
|
320
429
|
* `renderer` is narrowed to `WebGPURenderer` and `isLegacy` to `false`: the hook throws under
|
|
321
430
|
* the legacy renderer before either callback can run, so a callback never sees WebGL.
|
|
322
431
|
*/
|
|
323
|
-
type RenderPipelineCallbackState =
|
|
432
|
+
type RenderPipelineCallbackState = CreatorState & {
|
|
324
433
|
renderPipeline: ThreeRenderPipeline
|
|
325
434
|
passes: PassRecord & { scenePass: ScenePassNode }
|
|
326
435
|
renderer: three_webgpu.WebGPURenderer
|
|
@@ -331,7 +440,7 @@ declare global {
|
|
|
331
440
|
* What a callback may return to register entries into `state.passes`.
|
|
332
441
|
*
|
|
333
442
|
* `scenePass` is reserved. The hook owns that entry and its lifecycle: it caches the pass it
|
|
334
|
-
* created, and `rebuild()
|
|
443
|
+
* created, and `rebuild()`, `reset()` and unmount dispose that cached pass. A callback overwriting the
|
|
335
444
|
* store entry would leave the store pointing at a node the hook never disposes, and the hook
|
|
336
445
|
* disposing a pass nothing references. So returning it is a type error.
|
|
337
446
|
*/
|
|
@@ -343,15 +452,31 @@ declare global {
|
|
|
343
452
|
/** Main callback - runs second to configure outputNode, create effect passes */
|
|
344
453
|
type RenderPipelineMainCallback = (state: RenderPipelineCallbackState) => RegisteredPasses | void
|
|
345
454
|
|
|
455
|
+
/** Options for a configuring useRenderPipeline call */
|
|
456
|
+
interface RenderPipelineOptions {
|
|
457
|
+
/**
|
|
458
|
+
* Keep the pipeline rendering after the component unmounts, until another component configures
|
|
459
|
+
* the canvas's pipeline, `reset()`, or the canvas unmounts. Off by default: an owner frees its
|
|
460
|
+
* pipeline and scene pass when it unmounts. A remount is a new owner with a new pipeline either way.
|
|
461
|
+
*/
|
|
462
|
+
persist?: boolean
|
|
463
|
+
}
|
|
464
|
+
|
|
346
465
|
/** The imperative half of useRenderPipeline's return value, present in every state */
|
|
347
466
|
interface UseRenderPipelineActions {
|
|
348
467
|
/** Current passes from state */
|
|
349
468
|
passes: PassRecord
|
|
350
|
-
/** Clear
|
|
469
|
+
/** Clear the passes record. From a reader, acts on the pipeline that is rendering. */
|
|
351
470
|
clearPasses: () => void
|
|
352
|
-
/**
|
|
471
|
+
/**
|
|
472
|
+
* Free the pipeline and its scene pass now. The previous owner takes over, or the canvas
|
|
473
|
+
* goes back to plain rendering. From a reader, acts on the pipeline that is rendering.
|
|
474
|
+
*/
|
|
353
475
|
reset: () => void
|
|
354
|
-
/**
|
|
476
|
+
/**
|
|
477
|
+
* Re-run setup/main callbacks with current closure values, against a fresh scene pass. From
|
|
478
|
+
* a reader, rebuilds the pipeline that is rendering.
|
|
479
|
+
*/
|
|
355
480
|
rebuild: () => void
|
|
356
481
|
}
|
|
357
482
|
|
|
@@ -371,9 +496,9 @@ declare global {
|
|
|
371
496
|
renderPipeline: ThreeRenderPipeline
|
|
372
497
|
}
|
|
373
498
|
| {
|
|
374
|
-
/** False until
|
|
499
|
+
/** False until a configuring call has created the pipeline */
|
|
375
500
|
isReady: false
|
|
376
|
-
/**
|
|
501
|
+
/** No owner yet, or torn down by reset() or the owner unmounting */
|
|
377
502
|
renderPipeline: null
|
|
378
503
|
}
|
|
379
504
|
)
|
|
@@ -395,13 +520,14 @@ type ResourceLeafGuard<T> = (value: unknown) => value is T;
|
|
|
395
520
|
*
|
|
396
521
|
* @example
|
|
397
522
|
* ```tsx
|
|
398
|
-
* // With uniforms registered (see `Register` and the Typed
|
|
523
|
+
* // With uniforms registered (see `Register` and the Typed Resources guide), reads are typed by name
|
|
399
524
|
* useLocalNodes(({ uniforms }) => ({
|
|
400
525
|
* wobble: sin(uniforms.uTime.mul(2)),
|
|
401
526
|
* playerHealth: uniforms.scope('player').uHealth, // or uniforms.player.uHealth
|
|
402
527
|
* }), [])
|
|
403
528
|
*
|
|
404
|
-
* // Without registration
|
|
529
|
+
* // Without registration a read is loose: TSL takes it as is. A scope schema makes it exact.
|
|
530
|
+
* useLocalNodes(({ uniforms }) => ({ wobble: sin(uniforms.uTime.mul(2)) }), [])
|
|
405
531
|
* useLocalNodes(({ uniforms }) => {
|
|
406
532
|
* const player = uniforms.scope<{ uHealth: UniformNode<'float', number> }>('player')
|
|
407
533
|
* return { damage: player.uHealth.mul(2) }
|
|
@@ -414,16 +540,19 @@ type ResourceLeafGuard<T> = (value: unknown) => value is T;
|
|
|
414
540
|
* Property access returns `T` (assumes leaf node).
|
|
415
541
|
* Use `.scope(key)` for nested object access.
|
|
416
542
|
*
|
|
543
|
+
* `TLeaf` is what a scope schema must hold (`scope<{ uHealth: UniformNode<'float', number> }>()`),
|
|
544
|
+
* `TRead` what a leaf reads as without one. They differ for uniforms and nodes, whose unregistered
|
|
545
|
+
* reads are the loose `LooseUniformNode` / `LooseNode` (see those types for why).
|
|
417
546
|
*/
|
|
418
|
-
type ScopedStoreMethods<TLeaf> = {
|
|
547
|
+
type ScopedStoreMethods<TLeaf, TRead extends TLeaf = TLeaf> = {
|
|
419
548
|
/** Access a nested scope by key. Returns empty wrapper if scope doesn't exist. */
|
|
420
|
-
scope<TScope extends Record<string, TLeaf> = Record<string,
|
|
549
|
+
scope<TScope extends Record<string, TLeaf> = Record<string, TRead>>(key: string): ScopedStoreType<TLeaf, TScope, TRead>;
|
|
421
550
|
/** Check if a key exists in the store */
|
|
422
551
|
has(key: string): boolean;
|
|
423
552
|
/** Get all keys in the store */
|
|
424
553
|
keys(): string[];
|
|
425
554
|
};
|
|
426
|
-
type ScopedStoreType<TLeaf, TEntries extends Record<string, TLeaf> = Record<string, TLeaf
|
|
555
|
+
type ScopedStoreType<TLeaf, TEntries extends Record<string, TLeaf> = Record<string, TLeaf>, TRead extends TLeaf = TLeaf> = Readonly<TEntries> & ScopedStoreMethods<TLeaf, TRead>;
|
|
427
556
|
interface ScopedStoreData<TLeaf> {
|
|
428
557
|
[key: string]: TLeaf | ScopedStoreData<TLeaf>;
|
|
429
558
|
}
|
|
@@ -440,18 +569,18 @@ declare function createScopedStore<TLeaf>(data: ScopedStoreData<TLeaf>, isLeaf:
|
|
|
440
569
|
type CreatorState = Omit<RootState, 'uniforms' | 'nodes' | 'buffers' | 'gpuStorage'> & {
|
|
441
570
|
/** Type-safe uniform access - property access returns UniformNode, typed by name when registered */
|
|
442
571
|
uniforms: CreatorUniforms;
|
|
443
|
-
/**
|
|
444
|
-
nodes:
|
|
445
|
-
/**
|
|
446
|
-
buffers:
|
|
447
|
-
/**
|
|
448
|
-
gpuStorage:
|
|
572
|
+
/** Node access: each read a `LooseNode` (callable, every operator), typed by name when registered */
|
|
573
|
+
nodes: CreatorNodes;
|
|
574
|
+
/** Buffer access: typed by name when registered, BufferLike (typed arrays, attributes, nodes) otherwise */
|
|
575
|
+
buffers: CreatorBuffers;
|
|
576
|
+
/** GPU storage access: typed by name when registered, StorageLike (storage textures, nodes) otherwise */
|
|
577
|
+
gpuStorage: CreatorGPUStorage;
|
|
449
578
|
};
|
|
450
579
|
|
|
451
580
|
/**
|
|
452
|
-
* @fileoverview Typed
|
|
581
|
+
* @fileoverview Typed TSL resources by registration (the TanStack Router `Register` pattern).
|
|
453
582
|
*
|
|
454
|
-
* Nothing registered: every type below falls back to
|
|
583
|
+
* Nothing registered: every type below falls back to loose reads (`LooseUniformNode`, `LooseNode`).
|
|
455
584
|
* Registered once, anywhere in the app:
|
|
456
585
|
*
|
|
457
586
|
* ```ts
|
|
@@ -471,14 +600,25 @@ type CreatorState = Omit<RootState, 'uniforms' | 'nodes' | 'buffers' | 'gpuStora
|
|
|
471
600
|
*
|
|
472
601
|
* then `useUniforms().uTime`, `useUniforms('player').uHealth`, `useUniform('uTime')`,
|
|
473
602
|
* `useFrame(({ uniforms }) => uniforms.uTime)`, `useThree((s) => s.uniforms.uTime)` and a creator's
|
|
474
|
-
* `({ uniforms }) => uniforms.uTime` are typed by name, with no generics.
|
|
603
|
+
* `({ uniforms }) => uniforms.uTime` are typed by name, with no generics. Nodes register the same
|
|
604
|
+
* way, by their node types: `nodes: { wobble: Node<'float'>; rimLight: typeof rimLightFn }` and
|
|
605
|
+
* `nodeScopes: { fx: { blur: Node<'vec4'> } }`, and so do buffers (`buffers` / `bufferScopes`) and
|
|
606
|
+
* GPU storage (`gpuStorage` / `gpuStorageScopes`). Docs: docs/webgpu/typed-resources.mdx.
|
|
607
|
+
*
|
|
608
|
+
* Unregistered reads are loose: `LooseUniformNode` / `LooseNode`, which every operator accepts and
|
|
609
|
+
* a single `as` makes exact (see those types for why).
|
|
475
610
|
*/
|
|
476
611
|
|
|
477
612
|
/**
|
|
478
|
-
* Augment this to type
|
|
613
|
+
* Augment this to type TSL resources by name. Recognised keys:
|
|
479
614
|
* - `uniforms`: the root-level uniform inputs (e.g. `typeof globalUniforms`)
|
|
480
|
-
* - `scopes`: named scopes and their inputs (e.g. `{ player: typeof playerUniforms }`)
|
|
481
|
-
* - `
|
|
615
|
+
* - `scopes`: named uniform scopes and their inputs (e.g. `{ player: typeof playerUniforms }`)
|
|
616
|
+
* - `nodes`: the root-level nodes by node type (e.g. `{ wobble: Node<'float'>; rim: typeof rimFn }`)
|
|
617
|
+
* - `nodeScopes`: named node scopes and their nodes (e.g. `{ fx: { blur: Node<'vec4'> } }`)
|
|
618
|
+
* - `buffers` / `bufferScopes`: buffers by name (e.g. `{ positions: StorageBufferNode<'vec3'> }`)
|
|
619
|
+
* - `gpuStorage` / `gpuStorageScopes`: GPU storage by name (e.g. `{ heightMap: StorageTexture }`)
|
|
620
|
+
* - `strict`: `false` makes unregistered root keys loose instead of errors (default: strict), for
|
|
621
|
+
* every resource family alike
|
|
482
622
|
*/
|
|
483
623
|
interface Register {
|
|
484
624
|
}
|
|
@@ -503,9 +643,11 @@ type TypedUniforms = UniformNodesFor<RegisteredUniforms> & {
|
|
|
503
643
|
};
|
|
504
644
|
/**
|
|
505
645
|
* What `state.uniforms` and `useUniforms()` are: the registered shape (strict by default, so a typo
|
|
506
|
-
* is an error), or
|
|
646
|
+
* is an error), or the loose `LooseUniformStore` when nothing is registered. With `strict: false`
|
|
647
|
+
* an unregistered root key reads loose too. A loose read is a `LooseUniformNode`: every operator and
|
|
648
|
+
* material slot accepts it, and a single `as` gives it an exact type (see that type for why).
|
|
507
649
|
*/
|
|
508
|
-
type AppUniforms = IsRegistered extends true ? IsStrict extends true ? TypedUniforms : TypedUniforms &
|
|
650
|
+
type AppUniforms = IsRegistered extends true ? IsStrict extends true ? TypedUniforms : TypedUniforms & LooseUniformStore : LooseUniformStore;
|
|
509
651
|
/** Creator input at root level: new keys are free, registered keys must keep their registered type. */
|
|
510
652
|
type RootUniformInput = Partial<RegisteredUniforms> & UniformInputRecord;
|
|
511
653
|
/** Creator input for scope `S`: checked against the registered scope, free for any other scope. */
|
|
@@ -515,13 +657,101 @@ type RegisteredScopeUniforms<S extends keyof RegisteredScopes> = UniformNodesFor
|
|
|
515
657
|
/** A registered root uniform's node. */
|
|
516
658
|
type RegisteredUniform<K extends keyof RegisteredUniforms> = UniformNodesFor<RegisteredUniforms>[K];
|
|
517
659
|
/**
|
|
518
|
-
* `uniforms` in a creator (`useNodes(({ uniforms }) => ...)`). Unregistered: any name
|
|
519
|
-
* `
|
|
660
|
+
* `uniforms` in a creator (`useNodes(({ uniforms }) => ...)`). Unregistered: any name reads as a
|
|
661
|
+
* `LooseUniformNode` (or, by dot access, a scope of them), and `.scope(name)` as a record of them
|
|
662
|
+
* unless given a schema. Registered: typed by name like `state.uniforms`, and `.scope(name)` is
|
|
520
663
|
* typed for registered scopes.
|
|
521
664
|
*/
|
|
522
665
|
type CreatorUniforms = IsRegistered extends true ? {
|
|
523
|
-
scope<S extends keyof RegisteredScopes & string>(key: S): ScopedStoreType<UniformNode, RegisteredScopeUniforms<S
|
|
524
|
-
} & Readonly<AppUniforms> & ScopedStoreMethods<UniformNode> : ScopedStoreType<UniformNode>;
|
|
666
|
+
scope<S extends keyof RegisteredScopes & string>(key: S): ScopedStoreType<UniformNode, RegisteredScopeUniforms<S>, LooseUniformNode>;
|
|
667
|
+
} & Readonly<AppUniforms> & ScopedStoreMethods<UniformNode, LooseUniformNode> : ScopedStoreType<UniformNode, LooseUniformStore, LooseUniformNode>;
|
|
668
|
+
/** The registered root-level nodes, or `{}` when none are registered. */
|
|
669
|
+
type RegisteredNodes = Register extends {
|
|
670
|
+
nodes: infer N extends NodeRecord;
|
|
671
|
+
} ? N : {};
|
|
672
|
+
/** The registered node scopes and their nodes, or `{}` when none are registered. */
|
|
673
|
+
type RegisteredNodeScopes = Register extends {
|
|
674
|
+
nodeScopes: infer S extends Record<string, NodeRecord>;
|
|
675
|
+
} ? S : {};
|
|
676
|
+
type IsNodesRegistered = Register extends {
|
|
677
|
+
nodes: any;
|
|
678
|
+
} | {
|
|
679
|
+
nodeScopes: any;
|
|
680
|
+
} ? true : false;
|
|
681
|
+
type TypedNodes = RegisteredNodes & RegisteredNodeScopes;
|
|
682
|
+
/**
|
|
683
|
+
* What `state.nodes` and `useNodes()` are: the registered shape (strict by default, so a typo is an
|
|
684
|
+
* error), or the loose `LooseNodeStore` when no nodes are registered. With `strict: false` an
|
|
685
|
+
* unregistered root key reads loose too.
|
|
686
|
+
*/
|
|
687
|
+
type AppNodes = IsNodesRegistered extends true ? IsStrict extends true ? TypedNodes : TypedNodes & LooseNodeStore : LooseNodeStore;
|
|
688
|
+
/** Creator output at root level: new keys are free, registered keys must keep their registered type. */
|
|
689
|
+
type RootNodeInput = Partial<RegisteredNodes> & NodeRecord;
|
|
690
|
+
/** Creator output for scope `S`: checked against the registered scope, free for any other scope. */
|
|
691
|
+
type ScopeNodeInput<S extends string> = S extends keyof RegisteredNodeScopes ? Partial<RegisteredNodeScopes[S]> : unknown;
|
|
692
|
+
/**
|
|
693
|
+
* `nodes` in a creator. Unregistered: any name reads as a `LooseNode` (or, by dot access, a scope of
|
|
694
|
+
* them). Registered: typed by name like `state.nodes`, and `.scope(name)` is typed for registered
|
|
695
|
+
* scopes.
|
|
696
|
+
*/
|
|
697
|
+
type CreatorNodes = IsNodesRegistered extends true ? {
|
|
698
|
+
scope<S extends keyof RegisteredNodeScopes & string>(key: S): ScopedStoreType<NodeLike, RegisteredNodeScopes[S], LooseNode>;
|
|
699
|
+
} & Readonly<AppNodes> & ScopedStoreMethods<NodeLike, LooseNode> : ScopedStoreType<NodeLike, LooseNodeStore, LooseNode>;
|
|
700
|
+
/** A node reader's result for an explicit schema `T`, or loose nodes when none was given. */
|
|
701
|
+
type ReadNodes<T extends NodeRecord> = NodeRecord extends T ? Record<string, LooseNode> : T;
|
|
702
|
+
/** The registered root-level buffers, or `{}` when none are registered. */
|
|
703
|
+
type RegisteredBuffers = Register extends {
|
|
704
|
+
buffers: infer B extends BufferRecord;
|
|
705
|
+
} ? B : {};
|
|
706
|
+
/** The registered buffer scopes and their buffers, or `{}` when none are registered. */
|
|
707
|
+
type RegisteredBufferScopes = Register extends {
|
|
708
|
+
bufferScopes: infer S extends Record<string, BufferRecord>;
|
|
709
|
+
} ? S : {};
|
|
710
|
+
type IsBuffersRegistered = Register extends {
|
|
711
|
+
buffers: any;
|
|
712
|
+
} | {
|
|
713
|
+
bufferScopes: any;
|
|
714
|
+
} ? true : false;
|
|
715
|
+
type TypedBuffers = RegisteredBuffers & RegisteredBufferScopes;
|
|
716
|
+
/** What `state.buffers` and `useBuffers()` are: the registered shape, or `BufferStore` when none are. */
|
|
717
|
+
type AppBuffers = IsBuffersRegistered extends true ? IsStrict extends true ? TypedBuffers : TypedBuffers & BufferStore : BufferStore;
|
|
718
|
+
/** Creator output at root level: new keys are free, registered keys must keep their registered type. */
|
|
719
|
+
type RootBufferInput = Partial<RegisteredBuffers> & BufferRecord;
|
|
720
|
+
/** Creator output for scope `S`: checked against the registered scope, free for any other scope. */
|
|
721
|
+
type ScopeBufferInput<S extends string> = S extends keyof RegisteredBufferScopes ? Partial<RegisteredBufferScopes[S]> : unknown;
|
|
722
|
+
/** `buffers` in a creator: typed by name when registered, `BufferLike` reads otherwise. */
|
|
723
|
+
type CreatorBuffers = IsBuffersRegistered extends true ? {
|
|
724
|
+
scope<S extends keyof RegisteredBufferScopes & string>(key: S): ScopedStoreType<BufferLike, RegisteredBufferScopes[S]>;
|
|
725
|
+
} & Readonly<AppBuffers> & ScopedStoreMethods<BufferLike> : ScopedStoreType<BufferLike>;
|
|
726
|
+
/** The registered root-level GPU storage, or `{}` when none is registered. */
|
|
727
|
+
type RegisteredGPUStorage = Register extends {
|
|
728
|
+
gpuStorage: infer G extends StorageRecord;
|
|
729
|
+
} ? G : {};
|
|
730
|
+
/** The registered GPU storage scopes and their entries, or `{}` when none are registered. */
|
|
731
|
+
type RegisteredGPUStorageScopes = Register extends {
|
|
732
|
+
gpuStorageScopes: infer S extends Record<string, StorageRecord>;
|
|
733
|
+
} ? S : {};
|
|
734
|
+
type IsGPUStorageRegistered = Register extends {
|
|
735
|
+
gpuStorage: any;
|
|
736
|
+
} | {
|
|
737
|
+
gpuStorageScopes: any;
|
|
738
|
+
} ? true : false;
|
|
739
|
+
type TypedGPUStorage = RegisteredGPUStorage & RegisteredGPUStorageScopes;
|
|
740
|
+
/** What `state.gpuStorage` and `useGPUStorage()` are: the registered shape, or `StorageStore`. */
|
|
741
|
+
type AppGPUStorage = IsGPUStorageRegistered extends true ? IsStrict extends true ? TypedGPUStorage : TypedGPUStorage & StorageStore : StorageStore;
|
|
742
|
+
/** Creator output at root level: new keys are free, registered keys must keep their registered type. */
|
|
743
|
+
type RootGPUStorageInput = Partial<RegisteredGPUStorage> & StorageRecord;
|
|
744
|
+
/** Creator output for scope `S`: checked against the registered scope, free for any other scope. */
|
|
745
|
+
type ScopeGPUStorageInput<S extends string> = S extends keyof RegisteredGPUStorageScopes ? Partial<RegisteredGPUStorageScopes[S]> : unknown;
|
|
746
|
+
/** `gpuStorage` in a creator: typed by name when registered, `StorageLike` reads otherwise. */
|
|
747
|
+
type CreatorGPUStorage = IsGPUStorageRegistered extends true ? {
|
|
748
|
+
scope<S extends keyof RegisteredGPUStorageScopes & string>(key: S): ScopedStoreType<StorageLike, RegisteredGPUStorageScopes[S]>;
|
|
749
|
+
} & Readonly<AppGPUStorage> & ScopedStoreMethods<StorageLike> : ScopedStoreType<StorageLike>;
|
|
750
|
+
/**
|
|
751
|
+
* A reader's result for an explicit schema `T`, or loose uniforms when none was given (`T` is then
|
|
752
|
+
* its constraint, `UniformInputRecord`): `useUniforms<{ blur: number }>('fx')` vs `useUniforms('fx')`.
|
|
753
|
+
*/
|
|
754
|
+
type ReadUniforms<T extends UniformInputRecord> = UniformInputRecord extends T ? Record<string, LooseUniformNode> : UniformNodesFor<T>;
|
|
525
755
|
|
|
526
756
|
/** Uniforms that exist on every primary canvas from the start. See configureTSL. */
|
|
527
757
|
interface TSLConfig {
|
|
@@ -565,7 +795,7 @@ declare function useUniforms<T extends RootUniformInput>(uniforms: T): UniformsW
|
|
|
565
795
|
declare function useUniforms<T extends UniformInputRecord, S extends string>(uniforms: T & ScopeUniformInput<S>, scope: S): UniformsWithUtils<UniformNodesFor<T>>;
|
|
566
796
|
declare function useUniforms(): UniformsWithUtils<AppUniforms>;
|
|
567
797
|
declare function useUniforms<S extends keyof RegisteredScopes & string>(scope: S): UniformsWithUtils<RegisteredScopeUniforms<S>>;
|
|
568
|
-
declare function useUniforms<T extends UniformInputRecord>(scope?: string): UniformsWithUtils<
|
|
798
|
+
declare function useUniforms<T extends UniformInputRecord>(scope?: string): UniformsWithUtils<ReadUniforms<T>>;
|
|
569
799
|
/**
|
|
570
800
|
* Global rebuildUniforms function for HMR integration.
|
|
571
801
|
* Invalidates cached uniforms and increments _hmrVersion to trigger re-creation.
|
|
@@ -587,8 +817,10 @@ declare function rebuildAllUniforms(store: ReturnType<typeof useStore>, scope?:
|
|
|
587
817
|
* - UniformNode: existing uniforms (reused as-is)
|
|
588
818
|
*/
|
|
589
819
|
type UniformValue = number | boolean | string | Vector2 | Vector3 | Vector4 | Color | Matrix2 | Matrix3 | Matrix4 | Node | UniformNode;
|
|
820
|
+
/** `useUniform<T>(name)`'s result: exact for an explicit `T`, a `LooseUniformNode` without one. */
|
|
821
|
+
type ReadUniform<T extends UniformValue> = UniformValue extends T ? LooseUniformNode : UniformNodeFor<T>;
|
|
590
822
|
declare function useUniform<K extends keyof RegisteredUniforms & string>(name: K): RegisteredUniform<K>;
|
|
591
|
-
declare function useUniform<T extends UniformValue = UniformValue>(name: string):
|
|
823
|
+
declare function useUniform<T extends UniformValue = UniformValue>(name: string): ReadUniform<T>;
|
|
592
824
|
declare function useUniform<T extends UniformValue>(name: string, value: T): UniformNodeFor<T>;
|
|
593
825
|
|
|
594
826
|
/**
|
|
@@ -618,12 +850,12 @@ type NodesWithUtils<T extends Record<string, unknown> = NodeRecord> = T & {
|
|
|
618
850
|
clearNodes: ClearNodesFn;
|
|
619
851
|
rebuildNodes: RebuildNodesFn;
|
|
620
852
|
};
|
|
621
|
-
declare function useNodes(): NodesWithUtils<
|
|
622
|
-
declare function useNodes(scope:
|
|
623
|
-
declare function useNodes<T extends NodeRecord>(scope?: string): NodesWithUtils<T
|
|
624
|
-
declare function useNodes<T extends
|
|
625
|
-
declare function useNodes<T extends NodeRecord>(creator:
|
|
626
|
-
declare function useNodes(creatorOrScope
|
|
853
|
+
declare function useNodes(): NodesWithUtils<AppNodes>;
|
|
854
|
+
declare function useNodes<S extends keyof RegisteredNodeScopes & string>(scope: S): NodesWithUtils<RegisteredNodeScopes[S]>;
|
|
855
|
+
declare function useNodes<T extends NodeRecord>(scope?: string): NodesWithUtils<ReadNodes<T>>;
|
|
856
|
+
declare function useNodes<T extends RootNodeInput>(creator: NodeCreator<T>): NodesWithUtils<T>;
|
|
857
|
+
declare function useNodes<T extends NodeRecord, S extends string>(creator: (state: CreatorState) => T & ScopeNodeInput<S>, scope: S): NodesWithUtils<T>;
|
|
858
|
+
declare function useNodes<S extends string | undefined>(creatorOrScope: NodeCreator<NodeRecord> | string | undefined, scope: S & (string extends S ? unknown : never)): NodesWithUtils<Record<string, unknown>>;
|
|
627
859
|
/**
|
|
628
860
|
* Global rebuildNodes function for HMR integration.
|
|
629
861
|
* Invalidates cached nodes and increments _hmrVersion to trigger re-creation.
|
|
@@ -694,8 +926,8 @@ type LocalNodeInstaller = (state: CreatorState) => LocalNodeInstall;
|
|
|
694
926
|
*
|
|
695
927
|
* @example
|
|
696
928
|
* ```tsx
|
|
697
|
-
* // Resource-driven composition: no surrounding JS inputs. `uniforms.uTime` is typed when
|
|
698
|
-
* // app registers its uniforms (see `Register`)
|
|
929
|
+
* // Resource-driven composition: no surrounding JS inputs. `uniforms.uTime` is typed by name when
|
|
930
|
+
* // the app registers its uniforms (see `Register`), and a loose node TSL accepts as is otherwise.
|
|
699
931
|
* const { wobble, uTime } = useLocalNodes(({ uniforms, nodes }) => ({
|
|
700
932
|
* wobble: sin(uniforms.uTime.mul(2)),
|
|
701
933
|
* uTime: uniforms.uTime, // can return uniforms too
|
|
@@ -706,10 +938,10 @@ type LocalNodeInstaller = (state: CreatorState) => LocalNodeInstall;
|
|
|
706
938
|
* result: pattern === 'noise' ? nodes.noise : nodes.stripes,
|
|
707
939
|
* }), [pattern])
|
|
708
940
|
*
|
|
709
|
-
* // An unregistered uniform
|
|
710
|
-
* const { colorNode } = useLocalNodes(({ uniforms }) => {
|
|
711
|
-
* const
|
|
712
|
-
* return { colorNode: mix(colorA, colorB,
|
|
941
|
+
* // An unregistered uniform works as is; one `as` gives its exact type where that matters
|
|
942
|
+
* const { colorNode, facing } = useLocalNodes(({ uniforms }) => {
|
|
943
|
+
* const uDir = uniforms.uDir as UniformNode<'vec3', Vector3> // cross() wants a vec3
|
|
944
|
+
* return { colorNode: mix(colorA, colorB, uniforms.myUniform), facing: cross(uDir, normalView) }
|
|
713
945
|
* }, [])
|
|
714
946
|
* ```
|
|
715
947
|
*/
|
|
@@ -740,11 +972,13 @@ type BuffersWithUtils<T extends BufferRecordType | BufferStore = BufferRecordTyp
|
|
|
740
972
|
rebuildBuffers: RebuildBuffersFn;
|
|
741
973
|
disposeBuffers: DisposeBuffersFn;
|
|
742
974
|
};
|
|
743
|
-
declare function useBuffers(): BuffersWithUtils<
|
|
975
|
+
declare function useBuffers(): BuffersWithUtils<AppBuffers>;
|
|
976
|
+
declare function useBuffers<S extends keyof RegisteredBufferScopes & string>(scope: S): BuffersWithUtils<RegisteredBufferScopes[S]>;
|
|
744
977
|
declare function useBuffers(scope: string): BuffersWithUtils<Record<string, BufferLike>>;
|
|
745
978
|
declare function useBuffers<T extends Record<string, BufferLike>>(scope?: string): BuffersWithUtils<T>;
|
|
746
|
-
declare function useBuffers<T extends
|
|
747
|
-
declare function useBuffers<T extends Record<string, BufferLike
|
|
979
|
+
declare function useBuffers<T extends RootBufferInput>(creator: BufferCreator<T>): BuffersWithUtils<T>;
|
|
980
|
+
declare function useBuffers<T extends Record<string, BufferLike>, S extends string>(creator: (state: CreatorState) => T & ScopeBufferInput<S>, scope: S): BuffersWithUtils<T>;
|
|
981
|
+
declare function useBuffers<S extends string | undefined>(creator: BufferCreator<BufferRecord>, scope: S & (string extends S ? unknown : never)): BuffersWithUtils<BufferRecord>;
|
|
748
982
|
/**
|
|
749
983
|
* Global rebuildBuffers function for HMR integration.
|
|
750
984
|
* Invalidates cached buffers and increments _hmrVersion to trigger re-creation.
|
|
@@ -782,11 +1016,13 @@ type StorageWithUtils<T extends StorageRecordType | StorageStore = StorageRecord
|
|
|
782
1016
|
rebuildStorage: RebuildStorageFn;
|
|
783
1017
|
disposeStorage: DisposeStorageFn;
|
|
784
1018
|
};
|
|
785
|
-
declare function useGPUStorage(): StorageWithUtils<
|
|
1019
|
+
declare function useGPUStorage(): StorageWithUtils<AppGPUStorage>;
|
|
1020
|
+
declare function useGPUStorage<S extends keyof RegisteredGPUStorageScopes & string>(scope: S): StorageWithUtils<RegisteredGPUStorageScopes[S]>;
|
|
786
1021
|
declare function useGPUStorage(scope: string): StorageWithUtils<Record<string, StorageLike>>;
|
|
787
1022
|
declare function useGPUStorage<T extends Record<string, StorageLike>>(scope?: string): StorageWithUtils<T>;
|
|
788
|
-
declare function useGPUStorage<T extends
|
|
789
|
-
declare function useGPUStorage<T extends Record<string, StorageLike
|
|
1023
|
+
declare function useGPUStorage<T extends RootGPUStorageInput>(creator: StorageCreator<T>): StorageWithUtils<T>;
|
|
1024
|
+
declare function useGPUStorage<T extends Record<string, StorageLike>, S extends string>(creator: (state: CreatorState) => T & ScopeGPUStorageInput<S>, scope: S): StorageWithUtils<T>;
|
|
1025
|
+
declare function useGPUStorage<S extends string | undefined>(creator: StorageCreator<StorageRecord>, scope: S & (string extends S ? unknown : never)): StorageWithUtils<StorageRecord>;
|
|
790
1026
|
/**
|
|
791
1027
|
* Global rebuildStorage function for HMR integration.
|
|
792
1028
|
* Invalidates cached storage and increments _hmrVersion to trigger re-creation.
|
|
@@ -804,11 +1040,15 @@ declare function rebuildAllStorage(store: ReturnType<typeof useStore>, scope?: s
|
|
|
804
1040
|
* Hook for managing WebGPU RenderPipeline with automatic scenePass setup.
|
|
805
1041
|
*
|
|
806
1042
|
* Features:
|
|
807
|
-
* -
|
|
808
|
-
*
|
|
809
|
-
* -
|
|
810
|
-
* -
|
|
811
|
-
* -
|
|
1043
|
+
* - A call with a callback owns the canvas's pipeline: it creates the pipeline and a default
|
|
1044
|
+
* scenePass (no MRT), and frees both when it unmounts (opt out with `persist`)
|
|
1045
|
+
* - A call without callbacks only reads: it never creates, keeps alive or frees the pipeline
|
|
1046
|
+
* - The most recently mounted owner renders; when it unmounts, the previous owner takes over again
|
|
1047
|
+
* - StrictMode and Fast Refresh remounts reuse the graph instead of rebuilding it
|
|
1048
|
+
* - Callbacks receive the same state as creators (`uniforms`, `nodes`, ... wrapped, including
|
|
1049
|
+
* entries staged earlier in the render), and their reads are tracked as in useLocalNodes: a read
|
|
1050
|
+
* resource that appears, is replaced or is removed re-runs them
|
|
1051
|
+
* - Callbacks re-run on a hot update (`_hmrVersion`), on scene/camera change and on rebuild()
|
|
812
1052
|
* - A replaced scenePass is disposed once the new graph is installed, so rebuild() does not
|
|
813
1053
|
* strand its render target (and MRT attachments) on the GPU
|
|
814
1054
|
* - Any run that changes the output node sets RenderPipeline.needsUpdate, so rebuild() actually
|
|
@@ -816,6 +1056,7 @@ declare function rebuildAllStorage(store: ReturnType<typeof useStore>, scope?: s
|
|
|
816
1056
|
*
|
|
817
1057
|
* @param mainCB - Main callback to configure outputNode and create effect passes
|
|
818
1058
|
* @param setupCB - Optional setup callback to configure MRT on scenePass
|
|
1059
|
+
* @param options - `persist: true` keeps the pipeline after the component unmounts
|
|
819
1060
|
* @returns { passes, renderPipeline, clearPasses, reset, rebuild }
|
|
820
1061
|
*
|
|
821
1062
|
* @example
|
|
@@ -841,7 +1082,7 @@ declare function rebuildAllStorage(store: ReturnType<typeof useStore>, scope?: s
|
|
|
841
1082
|
* const { renderPipeline, passes } = useRenderPipeline()
|
|
842
1083
|
* ```
|
|
843
1084
|
*/
|
|
844
|
-
declare function useRenderPipeline(mainCB?: RenderPipelineMainCallback, setupCB?: RenderPipelineSetupCallback): UseRenderPipelineReturn;
|
|
1085
|
+
declare function useRenderPipeline(mainCB?: RenderPipelineMainCallback, setupCB?: RenderPipelineSetupCallback, options?: RenderPipelineOptions): UseRenderPipelineReturn;
|
|
845
1086
|
|
|
846
1087
|
export { configureTSL, createScopedStore, rebuildAllBuffers, rebuildAllNodes, rebuildAllStorage, rebuildAllUniforms, useBuffers, useGPUStorage, useLocalNodes, useNodes, useRenderPipeline, useUniform, useUniforms };
|
|
847
|
-
export type { AppUniforms, BufferCreator, BufferLike, BufferRecord, BufferStore, BuffersWithUtils, ClearBuffersFn, ClearNodesFn, ClearStorageFn, ClearUniformsFn, CreatorState, DisposeBuffersFn, DisposeStorageFn, LocalNodeCreator, LocalNodeInstall, LocalNodeInstaller, NodeCreator, NodeLike, NodeRecord, NodeStore, NodesWithUtils, RebuildBuffersFn, RebuildNodesFn, RebuildStorageFn, RebuildUniformsFn, Register, RegisteredScopeUniforms, RegisteredScopes, RegisteredUniform, RegisteredUniforms, RemoveBuffersFn, RemoveNodesFn, RemoveStorageFn, RemoveUniformsFn, RootUniformInput, ScopeUniformInput, ScopedStoreType, StorageCreator, StorageLike, StorageRecord, StorageStore, StorageWithUtils, TSLConfig, TSLNode, TSLNodeLike, TSLRootState, UniformCreator, UniformValue, UniformsWithUtils };
|
|
1088
|
+
export type { AppBuffers, AppGPUStorage, AppNodes, AppUniforms, BufferCreator, BufferLike, BufferRecord, BufferStore, BuffersWithUtils, ClearBuffersFn, ClearNodesFn, ClearStorageFn, ClearUniformsFn, CreatorState, DisposeBuffersFn, DisposeStorageFn, FnNodeLike, LocalNodeCreator, LocalNodeInstall, LocalNodeInstaller, LooseNode, LooseNodeEntry, LooseNodeStore, NodeCreator, NodeLike, NodeRecord, NodeStore, NodesWithUtils, RebuildBuffersFn, RebuildNodesFn, RebuildStorageFn, RebuildUniformsFn, Register, RegisteredBufferScopes, RegisteredBuffers, RegisteredGPUStorage, RegisteredGPUStorageScopes, RegisteredNodeScopes, RegisteredNodes, RegisteredScopeUniforms, RegisteredScopes, RegisteredUniform, RegisteredUniforms, RemoveBuffersFn, RemoveNodesFn, RemoveStorageFn, RemoveUniformsFn, RootBufferInput, RootGPUStorageInput, RootNodeInput, RootUniformInput, ScopeBufferInput, ScopeGPUStorageInput, ScopeNodeInput, ScopeUniformInput, ScopedStoreType, StorageCreator, StorageLike, StorageRecord, StorageStore, StorageWithUtils, TSLConfig, TSLNode, TSLNodeLike, TSLRootState, UniformCreator, UniformValue, UniformsWithUtils };
|