@react-three/fiber 10.0.0-canary.2c50459 → 10.0.0-canary.4a21acb
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 +214 -107
- package/dist/index.d.cts +49 -25
- package/dist/index.d.mts +49 -25
- package/dist/index.d.ts +49 -25
- package/dist/index.mjs +216 -109
- package/dist/legacy.cjs +169 -62
- package/dist/legacy.d.cts +49 -24
- package/dist/legacy.d.mts +49 -24
- package/dist/legacy.d.ts +49 -24
- package/dist/legacy.mjs +170 -63
- package/dist/webgpu/index.cjs +501 -635
- package/dist/webgpu/index.d.cts +83 -29
- package/dist/webgpu/index.d.mts +83 -29
- package/dist/webgpu/index.d.ts +83 -29
- package/dist/webgpu/index.mjs +503 -637
- package/package.json +3 -3
- package/readme.md +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as webgpu from 'three/webgpu';
|
|
2
|
-
import { RenderTarget, CubeReflectionMapping, EquirectangularReflectionMapping, CubeTextureLoader, Scene,
|
|
3
|
-
import { WebGLRenderTarget, WebGLRenderer } from 'three';
|
|
2
|
+
import { CubeRenderTarget, RenderTarget, CubeReflectionMapping, EquirectangularReflectionMapping, CubeTextureLoader, Scene, HalfFloatType, Color, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, ShaderMaterial, Uniform, SRGBColorSpace, RGBAFormat, UnsignedByteType, Vector3, Vector2, TextureLoader, Texture as Texture$1, CanvasTarget, Raycaster, OrthographicCamera, PerspectiveCamera, PCFShadowMap, VSMShadowMap, BasicShadowMap, ACESFilmicToneMapping, WebGPURenderer } from 'three/webgpu';
|
|
3
|
+
import { WebGLCubeRenderTarget, WebGLRenderTarget, WebGLRenderer } from 'three';
|
|
4
4
|
import { Inspector } from 'three/addons/inspector/Inspector.js';
|
|
5
5
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
6
6
|
import * as React from 'react';
|
|
@@ -36,10 +36,13 @@ const R3F_BUILD_WEBGPU = true;
|
|
|
36
36
|
|
|
37
37
|
const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
38
38
|
__proto__: null,
|
|
39
|
+
CubeRenderTarget: CubeRenderTarget,
|
|
40
|
+
CubeRenderTargetCompat: CubeRenderTarget,
|
|
39
41
|
Inspector: Inspector,
|
|
40
42
|
R3F_BUILD_LEGACY: R3F_BUILD_LEGACY,
|
|
41
43
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
42
44
|
RenderTargetCompat: RenderTarget,
|
|
45
|
+
WebGLCubeRenderTarget: WebGLCubeRenderTarget,
|
|
43
46
|
WebGLRenderTarget: WebGLRenderTarget,
|
|
44
47
|
WebGLRenderer: WebGLRenderer
|
|
45
48
|
}, [webgpu]);
|
|
@@ -313,15 +316,16 @@ function EnvironmentPortal({
|
|
|
313
316
|
preset = void 0,
|
|
314
317
|
extensions
|
|
315
318
|
}) {
|
|
316
|
-
const
|
|
319
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
320
|
+
const isLegacy = useThree$1((state) => state.isLegacy);
|
|
317
321
|
const defaultScene = useThree$1((state) => state.scene);
|
|
318
322
|
const camera = React.useRef(null);
|
|
319
323
|
const [virtualScene] = React.useState(() => new Scene());
|
|
320
324
|
const fbo = React.useMemo(() => {
|
|
321
|
-
const fbo2 = new WebGLCubeRenderTarget(resolution);
|
|
325
|
+
const fbo2 = isLegacy ? new WebGLCubeRenderTarget(resolution) : new CubeRenderTarget(resolution);
|
|
322
326
|
fbo2.texture.type = HalfFloatType;
|
|
323
327
|
return fbo2;
|
|
324
|
-
}, [resolution]);
|
|
328
|
+
}, [resolution, isLegacy]);
|
|
325
329
|
React.useEffect(() => {
|
|
326
330
|
return () => {
|
|
327
331
|
fbo.dispose();
|
|
@@ -329,10 +333,10 @@ function EnvironmentPortal({
|
|
|
329
333
|
}, [fbo]);
|
|
330
334
|
React.useLayoutEffect(() => {
|
|
331
335
|
if (frames === 1) {
|
|
332
|
-
const autoClear =
|
|
333
|
-
|
|
334
|
-
camera.current.update(
|
|
335
|
-
|
|
336
|
+
const autoClear = renderer.autoClear;
|
|
337
|
+
renderer.autoClear = true;
|
|
338
|
+
camera.current.update(renderer, virtualScene);
|
|
339
|
+
renderer.autoClear = autoClear;
|
|
336
340
|
}
|
|
337
341
|
return setEnvProps(background, scene, defaultScene, fbo.texture, {
|
|
338
342
|
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
@@ -349,7 +353,7 @@ function EnvironmentPortal({
|
|
|
349
353
|
defaultScene,
|
|
350
354
|
background,
|
|
351
355
|
frames,
|
|
352
|
-
|
|
356
|
+
renderer,
|
|
353
357
|
blur,
|
|
354
358
|
backgroundBlurriness,
|
|
355
359
|
backgroundIntensity,
|
|
@@ -360,10 +364,10 @@ function EnvironmentPortal({
|
|
|
360
364
|
let count = 1;
|
|
361
365
|
useFrame$1(() => {
|
|
362
366
|
if (frames === Infinity || count < frames) {
|
|
363
|
-
const autoClear =
|
|
364
|
-
|
|
365
|
-
camera.current.update(
|
|
366
|
-
|
|
367
|
+
const autoClear = renderer.autoClear;
|
|
368
|
+
renderer.autoClear = true;
|
|
369
|
+
camera.current.update(renderer, virtualScene);
|
|
370
|
+
renderer.autoClear = autoClear;
|
|
367
371
|
count++;
|
|
368
372
|
}
|
|
369
373
|
});
|
|
@@ -606,8 +610,7 @@ function prepare(target, root, type, props) {
|
|
|
606
610
|
object,
|
|
607
611
|
eventCount: 0,
|
|
608
612
|
handlers: {},
|
|
609
|
-
isHidden: false
|
|
610
|
-
deferredRefs: []
|
|
613
|
+
isHidden: false
|
|
611
614
|
};
|
|
612
615
|
if (object) object.__r3f = instance;
|
|
613
616
|
}
|
|
@@ -764,6 +767,17 @@ function unregisterVisibility(store, object) {
|
|
|
764
767
|
internal.visibilityRegistry.delete(object.uuid);
|
|
765
768
|
internal.occlusionCache.delete(object);
|
|
766
769
|
}
|
|
770
|
+
function updateVisibilityHandlers(store, object, handlers) {
|
|
771
|
+
const { internal } = store.getState();
|
|
772
|
+
const entry = internal.visibilityRegistry.get(object.uuid);
|
|
773
|
+
if (!entry) return false;
|
|
774
|
+
entry.handlers = handlers;
|
|
775
|
+
if ((handlers.onOccluded || handlers.onVisible) && !internal.occlusionEnabled) {
|
|
776
|
+
object.occlusionTest = true;
|
|
777
|
+
enableOcclusion(store);
|
|
778
|
+
}
|
|
779
|
+
return true;
|
|
780
|
+
}
|
|
767
781
|
function checkVisibility(state) {
|
|
768
782
|
const { internal, camera } = state;
|
|
769
783
|
const registry = internal.visibilityRegistry;
|
|
@@ -951,10 +965,7 @@ function applyProps(object, props) {
|
|
|
951
965
|
continue;
|
|
952
966
|
}
|
|
953
967
|
if (value === void 0) continue;
|
|
954
|
-
if (isFromRef(value))
|
|
955
|
-
instance?.deferredRefs?.push({ prop, ref: value[FROM_REF] });
|
|
956
|
-
continue;
|
|
957
|
-
}
|
|
968
|
+
if (isFromRef(value)) continue;
|
|
958
969
|
if (isOnce(value)) {
|
|
959
970
|
if (instance?.appliedOnce?.has(prop)) continue;
|
|
960
971
|
if (instance) {
|
|
@@ -990,6 +1001,19 @@ function applyProps(object, props) {
|
|
|
990
1001
|
} else if (isVectorLike(target) && is.num(value)) {
|
|
991
1002
|
if ("setScalar" in target && typeof target.setScalar === "function") target.setScalar(value);
|
|
992
1003
|
else target.set(value);
|
|
1004
|
+
} else if (root instanceof ShaderMaterial && key === "uniforms" && is.obj(value)) {
|
|
1005
|
+
if (!is.obj(root.uniforms)) root.uniforms = {};
|
|
1006
|
+
const uniforms = root.uniforms;
|
|
1007
|
+
const nextUniforms = value;
|
|
1008
|
+
for (const name in nextUniforms) {
|
|
1009
|
+
const uniform = nextUniforms[name];
|
|
1010
|
+
const targetUniform = uniforms[name];
|
|
1011
|
+
if (targetUniform) Object.assign(targetUniform, uniform);
|
|
1012
|
+
else {
|
|
1013
|
+
const nextUniform = uniform instanceof Uniform ? uniform.clone() : new Uniform(uniform.value);
|
|
1014
|
+
uniforms[name] = nextUniform;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
993
1017
|
} else {
|
|
994
1018
|
root[key] = value;
|
|
995
1019
|
if (key.endsWith("Node") && root.isMaterial) {
|
|
@@ -1008,6 +1032,9 @@ function applyProps(object, props) {
|
|
|
1008
1032
|
if (instance.eventCount && object2.raycast !== null) {
|
|
1009
1033
|
rootState.internal.interaction.push(object2);
|
|
1010
1034
|
}
|
|
1035
|
+
}
|
|
1036
|
+
if (instance?.parent && rootState?.internal && instance.object?.isObject3D) {
|
|
1037
|
+
const object2 = instance.object;
|
|
1011
1038
|
const root = findInitialRoot(instance);
|
|
1012
1039
|
const visibilityHandlers = {
|
|
1013
1040
|
onFramed: instance.handlers.onFramed,
|
|
@@ -1015,7 +1042,9 @@ function applyProps(object, props) {
|
|
|
1015
1042
|
onVisible: instance.handlers.onVisible
|
|
1016
1043
|
};
|
|
1017
1044
|
if (hasVisibilityHandlers(visibilityHandlers)) {
|
|
1018
|
-
|
|
1045
|
+
if (!updateVisibilityHandlers(root, object2, visibilityHandlers)) {
|
|
1046
|
+
registerVisibility(root, object2, visibilityHandlers);
|
|
1047
|
+
}
|
|
1019
1048
|
} else {
|
|
1020
1049
|
unregisterVisibility(root, object2);
|
|
1021
1050
|
}
|
|
@@ -1543,6 +1572,7 @@ function createPointerEvents(store) {
|
|
|
1543
1572
|
set((state) => ({ events: { ...state.events, connected: void 0 } }));
|
|
1544
1573
|
}
|
|
1545
1574
|
},
|
|
1575
|
+
// PREVIEW (A8): the XR pointer registration API may change before stable.
|
|
1546
1576
|
registerPointer: (config) => {
|
|
1547
1577
|
const pointerId = nextXRPointerId++;
|
|
1548
1578
|
xrPointers.set(pointerId, config);
|
|
@@ -1629,6 +1659,13 @@ function notifyAlpha({ message, link }) {
|
|
|
1629
1659
|
}
|
|
1630
1660
|
}
|
|
1631
1661
|
|
|
1662
|
+
const INTERNAL_LIB_MARKERS = ["zustand", "setState", "Object.assign"];
|
|
1663
|
+
function isInternalRendererAccess(stack, callerDepth = 2) {
|
|
1664
|
+
if (!stack) return false;
|
|
1665
|
+
const caller = stack.split("\n")[callerDepth] ?? "";
|
|
1666
|
+
return INTERNAL_LIB_MARKERS.some((m) => caller.includes(m));
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1632
1669
|
const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
|
|
1633
1670
|
const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React.createContext(null));
|
|
1634
1671
|
const createStore = (invalidate, advance) => {
|
|
@@ -1761,6 +1798,7 @@ const createStore = (invalidate, advance) => {
|
|
|
1761
1798
|
}),
|
|
1762
1799
|
setFrameloop: (frameloop = "always") => {
|
|
1763
1800
|
set(() => ({ frameloop }));
|
|
1801
|
+
getScheduler().frameloop = frameloop;
|
|
1764
1802
|
},
|
|
1765
1803
|
setError: (error) => set(() => ({ error })),
|
|
1766
1804
|
error: null,
|
|
@@ -1828,8 +1866,7 @@ const createStore = (invalidate, advance) => {
|
|
|
1828
1866
|
const currentState = rootStore.getState();
|
|
1829
1867
|
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
1830
1868
|
const stack = new Error().stack || "";
|
|
1831
|
-
|
|
1832
|
-
if (!isInternalAccess) {
|
|
1869
|
+
if (!isInternalRendererAccess(stack)) {
|
|
1833
1870
|
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
1834
1871
|
notifyDepreciated({
|
|
1835
1872
|
heading: "Accessing state.gl in WebGPU mode",
|
|
@@ -1942,19 +1979,25 @@ function loadingFn(extensions, onProgress) {
|
|
|
1942
1979
|
);
|
|
1943
1980
|
};
|
|
1944
1981
|
}
|
|
1945
|
-
function useLoader(loader, input, extensions, onProgress) {
|
|
1946
|
-
const
|
|
1982
|
+
function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
1983
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
1984
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
1947
1985
|
const fn = loadingFn(extensions, onProgress);
|
|
1948
|
-
const results =
|
|
1986
|
+
const results = cacheKeys.map(
|
|
1987
|
+
(key, index) => suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
1988
|
+
);
|
|
1949
1989
|
return Array.isArray(input) ? results : results[0];
|
|
1950
1990
|
}
|
|
1951
|
-
useLoader.preload = function(loader, input, extensions, onProgress) {
|
|
1952
|
-
const
|
|
1953
|
-
|
|
1991
|
+
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
1992
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
1993
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
1994
|
+
cacheKeys.forEach(
|
|
1995
|
+
(key, index) => preload(() => loadingFn(extensions, onProgress)(loader, inputs[index]), [loader, key])
|
|
1996
|
+
);
|
|
1954
1997
|
};
|
|
1955
|
-
useLoader.clear = function(loader, input) {
|
|
1956
|
-
const
|
|
1957
|
-
|
|
1998
|
+
useLoader.clear = function(loader, input, cacheKey) {
|
|
1999
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
2000
|
+
cacheKeys.forEach((key) => clear([loader, key]));
|
|
1958
2001
|
};
|
|
1959
2002
|
useLoader.loader = getLoader;
|
|
1960
2003
|
|
|
@@ -2376,7 +2419,7 @@ function advance(timestamp) {
|
|
|
2376
2419
|
getScheduler().step(timestamp);
|
|
2377
2420
|
}
|
|
2378
2421
|
|
|
2379
|
-
const version = "10.0.0-alpha.
|
|
2422
|
+
const version = "10.0.0-alpha.3";
|
|
2380
2423
|
const packageData = {
|
|
2381
2424
|
version: version};
|
|
2382
2425
|
|
|
@@ -13815,6 +13858,7 @@ function swapInstances() {
|
|
|
13815
13858
|
}
|
|
13816
13859
|
}
|
|
13817
13860
|
if (instance.isHidden) unhideInstance(instance);
|
|
13861
|
+
if (isObject3D(instance.object)) removeInteractivity(findInitialRoot(instance), instance.object);
|
|
13818
13862
|
if (instance.object.__r3f) delete instance.object.__r3f;
|
|
13819
13863
|
if (instance.type !== "primitive") disposeOnIdle(instance.object);
|
|
13820
13864
|
}
|
|
@@ -13827,6 +13871,8 @@ function swapInstances() {
|
|
|
13827
13871
|
instance.object.__r3f = instance;
|
|
13828
13872
|
setFiberRef(fiber, instance.object);
|
|
13829
13873
|
delete instance.appliedOnce;
|
|
13874
|
+
instance.eventCount = 0;
|
|
13875
|
+
instance.handlers = {};
|
|
13830
13876
|
applyProps(instance.object, instance.props);
|
|
13831
13877
|
if (instance.props.attach) {
|
|
13832
13878
|
attach(parent, instance);
|
|
@@ -14042,11 +14088,15 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
14042
14088
|
cloneMutableTextInstance(textInstance) {
|
|
14043
14089
|
return textInstance;
|
|
14044
14090
|
},
|
|
14091
|
+
// React 19.2 added these for root-level view transitions. They only run for hosts that opt into
|
|
14092
|
+
// view transitions by returning a container from cloneRootViewTransitionContainer; R3F renders
|
|
14093
|
+
// into a WebGL/WebGPU canvas, where cloning the root has no meaning, so we never opt in and
|
|
14094
|
+
// React never calls them. They stay as no-ops rather than throws: the host config is shared by
|
|
14095
|
+
// every root, and a throw here would turn a React-internal probe into a hard crash for users.
|
|
14096
|
+
// Guarded by a test asserting a full render + unmount never reaches them.
|
|
14045
14097
|
cloneRootViewTransitionContainer(_rootContainer) {
|
|
14046
|
-
throw new Error("Not implemented.");
|
|
14047
14098
|
},
|
|
14048
14099
|
removeRootViewTransitionClone(_rootContainer, _clone) {
|
|
14049
|
-
throw new Error("Not implemented.");
|
|
14050
14100
|
},
|
|
14051
14101
|
// https://github.com/facebook/react/pull/32465
|
|
14052
14102
|
createFragmentInstance: (_fiber) => null,
|
|
@@ -14131,6 +14181,7 @@ function createRoot(canvas) {
|
|
|
14131
14181
|
const lastConfiguredProps = {};
|
|
14132
14182
|
let configured = false;
|
|
14133
14183
|
let pending = null;
|
|
14184
|
+
let rendererSetup = null;
|
|
14134
14185
|
return {
|
|
14135
14186
|
async configure(props = {}) {
|
|
14136
14187
|
let resolve;
|
|
@@ -14161,7 +14212,7 @@ function createRoot(canvas) {
|
|
|
14161
14212
|
forceEven
|
|
14162
14213
|
} = props;
|
|
14163
14214
|
const textureColorSpace = is.obj(glConfig) && !is.fun(glConfig) && !isRenderer(glConfig) && glConfig.textureColorSpace || is.obj(rendererConfig) && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && rendererConfig.textureColorSpace || SRGBColorSpace;
|
|
14164
|
-
|
|
14215
|
+
let state = store.getState();
|
|
14165
14216
|
const defaultGLProps = {
|
|
14166
14217
|
canvas,
|
|
14167
14218
|
powerPreference: "high-performance",
|
|
@@ -14189,56 +14240,68 @@ function createRoot(canvas) {
|
|
|
14189
14240
|
"The `primaryCanvas` prop for multi-canvas rendering cannot be used with WebGL. Remove the `gl` prop or use WebGPU."
|
|
14190
14241
|
);
|
|
14191
14242
|
}
|
|
14192
|
-
if (
|
|
14193
|
-
|
|
14194
|
-
|
|
14195
|
-
|
|
14196
|
-
|
|
14197
|
-
|
|
14198
|
-
|
|
14199
|
-
|
|
14200
|
-
|
|
14201
|
-
|
|
14202
|
-
|
|
14203
|
-
|
|
14204
|
-
|
|
14205
|
-
|
|
14206
|
-
|
|
14207
|
-
|
|
14208
|
-
|
|
14209
|
-
|
|
14210
|
-
|
|
14211
|
-
|
|
14212
|
-
|
|
14213
|
-
|
|
14214
|
-
|
|
14215
|
-
|
|
14216
|
-
|
|
14217
|
-
|
|
14218
|
-
|
|
14219
|
-
|
|
14220
|
-
|
|
14221
|
-
|
|
14222
|
-
|
|
14223
|
-
|
|
14224
|
-
|
|
14225
|
-
|
|
14226
|
-
|
|
14227
|
-
|
|
14228
|
-
|
|
14229
|
-
|
|
14230
|
-
|
|
14231
|
-
|
|
14232
|
-
|
|
14233
|
-
|
|
14234
|
-
|
|
14235
|
-
|
|
14236
|
-
|
|
14237
|
-
|
|
14238
|
-
|
|
14243
|
+
if (!state.internal.actualRenderer) {
|
|
14244
|
+
if (!rendererSetup) {
|
|
14245
|
+
rendererSetup = (async () => {
|
|
14246
|
+
if (wantsGL) {
|
|
14247
|
+
renderer = await resolveRenderer(glConfig, defaultGLProps, WebGLRenderer);
|
|
14248
|
+
state.internal.actualRenderer = renderer;
|
|
14249
|
+
state.set({ isLegacy: true, gl: renderer, renderer, primaryStore: store });
|
|
14250
|
+
} else if (!wantsGL && primaryCanvas) {
|
|
14251
|
+
const primary = await waitForPrimary(primaryCanvas);
|
|
14252
|
+
renderer = primary.renderer;
|
|
14253
|
+
state.internal.actualRenderer = renderer;
|
|
14254
|
+
const canvasTarget = new CanvasTarget(canvas);
|
|
14255
|
+
primary.store.setState((prev) => ({
|
|
14256
|
+
internal: { ...prev.internal, isMultiCanvas: true }
|
|
14257
|
+
}));
|
|
14258
|
+
state.set((prev) => ({
|
|
14259
|
+
webGPUSupported: primary.store.getState().webGPUSupported,
|
|
14260
|
+
renderer,
|
|
14261
|
+
primaryStore: primary.store,
|
|
14262
|
+
internal: {
|
|
14263
|
+
...prev.internal,
|
|
14264
|
+
canvasTarget,
|
|
14265
|
+
isMultiCanvas: true,
|
|
14266
|
+
isSecondary: true,
|
|
14267
|
+
targetId: primaryCanvas
|
|
14268
|
+
}
|
|
14269
|
+
}));
|
|
14270
|
+
} else if (!wantsGL) {
|
|
14271
|
+
renderer = await resolveRenderer(rendererConfig, defaultGPUProps, WebGPURenderer);
|
|
14272
|
+
if (!renderer.hasInitialized?.()) {
|
|
14273
|
+
const size2 = computeInitialSize(canvas, propsSize);
|
|
14274
|
+
if (size2.width > 0 && size2.height > 0) {
|
|
14275
|
+
const pixelRatio = calculateDpr(dpr);
|
|
14276
|
+
canvas.width = size2.width * pixelRatio;
|
|
14277
|
+
canvas.height = size2.height * pixelRatio;
|
|
14278
|
+
}
|
|
14279
|
+
await renderer.init();
|
|
14280
|
+
}
|
|
14281
|
+
const backend = renderer.backend;
|
|
14282
|
+
const isWebGPUBackend = backend && "isWebGPUBackend" in backend;
|
|
14283
|
+
state.internal.actualRenderer = renderer;
|
|
14284
|
+
state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
|
|
14285
|
+
if (canvasId && !state.internal.isSecondary) {
|
|
14286
|
+
const canvasTarget = new CanvasTarget(canvas);
|
|
14287
|
+
const unregisterPrimary = registerPrimary(canvasId, renderer, store);
|
|
14288
|
+
state.set((prev) => ({
|
|
14289
|
+
internal: {
|
|
14290
|
+
...prev.internal,
|
|
14291
|
+
canvasTarget,
|
|
14292
|
+
unregisterPrimary
|
|
14293
|
+
}
|
|
14294
|
+
}));
|
|
14295
|
+
}
|
|
14239
14296
|
}
|
|
14240
|
-
}))
|
|
14297
|
+
})().catch((err) => {
|
|
14298
|
+
rendererSetup = null;
|
|
14299
|
+
throw err;
|
|
14300
|
+
});
|
|
14241
14301
|
}
|
|
14302
|
+
await rendererSetup;
|
|
14303
|
+
state = store.getState();
|
|
14304
|
+
renderer = state.internal.actualRenderer;
|
|
14242
14305
|
}
|
|
14243
14306
|
let raycaster = state.raycaster;
|
|
14244
14307
|
if (!raycaster) state.set({ raycaster: raycaster = new Raycaster() });
|
|
@@ -14588,7 +14651,8 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14588
14651
|
dispose(state.scene);
|
|
14589
14652
|
_roots.delete(canvas);
|
|
14590
14653
|
if (callback) callback(canvas);
|
|
14591
|
-
} catch {
|
|
14654
|
+
} catch (error) {
|
|
14655
|
+
console.warn("[R3F] Error while unmounting root; teardown may be incomplete:", error);
|
|
14592
14656
|
}
|
|
14593
14657
|
}, 500);
|
|
14594
14658
|
}
|
|
@@ -14651,6 +14715,7 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
14651
14715
|
viewport = rootState.viewport.getCurrentViewport(camera, new Vector3(), resolvedSize);
|
|
14652
14716
|
if (camera !== rootState.camera) updateCamera(camera, resolvedSize);
|
|
14653
14717
|
}
|
|
14718
|
+
const set = injectState.set;
|
|
14654
14719
|
return {
|
|
14655
14720
|
// The intersect consists of the previous root state
|
|
14656
14721
|
...rootState,
|
|
@@ -14669,7 +14734,7 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
14669
14734
|
size: resolvedSize,
|
|
14670
14735
|
viewport: { ...rootState.viewport, ...viewport },
|
|
14671
14736
|
// Layers are allowed to override events
|
|
14672
|
-
setEvents: (events2) =>
|
|
14737
|
+
setEvents: (events2) => set((state2) => ({ ...state2, events: { ...state2.events, ...events2 } })),
|
|
14673
14738
|
// Container for child attachment - the portalScene (injected or container itself)
|
|
14674
14739
|
internal: { ...rootState.internal, ...injectState.internal, container: portalScene }
|
|
14675
14740
|
};
|
|
@@ -14728,14 +14793,49 @@ function parseBackground(background) {
|
|
|
14728
14793
|
return null;
|
|
14729
14794
|
}
|
|
14730
14795
|
|
|
14796
|
+
function parseRendererConfig(rendererProp) {
|
|
14797
|
+
const isRendererConfig = typeof rendererProp === "object" && rendererProp !== null && !("render" in rendererProp) && ("primaryCanvas" in rendererProp || "scheduler" in rendererProp);
|
|
14798
|
+
if (isRendererConfig) {
|
|
14799
|
+
const { primaryCanvas: pc, scheduler: sc, ...rest } = rendererProp;
|
|
14800
|
+
return {
|
|
14801
|
+
primaryCanvas: pc,
|
|
14802
|
+
scheduler: sc,
|
|
14803
|
+
renderer: Object.keys(rest).length > 0 ? rest : rendererProp
|
|
14804
|
+
};
|
|
14805
|
+
}
|
|
14806
|
+
return { primaryCanvas: void 0, scheduler: void 0, renderer: rendererProp };
|
|
14807
|
+
}
|
|
14808
|
+
|
|
14809
|
+
const RESOURCE_KINDS = ["nodes", "uniforms", "buffers", "gpuStorage"];
|
|
14810
|
+
const registries = /* @__PURE__ */ new WeakMap();
|
|
14811
|
+
function getKindRegistry(store, kind) {
|
|
14812
|
+
let registry = registries.get(store);
|
|
14813
|
+
if (!registry) {
|
|
14814
|
+
registry = {
|
|
14815
|
+
nodes: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14816
|
+
uniforms: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14817
|
+
buffers: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14818
|
+
gpuStorage: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() }
|
|
14819
|
+
};
|
|
14820
|
+
registries.set(store, registry);
|
|
14821
|
+
}
|
|
14822
|
+
return registry[kind];
|
|
14823
|
+
}
|
|
14824
|
+
function invalidateResource(store, kind, scopeKey) {
|
|
14825
|
+
const registry = getKindRegistry(store, kind);
|
|
14826
|
+
{
|
|
14827
|
+
registry.valid.clear();
|
|
14828
|
+
registry.staged.clear();
|
|
14829
|
+
}
|
|
14830
|
+
}
|
|
14831
|
+
function invalidateAllResources(store) {
|
|
14832
|
+
for (const kind of RESOURCE_KINDS) invalidateResource(store, kind);
|
|
14833
|
+
}
|
|
14834
|
+
|
|
14731
14835
|
function clearHmrCaches(store) {
|
|
14732
|
-
store.
|
|
14733
|
-
|
|
14734
|
-
|
|
14735
|
-
buffers: {},
|
|
14736
|
-
gpuStorage: {},
|
|
14737
|
-
_hmrVersion: state._hmrVersion + 1
|
|
14738
|
-
}));
|
|
14836
|
+
const primary = store.getState().primaryStore ?? store;
|
|
14837
|
+
invalidateAllResources(primary);
|
|
14838
|
+
primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
|
|
14739
14839
|
}
|
|
14740
14840
|
|
|
14741
14841
|
function CanvasImpl({
|
|
@@ -14771,18 +14871,7 @@ function CanvasImpl({
|
|
|
14771
14871
|
forceEven,
|
|
14772
14872
|
...props
|
|
14773
14873
|
}) {
|
|
14774
|
-
const
|
|
14775
|
-
let primaryCanvas;
|
|
14776
|
-
let scheduler;
|
|
14777
|
-
let renderer;
|
|
14778
|
-
if (isRendererConfig) {
|
|
14779
|
-
const { primaryCanvas: pc, scheduler: sc, ...rest } = rendererProp;
|
|
14780
|
-
primaryCanvas = pc;
|
|
14781
|
-
scheduler = sc;
|
|
14782
|
-
renderer = Object.keys(rest).length > 0 ? rest : rendererProp;
|
|
14783
|
-
} else {
|
|
14784
|
-
renderer = rendererProp;
|
|
14785
|
-
}
|
|
14874
|
+
const { primaryCanvas, scheduler, renderer } = parseRendererConfig(rendererProp);
|
|
14786
14875
|
React.useMemo(() => extend(THREE), []);
|
|
14787
14876
|
const Bridge = useBridge();
|
|
14788
14877
|
const backgroundProps = React.useMemo(() => parseBackground(background), [background]);
|
|
@@ -14827,6 +14916,7 @@ function CanvasImpl({
|
|
|
14827
14916
|
const handleDropMissed = useMutableCallback(onDropMissed);
|
|
14828
14917
|
const [block, setBlock] = React.useState(false);
|
|
14829
14918
|
const [error, setError] = React.useState(false);
|
|
14919
|
+
const [fallbackVisible, setFallbackVisible] = React.useState(false);
|
|
14830
14920
|
if (block) throw block;
|
|
14831
14921
|
if (error) throw error;
|
|
14832
14922
|
const root = React.useRef(null);
|
|
@@ -14834,6 +14924,7 @@ function CanvasImpl({
|
|
|
14834
14924
|
const unsubscribeErrorRef = React.useRef(null);
|
|
14835
14925
|
useIsomorphicLayoutEffect(() => {
|
|
14836
14926
|
effectActiveRef.current = true;
|
|
14927
|
+
if (fallbackVisible) return;
|
|
14837
14928
|
const canvas = canvasRef.current;
|
|
14838
14929
|
if (effectiveSize.width > 0 && effectiveSize.height > 0 && canvas) {
|
|
14839
14930
|
if (!root.current) {
|
|
@@ -14854,7 +14945,7 @@ function CanvasImpl({
|
|
|
14854
14945
|
}
|
|
14855
14946
|
async function run() {
|
|
14856
14947
|
if (!effectActiveRef.current || !root.current) return;
|
|
14857
|
-
await root.current.configure({
|
|
14948
|
+
const configured = await root.current.configure({
|
|
14858
14949
|
id,
|
|
14859
14950
|
primaryCanvas,
|
|
14860
14951
|
scheduler,
|
|
@@ -14895,8 +14986,20 @@ function CanvasImpl({
|
|
|
14895
14986
|
}
|
|
14896
14987
|
onCreated?.(state);
|
|
14897
14988
|
}
|
|
14898
|
-
})
|
|
14899
|
-
|
|
14989
|
+
}).then(
|
|
14990
|
+
() => true,
|
|
14991
|
+
// Renderer setup failed (e.g. no WebGL/WebGPU support). The `fallback` prop lives
|
|
14992
|
+
// inside <canvas>, which browsers don't display, so surface it as visible DOM
|
|
14993
|
+
// instead; with no fallback, rethrow to an external error boundary. (#3757)
|
|
14994
|
+
(setupError) => {
|
|
14995
|
+
if (effectActiveRef.current) {
|
|
14996
|
+
if (fallback != null) setFallbackVisible(true);
|
|
14997
|
+
else setError(setupError);
|
|
14998
|
+
}
|
|
14999
|
+
return false;
|
|
15000
|
+
}
|
|
15001
|
+
);
|
|
15002
|
+
if (!configured || !effectActiveRef.current || !root.current) return;
|
|
14900
15003
|
root.current.render(
|
|
14901
15004
|
/* @__PURE__ */ jsx(Bridge, { children: /* @__PURE__ */ jsx(ErrorBoundary, { set: setError, children: /* @__PURE__ */ jsxs(React.Suspense, { fallback: /* @__PURE__ */ jsx(Block, { set: setBlock }), children: [
|
|
14902
15005
|
backgroundProps && /* @__PURE__ */ jsx(Environment, { ...backgroundProps }),
|
|
@@ -14959,7 +15062,11 @@ function CanvasImpl({
|
|
|
14959
15062
|
...style
|
|
14960
15063
|
},
|
|
14961
15064
|
...props,
|
|
14962
|
-
children:
|
|
15065
|
+
children: fallbackVisible ? (
|
|
15066
|
+
// Renderer setup failed: render the fallback as visible DOM. Inside <canvas> (below)
|
|
15067
|
+
// it exists in the tree but browsers never paint it, which is the whole bug (#3757).
|
|
15068
|
+
fallback
|
|
15069
|
+
) : /* @__PURE__ */ jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsx(
|
|
14963
15070
|
"canvas",
|
|
14964
15071
|
{
|
|
14965
15072
|
ref: canvasRef,
|