@react-three/fiber 10.0.0-canary.ac30da2 → 10.0.0-canary.af75fd4
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 +72 -30
- package/dist/index.d.cts +162 -25
- package/dist/index.d.mts +162 -25
- package/dist/index.d.ts +162 -25
- package/dist/index.mjs +72 -30
- package/dist/legacy.cjs +69 -26
- package/dist/legacy.d.cts +162 -25
- package/dist/legacy.d.mts +162 -25
- package/dist/legacy.d.ts +162 -25
- package/dist/legacy.mjs +69 -26
- package/dist/webgpu/index.cjs +92 -43
- package/dist/webgpu/index.d.cts +165 -40
- package/dist/webgpu/index.d.mts +165 -40
- package/dist/webgpu/index.d.ts +165 -40
- package/dist/webgpu/index.mjs +92 -43
- package/package.json +2 -2
package/dist/webgpu/index.cjs
CHANGED
|
@@ -935,7 +935,7 @@ const createStore = (invalidate, advance) => {
|
|
|
935
935
|
size: newSize,
|
|
936
936
|
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
937
937
|
}));
|
|
938
|
-
|
|
938
|
+
get().invalidate();
|
|
939
939
|
}
|
|
940
940
|
}
|
|
941
941
|
return;
|
|
@@ -950,15 +950,16 @@ const createStore = (invalidate, advance) => {
|
|
|
950
950
|
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
951
951
|
_sizeImperative: true
|
|
952
952
|
}));
|
|
953
|
-
|
|
953
|
+
get().invalidate();
|
|
954
954
|
},
|
|
955
955
|
setDpr: (dpr) => set((state2) => {
|
|
956
956
|
const resolved = calculateDpr(dpr);
|
|
957
957
|
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
958
958
|
}),
|
|
959
959
|
setFrameloop: (frameloop = "always") => {
|
|
960
|
+
const rootId = get().internal.rootId;
|
|
961
|
+
if (rootId) scheduler.getScheduler().setRootFrameloop(rootId, frameloop);
|
|
960
962
|
set(() => ({ frameloop }));
|
|
961
|
-
scheduler.getScheduler().frameloop = frameloop;
|
|
962
963
|
},
|
|
963
964
|
setError: (error) => set(() => ({ error })),
|
|
964
965
|
error: null,
|
|
@@ -1077,7 +1078,8 @@ const createStore = (invalidate, advance) => {
|
|
|
1077
1078
|
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
1078
1079
|
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
1079
1080
|
resizeTarget.setSize(size.width, size.height, false);
|
|
1080
|
-
|
|
1081
|
+
const activeTarget = actualRenderer.getCanvasTarget?.();
|
|
1082
|
+
if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
|
|
1081
1083
|
}
|
|
1082
1084
|
if (camera !== oldCamera) {
|
|
1083
1085
|
oldCamera = camera;
|
|
@@ -1263,6 +1265,13 @@ function useFrame$1(callback, priorityOrOptions) {
|
|
|
1263
1265
|
* Use for controlling the entire frame loop, adding phases, etc.
|
|
1264
1266
|
*/
|
|
1265
1267
|
scheduler: scheduler2,
|
|
1268
|
+
/**
|
|
1269
|
+
* The root that currently owns this job. Resolve on access because ambient
|
|
1270
|
+
* jobs can be adopted by a Canvas after the controls object is created.
|
|
1271
|
+
*/
|
|
1272
|
+
get rootId() {
|
|
1273
|
+
return scheduler.getScheduler().getJobRootId(id);
|
|
1274
|
+
},
|
|
1266
1275
|
/**
|
|
1267
1276
|
* Manually step this job only.
|
|
1268
1277
|
* Bypasses FPS limiting - always runs.
|
|
@@ -1279,6 +1288,14 @@ function useFrame$1(callback, priorityOrOptions) {
|
|
|
1279
1288
|
stepAll: (timestamp) => {
|
|
1280
1289
|
scheduler.getScheduler().step(timestamp);
|
|
1281
1290
|
},
|
|
1291
|
+
/**
|
|
1292
|
+
* Request frames for this job's owning root without waking sibling roots.
|
|
1293
|
+
*/
|
|
1294
|
+
invalidate: (frames, stackFrames) => {
|
|
1295
|
+
const scheduler3 = scheduler.getScheduler();
|
|
1296
|
+
const rootId = scheduler3.getJobRootId(id);
|
|
1297
|
+
if (rootId) scheduler3.invalidateRoot(rootId, frames, stackFrames);
|
|
1298
|
+
},
|
|
1282
1299
|
/**
|
|
1283
1300
|
* Pause this job (set enabled=false).
|
|
1284
1301
|
* Job remains registered but won't run.
|
|
@@ -1696,13 +1713,19 @@ function addTail(callback) {
|
|
|
1696
1713
|
return scheduler.getScheduler().onIdle(callback);
|
|
1697
1714
|
}
|
|
1698
1715
|
function invalidate(state, frames = 1, stackFrames = false) {
|
|
1699
|
-
|
|
1716
|
+
const rootId = state?.internal?.rootId;
|
|
1717
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
1718
|
+
if (rootId) scheduler$1.invalidateRoot(rootId, frames, stackFrames);
|
|
1719
|
+
else scheduler$1.invalidate(frames, stackFrames);
|
|
1700
1720
|
}
|
|
1701
|
-
function advance(timestamp) {
|
|
1702
|
-
|
|
1721
|
+
function advance(timestamp, runGlobalEffects, state) {
|
|
1722
|
+
const rootId = state?.internal?.rootId;
|
|
1723
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
1724
|
+
if (rootId) scheduler$1.stepRoot(rootId, timestamp);
|
|
1725
|
+
else scheduler$1.step(timestamp);
|
|
1703
1726
|
}
|
|
1704
1727
|
|
|
1705
|
-
const version = "10.0.0-alpha.
|
|
1728
|
+
const version = "10.0.0-alpha.4";
|
|
1706
1729
|
const packageData = {
|
|
1707
1730
|
version: version};
|
|
1708
1731
|
|
|
@@ -14218,9 +14241,8 @@ function createRoot(canvas) {
|
|
|
14218
14241
|
if (!renderer.hasInitialized?.()) {
|
|
14219
14242
|
const size2 = computeInitialSize(canvas, propsSize);
|
|
14220
14243
|
if (size2.width > 0 && size2.height > 0) {
|
|
14221
|
-
|
|
14222
|
-
|
|
14223
|
-
canvas.height = size2.height * pixelRatio;
|
|
14244
|
+
renderer.setPixelRatio(calculateDpr(dpr));
|
|
14245
|
+
renderer.setSize(size2.width, size2.height, false);
|
|
14224
14246
|
}
|
|
14225
14247
|
await renderer.init();
|
|
14226
14248
|
}
|
|
@@ -14229,7 +14251,7 @@ function createRoot(canvas) {
|
|
|
14229
14251
|
state.internal.actualRenderer = renderer;
|
|
14230
14252
|
state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
|
|
14231
14253
|
if (canvasId && !state.internal.isSecondary) {
|
|
14232
|
-
const canvasTarget =
|
|
14254
|
+
const canvasTarget = renderer.getCanvasTarget?.();
|
|
14233
14255
|
const unregisterPrimary = registerPrimary(canvasId, renderer, store);
|
|
14234
14256
|
state.set((prev) => ({
|
|
14235
14257
|
internal: {
|
|
@@ -14343,7 +14365,7 @@ function createRoot(canvas) {
|
|
|
14343
14365
|
const handleXRFrame = (timestamp, _frame) => {
|
|
14344
14366
|
const state2 = store.getState();
|
|
14345
14367
|
if (state2.frameloop === "never") return;
|
|
14346
|
-
advance(timestamp);
|
|
14368
|
+
advance(timestamp, true, state2);
|
|
14347
14369
|
};
|
|
14348
14370
|
const actualRenderer = state.internal.actualRenderer;
|
|
14349
14371
|
const handleSessionChange = () => {
|
|
@@ -14351,7 +14373,7 @@ function createRoot(canvas) {
|
|
|
14351
14373
|
const renderer2 = state2.internal.actualRenderer;
|
|
14352
14374
|
actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
|
|
14353
14375
|
renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
|
|
14354
|
-
if (!renderer2.xr.isPresenting) invalidate();
|
|
14376
|
+
if (!renderer2.xr.isPresenting) invalidate(state2);
|
|
14355
14377
|
};
|
|
14356
14378
|
const xr = {
|
|
14357
14379
|
connect() {
|
|
@@ -14433,14 +14455,19 @@ function createRoot(canvas) {
|
|
|
14433
14455
|
const newRootId = canvasId || scheduler$1.generateRootId();
|
|
14434
14456
|
const unregisterRoot = scheduler$1.registerRoot(newRootId, {
|
|
14435
14457
|
getState: () => store.getState(),
|
|
14436
|
-
onError: (err) => store.getState().setError(err)
|
|
14458
|
+
onError: (err) => store.getState().setError(err),
|
|
14459
|
+
frameloop: store.getState().frameloop,
|
|
14460
|
+
before: schedulerConfig?.before,
|
|
14461
|
+
after: schedulerConfig?.after,
|
|
14462
|
+
order: schedulerConfig?.order
|
|
14437
14463
|
});
|
|
14438
14464
|
const unregisterCanvasTarget = scheduler$1.register(
|
|
14439
14465
|
() => {
|
|
14440
14466
|
const state2 = store.getState();
|
|
14441
|
-
|
|
14467
|
+
const canvasTarget = state2.internal.canvasTarget;
|
|
14468
|
+
if (canvasTarget) {
|
|
14442
14469
|
const renderer2 = state2.internal.actualRenderer;
|
|
14443
|
-
renderer2.setCanvasTarget(
|
|
14470
|
+
if (renderer2.getCanvasTarget() !== canvasTarget) renderer2.setCanvasTarget(canvasTarget);
|
|
14444
14471
|
if (state2.internal.canvasTargetSizeDirty) {
|
|
14445
14472
|
state2.internal.canvasTargetSizeDirty = false;
|
|
14446
14473
|
renderer2.backend?.updateSize?.();
|
|
@@ -14513,8 +14540,7 @@ function createRoot(canvas) {
|
|
|
14513
14540
|
phase: "render",
|
|
14514
14541
|
system: true,
|
|
14515
14542
|
// Internal flag: this is a system job, not user-controlled
|
|
14516
|
-
//
|
|
14517
|
-
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
14543
|
+
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
14518
14544
|
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14519
14545
|
}
|
|
14520
14546
|
);
|
|
@@ -14533,8 +14559,21 @@ function createRoot(canvas) {
|
|
|
14533
14559
|
scheduler: scheduler$1
|
|
14534
14560
|
}
|
|
14535
14561
|
}));
|
|
14562
|
+
} else {
|
|
14563
|
+
const constraintsChanged = !is.equ(schedulerConfig?.before, lastConfiguredProps.schedulerBefore, shallowLoose) || !is.equ(schedulerConfig?.after, lastConfiguredProps.schedulerAfter, shallowLoose);
|
|
14564
|
+
if (constraintsChanged) {
|
|
14565
|
+
scheduler$1.setRootConstraints(rootId, {
|
|
14566
|
+
before: schedulerConfig?.before,
|
|
14567
|
+
after: schedulerConfig?.after
|
|
14568
|
+
});
|
|
14569
|
+
}
|
|
14570
|
+
if (schedulerConfig?.order !== lastConfiguredProps.schedulerOrder) {
|
|
14571
|
+
scheduler$1.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
14572
|
+
}
|
|
14536
14573
|
}
|
|
14537
|
-
|
|
14574
|
+
lastConfiguredProps.schedulerBefore = schedulerConfig?.before;
|
|
14575
|
+
lastConfiguredProps.schedulerAfter = schedulerConfig?.after;
|
|
14576
|
+
lastConfiguredProps.schedulerOrder = schedulerConfig?.order;
|
|
14538
14577
|
onCreated = onCreatedCallback;
|
|
14539
14578
|
configured = true;
|
|
14540
14579
|
resolve();
|
|
@@ -14576,18 +14615,23 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14576
14615
|
const fiber = root?.fiber;
|
|
14577
14616
|
if (fiber) {
|
|
14578
14617
|
const state = root?.store.getState();
|
|
14579
|
-
if (state)
|
|
14618
|
+
if (state) {
|
|
14619
|
+
state.internal.active = false;
|
|
14620
|
+
const unregisterRoot = state.internal.unregisterRoot;
|
|
14621
|
+
if (unregisterRoot) {
|
|
14622
|
+
unregisterRoot();
|
|
14623
|
+
state.internal.unregisterRoot = void 0;
|
|
14624
|
+
}
|
|
14625
|
+
}
|
|
14580
14626
|
reconciler.updateContainer(null, fiber, null, () => {
|
|
14581
14627
|
if (state) {
|
|
14582
14628
|
setTimeout(() => {
|
|
14583
14629
|
try {
|
|
14584
14630
|
const renderer = state.internal.actualRenderer;
|
|
14585
|
-
const unregisterRoot = state.internal.unregisterRoot;
|
|
14586
|
-
if (unregisterRoot) unregisterRoot();
|
|
14587
14631
|
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
14588
14632
|
if (unregisterPrimary) unregisterPrimary();
|
|
14589
14633
|
const canvasTarget = state.internal.canvasTarget;
|
|
14590
|
-
if (canvasTarget?.dispose) canvasTarget.dispose();
|
|
14634
|
+
if (state.internal.isSecondary && canvasTarget?.dispose) canvasTarget.dispose();
|
|
14591
14635
|
state.events.disconnect?.();
|
|
14592
14636
|
cleanupHelperGroup(root.store);
|
|
14593
14637
|
if (state.isLegacy && renderer) {
|
|
@@ -15128,9 +15172,9 @@ function CanvasImpl({
|
|
|
15128
15172
|
React__namespace.useMemo(() => extend(THREE), []);
|
|
15129
15173
|
const Bridge = useBridge();
|
|
15130
15174
|
const backgroundProps = React__namespace.useMemo(() => parseBackground(background), [background]);
|
|
15131
|
-
const
|
|
15175
|
+
const [hasInitialSize, setHasInitialSize] = React__namespace.useState(false);
|
|
15132
15176
|
const measureConfig = React__namespace.useMemo(() => {
|
|
15133
|
-
if (!
|
|
15177
|
+
if (!hasInitialSize) {
|
|
15134
15178
|
return {
|
|
15135
15179
|
...resize,
|
|
15136
15180
|
scroll: resize?.scroll ?? true,
|
|
@@ -15142,7 +15186,7 @@ function CanvasImpl({
|
|
|
15142
15186
|
debounce: { scroll: 50, resize: 0 },
|
|
15143
15187
|
...resize
|
|
15144
15188
|
};
|
|
15145
|
-
}, [
|
|
15189
|
+
}, [hasInitialSize, resize]);
|
|
15146
15190
|
const [containerRef, containerRect] = useMeasure__default(measureConfig);
|
|
15147
15191
|
const effectiveSize = React__namespace.useMemo(() => {
|
|
15148
15192
|
let w = width ?? containerRect.width;
|
|
@@ -15158,9 +15202,7 @@ function CanvasImpl({
|
|
|
15158
15202
|
left: containerRect.left
|
|
15159
15203
|
};
|
|
15160
15204
|
}, [width, height, containerRect, forceEven]);
|
|
15161
|
-
if (!
|
|
15162
|
-
hasInitialSizeRef.current = true;
|
|
15163
|
-
}
|
|
15205
|
+
if (!hasInitialSize && effectiveSize.width > 0 && effectiveSize.height > 0) setHasInitialSize(true);
|
|
15164
15206
|
const canvasRef = React__namespace.useRef(null);
|
|
15165
15207
|
const divRef = React__namespace.useRef(null);
|
|
15166
15208
|
React__namespace.useImperativeHandle(ref, () => canvasRef.current);
|
|
@@ -16019,7 +16061,7 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16019
16061
|
renderPipeline: null,
|
|
16020
16062
|
passes: {}
|
|
16021
16063
|
});
|
|
16022
|
-
scenePassCacheRef.current?.scenePass
|
|
16064
|
+
scenePassCacheRef.current?.scenePass.dispose();
|
|
16023
16065
|
callbacksRanRef.current = false;
|
|
16024
16066
|
scenePassCacheRef.current = null;
|
|
16025
16067
|
forceScenePassRebuildRef.current = false;
|
|
@@ -16034,6 +16076,9 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16034
16076
|
throw new Error("useRenderPipeline is only available with WebGPU renderer. Set renderer prop on Canvas.");
|
|
16035
16077
|
}
|
|
16036
16078
|
if (!renderer || !scene || !camera) return;
|
|
16079
|
+
if (!("isWebGPURenderer" in renderer)) {
|
|
16080
|
+
throw new Error("useRenderPipeline: renderer is not a WebGPURenderer but isLegacy is false.");
|
|
16081
|
+
}
|
|
16037
16082
|
const state = store.getState();
|
|
16038
16083
|
const set = store.setState;
|
|
16039
16084
|
try {
|
|
@@ -16065,7 +16110,12 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16065
16110
|
const shouldRunCallbacks = justCreatedPipeline || !callbacksRanRef.current || !cacheValid;
|
|
16066
16111
|
if (shouldRunCallbacks) {
|
|
16067
16112
|
if (setupCBRef.current) {
|
|
16068
|
-
const freshState = store.getState()
|
|
16113
|
+
const freshState = Object.assign({}, store.getState(), {
|
|
16114
|
+
renderPipeline: pipeline,
|
|
16115
|
+
passes: { ...currentPasses, scenePass },
|
|
16116
|
+
renderer,
|
|
16117
|
+
isLegacy: false
|
|
16118
|
+
});
|
|
16069
16119
|
const setupResult = setupCBRef.current(freshState);
|
|
16070
16120
|
if (setupResult && typeof setupResult === "object") {
|
|
16071
16121
|
currentPasses = { ...currentPasses, ...setupResult };
|
|
@@ -16073,7 +16123,12 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16073
16123
|
}
|
|
16074
16124
|
}
|
|
16075
16125
|
if (mainCBRef.current) {
|
|
16076
|
-
const freshState = store.getState()
|
|
16126
|
+
const freshState = Object.assign({}, store.getState(), {
|
|
16127
|
+
renderPipeline: pipeline,
|
|
16128
|
+
passes: { ...currentPasses, scenePass },
|
|
16129
|
+
renderer,
|
|
16130
|
+
isLegacy: false
|
|
16131
|
+
});
|
|
16077
16132
|
const mainResult = mainCBRef.current(freshState);
|
|
16078
16133
|
if (mainResult && typeof mainResult === "object") {
|
|
16079
16134
|
currentPasses = { ...currentPasses, ...mainResult };
|
|
@@ -16084,22 +16139,16 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16084
16139
|
callbacksRanRef.current = true;
|
|
16085
16140
|
}
|
|
16086
16141
|
if (outputNodeChanged) pipeline.needsUpdate = true;
|
|
16087
|
-
if (outgoingScenePass && outgoingScenePass !== scenePass) outgoingScenePass.dispose
|
|
16142
|
+
if (outgoingScenePass && outgoingScenePass !== scenePass) outgoingScenePass.dispose();
|
|
16088
16143
|
} catch (error) {
|
|
16089
16144
|
console.warn("[useRenderPipeline] Setup failed; the render pipeline was not configured:", error);
|
|
16090
16145
|
}
|
|
16091
16146
|
}, [store, renderer, scene, camera, isLegacy, rebuildVersion]);
|
|
16092
16147
|
const passes = useThree$1((s) => s.passes);
|
|
16093
16148
|
const renderPipeline = useThree$1((s) => s.renderPipeline);
|
|
16094
|
-
|
|
16095
|
-
|
|
16096
|
-
|
|
16097
|
-
clearPasses,
|
|
16098
|
-
reset,
|
|
16099
|
-
rebuild,
|
|
16100
|
-
// isReady indicates if RenderPipeline is configured and ready for rendering
|
|
16101
|
-
isReady: renderPipeline !== null
|
|
16102
|
-
};
|
|
16149
|
+
const actions = { passes, clearPasses, reset, rebuild };
|
|
16150
|
+
if (renderPipeline) return { ...actions, isReady: true, renderPipeline };
|
|
16151
|
+
return { ...actions, isReady: false, renderPipeline: null };
|
|
16103
16152
|
}
|
|
16104
16153
|
|
|
16105
16154
|
extend(THREE);
|
package/dist/webgpu/index.d.cts
CHANGED
|
@@ -365,6 +365,33 @@ type BufferRecord = Record<string, BufferLike>
|
|
|
365
365
|
*/
|
|
366
366
|
type BufferStore = Record<string, BufferLike | BufferRecord>
|
|
367
367
|
|
|
368
|
+
//* Node Types (useNodes) ========================================
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Structural shape of a TSL node as stored on `state.nodes`.
|
|
372
|
+
*
|
|
373
|
+
* Deliberately minimal rather than three's nominal `Node`: in @types/three several node classes
|
|
374
|
+
* TSL hands back (OperatorNode, ConstNode, ...) do not extend `Node` cleanly, so a `Node` bound
|
|
375
|
+
* would reject values `useNodes` creators legitimately return. This is the same shape
|
|
376
|
+
* `useNodes` already constrains creators to (`TSLNodeLike`).
|
|
377
|
+
*/
|
|
378
|
+
interface NodeLike {
|
|
379
|
+
uuid?: string
|
|
380
|
+
nodeType?: string | null
|
|
381
|
+
/** label method for chaining - sets the node's label and returns self */
|
|
382
|
+
label?: ((label: string) => NodeLike) | string
|
|
383
|
+
setName?: (name: string) => this
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/** Flat record of TSL nodes (no nested scopes) */
|
|
387
|
+
type NodeRecord = Record<string, NodeLike>
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Node store that can contain both root-level nodes and scoped node objects.
|
|
391
|
+
* Structure: { wobble: OperatorNode, fx: { blur: ShaderCallable } }
|
|
392
|
+
*/
|
|
393
|
+
type NodeStore = Record<string, NodeLike | NodeRecord>
|
|
394
|
+
|
|
368
395
|
//* Storage Types (useGPUStorage) ========================================
|
|
369
396
|
|
|
370
397
|
/**
|
|
@@ -498,8 +525,13 @@ interface InternalState {
|
|
|
498
525
|
/** Container for child attachment (scene for root, original container for portals) */
|
|
499
526
|
container?: THREE$1.Object3D
|
|
500
527
|
/**
|
|
501
|
-
* CanvasTarget
|
|
502
|
-
*
|
|
528
|
+
* The CanvasTarget this root sizes and renders through.
|
|
529
|
+
*
|
|
530
|
+
* A primary (`<Canvas id>`) owns the renderer's default target -- the one three itself built
|
|
531
|
+
* around the canvas element -- so sizing it is sizing the renderer. A secondary owns a target
|
|
532
|
+
* R3F created for its own element. Either way there is exactly one target per canvas element,
|
|
533
|
+
* and the canvas-target job makes it the renderer's active one before this root renders.
|
|
534
|
+
* Absent on WebGL and on an id-less WebGPU canvas, where the renderer is sized directly.
|
|
503
535
|
* @see https://threejs.org/docs/#api/en/renderers/common/CanvasTarget
|
|
504
536
|
*/
|
|
505
537
|
canvasTarget?: CanvasTarget
|
|
@@ -624,7 +656,7 @@ interface RootState {
|
|
|
624
656
|
/** Global TSL uniform nodes - root-level uniforms + scoped sub-objects. Use useUniforms() hook */
|
|
625
657
|
uniforms: UniformStore
|
|
626
658
|
/** Global TSL nodes - root-level nodes + scoped sub-objects. Use useNodes() hook */
|
|
627
|
-
nodes:
|
|
659
|
+
nodes: NodeStore
|
|
628
660
|
/** Global TSL buffer nodes - root-level buffers + scoped sub-objects. Use useBuffers() hook */
|
|
629
661
|
buffers: BufferStore
|
|
630
662
|
/** Global GPU storage (textures, etc.) - root-level storage + scoped sub-objects. Use useGPUStorage() hook */
|
|
@@ -636,7 +668,7 @@ interface RootState {
|
|
|
636
668
|
/** WebGPU RenderPipeline instance - use useRenderPipeline() hook */
|
|
637
669
|
renderPipeline: ThreeRenderPipeline | null
|
|
638
670
|
/** Global TSL pass nodes for render pipeline - use useRenderPipeline() hook */
|
|
639
|
-
passes:
|
|
671
|
+
passes: PassRecord
|
|
640
672
|
/** Internal version counter for HMR - incremented by rebuildNodes/rebuildUniforms to bust memoization */
|
|
641
673
|
_hmrVersion: number
|
|
642
674
|
/** Internal: whether setSize() has taken ownership of canvas dimensions */
|
|
@@ -724,12 +756,19 @@ type DefaultRendererProps = {
|
|
|
724
756
|
*/
|
|
725
757
|
interface CanvasSchedulerConfig {
|
|
726
758
|
/**
|
|
727
|
-
*
|
|
728
|
-
* Pass the `id` of another canvas.
|
|
759
|
+
* Run this Canvas root before the referenced Canvas root id(s).
|
|
729
760
|
*/
|
|
730
|
-
|
|
761
|
+
before?: string | string[]
|
|
731
762
|
/**
|
|
732
|
-
*
|
|
763
|
+
* Run this Canvas root after the referenced Canvas root id(s).
|
|
764
|
+
*/
|
|
765
|
+
after?: string | string[]
|
|
766
|
+
/**
|
|
767
|
+
* Numeric root order. Lower values run first.
|
|
768
|
+
*/
|
|
769
|
+
order?: number
|
|
770
|
+
/**
|
|
771
|
+
* Limit this Canvas's default render job (frames per second).
|
|
733
772
|
*/
|
|
734
773
|
fps?: number
|
|
735
774
|
}
|
|
@@ -1177,7 +1216,33 @@ declare global {
|
|
|
1177
1216
|
* ergonomics. The result is three's structural type, so members stay in sync with the
|
|
1178
1217
|
* installed three instead of needing to be mirrored by hand.
|
|
1179
1218
|
*/
|
|
1180
|
-
type UniformNode<T = unknown> = three_webgpu.UniformNode<
|
|
1219
|
+
type UniformNode<T = unknown> = three_webgpu.UniformNode<UniformNodeTypeFor<T>, T>
|
|
1220
|
+
|
|
1221
|
+
/**
|
|
1222
|
+
* three's node type name for a uniform value type, mirroring the `uniform()` overloads.
|
|
1223
|
+
* A `UniformNode<number>` is a `Node<'float'>`, so TSL math (`.mul`, `.add`, ...) accepts it.
|
|
1224
|
+
* Unknown or unlisted value types resolve to `unknown`, which TSL math rejects: narrow with
|
|
1225
|
+
* `as UniformNode<number>` (or the matching value type) at the call site.
|
|
1226
|
+
*/
|
|
1227
|
+
type UniformNodeTypeFor<T> = T extends number
|
|
1228
|
+
? 'float'
|
|
1229
|
+
: T extends boolean
|
|
1230
|
+
? 'bool'
|
|
1231
|
+
: T extends three_webgpu.Color
|
|
1232
|
+
? 'color'
|
|
1233
|
+
: T extends three_webgpu.Vector2
|
|
1234
|
+
? 'vec2'
|
|
1235
|
+
: T extends three_webgpu.Vector3
|
|
1236
|
+
? 'vec3'
|
|
1237
|
+
: T extends three_webgpu.Vector4
|
|
1238
|
+
? 'vec4'
|
|
1239
|
+
: T extends three_webgpu.Matrix2
|
|
1240
|
+
? 'mat2'
|
|
1241
|
+
: T extends three_webgpu.Matrix3
|
|
1242
|
+
? 'mat3'
|
|
1243
|
+
: T extends three_webgpu.Matrix4
|
|
1244
|
+
? 'mat4'
|
|
1245
|
+
: unknown
|
|
1181
1246
|
|
|
1182
1247
|
/**
|
|
1183
1248
|
* ShaderCallable - the return type of Fn()
|
|
@@ -1330,30 +1395,97 @@ declare global {
|
|
|
1330
1395
|
*/
|
|
1331
1396
|
type ThreeRenderPipeline = three_webgpu.RenderPipeline
|
|
1332
1397
|
|
|
1333
|
-
/**
|
|
1334
|
-
|
|
1398
|
+
/**
|
|
1399
|
+
* The pass `useRenderPipeline` creates for you: three's own `PassNode`, as returned by
|
|
1400
|
+
* `pass(scene, camera)` from `three/tsl`. Referenced from three so members like
|
|
1401
|
+
* `getTextureNode`, `setMRT` and `dispose` track the installed version.
|
|
1402
|
+
*/
|
|
1403
|
+
type ScenePassNode = three_webgpu.PassNode
|
|
1404
|
+
|
|
1405
|
+
/**
|
|
1406
|
+
* Pass record - stores TSL pass nodes for render pipeline.
|
|
1407
|
+
*
|
|
1408
|
+
* `scenePass` is the only key the library owns. It is optional here because this is also the
|
|
1409
|
+
* shape of `state.passes`, which is `{}` before the pipeline exists and again after `reset()`
|
|
1410
|
+
* or `clearPasses()`. Inside the callbacks it is always present; see
|
|
1411
|
+
* {@link RenderPipelineCallbackState}.
|
|
1412
|
+
*
|
|
1413
|
+
* Every other key is user-registered, via a callback's return value. Those are TSL nodes of
|
|
1414
|
+
* any kind, not only passes: texture reads of an MRT attachment, effect nodes, extra
|
|
1415
|
+
* `pass()` instances. `Node` is the common base, so that is the bound. Narrow at the call
|
|
1416
|
+
* site when you need a member, e.g. `passes.velocity as TextureNode`.
|
|
1417
|
+
*/
|
|
1418
|
+
interface PassRecord {
|
|
1419
|
+
scenePass?: ScenePassNode
|
|
1420
|
+
[key: string]: three_webgpu.Node
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
/**
|
|
1424
|
+
* State passed to pipeline callbacks after the active pipeline has been created.
|
|
1425
|
+
*
|
|
1426
|
+
* `passes.scenePass` is required here: the hook installs the default scene pass before either
|
|
1427
|
+
* callback runs, so callbacks can use it without a guard or a cast.
|
|
1428
|
+
*
|
|
1429
|
+
* `renderer` is narrowed to `WebGPURenderer` and `isLegacy` to `false`: the hook throws under
|
|
1430
|
+
* the legacy renderer before either callback can run, so a callback never sees WebGL.
|
|
1431
|
+
*/
|
|
1432
|
+
type RenderPipelineCallbackState = RootState & {
|
|
1433
|
+
renderPipeline: ThreeRenderPipeline
|
|
1434
|
+
passes: PassRecord & { scenePass: ScenePassNode }
|
|
1435
|
+
renderer: three_webgpu.WebGPURenderer
|
|
1436
|
+
isLegacy: false
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
/**
|
|
1440
|
+
* What a callback may return to register entries into `state.passes`.
|
|
1441
|
+
*
|
|
1442
|
+
* `scenePass` is reserved. The hook owns that entry and its lifecycle: it caches the pass it
|
|
1443
|
+
* created, and `rebuild()` / `reset()` dispose that cached pass. A callback overwriting the
|
|
1444
|
+
* store entry would leave the store pointing at a node the hook never disposes, and the hook
|
|
1445
|
+
* disposing a pass nothing references. So returning it is a type error.
|
|
1446
|
+
*/
|
|
1447
|
+
type RegisteredPasses = Record<string, three_webgpu.Node> & { scenePass?: never }
|
|
1335
1448
|
|
|
1336
1449
|
/** Setup callback - runs first to configure MRT, create additional passes */
|
|
1337
|
-
type RenderPipelineSetupCallback = (state:
|
|
1450
|
+
type RenderPipelineSetupCallback = (state: RenderPipelineCallbackState) => RegisteredPasses | void
|
|
1338
1451
|
|
|
1339
1452
|
/** Main callback - runs second to configure outputNode, create effect passes */
|
|
1340
|
-
type RenderPipelineMainCallback = (state:
|
|
1453
|
+
type RenderPipelineMainCallback = (state: RenderPipelineCallbackState) => RegisteredPasses | void
|
|
1341
1454
|
|
|
1342
|
-
/**
|
|
1343
|
-
interface
|
|
1455
|
+
/** The imperative half of useRenderPipeline's return value, present in every state */
|
|
1456
|
+
interface UseRenderPipelineActions {
|
|
1344
1457
|
/** Current passes from state */
|
|
1345
1458
|
passes: PassRecord
|
|
1346
|
-
/** RenderPipeline instance (null if not initialized) */
|
|
1347
|
-
renderPipeline: ThreeRenderPipeline | null
|
|
1348
1459
|
/** Clear all passes from state */
|
|
1349
1460
|
clearPasses: () => void
|
|
1350
1461
|
/** Reset RenderPipeline entirely (clears PP + passes) */
|
|
1351
1462
|
reset: () => void
|
|
1352
1463
|
/** Re-run setup/main callbacks with current closure values */
|
|
1353
1464
|
rebuild: () => void
|
|
1354
|
-
/** True when RenderPipeline is configured and ready */
|
|
1355
|
-
isReady: boolean
|
|
1356
1465
|
}
|
|
1466
|
+
|
|
1467
|
+
/**
|
|
1468
|
+
* Return type for useRenderPipeline hook, discriminated on `isReady`.
|
|
1469
|
+
*
|
|
1470
|
+
* `if (isReady)` narrows `renderPipeline` to non-null, which is what the docs already tell
|
|
1471
|
+
* callers to check. `passes.scenePass` deliberately stays optional in the ready branch:
|
|
1472
|
+
* `clearPasses()` empties the record while leaving the pipeline in place.
|
|
1473
|
+
*/
|
|
1474
|
+
type UseRenderPipelineReturn = UseRenderPipelineActions &
|
|
1475
|
+
(
|
|
1476
|
+
| {
|
|
1477
|
+
/** True when RenderPipeline is configured and ready */
|
|
1478
|
+
isReady: true
|
|
1479
|
+
/** RenderPipeline instance */
|
|
1480
|
+
renderPipeline: ThreeRenderPipeline
|
|
1481
|
+
}
|
|
1482
|
+
| {
|
|
1483
|
+
/** False until the pipeline has been created */
|
|
1484
|
+
isReady: false
|
|
1485
|
+
/** Not initialized yet, or torn down by reset() */
|
|
1486
|
+
renderPipeline: null
|
|
1487
|
+
}
|
|
1488
|
+
)
|
|
1357
1489
|
}
|
|
1358
1490
|
|
|
1359
1491
|
type MutableOrReadonlyParameters<T extends (...args: any) => any> = Parameters<T> | Readonly<Parameters<T>>
|
|
@@ -2144,7 +2276,10 @@ declare function addTail(callback: GlobalRenderCallback): () => void;
|
|
|
2144
2276
|
* Invalidates the view, requesting a frame to be rendered.
|
|
2145
2277
|
* In demand mode, this triggers the scheduler to run frames.
|
|
2146
2278
|
*
|
|
2147
|
-
*
|
|
2279
|
+
* With a state argument, only that root's jobs run on the requested frames; other
|
|
2280
|
+
* roots on 'demand' stay idle. Without one, every registered root is invalidated.
|
|
2281
|
+
*
|
|
2282
|
+
* @param state - Optional root state; targets the invalidation at that root
|
|
2148
2283
|
* @param frames - Number of frames to request (default: 1)
|
|
2149
2284
|
* @param stackFrames - If false, sets pendingFrames to frames. If true, adds to existing pendingFrames (default: false)
|
|
2150
2285
|
*
|
|
@@ -2155,14 +2290,16 @@ declare function invalidate(state?: RootState, frames?: number, stackFrames?: bo
|
|
|
2155
2290
|
* Advances the frameloop and runs render effects.
|
|
2156
2291
|
* Useful for when manually rendering via `frameloop="never"`.
|
|
2157
2292
|
*
|
|
2293
|
+
* With a state argument, only that root is stepped. Without one, every
|
|
2294
|
+
* registered root is stepped for backwards compatibility.
|
|
2295
|
+
*
|
|
2158
2296
|
* @param timestamp - The timestamp to use for this frame
|
|
2159
2297
|
* @param runGlobalEffects - Ignored (kept for backwards compat, global effects always run)
|
|
2160
|
-
* @param state -
|
|
2161
|
-
* @param frame - Ignored (kept for backwards compat)
|
|
2298
|
+
* @param state - Optional root state; targets the manual step at that root
|
|
2162
2299
|
*
|
|
2163
2300
|
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
|
|
2164
2301
|
*/
|
|
2165
|
-
declare function advance(timestamp: number): void;
|
|
2302
|
+
declare function advance(timestamp: number, runGlobalEffects?: boolean, state?: RootState): void;
|
|
2166
2303
|
|
|
2167
2304
|
/* eslint-disable @definitelytyped/no-unnecessary-generics */
|
|
2168
2305
|
declare function ReactReconciler<
|
|
@@ -3846,25 +3983,13 @@ declare function useUniform<T extends UniformValue>(name: string): UniformNode<T
|
|
|
3846
3983
|
declare function useUniform<T extends UniformValue>(name: string, value: T): UniformNode<Widen<T>>;
|
|
3847
3984
|
|
|
3848
3985
|
/**
|
|
3849
|
-
* Minimal interface for TSL nodes.
|
|
3850
|
-
*
|
|
3851
|
-
*
|
|
3852
|
-
* extend Node with all required properties.
|
|
3986
|
+
* Minimal interface for TSL nodes. The definition lives with the store types as `NodeLike`, so
|
|
3987
|
+
* the shape creators may return and the shape `state.nodes` holds are the same type by
|
|
3988
|
+
* construction. See `NodeLike` for why this is structural rather than three's `Node`.
|
|
3853
3989
|
*/
|
|
3854
|
-
|
|
3855
|
-
uuid?: string;
|
|
3856
|
-
nodeType?: string | null;
|
|
3857
|
-
/** label method for chaining - sets the node's label and returns self */
|
|
3858
|
-
label?: ((label: string) => TSLNodeLike) | string;
|
|
3859
|
-
setName?: (name: string) => this;
|
|
3860
|
-
}
|
|
3990
|
+
type TSLNodeLike = NodeLike;
|
|
3861
3991
|
/** TSL node type - alias for compatibility */
|
|
3862
3992
|
type TSLNode = TSLNodeLike;
|
|
3863
|
-
/**
|
|
3864
|
-
* A record of TSL nodes - allows mixed node types (OperatorNode, ConstNode, etc.)
|
|
3865
|
-
* Uses TSLNodeLike for broader compatibility with Three.js's TSL type definitions.
|
|
3866
|
-
*/
|
|
3867
|
-
type NodeRecord<T extends TSLNodeLike = TSLNodeLike> = Record<string, T>;
|
|
3868
3993
|
/**
|
|
3869
3994
|
* Creator function that returns a record of nodes.
|
|
3870
3995
|
* Uses TSLNodeLike constraint to allow mixed node types
|
|
@@ -4153,4 +4278,4 @@ declare const useThree: UseThreeWebGPU;
|
|
|
4153
4278
|
declare const useFrame: UseFrameWebGPU;
|
|
4154
4279
|
|
|
4155
4280
|
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, Texture, _roots, addAfterEffect, addEffect, addTail, advance, applyProps, attach, buildGraph, calculateDpr, clearNodeScope, clearRootNodes, clearRootUniforms, clearScope, context, createEvents, createPointerEvents, createPortal, createRoot, createScopedStore, createStore, createTextureOperations, detach, diffProps, dispose, createPointerEvents as events, extend, findInitialRoot, flushSync, fromRef, getInstanceProps, getPrimary, getPrimaryIds, getRootState, getUuidPrefix, hasConstructor, hasPrimary, invalidate, invalidateInstance, is, isColorRepresentation, isCopyable, isFromRef, isObject3D, isOnce, isOrthographicCamera, isRef, isRenderer, isTexture, isVectorLike, once, prepare, presetsObj, rebuildAllBuffers, rebuildAllNodes, rebuildAllStorage, rebuildAllUniforms, reconciler, registerPrimary, removeInteractivity, removeNodes, removeUniforms, resolve, swapInteractivity, unmountComponentAtNode, unregisterPrimary, updateCamera, updateFrustum, useBridge, useBuffers, useEnvironment, useFrame, useGPUStorage, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useLocalNodes, useMutableCallback, useNodes, useRenderPipeline, useRenderTarget, useStore, useTexture, useTextures, useThree, useUniform, useUniforms, waitForPrimary };
|
|
4156
|
-
export type { Act, Args, ArgsProp, AttachFnType, AttachType, BackgroundConfig, BackgroundProp, BaseRendererProps, Bridge, BufferCreator, BufferLike, BufferRecord, BufferStore, BuffersWithUtils, Camera, CameraProps, CanvasProps, CanvasSchedulerConfig, Catalogue, ClearBuffersFn, ClearNodesFn, ClearStorageFn, ClearUniformsFn, Color, ColorManagementConfig, ComputeFunction, ConstructorRepresentation, CreatorState, DefaultGLProps, DefaultRendererProps, Disposable, DisposeBuffersFn, DisposeOptions, DisposeStorageFn, DomEvent, Dpr, ElementProps, EnvironmentLoaderProps, EnvironmentProps, EquConfig, Euler, EventHandlers, EventManager, EventProps, Events, Extensions, FiberRoot, FilterFunction, FrameCallback, FrameNextCallback, FrameNextState, FrameState, Frameloop, GLProps, GLTFLike, GeometryProps, GeometryTransformProps, GlobalEffectType, GlobalRenderCallback, HostConfig, InferLoadResult, InjectState, InputLike, Instance, InstanceProps, WebGPUInternalState as InternalState, Intersection, IntersectionEvent, IsAllOptional, IsOptional, Layers, LegacyInternalState, LegacyRenderer, LegacyRootState, LoaderInstance, LoaderLike, LoaderResult, LocalNodeCreator, MappedTextureType, MathProps, MathRepresentation, MathType, MathTypes, Matrix3, Matrix4, Mutable, MutableOrReadonlyParameters, NodeCreator, NodeProps,
|
|
4281
|
+
export type { Act, Args, ArgsProp, AttachFnType, AttachType, BackgroundConfig, BackgroundProp, BaseRendererProps, Bridge, BufferCreator, BufferLike, BufferRecord, BufferStore, BuffersWithUtils, Camera, CameraProps, CanvasProps, CanvasSchedulerConfig, Catalogue, ClearBuffersFn, ClearNodesFn, ClearStorageFn, ClearUniformsFn, Color, ColorManagementConfig, ComputeFunction, ConstructorRepresentation, CreatorState, DefaultGLProps, DefaultRendererProps, Disposable, DisposeBuffersFn, DisposeOptions, DisposeStorageFn, DomEvent, Dpr, ElementProps, EnvironmentLoaderProps, EnvironmentProps, EquConfig, Euler, EventHandlers, EventManager, EventProps, Events, Extensions, FiberRoot, FilterFunction, FrameCallback, FrameNextCallback, FrameNextState, FrameState, Frameloop, GLProps, GLTFLike, GeometryProps, GeometryTransformProps, GlobalEffectType, GlobalRenderCallback, HostConfig, InferLoadResult, InjectState, InputLike, Instance, InstanceProps, WebGPUInternalState as InternalState, Intersection, IntersectionEvent, IsAllOptional, IsOptional, Layers, LegacyInternalState, LegacyRenderer, LegacyRootState, LoaderInstance, LoaderLike, LoaderResult, LocalNodeCreator, MappedTextureType, MathProps, MathRepresentation, MathType, MathTypes, Matrix3, Matrix4, Mutable, MutableOrReadonlyParameters, NodeCreator, NodeLike, NodeProps, NodeStore, NodesWithUtils, NonFunctionKeys, ObjectMap, OffscreenCanvas$1 as OffscreenCanvas, Overwrite, Performance, PointerCaptureTarget, PointerState, PresetsType, PrimaryCanvasEntry, Properties, Quaternion, WebGPUR3FRenderer as R3FRenderer, RaycastableRepresentation, ReactProps, RebuildBuffersFn, RebuildNodesFn, RebuildStorageFn, RebuildUniformsFn, ReconcilerRoot, RemoveBuffersFn, RemoveNodesFn, RemoveStorageFn, RemoveUniformsFn, RenderCallback, RenderProps, RenderTargetOptions, Renderer, RendererConfigExtended, RendererFactory, RendererProps, Root, WebGPURootState as RootState, RootStore, ScopedStoreType, SetBlock, Size, StorageCreator, StorageLike, StorageRecord, StorageStore, StorageWithUtils, Subscription, TSLNode, TSLNodeInput, TextureEntry, TextureInput, TextureNode, TextureOperations, TextureResult, ThreeCamera, ThreeElement, ThreeElements, ThreeElementsImpl, ThreeEvent, ThreeExports, ThreeToJSXElements, UnblockProps, UniformCreator, UniformValue, UniformsWithUtils, UseFrameWebGPU, UseTextureOptions, UseTexturesReturn, UseThreeWebGPU, Vector2, Vector3, Vector4, VectorRepresentation, Viewport, VisibilityEntry, WebGLDefaultProps, WebGLProps, WebGLShadowConfig, WebGPUDefaultProps, WebGPUProps, WebGPUShadowConfig, XRManager, XRPointerConfig };
|