@react-three/fiber 10.0.0-canary.0d86c23 → 10.0.0-canary.0f7fc9b
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 +41 -31
- package/dist/index.d.cts +18 -1
- package/dist/index.d.mts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.mjs +41 -31
- package/dist/legacy.cjs +40 -35
- package/dist/legacy.d.cts +17 -4
- package/dist/legacy.d.mts +17 -4
- package/dist/legacy.d.ts +17 -4
- package/dist/legacy.mjs +40 -35
- package/dist/webgpu/index.cjs +86 -57
- package/dist/webgpu/index.d.cts +40 -51
- package/dist/webgpu/index.d.mts +40 -51
- package/dist/webgpu/index.d.ts +40 -51
- package/dist/webgpu/index.mjs +86 -57
- package/package.json +1 -1
- package/readme.md +1 -1
package/dist/legacy.d.mts
CHANGED
|
@@ -38,9 +38,9 @@ function _mergeNamespaces(n, m) {
|
|
|
38
38
|
declare const R3F_BUILD_LEGACY = true;
|
|
39
39
|
declare const R3F_BUILD_WEBGPU = false;
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
type Inspector = never;
|
|
42
|
+
/** Not available on the legacy (WebGL-only) entry. */
|
|
43
|
+
declare function loadInspector(): Promise<never>;
|
|
44
44
|
declare const WebGPURenderer: {
|
|
45
45
|
new (): {};
|
|
46
46
|
};
|
|
@@ -58,7 +58,8 @@ var THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
58
58
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
59
59
|
RenderTarget: RenderTarget,
|
|
60
60
|
RenderTargetCompat: WebGLRenderTarget,
|
|
61
|
-
WebGPURenderer: WebGPURenderer
|
|
61
|
+
WebGPURenderer: WebGPURenderer,
|
|
62
|
+
loadInspector: loadInspector
|
|
62
63
|
}, [THREE$1]);
|
|
63
64
|
|
|
64
65
|
//* Utility Types ==============================
|
|
@@ -496,6 +497,18 @@ interface InternalState {
|
|
|
496
497
|
* @see https://threejs.org/docs/#api/en/renderers/common/CanvasTarget
|
|
497
498
|
*/
|
|
498
499
|
canvasTarget?: CanvasTarget
|
|
500
|
+
/**
|
|
501
|
+
* Set when this root's canvas target has been resized and the backend's cached render pass
|
|
502
|
+
* descriptor (which holds a depth-stencil view built once per canvas) is therefore stale.
|
|
503
|
+
*
|
|
504
|
+
* Flushed by the canvas-target job in the `start` phase, which is the only place this root's
|
|
505
|
+
* target is guaranteed to be the renderer's active one — `backend.updateSize()` operates on
|
|
506
|
+
* whatever `getCanvasTarget()` returns, so calling it from the resize subscription would
|
|
507
|
+
* invalidate some other canvas's descriptor instead.
|
|
508
|
+
*
|
|
509
|
+
* @see https://github.com/pmndrs/react-three-fiber/issues/3847
|
|
510
|
+
*/
|
|
511
|
+
canvasTargetSizeDirty?: boolean
|
|
499
512
|
/**
|
|
500
513
|
* Whether multi-canvas rendering is active.
|
|
501
514
|
* True when any canvas uses `renderer={{ primaryCanvas: 'id' }}` to share a renderer.
|
package/dist/legacy.d.ts
CHANGED
|
@@ -38,9 +38,9 @@ function _mergeNamespaces(n, m) {
|
|
|
38
38
|
declare const R3F_BUILD_LEGACY = true;
|
|
39
39
|
declare const R3F_BUILD_WEBGPU = false;
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
type Inspector = never;
|
|
42
|
+
/** Not available on the legacy (WebGL-only) entry. */
|
|
43
|
+
declare function loadInspector(): Promise<never>;
|
|
44
44
|
declare const WebGPURenderer: {
|
|
45
45
|
new (): {};
|
|
46
46
|
};
|
|
@@ -58,7 +58,8 @@ var THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
58
58
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
59
59
|
RenderTarget: RenderTarget,
|
|
60
60
|
RenderTargetCompat: WebGLRenderTarget,
|
|
61
|
-
WebGPURenderer: WebGPURenderer
|
|
61
|
+
WebGPURenderer: WebGPURenderer,
|
|
62
|
+
loadInspector: loadInspector
|
|
62
63
|
}, [THREE$1]);
|
|
63
64
|
|
|
64
65
|
//* Utility Types ==============================
|
|
@@ -496,6 +497,18 @@ interface InternalState {
|
|
|
496
497
|
* @see https://threejs.org/docs/#api/en/renderers/common/CanvasTarget
|
|
497
498
|
*/
|
|
498
499
|
canvasTarget?: CanvasTarget
|
|
500
|
+
/**
|
|
501
|
+
* Set when this root's canvas target has been resized and the backend's cached render pass
|
|
502
|
+
* descriptor (which holds a depth-stencil view built once per canvas) is therefore stale.
|
|
503
|
+
*
|
|
504
|
+
* Flushed by the canvas-target job in the `start` phase, which is the only place this root's
|
|
505
|
+
* target is guaranteed to be the renderer's active one — `backend.updateSize()` operates on
|
|
506
|
+
* whatever `getCanvasTarget()` returns, so calling it from the resize subscription would
|
|
507
|
+
* invalidate some other canvas's descriptor instead.
|
|
508
|
+
*
|
|
509
|
+
* @see https://github.com/pmndrs/react-three-fiber/issues/3847
|
|
510
|
+
*/
|
|
511
|
+
canvasTargetSizeDirty?: boolean
|
|
499
512
|
/**
|
|
500
513
|
* Whether multi-canvas rendering is active.
|
|
501
514
|
* True when any canvas uses `renderer={{ primaryCanvas: 'id' }}` to share a renderer.
|
package/dist/legacy.mjs
CHANGED
|
@@ -30,11 +30,9 @@ function _mergeNamespaces(n, m) {
|
|
|
30
30
|
|
|
31
31
|
const R3F_BUILD_LEGACY = true;
|
|
32
32
|
const R3F_BUILD_WEBGPU = false;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
};
|
|
33
|
+
async function loadInspector() {
|
|
34
|
+
throw new Error("Inspector is not available in legacy builds. Use @react-three/fiber/webgpu instead.");
|
|
35
|
+
}
|
|
38
36
|
const WebGPURenderer = class WebGPURenderer2 {
|
|
39
37
|
constructor() {
|
|
40
38
|
throw new Error("WebGPURenderer is not available in legacy builds. Use @react-three/fiber/webgpu instead.");
|
|
@@ -47,12 +45,12 @@ const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
47
45
|
__proto__: null,
|
|
48
46
|
CubeRenderTarget: CubeRenderTarget,
|
|
49
47
|
CubeRenderTargetCompat: WebGLCubeRenderTarget,
|
|
50
|
-
Inspector: Inspector,
|
|
51
48
|
R3F_BUILD_LEGACY: R3F_BUILD_LEGACY,
|
|
52
49
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
53
50
|
RenderTarget: RenderTarget,
|
|
54
51
|
RenderTargetCompat: WebGLRenderTarget,
|
|
55
|
-
WebGPURenderer: WebGPURenderer
|
|
52
|
+
WebGPURenderer: WebGPURenderer,
|
|
53
|
+
loadInspector: loadInspector
|
|
56
54
|
}, [three]);
|
|
57
55
|
|
|
58
56
|
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
@@ -1050,17 +1048,10 @@ const createStore = (invalidate, advance) => {
|
|
|
1050
1048
|
oldSize = size;
|
|
1051
1049
|
oldDpr = viewport.dpr;
|
|
1052
1050
|
updateCamera(camera, size);
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
1058
|
-
actualRenderer.setSize(size.width, size.height, false);
|
|
1059
|
-
if (canvasTarget) {
|
|
1060
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1061
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1051
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
1052
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
1053
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
1054
|
+
internal.canvasTargetSizeDirty = true;
|
|
1064
1055
|
}
|
|
1065
1056
|
if (camera !== oldCamera) {
|
|
1066
1057
|
oldCamera = camera;
|
|
@@ -1122,7 +1113,11 @@ function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
|
1122
1113
|
const results = cacheKeys.map(
|
|
1123
1114
|
(key, index) => suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
1124
1115
|
);
|
|
1125
|
-
|
|
1116
|
+
const stableRef = useRef(null);
|
|
1117
|
+
const previous = stableRef.current;
|
|
1118
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
1119
|
+
stableRef.current = stable;
|
|
1120
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
1126
1121
|
}
|
|
1127
1122
|
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
1128
1123
|
const inputs = Array.isArray(input) ? input : [input];
|
|
@@ -1287,6 +1282,11 @@ function getUrls(input) {
|
|
|
1287
1282
|
if (Array.isArray(input)) return input;
|
|
1288
1283
|
return Object.values(input);
|
|
1289
1284
|
}
|
|
1285
|
+
function inputSignature(input) {
|
|
1286
|
+
if (typeof input === "string") return input;
|
|
1287
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
1288
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
1289
|
+
}
|
|
1290
1290
|
function allUrlsCached(urls, textureCache) {
|
|
1291
1291
|
return urls.every((url) => textureCache.has(url));
|
|
1292
1292
|
}
|
|
@@ -1312,18 +1312,19 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1312
1312
|
const onLoadRef = useRef(onLoad);
|
|
1313
1313
|
onLoadRef.current = onLoad;
|
|
1314
1314
|
const onLoadCalledForRef = useRef(null);
|
|
1315
|
-
const
|
|
1315
|
+
const inputKey = useMemo(() => inputSignature(input), [input]);
|
|
1316
|
+
const stableInput = useMemo(() => input, [inputKey]);
|
|
1317
|
+
const urls = useMemo(() => getUrls(stableInput), [stableInput]);
|
|
1316
1318
|
const cachedResult = useMemo(() => {
|
|
1317
1319
|
if (!cache) return null;
|
|
1318
1320
|
const textures = store.getState().textures;
|
|
1319
1321
|
if (!allUrlsCached(urls, textures)) return null;
|
|
1320
|
-
return buildFromCache(
|
|
1321
|
-
}, [cache, urls,
|
|
1322
|
+
return buildFromCache(stableInput, textures);
|
|
1323
|
+
}, [cache, urls, stableInput, store]);
|
|
1322
1324
|
const loadedTextures = useLoader(
|
|
1323
1325
|
TextureLoader,
|
|
1324
|
-
IsObject(
|
|
1326
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
1325
1327
|
);
|
|
1326
|
-
const inputKey = urls.join("\0");
|
|
1327
1328
|
useLayoutEffect(() => {
|
|
1328
1329
|
if (cachedResult) return;
|
|
1329
1330
|
if (onLoadCalledForRef.current === inputKey) return;
|
|
@@ -1350,28 +1351,28 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1350
1351
|
}, [renderer, loadedTextures, cachedResult]);
|
|
1351
1352
|
const mappedTextures = useMemo(() => {
|
|
1352
1353
|
if (cachedResult) return cachedResult;
|
|
1353
|
-
if (IsObject(
|
|
1354
|
+
if (IsObject(stableInput)) {
|
|
1354
1355
|
const keyed = {};
|
|
1355
1356
|
const textureArray = loadedTextures;
|
|
1356
1357
|
let i = 0;
|
|
1357
|
-
for (const key in
|
|
1358
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
1358
1359
|
return keyed;
|
|
1359
1360
|
} else {
|
|
1360
1361
|
return loadedTextures;
|
|
1361
1362
|
}
|
|
1362
|
-
}, [
|
|
1363
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
1363
1364
|
useEffect(() => {
|
|
1364
1365
|
if (!cache) return;
|
|
1365
1366
|
const urlTextureMap = [];
|
|
1366
|
-
if (typeof
|
|
1367
|
-
urlTextureMap.push([
|
|
1368
|
-
} else if (Array.isArray(
|
|
1367
|
+
if (typeof stableInput === "string") {
|
|
1368
|
+
urlTextureMap.push([stableInput, mappedTextures]);
|
|
1369
|
+
} else if (Array.isArray(stableInput)) {
|
|
1369
1370
|
const textureArray = mappedTextures;
|
|
1370
|
-
|
|
1371
|
-
} else if (IsObject(
|
|
1371
|
+
stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1372
|
+
} else if (IsObject(stableInput)) {
|
|
1372
1373
|
const textureRecord = mappedTextures;
|
|
1373
|
-
for (const key in
|
|
1374
|
-
const url =
|
|
1374
|
+
for (const key in stableInput) {
|
|
1375
|
+
const url = stableInput[key];
|
|
1375
1376
|
urlTextureMap.push([url, textureRecord[key]]);
|
|
1376
1377
|
}
|
|
1377
1378
|
}
|
|
@@ -1400,7 +1401,7 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1400
1401
|
}
|
|
1401
1402
|
return { _textureRefs: refs };
|
|
1402
1403
|
});
|
|
1403
|
-
}, [cache,
|
|
1404
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
1404
1405
|
return mappedTextures;
|
|
1405
1406
|
}
|
|
1406
1407
|
useTexture.preload = (url) => useLoader.preload(TextureLoader, url);
|
|
@@ -14385,6 +14386,10 @@ function createRoot(canvas) {
|
|
|
14385
14386
|
if (state2.internal.isMultiCanvas && state2.internal.canvasTarget) {
|
|
14386
14387
|
const renderer2 = state2.internal.actualRenderer;
|
|
14387
14388
|
renderer2.setCanvasTarget(state2.internal.canvasTarget);
|
|
14389
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
14390
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
14391
|
+
renderer2.backend?.updateSize?.();
|
|
14392
|
+
}
|
|
14388
14393
|
}
|
|
14389
14394
|
},
|
|
14390
14395
|
{
|
package/dist/webgpu/index.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const webgpu = require('three/webgpu');
|
|
4
|
-
const Inspector_js = require('three/addons/inspector/Inspector.js');
|
|
5
4
|
const jsxRuntime = require('react/jsx-runtime');
|
|
6
5
|
const React = require('react');
|
|
7
6
|
const useMeasure = require('react-use-measure');
|
|
@@ -54,6 +53,10 @@ const Tb__default = /*#__PURE__*/_interopDefaultCompat(Tb);
|
|
|
54
53
|
|
|
55
54
|
const R3F_BUILD_LEGACY = false;
|
|
56
55
|
const R3F_BUILD_WEBGPU = true;
|
|
56
|
+
async function loadInspector() {
|
|
57
|
+
const { Inspector } = await import('three/addons/inspector/Inspector.js');
|
|
58
|
+
return Inspector;
|
|
59
|
+
}
|
|
57
60
|
const WebGLRenderer = class WebGLRenderer2 {
|
|
58
61
|
constructor() {
|
|
59
62
|
throw new Error(
|
|
@@ -67,13 +70,13 @@ const WebGLCubeRenderTarget = null;
|
|
|
67
70
|
const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
68
71
|
__proto__: null,
|
|
69
72
|
CubeRenderTargetCompat: webgpu.CubeRenderTarget,
|
|
70
|
-
Inspector: Inspector_js.Inspector,
|
|
71
73
|
R3F_BUILD_LEGACY: R3F_BUILD_LEGACY,
|
|
72
74
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
73
75
|
RenderTargetCompat: webgpu.RenderTarget,
|
|
74
76
|
WebGLCubeRenderTarget: WebGLCubeRenderTarget,
|
|
75
77
|
WebGLRenderTarget: WebGLRenderTarget,
|
|
76
|
-
WebGLRenderer: WebGLRenderer
|
|
78
|
+
WebGLRenderer: WebGLRenderer,
|
|
79
|
+
loadInspector: loadInspector
|
|
77
80
|
}, [webgpu__namespace]);
|
|
78
81
|
|
|
79
82
|
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
@@ -1071,17 +1074,10 @@ const createStore = (invalidate, advance) => {
|
|
|
1071
1074
|
oldSize = size;
|
|
1072
1075
|
oldDpr = viewport.dpr;
|
|
1073
1076
|
updateCamera(camera, size);
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
1079
|
-
actualRenderer.setSize(size.width, size.height, false);
|
|
1080
|
-
if (canvasTarget) {
|
|
1081
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1082
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1077
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
1078
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
1079
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
1080
|
+
internal.canvasTargetSizeDirty = true;
|
|
1085
1081
|
}
|
|
1086
1082
|
if (camera !== oldCamera) {
|
|
1087
1083
|
oldCamera = camera;
|
|
@@ -1143,7 +1139,11 @@ function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
|
1143
1139
|
const results = cacheKeys.map(
|
|
1144
1140
|
(key, index) => suspendReact.suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
1145
1141
|
);
|
|
1146
|
-
|
|
1142
|
+
const stableRef = React.useRef(null);
|
|
1143
|
+
const previous = stableRef.current;
|
|
1144
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
1145
|
+
stableRef.current = stable;
|
|
1146
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
1147
1147
|
}
|
|
1148
1148
|
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
1149
1149
|
const inputs = Array.isArray(input) ? input : [input];
|
|
@@ -1158,7 +1158,7 @@ useLoader.clear = function(loader, input, cacheKey) {
|
|
|
1158
1158
|
};
|
|
1159
1159
|
useLoader.loader = getLoader$1;
|
|
1160
1160
|
|
|
1161
|
-
function useFrame(callback, priorityOrOptions) {
|
|
1161
|
+
function useFrame$1(callback, priorityOrOptions) {
|
|
1162
1162
|
const store = React__namespace.useContext(context);
|
|
1163
1163
|
const isInsideCanvas = store !== null;
|
|
1164
1164
|
const scheduler$1 = scheduler.getScheduler();
|
|
@@ -1308,6 +1308,11 @@ function getUrls(input) {
|
|
|
1308
1308
|
if (Array.isArray(input)) return input;
|
|
1309
1309
|
return Object.values(input);
|
|
1310
1310
|
}
|
|
1311
|
+
function inputSignature(input) {
|
|
1312
|
+
if (typeof input === "string") return input;
|
|
1313
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
1314
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
1315
|
+
}
|
|
1311
1316
|
function allUrlsCached(urls, textureCache) {
|
|
1312
1317
|
return urls.every((url) => textureCache.has(url));
|
|
1313
1318
|
}
|
|
@@ -1326,25 +1331,26 @@ function buildFromCache(input, textureCache) {
|
|
|
1326
1331
|
}
|
|
1327
1332
|
}
|
|
1328
1333
|
function useTexture(input, optionsOrOnLoad) {
|
|
1329
|
-
const renderer = useThree((state) => state.internal.actualRenderer);
|
|
1334
|
+
const renderer = useThree$1((state) => state.internal.actualRenderer);
|
|
1330
1335
|
const store = useStore();
|
|
1331
1336
|
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
1332
1337
|
const { onLoad, cache = true } = options;
|
|
1333
1338
|
const onLoadRef = React.useRef(onLoad);
|
|
1334
1339
|
onLoadRef.current = onLoad;
|
|
1335
1340
|
const onLoadCalledForRef = React.useRef(null);
|
|
1336
|
-
const
|
|
1341
|
+
const inputKey = React.useMemo(() => inputSignature(input), [input]);
|
|
1342
|
+
const stableInput = React.useMemo(() => input, [inputKey]);
|
|
1343
|
+
const urls = React.useMemo(() => getUrls(stableInput), [stableInput]);
|
|
1337
1344
|
const cachedResult = React.useMemo(() => {
|
|
1338
1345
|
if (!cache) return null;
|
|
1339
1346
|
const textures = store.getState().textures;
|
|
1340
1347
|
if (!allUrlsCached(urls, textures)) return null;
|
|
1341
|
-
return buildFromCache(
|
|
1342
|
-
}, [cache, urls,
|
|
1348
|
+
return buildFromCache(stableInput, textures);
|
|
1349
|
+
}, [cache, urls, stableInput, store]);
|
|
1343
1350
|
const loadedTextures = useLoader(
|
|
1344
1351
|
webgpu.TextureLoader,
|
|
1345
|
-
IsObject(
|
|
1352
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
1346
1353
|
);
|
|
1347
|
-
const inputKey = urls.join("\0");
|
|
1348
1354
|
React.useLayoutEffect(() => {
|
|
1349
1355
|
if (cachedResult) return;
|
|
1350
1356
|
if (onLoadCalledForRef.current === inputKey) return;
|
|
@@ -1371,28 +1377,28 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1371
1377
|
}, [renderer, loadedTextures, cachedResult]);
|
|
1372
1378
|
const mappedTextures = React.useMemo(() => {
|
|
1373
1379
|
if (cachedResult) return cachedResult;
|
|
1374
|
-
if (IsObject(
|
|
1380
|
+
if (IsObject(stableInput)) {
|
|
1375
1381
|
const keyed = {};
|
|
1376
1382
|
const textureArray = loadedTextures;
|
|
1377
1383
|
let i = 0;
|
|
1378
|
-
for (const key in
|
|
1384
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
1379
1385
|
return keyed;
|
|
1380
1386
|
} else {
|
|
1381
1387
|
return loadedTextures;
|
|
1382
1388
|
}
|
|
1383
|
-
}, [
|
|
1389
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
1384
1390
|
React.useEffect(() => {
|
|
1385
1391
|
if (!cache) return;
|
|
1386
1392
|
const urlTextureMap = [];
|
|
1387
|
-
if (typeof
|
|
1388
|
-
urlTextureMap.push([
|
|
1389
|
-
} else if (Array.isArray(
|
|
1393
|
+
if (typeof stableInput === "string") {
|
|
1394
|
+
urlTextureMap.push([stableInput, mappedTextures]);
|
|
1395
|
+
} else if (Array.isArray(stableInput)) {
|
|
1390
1396
|
const textureArray = mappedTextures;
|
|
1391
|
-
|
|
1392
|
-
} else if (IsObject(
|
|
1397
|
+
stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1398
|
+
} else if (IsObject(stableInput)) {
|
|
1393
1399
|
const textureRecord = mappedTextures;
|
|
1394
|
-
for (const key in
|
|
1395
|
-
const url =
|
|
1400
|
+
for (const key in stableInput) {
|
|
1401
|
+
const url = stableInput[key];
|
|
1396
1402
|
urlTextureMap.push([url, textureRecord[key]]);
|
|
1397
1403
|
}
|
|
1398
1404
|
}
|
|
@@ -1421,7 +1427,7 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1421
1427
|
}
|
|
1422
1428
|
return { _textureRefs: refs };
|
|
1423
1429
|
});
|
|
1424
|
-
}, [cache,
|
|
1430
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
1425
1431
|
return mappedTextures;
|
|
1426
1432
|
}
|
|
1427
1433
|
useTexture.preload = (url) => useLoader.preload(webgpu.TextureLoader, url);
|
|
@@ -1492,13 +1498,13 @@ function useTextures(selector) {
|
|
|
1492
1498
|
};
|
|
1493
1499
|
}, [store]);
|
|
1494
1500
|
const subscribe = selector ? () => selector(registry) : (state) => state.textures;
|
|
1495
|
-
const selected = useThree(subscribe);
|
|
1501
|
+
const selected = useThree$1(subscribe);
|
|
1496
1502
|
return selector ? selected : registry;
|
|
1497
1503
|
}
|
|
1498
1504
|
|
|
1499
1505
|
function useRenderTarget(widthOrOptions, heightOrOptions, options) {
|
|
1500
|
-
const isLegacy = useThree((s) => s.isLegacy);
|
|
1501
|
-
const size = useThree((s) => s.size);
|
|
1506
|
+
const isLegacy = useThree$1((s) => s.isLegacy);
|
|
1507
|
+
const size = useThree$1((s) => s.size);
|
|
1502
1508
|
let width;
|
|
1503
1509
|
let height;
|
|
1504
1510
|
let opts;
|
|
@@ -1555,7 +1561,7 @@ function useEnvironment({
|
|
|
1555
1561
|
const { extension, isCubemap } = getExtension(files);
|
|
1556
1562
|
const loader = getLoader(extension);
|
|
1557
1563
|
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
1558
|
-
const renderer = useThree((state) => state.renderer);
|
|
1564
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
1559
1565
|
React.useLayoutEffect(() => {
|
|
1560
1566
|
if (extension !== "webp" && extension !== "jpg" && extension !== "jpeg") return;
|
|
1561
1567
|
function clearGainmapTexture() {
|
|
@@ -1648,7 +1654,7 @@ function useStore() {
|
|
|
1648
1654
|
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
1649
1655
|
return store;
|
|
1650
1656
|
}
|
|
1651
|
-
function useThree(selector = (state) => state, equalityFn) {
|
|
1657
|
+
function useThree$1(selector = (state) => state, equalityFn) {
|
|
1652
1658
|
return useStore()(selector, equalityFn);
|
|
1653
1659
|
}
|
|
1654
1660
|
function useInstanceHandle(ref) {
|
|
@@ -14435,6 +14441,10 @@ function createRoot(canvas) {
|
|
|
14435
14441
|
if (state2.internal.isMultiCanvas && state2.internal.canvasTarget) {
|
|
14436
14442
|
const renderer2 = state2.internal.actualRenderer;
|
|
14437
14443
|
renderer2.setCanvasTarget(state2.internal.canvasTarget);
|
|
14444
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
14445
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
14446
|
+
renderer2.backend?.updateSize?.();
|
|
14447
|
+
}
|
|
14438
14448
|
}
|
|
14439
14449
|
},
|
|
14440
14450
|
{
|
|
@@ -14739,7 +14749,7 @@ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {})
|
|
|
14739
14749
|
};
|
|
14740
14750
|
}
|
|
14741
14751
|
function EnvironmentMap({ scene, background = false, map, ...config }) {
|
|
14742
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14752
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14743
14753
|
React__namespace.useLayoutEffect(() => {
|
|
14744
14754
|
if (map) return setEnvProps(background, scene, defaultScene, map, config);
|
|
14745
14755
|
});
|
|
@@ -14757,7 +14767,7 @@ function EnvironmentCube({
|
|
|
14757
14767
|
...rest
|
|
14758
14768
|
}) {
|
|
14759
14769
|
const texture = useEnvironment(rest);
|
|
14760
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14770
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14761
14771
|
React__namespace.useLayoutEffect(() => {
|
|
14762
14772
|
return setEnvProps(background, scene, defaultScene, texture, {
|
|
14763
14773
|
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
@@ -14794,9 +14804,9 @@ function EnvironmentPortal({
|
|
|
14794
14804
|
preset = void 0,
|
|
14795
14805
|
extensions
|
|
14796
14806
|
}) {
|
|
14797
|
-
const renderer = useThree((state) => state.renderer);
|
|
14798
|
-
const isLegacy = useThree((state) => state.isLegacy);
|
|
14799
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14807
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
14808
|
+
const isLegacy = useThree$1((state) => state.isLegacy);
|
|
14809
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14800
14810
|
const camera = React__namespace.useRef(null);
|
|
14801
14811
|
const [virtualScene] = React__namespace.useState(() => new webgpu.Scene());
|
|
14802
14812
|
const fbo = React__namespace.useMemo(() => {
|
|
@@ -14840,7 +14850,7 @@ function EnvironmentPortal({
|
|
|
14840
14850
|
environmentRotation
|
|
14841
14851
|
]);
|
|
14842
14852
|
let count = 1;
|
|
14843
|
-
useFrame(() => {
|
|
14853
|
+
useFrame$1(() => {
|
|
14844
14854
|
if (frames === Infinity || count < frames) {
|
|
14845
14855
|
const autoClear = renderer.autoClear;
|
|
14846
14856
|
renderer.autoClear = true;
|
|
@@ -14880,7 +14890,7 @@ function EnvironmentGround(props) {
|
|
|
14880
14890
|
] });
|
|
14881
14891
|
}
|
|
14882
14892
|
function EnvironmentColor({ color, scene }) {
|
|
14883
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14893
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14884
14894
|
React__namespace.useLayoutEffect(() => {
|
|
14885
14895
|
if (color === void 0) return;
|
|
14886
14896
|
const target = resolveScene(scene || defaultScene);
|
|
@@ -15474,6 +15484,11 @@ function createTextureOperations(set) {
|
|
|
15474
15484
|
removeMultiple: (keys) => removeTextures(set, keys)
|
|
15475
15485
|
};
|
|
15476
15486
|
}
|
|
15487
|
+
function scopedNodeName(scope, name) {
|
|
15488
|
+
const raw = scope ? `${scope}_${name}` : name;
|
|
15489
|
+
const safe = raw.replace(/[^A-Za-z0-9_]/g, "_");
|
|
15490
|
+
return /^[A-Za-z_]/.test(safe) ? safe : `_${safe}`;
|
|
15491
|
+
}
|
|
15477
15492
|
function extractTSLValue(value) {
|
|
15478
15493
|
if (value === null || value === void 0) return value;
|
|
15479
15494
|
if (typeof value !== "object") return value;
|
|
@@ -15672,8 +15687,7 @@ function createUniform(inName, node, scope) {
|
|
|
15672
15687
|
const inValue = vectorize(node);
|
|
15673
15688
|
const newUniform = tsl.uniform(inValue);
|
|
15674
15689
|
if (typeof newUniform.setName === "function") {
|
|
15675
|
-
|
|
15676
|
-
newUniform.setName(name);
|
|
15690
|
+
newUniform.setName(scopedNodeName(scope, inName));
|
|
15677
15691
|
}
|
|
15678
15692
|
return newUniform;
|
|
15679
15693
|
}
|
|
@@ -15772,7 +15786,7 @@ function useNodes(creatorOrScope, scope) {
|
|
|
15772
15786
|
return creatorOrScope(createLazyCreatorState(store.getState(), store));
|
|
15773
15787
|
},
|
|
15774
15788
|
prepare: (name, node) => {
|
|
15775
|
-
node.setName?.(scope
|
|
15789
|
+
node.setName?.(scopedNodeName(scope, name));
|
|
15776
15790
|
return node;
|
|
15777
15791
|
}
|
|
15778
15792
|
});
|
|
@@ -15881,7 +15895,7 @@ function useBuffers(creatorOrScope, scope) {
|
|
|
15881
15895
|
},
|
|
15882
15896
|
prepare: (name, buffer) => {
|
|
15883
15897
|
if ("setName" in buffer && typeof buffer.setName === "function") {
|
|
15884
|
-
buffer.setName(scope
|
|
15898
|
+
buffer.setName(scopedNodeName(scope, name));
|
|
15885
15899
|
}
|
|
15886
15900
|
return buffer;
|
|
15887
15901
|
}
|
|
@@ -15952,7 +15966,7 @@ function useGPUStorage(creatorOrScope, scope) {
|
|
|
15952
15966
|
return creatorOrScope(createLazyCreatorState(store.getState(), store));
|
|
15953
15967
|
},
|
|
15954
15968
|
prepare: (name, storage) => {
|
|
15955
|
-
const label = scope
|
|
15969
|
+
const label = scopedNodeName(scope, name);
|
|
15956
15970
|
if ("setName" in storage && typeof storage.setName === "function") {
|
|
15957
15971
|
storage.setName(label);
|
|
15958
15972
|
}
|
|
@@ -15983,9 +15997,10 @@ function rebuildAllStorage(store, scope) {
|
|
|
15983
15997
|
|
|
15984
15998
|
function useRenderPipeline(mainCB, setupCB) {
|
|
15985
15999
|
const store = useStore();
|
|
15986
|
-
const { scene, camera, renderer, isLegacy } = useThree();
|
|
16000
|
+
const { scene, camera, renderer, isLegacy } = useThree$1();
|
|
15987
16001
|
const callbacksRanRef = React.useRef(false);
|
|
15988
16002
|
const scenePassCacheRef = React.useRef(null);
|
|
16003
|
+
const forceScenePassRebuildRef = React.useRef(false);
|
|
15989
16004
|
const mainCBRef = React.useRef(mainCB);
|
|
15990
16005
|
const setupCBRef = React.useRef(setupCB);
|
|
15991
16006
|
mainCBRef.current = mainCB;
|
|
@@ -15993,7 +16008,7 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
15993
16008
|
const [rebuildVersion, setRebuildVersion] = React.useState(0);
|
|
15994
16009
|
React.useEffect(() => {
|
|
15995
16010
|
callbacksRanRef.current = false;
|
|
15996
|
-
|
|
16011
|
+
forceScenePassRebuildRef.current = true;
|
|
15997
16012
|
}, []);
|
|
15998
16013
|
const clearPasses = React.useCallback(() => {
|
|
15999
16014
|
store.setState({ passes: {} });
|
|
@@ -16003,12 +16018,14 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16003
16018
|
renderPipeline: null,
|
|
16004
16019
|
passes: {}
|
|
16005
16020
|
});
|
|
16021
|
+
scenePassCacheRef.current?.scenePass?.dispose?.();
|
|
16006
16022
|
callbacksRanRef.current = false;
|
|
16007
16023
|
scenePassCacheRef.current = null;
|
|
16024
|
+
forceScenePassRebuildRef.current = false;
|
|
16008
16025
|
}, [store]);
|
|
16009
16026
|
const rebuild = React.useCallback(() => {
|
|
16010
16027
|
callbacksRanRef.current = false;
|
|
16011
|
-
|
|
16028
|
+
forceScenePassRebuildRef.current = true;
|
|
16012
16029
|
setRebuildVersion((v) => v + 1);
|
|
16013
16030
|
}, []);
|
|
16014
16031
|
React.useLayoutEffect(() => {
|
|
@@ -16026,16 +16043,23 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16026
16043
|
pipeline = new webgpu.RenderPipeline(renderer);
|
|
16027
16044
|
justCreatedPipeline = true;
|
|
16028
16045
|
}
|
|
16029
|
-
const cacheValid = scenePassCacheRef.current && scenePassCacheRef.current.sceneUuid === scene.uuid && scenePassCacheRef.current.cameraUuid === camera.uuid;
|
|
16046
|
+
const cacheValid = !forceScenePassRebuildRef.current && scenePassCacheRef.current && scenePassCacheRef.current.sceneUuid === scene.uuid && scenePassCacheRef.current.cameraUuid === camera.uuid;
|
|
16047
|
+
let outgoingScenePass = null;
|
|
16030
16048
|
let scenePass;
|
|
16031
16049
|
if (cacheValid) {
|
|
16032
16050
|
scenePass = scenePassCacheRef.current.scenePass;
|
|
16033
16051
|
} else {
|
|
16052
|
+
outgoingScenePass = scenePassCacheRef.current?.scenePass ?? null;
|
|
16034
16053
|
scenePass = tsl.pass(scene, camera);
|
|
16035
16054
|
scenePassCacheRef.current = { sceneUuid: scene.uuid, cameraUuid: camera.uuid, scenePass };
|
|
16055
|
+
forceScenePassRebuildRef.current = false;
|
|
16036
16056
|
}
|
|
16037
16057
|
currentPasses.scenePass = scenePass;
|
|
16038
|
-
|
|
16058
|
+
let outputNodeChanged = false;
|
|
16059
|
+
if (!pipeline.outputNode || justCreatedPipeline || pipeline.outputNode === outgoingScenePass) {
|
|
16060
|
+
pipeline.outputNode = scenePass;
|
|
16061
|
+
outputNodeChanged = true;
|
|
16062
|
+
}
|
|
16039
16063
|
set({ renderPipeline: pipeline, passes: currentPasses });
|
|
16040
16064
|
const shouldRunCallbacks = justCreatedPipeline || !callbacksRanRef.current || !cacheValid;
|
|
16041
16065
|
if (shouldRunCallbacks) {
|
|
@@ -16055,14 +16079,17 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16055
16079
|
set({ passes: currentPasses });
|
|
16056
16080
|
}
|
|
16057
16081
|
}
|
|
16082
|
+
outputNodeChanged = true;
|
|
16058
16083
|
callbacksRanRef.current = true;
|
|
16059
16084
|
}
|
|
16085
|
+
if (outputNodeChanged) pipeline.needsUpdate = true;
|
|
16086
|
+
if (outgoingScenePass && outgoingScenePass !== scenePass) outgoingScenePass.dispose?.();
|
|
16060
16087
|
} catch (error) {
|
|
16061
16088
|
console.warn("[useRenderPipeline] Setup failed; the render pipeline was not configured:", error);
|
|
16062
16089
|
}
|
|
16063
16090
|
}, [store, renderer, scene, camera, isLegacy, rebuildVersion]);
|
|
16064
|
-
const passes = useThree((s) => s.passes);
|
|
16065
|
-
const renderPipeline = useThree((s) => s.renderPipeline);
|
|
16091
|
+
const passes = useThree$1((s) => s.passes);
|
|
16092
|
+
const renderPipeline = useThree$1((s) => s.renderPipeline);
|
|
16066
16093
|
return {
|
|
16067
16094
|
passes,
|
|
16068
16095
|
renderPipeline,
|
|
@@ -16075,6 +16102,8 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16075
16102
|
}
|
|
16076
16103
|
|
|
16077
16104
|
extend(THREE);
|
|
16105
|
+
const useThree = useThree$1;
|
|
16106
|
+
const useFrame = useFrame$1;
|
|
16078
16107
|
|
|
16079
16108
|
exports.Scheduler = scheduler.Scheduler;
|
|
16080
16109
|
exports.getScheduler = scheduler.getScheduler;
|