@react-three/fiber 10.0.0-canary.0d86c23 → 10.0.0-canary.0ea97c0
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 +119 -61
- package/dist/index.d.cts +180 -26
- package/dist/index.d.mts +180 -26
- package/dist/index.d.ts +180 -26
- package/dist/index.mjs +119 -61
- package/dist/legacy.cjs +115 -61
- package/dist/legacy.d.cts +179 -29
- package/dist/legacy.d.mts +179 -29
- package/dist/legacy.d.ts +179 -29
- package/dist/legacy.mjs +115 -61
- package/dist/webgpu/index.cjs +182 -98
- package/dist/webgpu/index.d.cts +204 -90
- package/dist/webgpu/index.d.mts +204 -90
- package/dist/webgpu/index.d.ts +204 -90
- package/dist/webgpu/index.mjs +182 -98
- package/package.json +2 -2
- package/readme.md +1 -1
package/dist/webgpu/index.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as webgpu from 'three/webgpu';
|
|
2
2
|
import { CubeRenderTarget, RenderTarget, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, ShaderMaterial, Uniform, SRGBColorSpace, RGBAFormat, UnsignedByteType, Vector3, Vector2, TextureLoader, Texture as Texture$1, CubeReflectionMapping, EquirectangularReflectionMapping, CubeTextureLoader, CanvasTarget, Raycaster, OrthographicCamera, PerspectiveCamera, Scene, PCFShadowMap, VSMShadowMap, BasicShadowMap, ACESFilmicToneMapping, WebGPURenderer, HalfFloatType, Color, Vector4, RenderPipeline } from 'three/webgpu';
|
|
3
|
-
import { Inspector } from 'three/addons/inspector/Inspector.js';
|
|
4
3
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
5
4
|
import * as React from 'react';
|
|
6
5
|
import React__default, { useRef, useMemo, useLayoutEffect, useEffect, useContext, useImperativeHandle, useCallback, useState } from 'react';
|
|
@@ -34,6 +33,10 @@ function _mergeNamespaces(n, m) {
|
|
|
34
33
|
|
|
35
34
|
const R3F_BUILD_LEGACY = false;
|
|
36
35
|
const R3F_BUILD_WEBGPU = true;
|
|
36
|
+
async function loadInspector() {
|
|
37
|
+
const { Inspector } = await import('three/addons/inspector/Inspector.js');
|
|
38
|
+
return Inspector;
|
|
39
|
+
}
|
|
37
40
|
const WebGLRenderer = class WebGLRenderer2 {
|
|
38
41
|
constructor() {
|
|
39
42
|
throw new Error(
|
|
@@ -47,13 +50,13 @@ const WebGLCubeRenderTarget = null;
|
|
|
47
50
|
const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
48
51
|
__proto__: null,
|
|
49
52
|
CubeRenderTargetCompat: CubeRenderTarget,
|
|
50
|
-
Inspector: Inspector,
|
|
51
53
|
R3F_BUILD_LEGACY: R3F_BUILD_LEGACY,
|
|
52
54
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
53
55
|
RenderTargetCompat: RenderTarget,
|
|
54
56
|
WebGLCubeRenderTarget: WebGLCubeRenderTarget,
|
|
55
57
|
WebGLRenderTarget: WebGLRenderTarget,
|
|
56
|
-
WebGLRenderer: WebGLRenderer
|
|
58
|
+
WebGLRenderer: WebGLRenderer,
|
|
59
|
+
loadInspector: loadInspector
|
|
57
60
|
}, [webgpu]);
|
|
58
61
|
|
|
59
62
|
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
@@ -609,7 +612,12 @@ function diffProps(instance, newProps) {
|
|
|
609
612
|
const changedProps = {};
|
|
610
613
|
for (const prop in newProps) {
|
|
611
614
|
if (RESERVED_PROPS.includes(prop)) continue;
|
|
612
|
-
if (is.equ(newProps[prop], instance.props[prop]))
|
|
615
|
+
if (is.equ(newProps[prop], instance.props[prop])) {
|
|
616
|
+
const value = newProps[prop];
|
|
617
|
+
if (!isCopyable(value)) continue;
|
|
618
|
+
const { target } = resolve(instance.object, prop);
|
|
619
|
+
if (!isCopyable(target) || target.constructor !== value.constructor) continue;
|
|
620
|
+
}
|
|
613
621
|
changedProps[prop] = newProps[prop];
|
|
614
622
|
for (const other in newProps) {
|
|
615
623
|
if (other.startsWith(`${prop}-`)) changedProps[other] = newProps[other];
|
|
@@ -912,7 +920,7 @@ const createStore = (invalidate, advance) => {
|
|
|
912
920
|
size: newSize,
|
|
913
921
|
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
914
922
|
}));
|
|
915
|
-
|
|
923
|
+
get().invalidate();
|
|
916
924
|
}
|
|
917
925
|
}
|
|
918
926
|
return;
|
|
@@ -927,15 +935,16 @@ const createStore = (invalidate, advance) => {
|
|
|
927
935
|
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
928
936
|
_sizeImperative: true
|
|
929
937
|
}));
|
|
930
|
-
|
|
938
|
+
get().invalidate();
|
|
931
939
|
},
|
|
932
940
|
setDpr: (dpr) => set((state2) => {
|
|
933
941
|
const resolved = calculateDpr(dpr);
|
|
934
942
|
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
935
943
|
}),
|
|
936
944
|
setFrameloop: (frameloop = "always") => {
|
|
945
|
+
const rootId = get().internal.rootId;
|
|
946
|
+
if (rootId) getScheduler().setRootFrameloop(rootId, frameloop);
|
|
937
947
|
set(() => ({ frameloop }));
|
|
938
|
-
getScheduler().frameloop = frameloop;
|
|
939
948
|
},
|
|
940
949
|
setError: (error) => set(() => ({ error })),
|
|
941
950
|
error: null,
|
|
@@ -1051,17 +1060,11 @@ const createStore = (invalidate, advance) => {
|
|
|
1051
1060
|
oldSize = size;
|
|
1052
1061
|
oldDpr = viewport.dpr;
|
|
1053
1062
|
updateCamera(camera, size);
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
actualRenderer.setSize(size.width, size.height, false);
|
|
1060
|
-
if (canvasTarget) {
|
|
1061
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1062
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1063
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
1064
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
1065
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
1066
|
+
const activeTarget = actualRenderer.getCanvasTarget?.();
|
|
1067
|
+
if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
|
|
1065
1068
|
}
|
|
1066
1069
|
if (camera !== oldCamera) {
|
|
1067
1070
|
oldCamera = camera;
|
|
@@ -1123,7 +1126,11 @@ function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
|
1123
1126
|
const results = cacheKeys.map(
|
|
1124
1127
|
(key, index) => suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
1125
1128
|
);
|
|
1126
|
-
|
|
1129
|
+
const stableRef = useRef(null);
|
|
1130
|
+
const previous = stableRef.current;
|
|
1131
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
1132
|
+
stableRef.current = stable;
|
|
1133
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
1127
1134
|
}
|
|
1128
1135
|
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
1129
1136
|
const inputs = Array.isArray(input) ? input : [input];
|
|
@@ -1138,7 +1145,7 @@ useLoader.clear = function(loader, input, cacheKey) {
|
|
|
1138
1145
|
};
|
|
1139
1146
|
useLoader.loader = getLoader$1;
|
|
1140
1147
|
|
|
1141
|
-
function useFrame(callback, priorityOrOptions) {
|
|
1148
|
+
function useFrame$1(callback, priorityOrOptions) {
|
|
1142
1149
|
const store = React.useContext(context);
|
|
1143
1150
|
const isInsideCanvas = store !== null;
|
|
1144
1151
|
const scheduler = getScheduler();
|
|
@@ -1243,6 +1250,13 @@ function useFrame(callback, priorityOrOptions) {
|
|
|
1243
1250
|
* Use for controlling the entire frame loop, adding phases, etc.
|
|
1244
1251
|
*/
|
|
1245
1252
|
scheduler: scheduler2,
|
|
1253
|
+
/**
|
|
1254
|
+
* The root that currently owns this job. Resolve on access because ambient
|
|
1255
|
+
* jobs can be adopted by a Canvas after the controls object is created.
|
|
1256
|
+
*/
|
|
1257
|
+
get rootId() {
|
|
1258
|
+
return getScheduler().getJobRootId(id);
|
|
1259
|
+
},
|
|
1246
1260
|
/**
|
|
1247
1261
|
* Manually step this job only.
|
|
1248
1262
|
* Bypasses FPS limiting - always runs.
|
|
@@ -1259,6 +1273,14 @@ function useFrame(callback, priorityOrOptions) {
|
|
|
1259
1273
|
stepAll: (timestamp) => {
|
|
1260
1274
|
getScheduler().step(timestamp);
|
|
1261
1275
|
},
|
|
1276
|
+
/**
|
|
1277
|
+
* Request frames for this job's owning root without waking sibling roots.
|
|
1278
|
+
*/
|
|
1279
|
+
invalidate: (frames, stackFrames) => {
|
|
1280
|
+
const scheduler3 = getScheduler();
|
|
1281
|
+
const rootId = scheduler3.getJobRootId(id);
|
|
1282
|
+
if (rootId) scheduler3.invalidateRoot(rootId, frames, stackFrames);
|
|
1283
|
+
},
|
|
1262
1284
|
/**
|
|
1263
1285
|
* Pause this job (set enabled=false).
|
|
1264
1286
|
* Job remains registered but won't run.
|
|
@@ -1288,6 +1310,11 @@ function getUrls(input) {
|
|
|
1288
1310
|
if (Array.isArray(input)) return input;
|
|
1289
1311
|
return Object.values(input);
|
|
1290
1312
|
}
|
|
1313
|
+
function inputSignature(input) {
|
|
1314
|
+
if (typeof input === "string") return input;
|
|
1315
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
1316
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
1317
|
+
}
|
|
1291
1318
|
function allUrlsCached(urls, textureCache) {
|
|
1292
1319
|
return urls.every((url) => textureCache.has(url));
|
|
1293
1320
|
}
|
|
@@ -1306,25 +1333,26 @@ function buildFromCache(input, textureCache) {
|
|
|
1306
1333
|
}
|
|
1307
1334
|
}
|
|
1308
1335
|
function useTexture(input, optionsOrOnLoad) {
|
|
1309
|
-
const renderer = useThree((state) => state.internal.actualRenderer);
|
|
1336
|
+
const renderer = useThree$1((state) => state.internal.actualRenderer);
|
|
1310
1337
|
const store = useStore();
|
|
1311
1338
|
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
1312
1339
|
const { onLoad, cache = true } = options;
|
|
1313
1340
|
const onLoadRef = useRef(onLoad);
|
|
1314
1341
|
onLoadRef.current = onLoad;
|
|
1315
1342
|
const onLoadCalledForRef = useRef(null);
|
|
1316
|
-
const
|
|
1343
|
+
const inputKey = useMemo(() => inputSignature(input), [input]);
|
|
1344
|
+
const stableInput = useMemo(() => input, [inputKey]);
|
|
1345
|
+
const urls = useMemo(() => getUrls(stableInput), [stableInput]);
|
|
1317
1346
|
const cachedResult = useMemo(() => {
|
|
1318
1347
|
if (!cache) return null;
|
|
1319
1348
|
const textures = store.getState().textures;
|
|
1320
1349
|
if (!allUrlsCached(urls, textures)) return null;
|
|
1321
|
-
return buildFromCache(
|
|
1322
|
-
}, [cache, urls,
|
|
1350
|
+
return buildFromCache(stableInput, textures);
|
|
1351
|
+
}, [cache, urls, stableInput, store]);
|
|
1323
1352
|
const loadedTextures = useLoader(
|
|
1324
1353
|
TextureLoader,
|
|
1325
|
-
IsObject(
|
|
1354
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
1326
1355
|
);
|
|
1327
|
-
const inputKey = urls.join("\0");
|
|
1328
1356
|
useLayoutEffect(() => {
|
|
1329
1357
|
if (cachedResult) return;
|
|
1330
1358
|
if (onLoadCalledForRef.current === inputKey) return;
|
|
@@ -1351,28 +1379,28 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1351
1379
|
}, [renderer, loadedTextures, cachedResult]);
|
|
1352
1380
|
const mappedTextures = useMemo(() => {
|
|
1353
1381
|
if (cachedResult) return cachedResult;
|
|
1354
|
-
if (IsObject(
|
|
1382
|
+
if (IsObject(stableInput)) {
|
|
1355
1383
|
const keyed = {};
|
|
1356
1384
|
const textureArray = loadedTextures;
|
|
1357
1385
|
let i = 0;
|
|
1358
|
-
for (const key in
|
|
1386
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
1359
1387
|
return keyed;
|
|
1360
1388
|
} else {
|
|
1361
1389
|
return loadedTextures;
|
|
1362
1390
|
}
|
|
1363
|
-
}, [
|
|
1391
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
1364
1392
|
useEffect(() => {
|
|
1365
1393
|
if (!cache) return;
|
|
1366
1394
|
const urlTextureMap = [];
|
|
1367
|
-
if (typeof
|
|
1368
|
-
urlTextureMap.push([
|
|
1369
|
-
} else if (Array.isArray(
|
|
1395
|
+
if (typeof stableInput === "string") {
|
|
1396
|
+
urlTextureMap.push([stableInput, mappedTextures]);
|
|
1397
|
+
} else if (Array.isArray(stableInput)) {
|
|
1370
1398
|
const textureArray = mappedTextures;
|
|
1371
|
-
|
|
1372
|
-
} else if (IsObject(
|
|
1399
|
+
stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1400
|
+
} else if (IsObject(stableInput)) {
|
|
1373
1401
|
const textureRecord = mappedTextures;
|
|
1374
|
-
for (const key in
|
|
1375
|
-
const url =
|
|
1402
|
+
for (const key in stableInput) {
|
|
1403
|
+
const url = stableInput[key];
|
|
1376
1404
|
urlTextureMap.push([url, textureRecord[key]]);
|
|
1377
1405
|
}
|
|
1378
1406
|
}
|
|
@@ -1401,7 +1429,7 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1401
1429
|
}
|
|
1402
1430
|
return { _textureRefs: refs };
|
|
1403
1431
|
});
|
|
1404
|
-
}, [cache,
|
|
1432
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
1405
1433
|
return mappedTextures;
|
|
1406
1434
|
}
|
|
1407
1435
|
useTexture.preload = (url) => useLoader.preload(TextureLoader, url);
|
|
@@ -1472,13 +1500,13 @@ function useTextures(selector) {
|
|
|
1472
1500
|
};
|
|
1473
1501
|
}, [store]);
|
|
1474
1502
|
const subscribe = selector ? () => selector(registry) : (state) => state.textures;
|
|
1475
|
-
const selected = useThree(subscribe);
|
|
1503
|
+
const selected = useThree$1(subscribe);
|
|
1476
1504
|
return selector ? selected : registry;
|
|
1477
1505
|
}
|
|
1478
1506
|
|
|
1479
1507
|
function useRenderTarget(widthOrOptions, heightOrOptions, options) {
|
|
1480
|
-
const isLegacy = useThree((s) => s.isLegacy);
|
|
1481
|
-
const size = useThree((s) => s.size);
|
|
1508
|
+
const isLegacy = useThree$1((s) => s.isLegacy);
|
|
1509
|
+
const size = useThree$1((s) => s.size);
|
|
1482
1510
|
let width;
|
|
1483
1511
|
let height;
|
|
1484
1512
|
let opts;
|
|
@@ -1535,7 +1563,7 @@ function useEnvironment({
|
|
|
1535
1563
|
const { extension, isCubemap } = getExtension(files);
|
|
1536
1564
|
const loader = getLoader(extension);
|
|
1537
1565
|
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
1538
|
-
const renderer = useThree((state) => state.renderer);
|
|
1566
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
1539
1567
|
useLayoutEffect(() => {
|
|
1540
1568
|
if (extension !== "webp" && extension !== "jpg" && extension !== "jpeg") return;
|
|
1541
1569
|
function clearGainmapTexture() {
|
|
@@ -1628,7 +1656,7 @@ function useStore() {
|
|
|
1628
1656
|
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
1629
1657
|
return store;
|
|
1630
1658
|
}
|
|
1631
|
-
function useThree(selector = (state) => state, equalityFn) {
|
|
1659
|
+
function useThree$1(selector = (state) => state, equalityFn) {
|
|
1632
1660
|
return useStore()(selector, equalityFn);
|
|
1633
1661
|
}
|
|
1634
1662
|
function useInstanceHandle(ref) {
|
|
@@ -1670,13 +1698,19 @@ function addTail(callback) {
|
|
|
1670
1698
|
return getScheduler().onIdle(callback);
|
|
1671
1699
|
}
|
|
1672
1700
|
function invalidate(state, frames = 1, stackFrames = false) {
|
|
1673
|
-
|
|
1701
|
+
const rootId = state?.internal?.rootId;
|
|
1702
|
+
const scheduler = getScheduler();
|
|
1703
|
+
if (rootId) scheduler.invalidateRoot(rootId, frames, stackFrames);
|
|
1704
|
+
else scheduler.invalidate(frames, stackFrames);
|
|
1674
1705
|
}
|
|
1675
|
-
function advance(timestamp) {
|
|
1676
|
-
|
|
1706
|
+
function advance(timestamp, runGlobalEffects, state) {
|
|
1707
|
+
const rootId = state?.internal?.rootId;
|
|
1708
|
+
const scheduler = getScheduler();
|
|
1709
|
+
if (rootId) scheduler.stepRoot(rootId, timestamp);
|
|
1710
|
+
else scheduler.step(timestamp);
|
|
1677
1711
|
}
|
|
1678
1712
|
|
|
1679
|
-
const version = "10.0.0-alpha.
|
|
1713
|
+
const version = "10.0.0-alpha.4";
|
|
1680
1714
|
const packageData = {
|
|
1681
1715
|
version: version};
|
|
1682
1716
|
|
|
@@ -14192,9 +14226,8 @@ function createRoot(canvas) {
|
|
|
14192
14226
|
if (!renderer.hasInitialized?.()) {
|
|
14193
14227
|
const size2 = computeInitialSize(canvas, propsSize);
|
|
14194
14228
|
if (size2.width > 0 && size2.height > 0) {
|
|
14195
|
-
|
|
14196
|
-
|
|
14197
|
-
canvas.height = size2.height * pixelRatio;
|
|
14229
|
+
renderer.setPixelRatio(calculateDpr(dpr));
|
|
14230
|
+
renderer.setSize(size2.width, size2.height, false);
|
|
14198
14231
|
}
|
|
14199
14232
|
await renderer.init();
|
|
14200
14233
|
}
|
|
@@ -14203,7 +14236,7 @@ function createRoot(canvas) {
|
|
|
14203
14236
|
state.internal.actualRenderer = renderer;
|
|
14204
14237
|
state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
|
|
14205
14238
|
if (canvasId && !state.internal.isSecondary) {
|
|
14206
|
-
const canvasTarget =
|
|
14239
|
+
const canvasTarget = renderer.getCanvasTarget?.();
|
|
14207
14240
|
const unregisterPrimary = registerPrimary(canvasId, renderer, store);
|
|
14208
14241
|
state.set((prev) => ({
|
|
14209
14242
|
internal: {
|
|
@@ -14317,7 +14350,7 @@ function createRoot(canvas) {
|
|
|
14317
14350
|
const handleXRFrame = (timestamp, _frame) => {
|
|
14318
14351
|
const state2 = store.getState();
|
|
14319
14352
|
if (state2.frameloop === "never") return;
|
|
14320
|
-
advance(timestamp);
|
|
14353
|
+
advance(timestamp, true, state2);
|
|
14321
14354
|
};
|
|
14322
14355
|
const actualRenderer = state.internal.actualRenderer;
|
|
14323
14356
|
const handleSessionChange = () => {
|
|
@@ -14325,7 +14358,7 @@ function createRoot(canvas) {
|
|
|
14325
14358
|
const renderer2 = state2.internal.actualRenderer;
|
|
14326
14359
|
actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
|
|
14327
14360
|
renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
|
|
14328
|
-
if (!renderer2.xr.isPresenting) invalidate();
|
|
14361
|
+
if (!renderer2.xr.isPresenting) invalidate(state2);
|
|
14329
14362
|
};
|
|
14330
14363
|
const xr = {
|
|
14331
14364
|
connect() {
|
|
@@ -14407,14 +14440,23 @@ function createRoot(canvas) {
|
|
|
14407
14440
|
const newRootId = canvasId || scheduler.generateRootId();
|
|
14408
14441
|
const unregisterRoot = scheduler.registerRoot(newRootId, {
|
|
14409
14442
|
getState: () => store.getState(),
|
|
14410
|
-
onError: (err) => store.getState().setError(err)
|
|
14443
|
+
onError: (err) => store.getState().setError(err),
|
|
14444
|
+
frameloop: store.getState().frameloop,
|
|
14445
|
+
before: schedulerConfig?.before,
|
|
14446
|
+
after: schedulerConfig?.after,
|
|
14447
|
+
order: schedulerConfig?.order
|
|
14411
14448
|
});
|
|
14412
14449
|
const unregisterCanvasTarget = scheduler.register(
|
|
14413
14450
|
() => {
|
|
14414
14451
|
const state2 = store.getState();
|
|
14415
|
-
|
|
14452
|
+
const canvasTarget = state2.internal.canvasTarget;
|
|
14453
|
+
if (canvasTarget) {
|
|
14416
14454
|
const renderer2 = state2.internal.actualRenderer;
|
|
14417
|
-
renderer2.setCanvasTarget(
|
|
14455
|
+
if (renderer2.getCanvasTarget() !== canvasTarget) renderer2.setCanvasTarget(canvasTarget);
|
|
14456
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
14457
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
14458
|
+
renderer2.backend?.updateSize?.();
|
|
14459
|
+
}
|
|
14418
14460
|
}
|
|
14419
14461
|
},
|
|
14420
14462
|
{
|
|
@@ -14483,8 +14525,7 @@ function createRoot(canvas) {
|
|
|
14483
14525
|
phase: "render",
|
|
14484
14526
|
system: true,
|
|
14485
14527
|
// Internal flag: this is a system job, not user-controlled
|
|
14486
|
-
//
|
|
14487
|
-
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
14528
|
+
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
14488
14529
|
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14489
14530
|
}
|
|
14490
14531
|
);
|
|
@@ -14503,8 +14544,21 @@ function createRoot(canvas) {
|
|
|
14503
14544
|
scheduler
|
|
14504
14545
|
}
|
|
14505
14546
|
}));
|
|
14547
|
+
} else {
|
|
14548
|
+
const constraintsChanged = !is.equ(schedulerConfig?.before, lastConfiguredProps.schedulerBefore, shallowLoose) || !is.equ(schedulerConfig?.after, lastConfiguredProps.schedulerAfter, shallowLoose);
|
|
14549
|
+
if (constraintsChanged) {
|
|
14550
|
+
scheduler.setRootConstraints(rootId, {
|
|
14551
|
+
before: schedulerConfig?.before,
|
|
14552
|
+
after: schedulerConfig?.after
|
|
14553
|
+
});
|
|
14554
|
+
}
|
|
14555
|
+
if (schedulerConfig?.order !== lastConfiguredProps.schedulerOrder) {
|
|
14556
|
+
scheduler.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
14557
|
+
}
|
|
14506
14558
|
}
|
|
14507
|
-
|
|
14559
|
+
lastConfiguredProps.schedulerBefore = schedulerConfig?.before;
|
|
14560
|
+
lastConfiguredProps.schedulerAfter = schedulerConfig?.after;
|
|
14561
|
+
lastConfiguredProps.schedulerOrder = schedulerConfig?.order;
|
|
14508
14562
|
onCreated = onCreatedCallback;
|
|
14509
14563
|
configured = true;
|
|
14510
14564
|
resolve();
|
|
@@ -14546,18 +14600,23 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14546
14600
|
const fiber = root?.fiber;
|
|
14547
14601
|
if (fiber) {
|
|
14548
14602
|
const state = root?.store.getState();
|
|
14549
|
-
if (state)
|
|
14603
|
+
if (state) {
|
|
14604
|
+
state.internal.active = false;
|
|
14605
|
+
const unregisterRoot = state.internal.unregisterRoot;
|
|
14606
|
+
if (unregisterRoot) {
|
|
14607
|
+
unregisterRoot();
|
|
14608
|
+
state.internal.unregisterRoot = void 0;
|
|
14609
|
+
}
|
|
14610
|
+
}
|
|
14550
14611
|
reconciler.updateContainer(null, fiber, null, () => {
|
|
14551
14612
|
if (state) {
|
|
14552
14613
|
setTimeout(() => {
|
|
14553
14614
|
try {
|
|
14554
14615
|
const renderer = state.internal.actualRenderer;
|
|
14555
|
-
const unregisterRoot = state.internal.unregisterRoot;
|
|
14556
|
-
if (unregisterRoot) unregisterRoot();
|
|
14557
14616
|
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
14558
14617
|
if (unregisterPrimary) unregisterPrimary();
|
|
14559
14618
|
const canvasTarget = state.internal.canvasTarget;
|
|
14560
|
-
if (canvasTarget?.dispose) canvasTarget.dispose();
|
|
14619
|
+
if (state.internal.isSecondary && canvasTarget?.dispose) canvasTarget.dispose();
|
|
14561
14620
|
state.events.disconnect?.();
|
|
14562
14621
|
cleanupHelperGroup(root.store);
|
|
14563
14622
|
if (state.isLegacy && renderer) {
|
|
@@ -14719,7 +14778,7 @@ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {})
|
|
|
14719
14778
|
};
|
|
14720
14779
|
}
|
|
14721
14780
|
function EnvironmentMap({ scene, background = false, map, ...config }) {
|
|
14722
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14781
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14723
14782
|
React.useLayoutEffect(() => {
|
|
14724
14783
|
if (map) return setEnvProps(background, scene, defaultScene, map, config);
|
|
14725
14784
|
});
|
|
@@ -14737,7 +14796,7 @@ function EnvironmentCube({
|
|
|
14737
14796
|
...rest
|
|
14738
14797
|
}) {
|
|
14739
14798
|
const texture = useEnvironment(rest);
|
|
14740
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14799
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14741
14800
|
React.useLayoutEffect(() => {
|
|
14742
14801
|
return setEnvProps(background, scene, defaultScene, texture, {
|
|
14743
14802
|
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
@@ -14774,9 +14833,9 @@ function EnvironmentPortal({
|
|
|
14774
14833
|
preset = void 0,
|
|
14775
14834
|
extensions
|
|
14776
14835
|
}) {
|
|
14777
|
-
const renderer = useThree((state) => state.renderer);
|
|
14778
|
-
const isLegacy = useThree((state) => state.isLegacy);
|
|
14779
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14836
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
14837
|
+
const isLegacy = useThree$1((state) => state.isLegacy);
|
|
14838
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14780
14839
|
const camera = React.useRef(null);
|
|
14781
14840
|
const [virtualScene] = React.useState(() => new Scene());
|
|
14782
14841
|
const fbo = React.useMemo(() => {
|
|
@@ -14820,7 +14879,7 @@ function EnvironmentPortal({
|
|
|
14820
14879
|
environmentRotation
|
|
14821
14880
|
]);
|
|
14822
14881
|
let count = 1;
|
|
14823
|
-
useFrame(() => {
|
|
14882
|
+
useFrame$1(() => {
|
|
14824
14883
|
if (frames === Infinity || count < frames) {
|
|
14825
14884
|
const autoClear = renderer.autoClear;
|
|
14826
14885
|
renderer.autoClear = true;
|
|
@@ -14860,7 +14919,7 @@ function EnvironmentGround(props) {
|
|
|
14860
14919
|
] });
|
|
14861
14920
|
}
|
|
14862
14921
|
function EnvironmentColor({ color, scene }) {
|
|
14863
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14922
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14864
14923
|
React.useLayoutEffect(() => {
|
|
14865
14924
|
if (color === void 0) return;
|
|
14866
14925
|
const target = resolveScene(scene || defaultScene);
|
|
@@ -15098,9 +15157,9 @@ function CanvasImpl({
|
|
|
15098
15157
|
React.useMemo(() => extend(THREE), []);
|
|
15099
15158
|
const Bridge = useBridge();
|
|
15100
15159
|
const backgroundProps = React.useMemo(() => parseBackground(background), [background]);
|
|
15101
|
-
const
|
|
15160
|
+
const [hasInitialSize, setHasInitialSize] = React.useState(false);
|
|
15102
15161
|
const measureConfig = React.useMemo(() => {
|
|
15103
|
-
if (!
|
|
15162
|
+
if (!hasInitialSize) {
|
|
15104
15163
|
return {
|
|
15105
15164
|
...resize,
|
|
15106
15165
|
scroll: resize?.scroll ?? true,
|
|
@@ -15112,7 +15171,7 @@ function CanvasImpl({
|
|
|
15112
15171
|
debounce: { scroll: 50, resize: 0 },
|
|
15113
15172
|
...resize
|
|
15114
15173
|
};
|
|
15115
|
-
}, [
|
|
15174
|
+
}, [hasInitialSize, resize]);
|
|
15116
15175
|
const [containerRef, containerRect] = useMeasure(measureConfig);
|
|
15117
15176
|
const effectiveSize = React.useMemo(() => {
|
|
15118
15177
|
let w = width ?? containerRect.width;
|
|
@@ -15128,9 +15187,7 @@ function CanvasImpl({
|
|
|
15128
15187
|
left: containerRect.left
|
|
15129
15188
|
};
|
|
15130
15189
|
}, [width, height, containerRect, forceEven]);
|
|
15131
|
-
if (!
|
|
15132
|
-
hasInitialSizeRef.current = true;
|
|
15133
|
-
}
|
|
15190
|
+
if (!hasInitialSize && effectiveSize.width > 0 && effectiveSize.height > 0) setHasInitialSize(true);
|
|
15134
15191
|
const canvasRef = React.useRef(null);
|
|
15135
15192
|
const divRef = React.useRef(null);
|
|
15136
15193
|
React.useImperativeHandle(ref, () => canvasRef.current);
|
|
@@ -15244,6 +15301,7 @@ function CanvasImpl({
|
|
|
15244
15301
|
const canvas = canvasRef.current;
|
|
15245
15302
|
if (canvas) {
|
|
15246
15303
|
return () => {
|
|
15304
|
+
if (canvas.isConnected) return;
|
|
15247
15305
|
unmountComponentAtNode(canvas);
|
|
15248
15306
|
root.current = null;
|
|
15249
15307
|
};
|
|
@@ -15454,6 +15512,11 @@ function createTextureOperations(set) {
|
|
|
15454
15512
|
removeMultiple: (keys) => removeTextures(set, keys)
|
|
15455
15513
|
};
|
|
15456
15514
|
}
|
|
15515
|
+
function scopedNodeName(scope, name) {
|
|
15516
|
+
const raw = scope ? `${scope}_${name}` : name;
|
|
15517
|
+
const safe = raw.replace(/[^A-Za-z0-9_]/g, "_");
|
|
15518
|
+
return /^[A-Za-z_]/.test(safe) ? safe : `_${safe}`;
|
|
15519
|
+
}
|
|
15457
15520
|
function extractTSLValue(value) {
|
|
15458
15521
|
if (value === null || value === void 0) return value;
|
|
15459
15522
|
if (typeof value !== "object") return value;
|
|
@@ -15652,8 +15715,7 @@ function createUniform(inName, node, scope) {
|
|
|
15652
15715
|
const inValue = vectorize(node);
|
|
15653
15716
|
const newUniform = uniform(inValue);
|
|
15654
15717
|
if (typeof newUniform.setName === "function") {
|
|
15655
|
-
|
|
15656
|
-
newUniform.setName(name);
|
|
15718
|
+
newUniform.setName(scopedNodeName(scope, inName));
|
|
15657
15719
|
}
|
|
15658
15720
|
return newUniform;
|
|
15659
15721
|
}
|
|
@@ -15752,7 +15814,7 @@ function useNodes(creatorOrScope, scope) {
|
|
|
15752
15814
|
return creatorOrScope(createLazyCreatorState(store.getState(), store));
|
|
15753
15815
|
},
|
|
15754
15816
|
prepare: (name, node) => {
|
|
15755
|
-
node.setName?.(scope
|
|
15817
|
+
node.setName?.(scopedNodeName(scope, name));
|
|
15756
15818
|
return node;
|
|
15757
15819
|
}
|
|
15758
15820
|
});
|
|
@@ -15861,7 +15923,7 @@ function useBuffers(creatorOrScope, scope) {
|
|
|
15861
15923
|
},
|
|
15862
15924
|
prepare: (name, buffer) => {
|
|
15863
15925
|
if ("setName" in buffer && typeof buffer.setName === "function") {
|
|
15864
|
-
buffer.setName(scope
|
|
15926
|
+
buffer.setName(scopedNodeName(scope, name));
|
|
15865
15927
|
}
|
|
15866
15928
|
return buffer;
|
|
15867
15929
|
}
|
|
@@ -15932,7 +15994,7 @@ function useGPUStorage(creatorOrScope, scope) {
|
|
|
15932
15994
|
return creatorOrScope(createLazyCreatorState(store.getState(), store));
|
|
15933
15995
|
},
|
|
15934
15996
|
prepare: (name, storage) => {
|
|
15935
|
-
const label = scope
|
|
15997
|
+
const label = scopedNodeName(scope, name);
|
|
15936
15998
|
if ("setName" in storage && typeof storage.setName === "function") {
|
|
15937
15999
|
storage.setName(label);
|
|
15938
16000
|
}
|
|
@@ -15963,9 +16025,10 @@ function rebuildAllStorage(store, scope) {
|
|
|
15963
16025
|
|
|
15964
16026
|
function useRenderPipeline(mainCB, setupCB) {
|
|
15965
16027
|
const store = useStore();
|
|
15966
|
-
const { scene, camera, renderer, isLegacy } = useThree();
|
|
16028
|
+
const { scene, camera, renderer, isLegacy } = useThree$1();
|
|
15967
16029
|
const callbacksRanRef = useRef(false);
|
|
15968
16030
|
const scenePassCacheRef = useRef(null);
|
|
16031
|
+
const forceScenePassRebuildRef = useRef(false);
|
|
15969
16032
|
const mainCBRef = useRef(mainCB);
|
|
15970
16033
|
const setupCBRef = useRef(setupCB);
|
|
15971
16034
|
mainCBRef.current = mainCB;
|
|
@@ -15973,7 +16036,7 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
15973
16036
|
const [rebuildVersion, setRebuildVersion] = useState(0);
|
|
15974
16037
|
useEffect(() => {
|
|
15975
16038
|
callbacksRanRef.current = false;
|
|
15976
|
-
|
|
16039
|
+
forceScenePassRebuildRef.current = true;
|
|
15977
16040
|
}, []);
|
|
15978
16041
|
const clearPasses = useCallback(() => {
|
|
15979
16042
|
store.setState({ passes: {} });
|
|
@@ -15983,12 +16046,14 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
15983
16046
|
renderPipeline: null,
|
|
15984
16047
|
passes: {}
|
|
15985
16048
|
});
|
|
16049
|
+
scenePassCacheRef.current?.scenePass.dispose();
|
|
15986
16050
|
callbacksRanRef.current = false;
|
|
15987
16051
|
scenePassCacheRef.current = null;
|
|
16052
|
+
forceScenePassRebuildRef.current = false;
|
|
15988
16053
|
}, [store]);
|
|
15989
16054
|
const rebuild = useCallback(() => {
|
|
15990
16055
|
callbacksRanRef.current = false;
|
|
15991
|
-
|
|
16056
|
+
forceScenePassRebuildRef.current = true;
|
|
15992
16057
|
setRebuildVersion((v) => v + 1);
|
|
15993
16058
|
}, []);
|
|
15994
16059
|
useLayoutEffect(() => {
|
|
@@ -15996,6 +16061,9 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
15996
16061
|
throw new Error("useRenderPipeline is only available with WebGPU renderer. Set renderer prop on Canvas.");
|
|
15997
16062
|
}
|
|
15998
16063
|
if (!renderer || !scene || !camera) return;
|
|
16064
|
+
if (!("isWebGPURenderer" in renderer)) {
|
|
16065
|
+
throw new Error("useRenderPipeline: renderer is not a WebGPURenderer but isLegacy is false.");
|
|
16066
|
+
}
|
|
15999
16067
|
const state = store.getState();
|
|
16000
16068
|
const set = store.setState;
|
|
16001
16069
|
try {
|
|
@@ -16006,21 +16074,33 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16006
16074
|
pipeline = new RenderPipeline(renderer);
|
|
16007
16075
|
justCreatedPipeline = true;
|
|
16008
16076
|
}
|
|
16009
|
-
const cacheValid = scenePassCacheRef.current && scenePassCacheRef.current.sceneUuid === scene.uuid && scenePassCacheRef.current.cameraUuid === camera.uuid;
|
|
16077
|
+
const cacheValid = !forceScenePassRebuildRef.current && scenePassCacheRef.current && scenePassCacheRef.current.sceneUuid === scene.uuid && scenePassCacheRef.current.cameraUuid === camera.uuid;
|
|
16078
|
+
let outgoingScenePass = null;
|
|
16010
16079
|
let scenePass;
|
|
16011
16080
|
if (cacheValid) {
|
|
16012
16081
|
scenePass = scenePassCacheRef.current.scenePass;
|
|
16013
16082
|
} else {
|
|
16083
|
+
outgoingScenePass = scenePassCacheRef.current?.scenePass ?? null;
|
|
16014
16084
|
scenePass = pass(scene, camera);
|
|
16015
16085
|
scenePassCacheRef.current = { sceneUuid: scene.uuid, cameraUuid: camera.uuid, scenePass };
|
|
16086
|
+
forceScenePassRebuildRef.current = false;
|
|
16016
16087
|
}
|
|
16017
16088
|
currentPasses.scenePass = scenePass;
|
|
16018
|
-
|
|
16089
|
+
let outputNodeChanged = false;
|
|
16090
|
+
if (!pipeline.outputNode || justCreatedPipeline || pipeline.outputNode === outgoingScenePass) {
|
|
16091
|
+
pipeline.outputNode = scenePass;
|
|
16092
|
+
outputNodeChanged = true;
|
|
16093
|
+
}
|
|
16019
16094
|
set({ renderPipeline: pipeline, passes: currentPasses });
|
|
16020
16095
|
const shouldRunCallbacks = justCreatedPipeline || !callbacksRanRef.current || !cacheValid;
|
|
16021
16096
|
if (shouldRunCallbacks) {
|
|
16022
16097
|
if (setupCBRef.current) {
|
|
16023
|
-
const freshState = store.getState()
|
|
16098
|
+
const freshState = Object.assign({}, store.getState(), {
|
|
16099
|
+
renderPipeline: pipeline,
|
|
16100
|
+
passes: { ...currentPasses, scenePass },
|
|
16101
|
+
renderer,
|
|
16102
|
+
isLegacy: false
|
|
16103
|
+
});
|
|
16024
16104
|
const setupResult = setupCBRef.current(freshState);
|
|
16025
16105
|
if (setupResult && typeof setupResult === "object") {
|
|
16026
16106
|
currentPasses = { ...currentPasses, ...setupResult };
|
|
@@ -16028,32 +16108,36 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16028
16108
|
}
|
|
16029
16109
|
}
|
|
16030
16110
|
if (mainCBRef.current) {
|
|
16031
|
-
const freshState = store.getState()
|
|
16111
|
+
const freshState = Object.assign({}, store.getState(), {
|
|
16112
|
+
renderPipeline: pipeline,
|
|
16113
|
+
passes: { ...currentPasses, scenePass },
|
|
16114
|
+
renderer,
|
|
16115
|
+
isLegacy: false
|
|
16116
|
+
});
|
|
16032
16117
|
const mainResult = mainCBRef.current(freshState);
|
|
16033
16118
|
if (mainResult && typeof mainResult === "object") {
|
|
16034
16119
|
currentPasses = { ...currentPasses, ...mainResult };
|
|
16035
16120
|
set({ passes: currentPasses });
|
|
16036
16121
|
}
|
|
16037
16122
|
}
|
|
16123
|
+
outputNodeChanged = true;
|
|
16038
16124
|
callbacksRanRef.current = true;
|
|
16039
16125
|
}
|
|
16126
|
+
if (outputNodeChanged) pipeline.needsUpdate = true;
|
|
16127
|
+
if (outgoingScenePass && outgoingScenePass !== scenePass) outgoingScenePass.dispose();
|
|
16040
16128
|
} catch (error) {
|
|
16041
16129
|
console.warn("[useRenderPipeline] Setup failed; the render pipeline was not configured:", error);
|
|
16042
16130
|
}
|
|
16043
16131
|
}, [store, renderer, scene, camera, isLegacy, rebuildVersion]);
|
|
16044
|
-
const passes = useThree((s) => s.passes);
|
|
16045
|
-
const renderPipeline = useThree((s) => s.renderPipeline);
|
|
16046
|
-
|
|
16047
|
-
|
|
16048
|
-
|
|
16049
|
-
clearPasses,
|
|
16050
|
-
reset,
|
|
16051
|
-
rebuild,
|
|
16052
|
-
// isReady indicates if RenderPipeline is configured and ready for rendering
|
|
16053
|
-
isReady: renderPipeline !== null
|
|
16054
|
-
};
|
|
16132
|
+
const passes = useThree$1((s) => s.passes);
|
|
16133
|
+
const renderPipeline = useThree$1((s) => s.renderPipeline);
|
|
16134
|
+
const actions = { passes, clearPasses, reset, rebuild };
|
|
16135
|
+
if (renderPipeline) return { ...actions, isReady: true, renderPipeline };
|
|
16136
|
+
return { ...actions, isReady: false, renderPipeline: null };
|
|
16055
16137
|
}
|
|
16056
16138
|
|
|
16057
16139
|
extend(THREE);
|
|
16140
|
+
const useThree = useThree$1;
|
|
16141
|
+
const useFrame = useFrame$1;
|
|
16058
16142
|
|
|
16059
16143
|
export { Block, Canvas, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, ErrorBoundary, FROM_REF, IsObject, ONCE, Portal, R3F_BUILD_LEGACY, R3F_BUILD_WEBGPU, REACT_INTERNAL_PROPS, RESERVED_PROPS, 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$1 as 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 };
|