@volter/game-editor 0.5.65
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/BUNDLED_NOTICES +11228 -0
- package/LICENSE +686 -0
- package/LICENSE-BLENDER +1409 -0
- package/LICENSE-MCP +21 -0
- package/NOTICE +21 -0
- package/catalog/entries/audio.json +14 -0
- package/catalog/entries/bake.json +36 -0
- package/catalog/entries/blender.json +17 -0
- package/catalog/entries/react-root.json +24 -0
- package/catalog/entries/reflections.json +29 -0
- package/catalog/entries/static-batch.json +25 -0
- package/catalog/project-source/LICENSE +37 -0
- package/catalog/project-source/src/contributions/bake.kind.ts +40 -0
- package/catalog/project-source/src/contributions/builder-document.tsx +65 -0
- package/catalog/project-source/src/contributions/builder-state.ts +27 -0
- package/catalog/project-source/src/contributions/builder-ui.tsx +61 -0
- package/catalog/project-source/src/contributions/module-source.ts +502 -0
- package/catalog/project-source/src/contributions/pages.finder.ts +61 -0
- package/catalog/project-source/src/lib/audio/sfx.ts +255 -0
- package/catalog/project-source/src/lib/bake/asset-seed.ts +128 -0
- package/catalog/project-source/src/lib/bake/bake-schema.ts +65 -0
- package/catalog/project-source/src/lib/bake/clip-layering.ts +203 -0
- package/catalog/project-source/src/lib/bake/gltf-bake.ts +657 -0
- package/catalog/project-source/src/lib/bake/mesh-slice.ts +157 -0
- package/catalog/project-source/src/lib/bake/node-image.ts +463 -0
- package/catalog/project-source/src/lib/bake/object3d-bake.ts +121 -0
- package/catalog/project-source/src/lib/bake/object3d-lifecycle.ts +15 -0
- package/catalog/project-source/src/lib/bake/object3d-source.ts +8 -0
- package/catalog/project-source/src/lib/bake/params.ts +75 -0
- package/catalog/project-source/src/lib/bake/rest-relative-animation.ts +217 -0
- package/catalog/project-source/src/lib/bake/use-model.ts +95 -0
- package/catalog/project-source/src/lib/react-root/index.ts +20 -0
- package/catalog/project-source/src/lib/react-root/react-root-adapter.tsx +57 -0
- package/catalog/project-source/src/lib/reflections/ReflectionProbe.tsx +201 -0
- package/catalog/project-source/src/lib/reflections/index.ts +19 -0
- package/catalog/project-source/src/lib/reflections/probe-controller.ts +75 -0
- package/catalog/project-source/src/lib/reflections/reflection-probe-registry.ts +402 -0
- package/catalog/project-source/src/lib/reflections/volume-reflection-material.ts +416 -0
- package/catalog/project-source/src/lib/static-batch/Frozen.tsx +91 -0
- package/catalog/project-source/src/lib/static-batch/freeze.ts +579 -0
- package/catalog/project-source/src/lib/static-batch/index.ts +44 -0
- package/catalog/project-source/src/lib/static-batch/mutation-watch.ts +149 -0
- package/catalog/project-source/src/lib/static-batch/shadow-cache.ts +171 -0
- package/catalog/project-source/src/tools/bake-module.tool.ts +139 -0
- package/catalog/project-source/src/tools/bake-preview.tool.ts +475 -0
- package/dist/.vite/manifest.json +8304 -0
- package/dist/assets/AssetBudgetPanel-J9--TZPU.js +23 -0
- package/dist/assets/AudioViewer-CR7333fe.js +1 -0
- package/dist/assets/BVHLoader-6bQIXhMX.js +1 -0
- package/dist/assets/BufferGeometryUtils-Nz37EVXf.js +1 -0
- package/dist/assets/CCDIKSolver-CD7vLpsK.js +1 -0
- package/dist/assets/CSS3DRenderer-CL7ABLVK.js +1 -0
- package/dist/assets/CanvasSceneViewport-Bpi6gVTC.js +1 -0
- package/dist/assets/ColladaLoader-aVOPIsCh.js +3 -0
- package/dist/assets/ColorInput-DQBNrW-K.js +1 -0
- package/dist/assets/ConvexGeometry-CAzXlPVG.js +1 -0
- package/dist/assets/ConvexHull-BINCESFp.js +1 -0
- package/dist/assets/CopyShader-BzTUYzf6.js +24 -0
- package/dist/assets/DecalGeometry-160KRdfg.js +1 -0
- package/dist/assets/EXRLoader-Cdans_oJ.js +1 -0
- package/dist/assets/EffectComposer-DQxfsXBZ.js +1 -0
- package/dist/assets/EntityModelDocument-Ccvw66N9.js +1 -0
- package/dist/assets/EnvironmentAssetDocument-Dg-Qq6O6.js +1 -0
- package/dist/assets/FBXLoader-B4MoUtAn.js +1 -0
- package/dist/assets/Fbo-Dz-Soul3.js +1 -0
- package/dist/assets/FontLoader-CvGoVI5a.js +2 -0
- package/dist/assets/GLTFExporter-HgrCle4L.js +1 -0
- package/dist/assets/GameplaySessionTimeline-B52W3FVZ.js +1 -0
- package/dist/assets/Gltf-UHVWKz65.js +2 -0
- package/dist/assets/HDRLoader-THU88oVD.js +5 -0
- package/dist/assets/ImageViewer-Tn7s_MnW.js +1 -0
- package/dist/assets/InspectorCanvasPreview-CEr_Kxna.js +1 -0
- package/dist/assets/InspectorObjectPreview-CVejvLRg.js +1 -0
- package/dist/assets/JsonAssetDocument-C7VGcLhu.js +3 -0
- package/dist/assets/LineSegments2-CsOpKSiM.js +370 -0
- package/dist/assets/MTLLoader-_Xzd4_0p.js +2 -0
- package/dist/assets/MarchingCubes-Bsp4wrzd.js +1 -0
- package/dist/assets/MeshBVH-BiDHDcu-.js +1 -0
- package/dist/assets/ModelAssetDocument-F5GACirk.js +1 -0
- package/dist/assets/NonThreeAuthoringBootstrap-C3woOMxX.js +1 -0
- package/dist/assets/OBJLoader-BhIC6Hwo.js +5 -0
- package/dist/assets/Object3DDocumentViewport-DB7T0NTl.js +2 -0
- package/dist/assets/Object3DPreview-DL8oi7Xs.js +2 -0
- package/dist/assets/OnlineAssetDetail-C6z9RvYK.js +2 -0
- package/dist/assets/OrbitControls-CM3bPray.js +1 -0
- package/dist/assets/OrbitControls-DLpayAaK.js +1 -0
- package/dist/assets/OrthographicCamera-bQozawrh.js +1 -0
- package/dist/assets/PLYLoader-DYQqs5Ik.js +2 -0
- package/dist/assets/PerspectiveCamera-CQ2lh01o.js +1 -0
- package/dist/assets/PlayBar-BR-Vg3Jb.js +2 -0
- package/dist/assets/RGBELoader-BgBcQv8j.js +1 -0
- package/dist/assets/RectAreaLightUniformsLib-CMMoWfll.js +1 -0
- package/dist/assets/RenderPass-DPrn-Uky.js +1 -0
- package/dist/assets/ResolutionPicker-C67vs1F3.js +1 -0
- package/dist/assets/RootSelectionOverlay-BZPlxmXU.js +1 -0
- package/dist/assets/RoundedBox-BDGBg6QZ.js +1 -0
- package/dist/assets/RoundedBoxGeometry-CyUuYPfW.js +1 -0
- package/dist/assets/STLLoader-Dyv3lsxY.js +1 -0
- package/dist/assets/SelectionBox-D_75KrNW.js +1 -0
- package/dist/assets/ShaderPass-QYRpPuFJ.js +1 -0
- package/dist/assets/ShadowEditor-DkImwu1Y.js +1 -0
- package/dist/assets/SimplifyModifier-C8ayvRzd.js +1 -0
- package/dist/assets/SkeletonUtils-Cps8GOC6.js +1 -0
- package/dist/assets/Sky-CQKCgYDs.js +154 -0
- package/dist/assets/SourceAssetViewer-2SWQoUut.js +12 -0
- package/dist/assets/StageHost-BN-IoTef.js +2 -0
- package/dist/assets/StoryPreviewMount-DjyxRCXu.js +1 -0
- package/dist/assets/TDSLoader-D_T8XJ81.js +1 -0
- package/dist/assets/TextGeometry-DOWAEUV0.js +1 -0
- package/dist/assets/ThreeBoardDocument-CVncZyIq.js +2 -0
- package/dist/assets/ThreeIsolationSceneContent-C8C8whSF.js +1 -0
- package/dist/assets/ToolObject3DPreview-BRoDWe4Q.js +1 -0
- package/dist/assets/TrackballControls-DfznuQTh.js +1 -0
- package/dist/assets/TransientHint-BB1fwrvK.js +1 -0
- package/dist/assets/UnrealBloomPass-CR-cS_K5.js +83 -0
- package/dist/assets/VideoViewer-C6kocgIU.js +1 -0
- package/dist/assets/_commonjsHelpers-D6-XlEtG.js +1 -0
- package/dist/assets/active-ingest-CT6jSGhr.js +3 -0
- package/dist/assets/adapter-surface-Y37Nzcyw.js +1 -0
- package/dist/assets/after-paint-CB4bz1-e.js +1 -0
- package/dist/assets/agx-base-srgb-BjWZJgrZ.lut +0 -0
- package/dist/assets/agx-look-medium-high-contrast-D5F_ob1L.lut +0 -0
- package/dist/assets/agx-look-punchy-dxsnycNs.lut +0 -0
- package/dist/assets/animation-clock-CnjZqfJp.js +1 -0
- package/dist/assets/asset-budget-asset.menu-Di3KiQCd.js +1 -0
- package/dist/assets/asset-budget.action-DCzzcuTh.js +1 -0
- package/dist/assets/asset-budget.document-BWU8wnVW.js +1 -0
- package/dist/assets/asset-budget.menu-BGZpT_31.js +1 -0
- package/dist/assets/asset-editor-persistence-BBaONOJt.js +1 -0
- package/dist/assets/asset-loaders-BOy5Ss8k.js +2 -0
- package/dist/assets/asset-parse-error-BHMwBRU3.js +3 -0
- package/dist/assets/assets-BuSoGjBX.js +1 -0
- package/dist/assets/audio-meter-CyiToeUW.js +1 -0
- package/dist/assets/audio-unlock.service-CfUgUQVy.js +1 -0
- package/dist/assets/audio.utility-C6K6jem8.js +1 -0
- package/dist/assets/authoring-CgcOFhGS.js +1 -0
- package/dist/assets/autoplay.service-BZBGNSvt.js +1 -0
- package/dist/assets/axe-LkjAB6Lv.js +30 -0
- package/dist/assets/babylon-authoring-adapter-CL02gWDn.js +1 -0
- package/dist/assets/binding-Bmxqznjk.js +1 -0
- package/dist/assets/binding-identity-DcTpbvyg.js +1 -0
- package/dist/assets/binding-resolver-Dsh-6Vor.js +2 -0
- package/dist/assets/blender-emscripten-engine-9ZIRYNhe.js +2 -0
- package/dist/assets/blender-node-editor.document-iIDkB9sI.js +1 -0
- package/dist/assets/blender-properties-tab-C5CyPydi.js +3 -0
- package/dist/assets/blender-runtime-host-BpBwGv7r.js +4 -0
- package/dist/assets/blender-runtime-skin-DyQ9B6CR.js +7140 -0
- package/dist/assets/blender-runtime.document-lIYhhPtv.js +8 -0
- package/dist/assets/blender-timeline.document-77fx96N7.js +1 -0
- package/dist/assets/blender-uv-editor.document-fsT7B4gV.js +1 -0
- package/dist/assets/blender-version.status-o6dBm3n6.js +1 -0
- package/dist/assets/blender-wali-engine-wTOcrOMC.js +2 -0
- package/dist/assets/blender.command-BtJeWk-A.js +1 -0
- package/dist/assets/blender.keymap-GAQgeklK.js +1 -0
- package/dist/assets/blender.status-ujwGU6dU.js +1 -0
- package/dist/assets/blender.style-Dcem5f_T.js +1 -0
- package/dist/assets/board-guides-DziKSTss.js +1 -0
- package/dist/assets/body-marks-h_xDxiDE.js +1 -0
- package/dist/assets/bridge.command-o5gDNEwa.js +3 -0
- package/dist/assets/browserAll-DeWblVez.js +1 -0
- package/dist/assets/build-profiles.document-kW8iw8Xj.js +2 -0
- package/dist/assets/build-progress.status-BNRLytg2.js +1 -0
- package/dist/assets/build-session-C_sg3CEn.js +9 -0
- package/dist/assets/build.action-lYjTLb7K.js +1 -0
- package/dist/assets/build.command-DIGgUPU_.js +1 -0
- package/dist/assets/build.header-CKajx5U3.js +1 -0
- package/dist/assets/build.menu-BdU0QXny.js +1 -0
- package/dist/assets/build.service-CbBAyeu3.js +1 -0
- package/dist/assets/bus-mixer-CGfWDP3C.js +1 -0
- package/dist/assets/camera-KEsKvOL7.js +1 -0
- package/dist/assets/camera-runtime.inspector-B7unX4g1.js +1 -0
- package/dist/assets/canvas-entry-runtime-SfBxaR9M.js +2 -0
- package/dist/assets/capability-coverage-Czas4C18.js +7 -0
- package/dist/assets/chrome-trace-YZHMz60-.js +1 -0
- package/dist/assets/client-DNXj_opT.js +25 -0
- package/dist/assets/clip-planes-CnAI6DZn.js +1 -0
- package/dist/assets/collaboration-presence-DLoZ7EA3.js +1 -0
- package/dist/assets/collider-Bw0mXlsW.js +1 -0
- package/dist/assets/collider-dimensions-9xoFADXN.js +1 -0
- package/dist/assets/collision-system-DpNUJRJ3.js +1 -0
- package/dist/assets/command-results-CUQD49AB.js +1 -0
- package/dist/assets/component-board-registry-DrIa2csL.js +1 -0
- package/dist/assets/component-board.service-DCwcUssB.js +2 -0
- package/dist/assets/component-board.service-DidCyM4O.js +2 -0
- package/dist/assets/component-verbs.command-7xzfjGMZ.js +1 -0
- package/dist/assets/component-verbs.service-Bv9jId3q.js +1 -0
- package/dist/assets/config-CEZk921y.js +6 -0
- package/dist/assets/configurations-DTBMdaTL.js +1 -0
- package/dist/assets/connection.status-BifnQdOs.js +1 -0
- package/dist/assets/console-bridge-CHcb-xk5.js +1 -0
- package/dist/assets/constraint-De8f1Uiq.js +1 -0
- package/dist/assets/constraints.inspector-B9U9Yj-u.js +1 -0
- package/dist/assets/countdown-timer-CUm74dom.js +1 -0
- package/dist/assets/coverage.service-VTX5Mcsx.js +3 -0
- package/dist/assets/crash-null-boundary-v3a0uEgw.js +1 -0
- package/dist/assets/create-runtime-CVCc1BDx.js +1 -0
- package/dist/assets/curve-7Q79VgU4.js +1 -0
- package/dist/assets/data-asset-4hjS642k.js +5 -0
- package/dist/assets/data-check-core-CQEjuFyt.js +1 -0
- package/dist/assets/data-ref-CQI28C0D.js +1 -0
- package/dist/assets/debug-bridge-CCohG-d-.js +1 -0
- package/dist/assets/debug-registry-Dgvitx8M.js +1 -0
- package/dist/assets/defaults-DKiBJCPN.js +1 -0
- package/dist/assets/deferred-commands-CEMmvL47.js +1 -0
- package/dist/assets/deferred-ingest-play-DCJi_Pgu.js +2 -0
- package/dist/assets/design-time-layers-wYgOTgni.js +1 -0
- package/dist/assets/design-time-mount-registry-DUpXCg1U.js +1 -0
- package/dist/assets/design-time-mount.service-BzY21e1F.js +2 -0
- package/dist/assets/design-time-react-mount-DM9WLrF2.js +1 -0
- package/dist/assets/dev-build-gDYrq68M.js +1 -0
- package/dist/assets/directional-shadow-fit-BVkOKAv2.js +1 -0
- package/dist/assets/document-preview-three-Kbg2GCLm.js +1 -0
- package/dist/assets/dom-authoring-adapter-CY8C7f4T.js +1 -0
- package/dist/assets/draco3d-BBUTcNkz.js +1 -0
- package/dist/assets/draco_decoder-DsQ12WqX.wasm +0 -0
- package/dist/assets/draco_encoder-2Tcju8Ns.wasm +0 -0
- package/dist/assets/edit-mode-audio.service-Bzetwd5B.js +1 -0
- package/dist/assets/edit-mode-authoring-B47TfLqu.js +1 -0
- package/dist/assets/edit-mode-networking.service-YCX6RRb_.js +1 -0
- package/dist/assets/editor-api-BoJIcyZG.js +1 -0
- package/dist/assets/editor-port-C_FeBdeV.js +1 -0
- package/dist/assets/editor-presentation-activity-C7SNSmTd.js +1 -0
- package/dist/assets/entry-adjudication-Cq8Yeb74.js +1 -0
- package/dist/assets/environment-capture-7himRh2L.js +1 -0
- package/dist/assets/esbuild-BHljloGq.wasm +0 -0
- package/dist/assets/events-156d8d12.esm-ErOhDXXB.js +36 -0
- package/dist/assets/extend-B-eOccUm.js +36 -0
- package/dist/assets/extends-CF3RwP-h.js +1 -0
- package/dist/assets/eyedropper-session-bjPXnfeX.js +1 -0
- package/dist/assets/fflate.module-DPuTF8aG.js +6 -0
- package/dist/assets/filmic-srgb-Ct35FIH6.lut +0 -0
- package/dist/assets/first-party-audio-system-DxnGJOER.js +1 -0
- package/dist/assets/first-party-navigation-system-CL5Bquub.js +1 -0
- package/dist/assets/fork-menu-BoVyw2Wu.js +1 -0
- package/dist/assets/frame-debugger-store-D1Mf_5up.js +1 -0
- package/dist/assets/frame-delta-D2nsw_Ht.js +1 -0
- package/dist/assets/frame-pacing-D5acoOzO.js +1 -0
- package/dist/assets/frame-selector-cache-cCeUbcjG.js +1 -0
- package/dist/assets/game-DHOZVb-7.js +1 -0
- package/dist/assets/game-contract-seams-a5YXejOu.js +1 -0
- package/dist/assets/game-css-scope-transform-Eng4wS8E.js +33 -0
- package/dist/assets/game-document.service-DbRfx2V0.js +1 -0
- package/dist/assets/game-eval.command-D-7Dxbj_.js +2 -0
- package/dist/assets/game-input-seams-CIQdetRw.js +1 -0
- package/dist/assets/game-loop-CZvXlY00.js +1 -0
- package/dist/assets/game-module-access-B2mFxv-i.js +1 -0
- package/dist/assets/game.layout-CBASrvQu.js +1 -0
- package/dist/assets/gameplay-export-BoKXm51x.js +1 -0
- package/dist/assets/gameplay-replay-e5umMlXv.js +1 -0
- package/dist/assets/gameplay-rng-trap-CTNhm-UW.js +3 -0
- package/dist/assets/gameplay.command-DxcVYX6F.js +1 -0
- package/dist/assets/generation-DhwCUHPf.css +1 -0
- package/dist/assets/generation-jobs-BQrXbGp_.js +1 -0
- package/dist/assets/generation.service-CDIgObuw.js +1 -0
- package/dist/assets/generations-DzUogZsM.js +1 -0
- package/dist/assets/generations.status-CgOUBCum.js +1 -0
- package/dist/assets/hierarchy-marks-BLPfSIym.js +1 -0
- package/dist/assets/host-pointer-DbGSCjE9.js +1 -0
- package/dist/assets/hosted-asset-materialization-CiIvWkGU.js +2 -0
- package/dist/assets/ibl-override-material-BlmCxFKq.js +6 -0
- package/dist/assets/index-96FBF1Oj.js +1 -0
- package/dist/assets/index-BAWkB0dv.js +1 -0
- package/dist/assets/index-BDnS2b6S.js +1 -0
- package/dist/assets/index-BHp07vN0.js +2 -0
- package/dist/assets/index-BMxv2MNV.js +1 -0
- package/dist/assets/index-BP6wv2A0.js +5 -0
- package/dist/assets/index-BcCBqgM_.js +952 -0
- package/dist/assets/index-Bge9JUr6.js +1 -0
- package/dist/assets/index-BjTCPEQ7.js +134 -0
- package/dist/assets/index-BncK9THk.js +1 -0
- package/dist/assets/index-CJbYy-CF.js +3 -0
- package/dist/assets/index-CVCb_ImQ.js +1 -0
- package/dist/assets/index-CZd9o7Lu.js +1 -0
- package/dist/assets/index-CanA16PU.js +2 -0
- package/dist/assets/index-CinJrH5C.js +9 -0
- package/dist/assets/index-CtzuWnCS.js +1 -0
- package/dist/assets/index-D2fNXpHa.css +1 -0
- package/dist/assets/index-DUpHH6JR.js +3120 -0
- package/dist/assets/index-DUqP1RMl.js +1 -0
- package/dist/assets/index-D_NuPfjr.js +9 -0
- package/dist/assets/index-Da9JhEvW.js +25 -0
- package/dist/assets/index-DgapqSPi.js +7 -0
- package/dist/assets/index-FUuS4qwW.js +562 -0
- package/dist/assets/index-GIL7oGEO.js +4894 -0
- package/dist/assets/index-IEjydI9d.js +1 -0
- package/dist/assets/index-OrYXPk3Z.js +487 -0
- package/dist/assets/index-V1R-e5Bd.js +1 -0
- package/dist/assets/index-bQE2NA0D.js +1 -0
- package/dist/assets/index-gHZae-lw.js +13 -0
- package/dist/assets/index-mjWQmGhM.js +1 -0
- package/dist/assets/index-nmcBqr7Y.js +1 -0
- package/dist/assets/inference-diagnostics-Dhmtfbq_.js +1 -0
- package/dist/assets/ingest-BbYMC2vQ.js +1 -0
- package/dist/assets/ingest-boot-viewport-D5rI_Kk_.js +1 -0
- package/dist/assets/ingest-siblings-Bop2kqVl.js +1 -0
- package/dist/assets/ingest-source-persistence-C_6Hiyra.js +1 -0
- package/dist/assets/ingest.service-BTDnQfM1.js +1 -0
- package/dist/assets/input-manager-DH_hGW6d.js +1 -0
- package/dist/assets/input-router-BNQvtIqw.js +1 -0
- package/dist/assets/inspect-BZfi3mmo.js +1 -0
- package/dist/assets/inspection-CObLhnrs.js +1 -0
- package/dist/assets/instance-fork-actions-D3sRzS3K.js +1 -0
- package/dist/assets/instances.command-D6UkZNO8.js +1 -0
- package/dist/assets/instruments-CKR02Y8I.js +1 -0
- package/dist/assets/json-history-resource-BbxllWfV.js +1 -0
- package/dist/assets/jsx-runtime-DPjLkJKQ.js +9 -0
- package/dist/assets/light-D-_wsKTq.js +1 -0
- package/dist/assets/light-camera-factory-CWbbe9gI.js +1 -0
- package/dist/assets/lil-gui.module.min-BF55BEwA.js +10 -0
- package/dist/assets/live-behaviors-Bxq49Maz.js +1 -0
- package/dist/assets/live-gesture-lock-DJbrjOqf.js +1 -0
- package/dist/assets/loader-CaF_I7Yt.js +1 -0
- package/dist/assets/logger-Dqis-7W1.js +1 -0
- package/dist/assets/loop-gate-report-N52EWFGD.js +1 -0
- package/dist/assets/matcap-texture-CVfalpWT.js +1 -0
- package/dist/assets/material-CpAdjDxn.js +1 -0
- package/dist/assets/material-factory-Bz6h__6g.js +1 -0
- package/dist/assets/mesh-B3WPtNKO.js +1 -0
- package/dist/assets/mesh-shadow-CZnXrw_l.js +1 -0
- package/dist/assets/mikktspace.module-DO88SLib.js +1 -0
- package/dist/assets/model-asset-sections-CFvvihfx.css +1 -0
- package/dist/assets/model-asset-sections.service-CHhFS3ZX.js +1 -0
- package/dist/assets/model.layout-BJUEQYUI.js +1 -0
- package/dist/assets/models.finder-G2jQgIRu.js +1 -0
- package/dist/assets/module-mode-DVBLT9d-.js +2 -0
- package/dist/assets/mount-canvas-ingest-root-DDuAWf_C.js +2 -0
- package/dist/assets/mount-dom-ingest-root-D_EiBgpn.js +2 -0
- package/dist/assets/mount-game-6t9cKNo4.js +1 -0
- package/dist/assets/mount-ingest-root-glv2SSWf.js +2 -0
- package/dist/assets/mount-manifest-CGVxhmAw.js +1 -0
- package/dist/assets/mount-readiness-Ds0HvvLH.js +4 -0
- package/dist/assets/mount-three-ingest-root-hrUt9VVU.js +1 -0
- package/dist/assets/mounted-authoring-Dmg5xmhP.js +1 -0
- package/dist/assets/mounted-story-viewport-source-DjP6RA9U.js +1 -0
- package/dist/assets/native-debug-module-CWicoSGD.js +1 -0
- package/dist/assets/native-entry-surface-BE8LJNdu.js +1 -0
- package/dist/assets/navigation-CIiCx-SM.js +1 -0
- package/dist/assets/navmesh-workflow-store-Cmnm57TB.js +1 -0
- package/dist/assets/navmesh.menu-CAKiH8PW.js +1 -0
- package/dist/assets/navmesh.service-jgDWlgj1.js +1 -0
- package/dist/assets/network.utility-CEu5nHf7.js +1 -0
- package/dist/assets/object-marks-DwvIEBOK.js +1 -0
- package/dist/assets/object3d-authoring-subject-CH5sI2oP.js +1 -0
- package/dist/assets/output-DK8waum9.js +195 -0
- package/dist/assets/particles-Y626p22p.js +1 -0
- package/dist/assets/particles-factory-DnLOHXT8.js +1 -0
- package/dist/assets/pasteboard-materialize-BqSS4QzV.js +20 -0
- package/dist/assets/pasteboard.action-DU3UHtJG.js +2 -0
- package/dist/assets/performance-profiler-D_Jey87L.js +1 -0
- package/dist/assets/physics-registry-B2Jkp8e6.js +1 -0
- package/dist/assets/physics-registry-CUB9cT9p.js +1 -0
- package/dist/assets/pixi-authoring-adapter-CjibysC3.js +1 -0
- package/dist/assets/pixi-live-write-target-DuWydlWb.js +1 -0
- package/dist/assets/pixi-primitive-DlWbUPN9.js +1 -0
- package/dist/assets/pixi-react-root-factory-DYsznYRQ.js +1 -0
- package/dist/assets/pixi-story-model-DNkfnWUV.js +1 -0
- package/dist/assets/pixi-transform-channels-VjdohT11.js +1 -0
- package/dist/assets/play-mode-BFU2PCkG.js +22 -0
- package/dist/assets/play.command-BpqqLqkq.js +2 -0
- package/dist/assets/playtest-BXIL1JEF.js +1 -0
- package/dist/assets/pose-guard-6Osb2cFu.js +1 -0
- package/dist/assets/presentation-BPP5pXeQ.js +1 -0
- package/dist/assets/product-DFhyARJj.js +1 -0
- package/dist/assets/profiler.action-CaXJDp3t.js +1 -0
- package/dist/assets/profiler.menu-BIMF6Bi4.js +1 -0
- package/dist/assets/profiler.utility-BExw9wBO.js +1 -0
- package/dist/assets/project-authoring-session-Bnt6icLr.js +2 -0
- package/dist/assets/project-provenance-BoP3nrle.js +1 -0
- package/dist/assets/prompt-labels-DSMdM2_B.js +1 -0
- package/dist/assets/properties-bone-constraints.inspector-ByT6p7S-.js +1 -0
- package/dist/assets/properties-bone.inspector-z4qJwKO5.js +1 -0
- package/dist/assets/properties-collection.inspector-D0_3ijWU.js +1 -0
- package/dist/assets/properties-constraints.inspector-CESzjuls.js +1 -0
- package/dist/assets/properties-data.inspector-hG8Wgyzb.js +1 -0
- package/dist/assets/properties-material.inspector-CzY0JCQ6.js +1 -0
- package/dist/assets/properties-modifiers.inspector-3dDhwf7g.js +1 -0
- package/dist/assets/properties-object.inspector-CiarfxkT.js +1 -0
- package/dist/assets/properties-output.inspector-DKJxmKSD.js +1 -0
- package/dist/assets/properties-particles.inspector-CCEdYWGm.js +1 -0
- package/dist/assets/properties-physics.inspector-B2c0KUyA.js +1 -0
- package/dist/assets/properties-render.inspector-Bcm0HLRW.js +1 -0
- package/dist/assets/properties-scene.inspector-PIM_eTb_.js +1 -0
- package/dist/assets/properties-texture.inspector-CgFlnyr8.js +1 -0
- package/dist/assets/properties-view-layer.inspector-DGjF_Aqo.js +1 -0
- package/dist/assets/properties-world.inspector-CrMvaRvB.js +1 -0
- package/dist/assets/r3f-design-session-D-4yyDO9.js +2 -0
- package/dist/assets/r3f-physics-binding-BBo8oma9.js +1 -0
- package/dist/assets/r3f-root-factory-z9llD1OU.js +1 -0
- package/dist/assets/r3f-source-authoring-adapter-w6Bc60K-.js +13 -0
- package/dist/assets/rapier-physics-adapter-CaZqWLu0.js +1 -0
- package/dist/assets/rapier-physics-bridge-CMoeVo3Y.js +1 -0
- package/dist/assets/react-18-By2b4xR9.js +1 -0
- package/dist/assets/react-inspector.service-B_neRnSK.js +1 -0
- package/dist/assets/react-root-CEz5NTck.js +1 -0
- package/dist/assets/react-story-board-BDDwiE2H.js +1 -0
- package/dist/assets/react-three-fiber.esm-CycrbDlA.js +1 -0
- package/dist/assets/react-three-rapier.esm-CEfKpvxT.js +1 -0
- package/dist/assets/react-world-authoring-adapter-DmrwM3py.js +1 -0
- package/dist/assets/realm-services-CobQsq_X.js +1 -0
- package/dist/assets/rebind-controller-Dtq19Vb3.js +1 -0
- package/dist/assets/recast-navigation.wasm-compat-Dsoa_MD-.js +1 -0
- package/dist/assets/reflection-probe-Don-M3Fj.js +1 -0
- package/dist/assets/reflection-probe-capture.inspector-CmFUoJCx.js +1 -0
- package/dist/assets/register-render-vitals-BiZk29b2.js +1 -0
- package/dist/assets/registry-02YZjMNp.js +1 -0
- package/dist/assets/relative-path-guard-GiM7Lsz8.js +1 -0
- package/dist/assets/render-audio-control-vMRlePWb.js +1 -0
- package/dist/assets/render-batch-system-0vq7p0VC.js +1 -0
- package/dist/assets/render-census-BrQX_CXv.js +1 -0
- package/dist/assets/render-control-Df3yTiyr.js +1 -0
- package/dist/assets/render-env-D2IV2x5k.js +1 -0
- package/dist/assets/render-features-CPQ_e568.js +1 -0
- package/dist/assets/render-seed-DF4JHy7P.js +1 -0
- package/dist/assets/render-settings-Bw4W9SYF.js +1 -0
- package/dist/assets/render-vitals-BZ5HtvMi.js +1 -0
- package/dist/assets/renderer-config-BqG4O8i9.js +1 -0
- package/dist/assets/resolve-three-SZE_WWUM.js +702 -0
- package/dist/assets/root-seam-contract-Z0VWX3Bk.js +1 -0
- package/dist/assets/rrweb-Cd2ifIRP.js +142 -0
- package/dist/assets/run-ticks-settled-C4ksViyA.js +1 -0
- package/dist/assets/runtime-inspection-l2iFQSsg.js +1 -0
- package/dist/assets/scene-capture-BQKzU0NT.js +1 -0
- package/dist/assets/scene-capture-CGYF-Viw.js +1 -0
- package/dist/assets/scene-document.service-qkDjUrlP.js +2 -0
- package/dist/assets/scene-framing-Cat0GtyJ.js +1 -0
- package/dist/assets/scene-index-B6BZOHMk.js +1 -0
- package/dist/assets/scene-query-C7_N-TpI.js +1 -0
- package/dist/assets/schema-kl9-2B_J.js +1 -0
- package/dist/assets/sculpt.layout-zJF55yCR.js +1 -0
- package/dist/assets/seeded-random-i3mtgBKZ.js +1 -0
- package/dist/assets/session-CZ5JPg-z.js +4877 -0
- package/dist/assets/setup-audio-S8GQF91f.js +1 -0
- package/dist/assets/setup-particles-GCXlnkj_.js +1 -0
- package/dist/assets/setup-physics-BeZ7-LKD.js +1 -0
- package/dist/assets/setup-renderer-DVXaSGin.js +1587 -0
- package/dist/assets/shading.layout-DULYZV6M.js +1 -0
- package/dist/assets/sim-clock-CLflx7kg.js +1 -0
- package/dist/assets/sky-precompute-worker-ChN7J87v.js +1 -0
- package/dist/assets/soft-particle-depth-DGvfQDi1.js +1 -0
- package/dist/assets/source-object3d-authoring-adapter-B-L6Ha6f.js +1 -0
- package/dist/assets/source-persistence-backend-C-aR-B_Y.js +1 -0
- package/dist/assets/spark-renderer-lifecycle-ynWESJcv.js +1 -0
- package/dist/assets/spark.module-4pXQoz5d.js +12120 -0
- package/dist/assets/stage-invalidation-DBg3C3Ta.js +1 -0
- package/dist/assets/stage-keyboard-n-5kKH-m.js +1 -0
- package/dist/assets/stage-overlay-set-B9zp2sLB.js +1 -0
- package/dist/assets/stage-presence-markers-DiGI6A45.js +1 -0
- package/dist/assets/standard-viewport-dressing-CzjAe_0A.js +7 -0
- package/dist/assets/state-bridge-DLP1jLRW.js +1 -0
- package/dist/assets/state-watch.action-BOvQR2qt.js +1 -0
- package/dist/assets/state-watch.menu-CNLvDeeY.js +1 -0
- package/dist/assets/state-watch.utility-Bg1tTTQU.js +1 -0
- package/dist/assets/static-batch-advisor-B13QEH7d.js +1 -0
- package/dist/assets/stats.module-BL02l9NC.js +1 -0
- package/dist/assets/story-arg-descriptors-Ek86ExX7.js +1 -0
- package/dist/assets/story-capture-_gC8dXV-.js +1 -0
- package/dist/assets/story-documents--TDLaPeL.js +3 -0
- package/dist/assets/story-documents.service-BiS_YbNQ.js +1 -0
- package/dist/assets/story-documents.service-CxOPYJ2j.js +1 -0
- package/dist/assets/story-media-presence-BHzk2IV5.js +1 -0
- package/dist/assets/story-mount-turn-DFRTj5hi.js +1 -0
- package/dist/assets/story-pixi-preview-BUrOJZXS.js +1 -0
- package/dist/assets/story-presentation-j2AVN-mK.js +1 -0
- package/dist/assets/story-three-preview-BHEDZzcl.js +2 -0
- package/dist/assets/structural-ids-Dc-7rEwi.js +1 -0
- package/dist/assets/structural-signature-0w-i_ats.js +1 -0
- package/dist/assets/surface-content-Dg9Kkazf.js +1 -0
- package/dist/assets/surface-state-DaxyruCj.js +3 -0
- package/dist/assets/system-adapters-rIC8FSGP.js +1 -0
- package/dist/assets/system-runner-DkOjxEBt.js +1 -0
- package/dist/assets/system-slot-E2mEdiih.js +1 -0
- package/dist/assets/team-playtest.service-DqOinFVA.js +1 -0
- package/dist/assets/texture.layout-DASpHVht.js +1 -0
- package/dist/assets/three-CDSueJyJ.js +1 -0
- package/dist/assets/three-authoring-adapter-CmSQ3Vui.js +1 -0
- package/dist/assets/three-authoring.service-iuHLwtf1.js +2 -0
- package/dist/assets/three-ingest-runtime-QzDYk6tU.js +1 -0
- package/dist/assets/three-projection-core-BmKMZ-nf.js +1 -0
- package/dist/assets/three-viewport-presentation-QBQpSdMh.js +1 -0
- package/dist/assets/three.module-D396a9Mn.js +3840 -0
- package/dist/assets/three.quarks.esm-B1C61jGo.js +1039 -0
- package/dist/assets/tools-B_NJsk05.js +1 -0
- package/dist/assets/transform-writer-BhBBTx33.js +1 -0
- package/dist/assets/transport.header-B-6HQlU2.js +1 -0
- package/dist/assets/trigger-volume-BNK2XzPL.js +1 -0
- package/dist/assets/tuples-CIQ4Bn1U.js +1 -0
- package/dist/assets/tween.module-DciWpAG6.js +1 -0
- package/dist/assets/ui-board-document-Bwtt--xp.js +2 -0
- package/dist/assets/unexported-game-trap-Dm1JYKHy.js +2 -0
- package/dist/assets/unmanaged-root-detector-B8CpbkSN.js +2 -0
- package/dist/assets/upstream-pin-BdgRH6ID.js +1 -0
- package/dist/assets/use-data-Dzq-MytE.js +1 -0
- package/dist/assets/use-live-actor-state-DErbWQWF.js +1 -0
- package/dist/assets/use-selection-DbR73-xd.js +1 -0
- package/dist/assets/user-data-BB2Of6Ht.js +1 -0
- package/dist/assets/utility-view-state-BHypxA33.js +1 -0
- package/dist/assets/uv-editing.layout-BEKHxmHw.js +1 -0
- package/dist/assets/vgai-shared-fontawesome-CU65D4Ij.js +1 -0
- package/dist/assets/vgai-shared-jsx-dev-runtime-DFDKL7fx.js +1 -0
- package/dist/assets/vgai-shared-jsx-runtime-DIqBpTut.js +1 -0
- package/dist/assets/vgai-shared-react-BT7rMc2H.js +1 -0
- package/dist/assets/vgai-shared-react-dom-DFajMqMT.js +1 -0
- package/dist/assets/vgai-shared-react-dom-client-S0ozfl6_.js +1 -0
- package/dist/assets/vgai-shared-three-Bc5PvpLM.js +1 -0
- package/dist/assets/viewport-pick-context-DkawXbEi.js +1 -0
- package/dist/assets/viewport-root-presentation-CWsE56K6.js +1 -0
- package/dist/assets/viewport-shading-BuA88e_A.js +1 -0
- package/dist/assets/viewport-shading-boundary-B_-_gABg.js +82 -0
- package/dist/assets/viewport-surface-status-B3om4Kcf.js +1 -0
- package/dist/assets/vision_bundle-DX0dWqEa.js +15 -0
- package/dist/assets/voxel-surface-DtcsSWRL.js +1 -0
- package/dist/assets/wav-encode-D31zWF6O.js +1 -0
- package/dist/assets/webgl-frame-capture-FlF9zQmW.js +1 -0
- package/dist/assets/webgl-gpu-timer-D3YX7RaD.js +1 -0
- package/dist/assets/webworkerAll-CM2o_dnz.js +1 -0
- package/dist/assets/worker-UrMcrc5_.js +2 -0
- package/dist/assets/world-documents-147tiFZe.js +1 -0
- package/dist/assets/world-root-stage-binding-vwTrtBz6.js +1 -0
- package/dist/assets/world-state-BWG-IcOd.js +1 -0
- package/dist/assets/writer-B-KovzkA.js +5 -0
- package/dist/assets/xstate-animation-binding-Brd0NST6.js +1 -0
- package/dist/assets/xstate-animation-meta-Q3u9zh_m.js +1 -0
- package/dist/assets/xstate-behavior.action-B8UluFBK.js +1 -0
- package/dist/assets/xstate-behavior.document-CKAsE45I.js +1 -0
- package/dist/assets/xstate-behavior.inspector-vJJyuifc.js +1 -0
- package/dist/assets/xstate-behavior.menu-BXbPICIh.js +1 -0
- package/dist/assets/xstate-inspection-BsZv8LS9.js +1 -0
- package/dist/vgai-shared-react.json +10 -0
- package/dist/vgai-shared-three.json +3 -0
- package/dist-node/cli.js +9320 -0
- package/dist-node/create.js +3239 -0
- package/package.json +91 -0
- package/presets.mjs +2 -0
- package/src/contributions.d.ts +4 -0
- package/src/index.ts +38 -0
- package/starter/cube.blend +0 -0
- package/starter/cube.py +81 -0
- package/template/.agents/references/project-manual.md +341 -0
- package/template/.agents/skills/editor/SKILL.md +53 -0
- package/template/.agents/skills/editor/agents/openai.yaml +4 -0
- package/template/.agents/skills/editor/references/editor-control.md +363 -0
- package/template/.agents/skills/vgai-3d-models/SKILL.md +64 -0
- package/template/.agents/skills/vgai-ingest-existing-game/SKILL.md +112 -0
- package/template/.agents/skills/vgai-threejs-authoring/SKILL.md +347 -0
- package/template/.agents/skills/vgai-threejs-authoring/agents/openai.yaml +4 -0
- package/template/.agents/skills/vgai-threejs-authoring/references/helper-catalog.md +65 -0
- package/template/.claude/skills/editor/SKILL.md +53 -0
- package/template/.claude/skills/editor/agents/openai.yaml +4 -0
- package/template/.claude/skills/editor/references/editor-control.md +363 -0
- package/template/.claude/skills/vgai-3d-models/SKILL.md +64 -0
- package/template/.claude/skills/vgai-ingest-existing-game/SKILL.md +112 -0
- package/template/.claude/skills/vgai-threejs-authoring/SKILL.md +347 -0
- package/template/.claude/skills/vgai-threejs-authoring/agents/openai.yaml +4 -0
- package/template/.claude/skills/vgai-threejs-authoring/references/helper-catalog.md +65 -0
- package/template/.github/copilot-instructions.md +6 -0
- package/template/.github/skills/editor/SKILL.md +53 -0
- package/template/.github/skills/editor/agents/openai.yaml +4 -0
- package/template/.github/skills/editor/references/editor-control.md +363 -0
- package/template/.github/skills/vgai-3d-models/SKILL.md +64 -0
- package/template/.github/skills/vgai-ingest-existing-game/SKILL.md +112 -0
- package/template/.github/skills/vgai-threejs-authoring/SKILL.md +347 -0
- package/template/.github/skills/vgai-threejs-authoring/agents/openai.yaml +4 -0
- package/template/.github/skills/vgai-threejs-authoring/references/helper-catalog.md +65 -0
- package/template/.mcp.json +12 -0
- package/template/.vgai/assets.json +1 -0
- package/template/.vgai/provenance.json +4 -0
- package/template/.volter/tracker/validation/.preset.base.mts +178 -0
- package/template/.volter/tracker/validation/preset.mts +186 -0
- package/template/.volter/tracker/visualizer/.extension.base.tsx +14 -0
- package/template/.volter/tracker/visualizer/extension.tsx +14 -0
- package/template/.volter/tracker-config.json +17 -0
- package/template/AGENTS.md +176 -0
- package/template/CLAUDE.md +1 -0
- package/template/DEVLOG.md +20 -0
- package/template/IDIOMS.md +118 -0
- package/template/LICENSE +30 -0
- package/template/README.md +83 -0
- package/template/ROADMAP.md +20 -0
- package/template/asset-manifest.json +3 -0
- package/template/check-idioms.ts +1533 -0
- package/template/index.html +18 -0
- package/template/manifest-entry-modules-plugin.ts +53 -0
- package/template/package.json +62 -0
- package/template/public/jsm/libs/basis/basis_transcoder.js +19 -0
- package/template/public/jsm/libs/basis/basis_transcoder.wasm +0 -0
- package/template/public/jsm/libs/draco/gltf/draco_decoder.js +33 -0
- package/template/public/jsm/libs/draco/gltf/draco_decoder.wasm +0 -0
- package/template/public/jsm/libs/draco/gltf/draco_encoder.js +33 -0
- package/template/public/jsm/libs/draco/gltf/draco_wasm_wrapper.js +116 -0
- package/template/public/shaders/daylight-sky.frag.glsl +15 -0
- package/template/public/shaders/daylight-sky.vert.glsl +7 -0
- package/template/scripts/patch-drei-stats-gl.mjs +35 -0
- package/template/server/colyseus-setup.ts +111 -0
- package/template/server/loopback.ts +76 -0
- package/template/server/main.ts +78 -0
- package/template/server/rooms/arena-room.ts +488 -0
- package/template/server/rooms/game-room.ts +274 -0
- package/template/server/rooms.ts +15 -0
- package/template/server/tsconfig.json +19 -0
- package/template/src/bot/QaTester.tsx +35 -0
- package/template/src/bot/behaviors.ts +203 -0
- package/template/src/bot/bot-station.ts +192 -0
- package/template/src/bot/tester-run.ts +238 -0
- package/template/src/bot/tester-station.ts +193 -0
- package/template/src/components/environment/DaylightSky.tsx +54 -0
- package/template/src/components/environment/Ground.tsx +129 -0
- package/template/src/components/environment/SceneAtmosphere.tsx +14 -0
- package/template/src/components/environment/SoftGroundShadow.tsx +62 -0
- package/template/src/components/environment/SunShadowFit.tsx +141 -0
- package/template/src/contributions/README.md +98 -0
- package/template/src/contributions/analytics.analytics.tsx +26 -0
- package/template/src/contributions/data.document.tsx +35 -0
- package/template/src/contributions/pages.finder.ts +61 -0
- package/template/src/contributions/tester.inspector.tsx +64 -0
- package/template/src/contributions/use-game-modules.ts +80 -0
- package/template/src/data/README.md +17 -0
- package/template/src/input.ts +97 -0
- package/template/src/lib/audio/capability.json +4 -0
- package/template/src/lib/audio/sfx.ts +255 -0
- package/template/src/lib/react-root/capability.json +4 -0
- package/template/src/lib/react-root/index.ts +20 -0
- package/template/src/lib/react-root/react-root-adapter.tsx +57 -0
- package/template/src/lib/reflections/ReflectionProbe.tsx +201 -0
- package/template/src/lib/reflections/capability.json +4 -0
- package/template/src/lib/reflections/index.ts +19 -0
- package/template/src/lib/reflections/probe-controller.ts +75 -0
- package/template/src/lib/reflections/reflection-probe-registry.ts +402 -0
- package/template/src/lib/reflections/volume-reflection-material.ts +416 -0
- package/template/src/lib/static-batch/Frozen.tsx +91 -0
- package/template/src/lib/static-batch/capability.json +4 -0
- package/template/src/lib/static-batch/freeze.ts +579 -0
- package/template/src/lib/static-batch/index.ts +44 -0
- package/template/src/lib/static-batch/mutation-watch.ts +149 -0
- package/template/src/lib/static-batch/shadow-cache.ts +171 -0
- package/template/src/main.ts +63 -0
- package/template/src/manifest-entry-modules.d.ts +3 -0
- package/template/src/prefabs/HeroBox.stories.tsx +23 -0
- package/template/src/prefabs/HeroBox.tsx +35 -0
- package/template/src/scenes/MainScene.tsx +77 -0
- package/template/src/world.tsx +87 -0
- package/template/tsconfig.json +35 -0
- package/template/tsconfig.node.json +32 -0
- package/template/tsconfig.tools.json +22 -0
- package/template/validate-asset-content.ts +27 -0
- package/template/validate-assets.ts +60 -0
- package/template/validate-manifest.ts +55 -0
- package/template/vgai.adapter.ts +76 -0
- package/template/vgai.project.json +24 -0
- package/template/vite.config.ts +247 -0
- package/template-dotfiles/gitignore +63 -0
- package/workbench/src/media/game-cover.css +83 -0
- package/workbench/src/product.contribution.ts +188 -0
- package/workbench/src/vgaiGameSkew.ts +276 -0
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ADVANCED path: a material this factory creates and owns, which blends
|
|
3
|
+
* several probe volumes per fragment with box projection.
|
|
4
|
+
*
|
|
5
|
+
* Nothing reaches this except a material an author asked for by calling
|
|
6
|
+
* {@link createVolumeReflectionMaterial}. An ordinary captured reflection is a
|
|
7
|
+
* probe's PMREM texture assigned as a native `envMap` by the author (see
|
|
8
|
+
* `ReflectionProbe.tsx`), and no standard material is ever scanned, cloned or
|
|
9
|
+
* patched to get one. What you get HERE, and only by creating this material,
|
|
10
|
+
* is the model native `envMap` cannot express — one environment per FRAGMENT,
|
|
11
|
+
* so a wall crossing two rooms fades between their probes, an interior reads
|
|
12
|
+
* its projection box instead of a point capture, and a higher-priority probe
|
|
13
|
+
* wins outright inside an overlap.
|
|
14
|
+
*
|
|
15
|
+
* Native material controls stay native. It IS a `MeshStandardMaterial`:
|
|
16
|
+
* `color`, `roughness`, `metalness`, maps and `envMapIntensity` behave exactly
|
|
17
|
+
* as three defines them, the per-probe `intensity` prop is the library's own
|
|
18
|
+
* weighting on top, and where no probe applies the fragment falls back to
|
|
19
|
+
* three's unmodified functions over the material's or scene's environment.
|
|
20
|
+
* (`envMapRotation` applies to that fallback only — a local probe's
|
|
21
|
+
* orientation is its node's transform, which the box projection is expressed
|
|
22
|
+
* in.)
|
|
23
|
+
*
|
|
24
|
+
* **Probes of different resolutions blend together.** Three's own
|
|
25
|
+
* `textureCubeUV` finds a mip using constants the compiler derives from the
|
|
26
|
+
* ONE installed `envMap`; {@link cubeUvSamplingFunctions} is that same sampler
|
|
27
|
+
* with the atlas layout passed in per call, so each probe is sampled inside
|
|
28
|
+
* its own rectangle and the author never has to align resolutions or supply a
|
|
29
|
+
* matching scene environment.
|
|
30
|
+
*/
|
|
31
|
+
import {
|
|
32
|
+
baseIblFunctions,
|
|
33
|
+
createIblSentinelTexture,
|
|
34
|
+
IBL_WORLD_POSITION,
|
|
35
|
+
type IblOverride,
|
|
36
|
+
type IblOverrideShader,
|
|
37
|
+
overrideMaterialIbl,
|
|
38
|
+
} from '@volter/threejs-runtime/render/ibl-override-material';
|
|
39
|
+
import {
|
|
40
|
+
MeshPhysicalMaterial,
|
|
41
|
+
type MeshPhysicalMaterialParameters,
|
|
42
|
+
MeshStandardMaterial,
|
|
43
|
+
type MeshStandardMaterialParameters,
|
|
44
|
+
type Scene,
|
|
45
|
+
ShaderChunk,
|
|
46
|
+
type Texture,
|
|
47
|
+
Vector3,
|
|
48
|
+
type WebGLRenderer,
|
|
49
|
+
} from 'three';
|
|
50
|
+
import {
|
|
51
|
+
acquireReflectionProbeRegistry,
|
|
52
|
+
type ReflectionProbeRegistryLease,
|
|
53
|
+
type ReflectionProbeRuntime,
|
|
54
|
+
} from './reflection-probe-registry';
|
|
55
|
+
|
|
56
|
+
/** The uniform arrays are declared at a fixed length; this is that length's ceiling. */
|
|
57
|
+
const MAX_PROBES = 8;
|
|
58
|
+
|
|
59
|
+
export interface VolumeReflectionMaterialOptions extends MeshStandardMaterialParameters {
|
|
60
|
+
/** Ceiling on simultaneously blended probes; capped at {@link MAX_PROBES}. */
|
|
61
|
+
readonly maxProbes?: number;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface VolumeReflectionMaterialHandle<
|
|
65
|
+
T extends MeshStandardMaterial = MeshStandardMaterial,
|
|
66
|
+
> {
|
|
67
|
+
/** The material this factory created. Use it like any `MeshStandardMaterial`. */
|
|
68
|
+
readonly material: T;
|
|
69
|
+
/** Releases the registry lease and the material's own GPU resources. */
|
|
70
|
+
dispose(): void;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Three's CubeUV sampler with the atlas layout supplied per texture, so one
|
|
75
|
+
* material can sample probe atlases of different sizes. Every name is prefixed,
|
|
76
|
+
* because three's own copy of this chunk is in the same program and is what
|
|
77
|
+
* the native fallback still uses.
|
|
78
|
+
*/
|
|
79
|
+
function cubeUvSamplingFunctions(): string {
|
|
80
|
+
return ShaderChunk.cube_uv_reflection_fragment
|
|
81
|
+
.replace(
|
|
82
|
+
/\b(textureCubeUV|bilinearCubeUV)\(([^)]*)\)/g,
|
|
83
|
+
(_match, name: string, args: string) =>
|
|
84
|
+
`${name === 'textureCubeUV' ? 'vgaiTextureCubeUV' : 'vgaiBilinearCubeUV'}(${args.trim()}, ${args.includes('sampler2D') ? 'vec3 ' : ''}vgaiAtlasSize)`,
|
|
85
|
+
)
|
|
86
|
+
.replace(/\b(getFace|getUV|roughnessToMip)\b/g, 'vgai$1')
|
|
87
|
+
.replace(/\bcubeUV_(\w+)\b/g, 'vgaiCubeUV_$1')
|
|
88
|
+
.replaceAll('CUBEUV_MAX_MIP', 'vgaiAtlasSize.z')
|
|
89
|
+
.replaceAll('CUBEUV_TEXEL_WIDTH', 'vgaiAtlasSize.x')
|
|
90
|
+
.replaceAll('CUBEUV_TEXEL_HEIGHT', 'vgaiAtlasSize.y');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* `(texelWidth, texelHeight, maxMip)` for one PMREM atlas — three's own
|
|
95
|
+
* `generateCubeUVSize`, which reads the installed envMap's image height, asked
|
|
96
|
+
* per texture instead.
|
|
97
|
+
*/
|
|
98
|
+
function atlasSizeOf(texture: Texture | null): Vector3 {
|
|
99
|
+
const height = (texture?.image as { height?: number } | undefined)?.height ?? 0;
|
|
100
|
+
if (height <= 0) return new Vector3(0, 0, 0);
|
|
101
|
+
const maxMip = Math.log2(height) - 2;
|
|
102
|
+
return new Vector3(1 / (3 * Math.max(2 ** maxMip, 7 * 16)), 1 / height, maxMip);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function probeWeight(index: number): string {
|
|
106
|
+
return `
|
|
107
|
+
vec3 lp = (vgaiProbeWorldToLocal[${index}] * vec4(${IBL_WORLD_POSITION}, 1.0)).xyz;
|
|
108
|
+
float weight = 0.0;
|
|
109
|
+
if (vgaiProbeShape[${index}] < 0.5) {
|
|
110
|
+
vec3 edge = vgaiProbeExtents[${index}] - abs(lp);
|
|
111
|
+
if (all(greaterThanEqual(edge, vec3(0.0)))) {
|
|
112
|
+
float nearest = min(edge.x, min(edge.y, edge.z));
|
|
113
|
+
weight = vgaiProbeBlendDistance[${index}] > 0.0001
|
|
114
|
+
? clamp(nearest / vgaiProbeBlendDistance[${index}], 0.0, 1.0)
|
|
115
|
+
: 1.0;
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
float edge = vgaiProbeRadius[${index}] - length(lp);
|
|
119
|
+
if (edge >= 0.0) {
|
|
120
|
+
weight = vgaiProbeBlendDistance[${index}] > 0.0001
|
|
121
|
+
? clamp(edge / vgaiProbeBlendDistance[${index}], 0.0, 1.0)
|
|
122
|
+
: 1.0;
|
|
123
|
+
}
|
|
124
|
+
}`;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function probeWeightBlock(index: number): string {
|
|
128
|
+
return `
|
|
129
|
+
if (vgaiProbeReady[${index}] > 0.5) {${probeWeight(index)}
|
|
130
|
+
if (weight > 0.0) bestPriority = max(bestPriority, vgaiProbePriority[${index}]);
|
|
131
|
+
}`;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function probeSampleBlock(index: number, roughness: string, direction: string): string {
|
|
135
|
+
return `
|
|
136
|
+
if (vgaiProbeReady[${index}] > 0.5 && abs(vgaiProbePriority[${index}] - bestPriority) < 0.001) {${probeWeight(index)}
|
|
137
|
+
if (weight > 0.0) {
|
|
138
|
+
vec3 probeDirection = (vgaiProbeWorldToLocal[${index}] * vec4(${direction}, 0.0)).xyz;
|
|
139
|
+
if (vgaiProbeParallax[${index}] > 0.5) {
|
|
140
|
+
vec3 boxPos = lp - vgaiProbeParallaxOffset[${index}];
|
|
141
|
+
vec3 safeDirection = sign(probeDirection) * max(abs(probeDirection), vec3(0.00001));
|
|
142
|
+
vec3 rayMax = (vgaiProbeParallaxExtents[${index}] - boxPos) / safeDirection;
|
|
143
|
+
vec3 rayMin = (-vgaiProbeParallaxExtents[${index}] - boxPos) / safeDirection;
|
|
144
|
+
vec3 rayDistance = mix(rayMin, rayMax, greaterThan(safeDirection, vec3(0.0)));
|
|
145
|
+
float nearestFace = min(rayDistance.x, min(rayDistance.y, rayDistance.z));
|
|
146
|
+
probeDirection = boxPos + safeDirection * nearestFace
|
|
147
|
+
+ vgaiProbeParallaxOffset[${index}] - vgaiProbeCaptureOffset[${index}];
|
|
148
|
+
}
|
|
149
|
+
accumulated += vgaiTextureCubeUV(
|
|
150
|
+
vgaiProbeMap${index}, probeDirection, ${roughness}, vgaiProbeAtlasSize[${index}]
|
|
151
|
+
).rgb * vgaiProbeIntensity[${index}] * weight;
|
|
152
|
+
totalWeight += weight;
|
|
153
|
+
}
|
|
154
|
+
}`;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function volumeReflectionShader(probeCount: number): string {
|
|
158
|
+
const samplers = Array.from(
|
|
159
|
+
{ length: probeCount },
|
|
160
|
+
(_, index) => `uniform sampler2D vgaiProbeMap${index};`,
|
|
161
|
+
).join('\n');
|
|
162
|
+
const weights = Array.from({ length: probeCount }, (_, index) => probeWeightBlock(index)).join(
|
|
163
|
+
'\n',
|
|
164
|
+
);
|
|
165
|
+
const radiance = Array.from({ length: probeCount }, (_, index) =>
|
|
166
|
+
probeSampleBlock(index, 'roughness', 'worldReflect'),
|
|
167
|
+
).join('\n');
|
|
168
|
+
const irradiance = Array.from({ length: probeCount }, (_, index) =>
|
|
169
|
+
probeSampleBlock(index, '1.0', 'worldNormal'),
|
|
170
|
+
).join('\n');
|
|
171
|
+
return `${baseIblFunctions()}
|
|
172
|
+
${cubeUvSamplingFunctions()}
|
|
173
|
+
#ifdef USE_ENVMAP
|
|
174
|
+
uniform float vgaiProbeReady[${probeCount}];
|
|
175
|
+
uniform mat4 vgaiProbeWorldToLocal[${probeCount}];
|
|
176
|
+
uniform vec3 vgaiProbeExtents[${probeCount}];
|
|
177
|
+
uniform vec3 vgaiProbeParallaxExtents[${probeCount}];
|
|
178
|
+
uniform vec3 vgaiProbeParallaxOffset[${probeCount}];
|
|
179
|
+
uniform vec3 vgaiProbeCaptureOffset[${probeCount}];
|
|
180
|
+
uniform vec3 vgaiProbeAtlasSize[${probeCount}];
|
|
181
|
+
uniform float vgaiProbeShape[${probeCount}];
|
|
182
|
+
uniform float vgaiProbeRadius[${probeCount}];
|
|
183
|
+
uniform float vgaiProbeBlendDistance[${probeCount}];
|
|
184
|
+
uniform float vgaiProbePriority[${probeCount}];
|
|
185
|
+
uniform float vgaiProbeIntensity[${probeCount}];
|
|
186
|
+
uniform float vgaiProbeParallax[${probeCount}];
|
|
187
|
+
uniform float vgaiBaseEnvironment;
|
|
188
|
+
${samplers}
|
|
189
|
+
|
|
190
|
+
vec3 getIBLIrradiance(const in vec3 normal) {
|
|
191
|
+
#ifdef ENVMAP_TYPE_CUBE_UV
|
|
192
|
+
vec3 baseIrradiance = getBaseIBLIrradiance(normal) * vgaiBaseEnvironment;
|
|
193
|
+
vec3 worldNormal = inverseTransformDirection(normal, viewMatrix);
|
|
194
|
+
float bestPriority = -1000000.0;
|
|
195
|
+
${weights}
|
|
196
|
+
vec3 accumulated = vec3(0.0);
|
|
197
|
+
float totalWeight = 0.0;
|
|
198
|
+
${irradiance}
|
|
199
|
+
return totalWeight > 0.0
|
|
200
|
+
? PI * accumulated / totalWeight * envMapIntensity
|
|
201
|
+
: baseIrradiance;
|
|
202
|
+
#else
|
|
203
|
+
return getBaseIBLIrradiance(normal);
|
|
204
|
+
#endif
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
vec3 getIBLRadiance(const in vec3 viewDir, const in vec3 normal, const in float roughness) {
|
|
208
|
+
#ifdef ENVMAP_TYPE_CUBE_UV
|
|
209
|
+
vec3 baseRadiance = getBaseIBLRadiance(viewDir, normal, roughness) * vgaiBaseEnvironment;
|
|
210
|
+
vec3 reflected = reflect(-viewDir, normal);
|
|
211
|
+
reflected = normalize(mix(reflected, normal, roughness * roughness));
|
|
212
|
+
vec3 worldReflect = inverseTransformDirection(reflected, viewMatrix);
|
|
213
|
+
float bestPriority = -1000000.0;
|
|
214
|
+
${weights}
|
|
215
|
+
vec3 accumulated = vec3(0.0);
|
|
216
|
+
float totalWeight = 0.0;
|
|
217
|
+
${radiance}
|
|
218
|
+
return totalWeight > 0.0
|
|
219
|
+
? accumulated / totalWeight * envMapIntensity
|
|
220
|
+
: baseRadiance;
|
|
221
|
+
#else
|
|
222
|
+
return getBaseIBLRadiance(viewDir, normal, roughness);
|
|
223
|
+
#endif
|
|
224
|
+
}
|
|
225
|
+
#endif`;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function writeProbeUniforms(
|
|
229
|
+
shader: IblOverrideShader | null,
|
|
230
|
+
probes: readonly ReflectionProbeRuntime[],
|
|
231
|
+
baseEnvironment: boolean,
|
|
232
|
+
capturing: boolean,
|
|
233
|
+
): void {
|
|
234
|
+
if (!shader) return;
|
|
235
|
+
const values = <T>(name: string, value: T) => {
|
|
236
|
+
shader.uniforms[name] = { value };
|
|
237
|
+
};
|
|
238
|
+
values(
|
|
239
|
+
'vgaiProbeReady',
|
|
240
|
+
probes.map((probe) => Number(probe.ready && !capturing)),
|
|
241
|
+
);
|
|
242
|
+
values(
|
|
243
|
+
'vgaiProbeWorldToLocal',
|
|
244
|
+
probes.map((probe) => probe.worldToLocal),
|
|
245
|
+
);
|
|
246
|
+
values(
|
|
247
|
+
'vgaiProbeExtents',
|
|
248
|
+
probes.map((probe) => probe.extents),
|
|
249
|
+
);
|
|
250
|
+
values(
|
|
251
|
+
'vgaiProbeParallaxExtents',
|
|
252
|
+
probes.map((probe) => probe.parallaxExtents),
|
|
253
|
+
);
|
|
254
|
+
values(
|
|
255
|
+
'vgaiProbeParallaxOffset',
|
|
256
|
+
probes.map((probe) => probe.parallaxOffset),
|
|
257
|
+
);
|
|
258
|
+
values(
|
|
259
|
+
'vgaiProbeCaptureOffset',
|
|
260
|
+
probes.map((probe) => probe.captureOffset),
|
|
261
|
+
);
|
|
262
|
+
values(
|
|
263
|
+
'vgaiProbeAtlasSize',
|
|
264
|
+
probes.map((probe) => atlasSizeOf(probe.texture)),
|
|
265
|
+
);
|
|
266
|
+
values(
|
|
267
|
+
'vgaiProbeShape',
|
|
268
|
+
probes.map((probe) => Number(probe.mark.config.shape === 'sphere')),
|
|
269
|
+
);
|
|
270
|
+
values(
|
|
271
|
+
'vgaiProbeRadius',
|
|
272
|
+
probes.map((probe) => Math.max(0.01, probe.mark.config.radius)),
|
|
273
|
+
);
|
|
274
|
+
values(
|
|
275
|
+
'vgaiProbeBlendDistance',
|
|
276
|
+
probes.map((probe) => Math.max(0, probe.mark.config.blendDistance)),
|
|
277
|
+
);
|
|
278
|
+
values(
|
|
279
|
+
'vgaiProbePriority',
|
|
280
|
+
probes.map((probe) => probe.mark.config.priority),
|
|
281
|
+
);
|
|
282
|
+
values(
|
|
283
|
+
'vgaiProbeIntensity',
|
|
284
|
+
probes.map((probe) => Math.max(0, probe.mark.config.intensity)),
|
|
285
|
+
);
|
|
286
|
+
values(
|
|
287
|
+
'vgaiProbeParallax',
|
|
288
|
+
probes.map((probe) => Number(probe.mark.config.parallaxProjection)),
|
|
289
|
+
);
|
|
290
|
+
values('vgaiBaseEnvironment', baseEnvironment ? 1 : 0);
|
|
291
|
+
probes.forEach((probe, index) => {
|
|
292
|
+
values(`vgaiProbeMap${index}`, probe.texture);
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Create a `MeshStandardMaterial` that blends the scene's reflection probes
|
|
298
|
+
* per fragment. `options` are ordinary material parameters plus `maxProbes`.
|
|
299
|
+
*
|
|
300
|
+
* The material is this factory's: no existing material is mutated, and only
|
|
301
|
+
* meshes the author assigns it to are affected. Assigning `envMap` later works
|
|
302
|
+
* as usual and takes over the fallback term — the black texture that keeps
|
|
303
|
+
* three's IBL entry points compiled when there is no environment at all is
|
|
304
|
+
* installed behind that property and never replaces an assigned map.
|
|
305
|
+
*/
|
|
306
|
+
export function createVolumeReflectionMaterial(
|
|
307
|
+
renderer: WebGLRenderer,
|
|
308
|
+
scene: Scene,
|
|
309
|
+
options: VolumeReflectionMaterialOptions = {},
|
|
310
|
+
): VolumeReflectionMaterialHandle {
|
|
311
|
+
const { maxProbes, ...parameters } = options;
|
|
312
|
+
return ownVolumeReflectionMaterial(
|
|
313
|
+
renderer,
|
|
314
|
+
scene,
|
|
315
|
+
new MeshStandardMaterial(parameters),
|
|
316
|
+
maxProbes,
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export interface VolumeReflectionPhysicalMaterialOptions extends MeshPhysicalMaterialParameters {
|
|
321
|
+
readonly maxProbes?: number;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** The same explicit volume effect with Three's physical material controls. */
|
|
325
|
+
export function createVolumeReflectionPhysicalMaterial(
|
|
326
|
+
renderer: WebGLRenderer,
|
|
327
|
+
scene: Scene,
|
|
328
|
+
options: VolumeReflectionPhysicalMaterialOptions = {},
|
|
329
|
+
): VolumeReflectionMaterialHandle<MeshPhysicalMaterial> {
|
|
330
|
+
const { maxProbes, ...parameters } = options;
|
|
331
|
+
return ownVolumeReflectionMaterial(
|
|
332
|
+
renderer,
|
|
333
|
+
scene,
|
|
334
|
+
new MeshPhysicalMaterial(parameters),
|
|
335
|
+
maxProbes,
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function ownVolumeReflectionMaterial<T extends MeshStandardMaterial>(
|
|
340
|
+
renderer: WebGLRenderer,
|
|
341
|
+
scene: Scene,
|
|
342
|
+
material: T,
|
|
343
|
+
maxProbes: number | undefined,
|
|
344
|
+
): VolumeReflectionMaterialHandle<T> {
|
|
345
|
+
const limit = Math.min(MAX_PROBES, Math.max(1, Math.round(maxProbes ?? MAX_PROBES)));
|
|
346
|
+
const sentinel = createIblSentinelTexture();
|
|
347
|
+
let authoredEnvMap = material.envMap;
|
|
348
|
+
let override: IblOverride | null = null;
|
|
349
|
+
let installedCount = 0;
|
|
350
|
+
let warnedOverflow = false;
|
|
351
|
+
let eligible: readonly ReflectionProbeRuntime[] = [];
|
|
352
|
+
let isCapturing = false;
|
|
353
|
+
let lease: ReflectionProbeRegistryLease | null = acquireReflectionProbeRegistry(renderer, scene);
|
|
354
|
+
|
|
355
|
+
// Three deletes both IBL entry points from a program with no environment at
|
|
356
|
+
// all, so a probe-only material needs one native input present to keep them.
|
|
357
|
+
// The author's own value always wins, and `scene.environment` is left to
|
|
358
|
+
// three whenever it exists.
|
|
359
|
+
const hasBaseEnvironment = () => Boolean(authoredEnvMap ?? scene.environment);
|
|
360
|
+
Object.defineProperty(material, 'envMap', {
|
|
361
|
+
configurable: true,
|
|
362
|
+
enumerable: true,
|
|
363
|
+
get: () => authoredEnvMap ?? (scene.environment ? null : sentinel),
|
|
364
|
+
set: (value: Texture | null) => {
|
|
365
|
+
authoredEnvMap = value;
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
const uninstall = () => {
|
|
370
|
+
override?.restore();
|
|
371
|
+
override = null;
|
|
372
|
+
installedCount = 0;
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
const install = (count: number) => {
|
|
376
|
+
uninstall();
|
|
377
|
+
installedCount = count;
|
|
378
|
+
override = overrideMaterialIbl(material, {
|
|
379
|
+
fragment: () => volumeReflectionShader(count),
|
|
380
|
+
cacheKey: () => `vgai-volume-reflections:${count}`,
|
|
381
|
+
onCompile: (shader) =>
|
|
382
|
+
writeProbeUniforms(shader, eligible, hasBaseEnvironment(), isCapturing),
|
|
383
|
+
});
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
const unobserve = lease.registry.observe(
|
|
387
|
+
(probes: readonly ReflectionProbeRuntime[], capturing: boolean) => {
|
|
388
|
+
isCapturing = capturing;
|
|
389
|
+
eligible = probes.slice(0, limit);
|
|
390
|
+
if (probes.length > limit && !warnedOverflow) {
|
|
391
|
+
warnedOverflow = true;
|
|
392
|
+
// biome-ignore lint/suspicious/noConsole: the uniform arrays have a fixed ceiling; say which probes fell off it.
|
|
393
|
+
console.warn(
|
|
394
|
+
`[reflections] "${material.name || 'volume reflection material'}" blends at most ${limit} probes; ${probes.length - limit} more are in the scene and are not sampled.`,
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
if (eligible.length !== installedCount) {
|
|
398
|
+
if (eligible.length === 0) uninstall();
|
|
399
|
+
else install(eligible.length);
|
|
400
|
+
}
|
|
401
|
+
writeProbeUniforms(override?.shader ?? null, eligible, hasBaseEnvironment(), capturing);
|
|
402
|
+
},
|
|
403
|
+
);
|
|
404
|
+
|
|
405
|
+
return {
|
|
406
|
+
material,
|
|
407
|
+
dispose() {
|
|
408
|
+
unobserve();
|
|
409
|
+
uninstall();
|
|
410
|
+
sentinel.dispose();
|
|
411
|
+
material.dispose();
|
|
412
|
+
lease?.release();
|
|
413
|
+
lease = null;
|
|
414
|
+
},
|
|
415
|
+
};
|
|
416
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<Frozen>` — the DECLARATION that a subtree is mount-static scenery, and the
|
|
3
|
+
* one line that turns it into a handful of draw calls.
|
|
4
|
+
*
|
|
5
|
+
* ```tsx
|
|
6
|
+
* <Frozen name="Terminal">
|
|
7
|
+
* {panels.map((p) => (
|
|
8
|
+
* <mesh key={p.id} position={p.at} castShadow receiveShadow>
|
|
9
|
+
* <boxGeometry args={[p.w, p.h, 0.1]} />
|
|
10
|
+
* <meshStandardMaterial color="#c8ccd0" />
|
|
11
|
+
* </mesh>
|
|
12
|
+
* ))}
|
|
13
|
+
* </Frozen>
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Eight hundred panels stay eight hundred authored, named, selectable nodes —
|
|
17
|
+
* and become one or two draws. Nothing about how the scenery is WRITTEN
|
|
18
|
+
* changes; the wrapper is a statement about its lifetime, not a different way
|
|
19
|
+
* to build a world. `freeze.ts` is the mechanism and the place to read what
|
|
20
|
+
* gets collapsed and what is refused.
|
|
21
|
+
*
|
|
22
|
+
* ── THE CONTRACT ────────────────────────────────────────────────────────────
|
|
23
|
+
* Nothing under a `<Frozen>` may move, re-colour, unmount, or conditionally
|
|
24
|
+
* appear after mount. The batched copies are what you see; the originals are
|
|
25
|
+
* hidden, so a later change to one is simply never drawn. Reactive scenery —
|
|
26
|
+
* a signal that changes colour, a door that opens, anything driven by state —
|
|
27
|
+
* belongs OUTSIDE the wrapper, and the callsite splits exactly on that line.
|
|
28
|
+
* In a dev build, `mutation-watch.ts` samples the hidden originals and says so
|
|
29
|
+
* once if the contract breaks; a ship build pays nothing for that.
|
|
30
|
+
*
|
|
31
|
+
* A subtree inside the wrapper that must NOT be batched declares itself:
|
|
32
|
+
* `userData={{ staticBatch: false }}`. That is a statement of intent, so it is
|
|
33
|
+
* silent — unlike a mesh the batcher refuses on its own (transparent, skinned,
|
|
34
|
+
* multi-material…), which is aggregated into one console line per wrapper.
|
|
35
|
+
*
|
|
36
|
+
* The wrapper itself stays mobile: products are baked into ITS local space, so
|
|
37
|
+
* moving or rotating the `<Frozen>` group still moves the whole assembly.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
import type { ThreeElements } from '@react-three/fiber';
|
|
41
|
+
import { devBuildEnabled } from '@volter/game-runtime/runtime/dev-build';
|
|
42
|
+
import { type ReactNode, useLayoutEffect, useRef } from 'react';
|
|
43
|
+
import type * as THREE from 'three';
|
|
44
|
+
import { activateFrozenBatch, describeFrozenSkips, freezeSubtree, restoreFrozen } from './freeze';
|
|
45
|
+
import { watchFrozenMutations } from './mutation-watch';
|
|
46
|
+
|
|
47
|
+
export type FrozenProps = ThreeElements['group'] & {
|
|
48
|
+
/** Names the group, every console line about it, and the census row you
|
|
49
|
+
* would drill into. Worth setting: the advisory that sends people here
|
|
50
|
+
* names a subtree, and this is what makes that name resolve. */
|
|
51
|
+
readonly name?: string;
|
|
52
|
+
readonly children?: ReactNode;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export function Frozen({ name = 'Frozen', children, ...props }: FrozenProps) {
|
|
56
|
+
const group = useRef<THREE.Group>(null);
|
|
57
|
+
|
|
58
|
+
// useLayoutEffect, not useEffect: this runs AFTER the children have been
|
|
59
|
+
// attached to the group and BEFORE the browser paints, so no frame is ever
|
|
60
|
+
// drawn with both the originals and the batched copies visible.
|
|
61
|
+
useLayoutEffect(() => {
|
|
62
|
+
const root = group.current;
|
|
63
|
+
if (!root) return;
|
|
64
|
+
|
|
65
|
+
const batch = freezeSubtree(root, name);
|
|
66
|
+
// Degrade LOUDLY — a wrapper that silently declined most of its subtree
|
|
67
|
+
// looks identical to one that worked. Under the dev gate, though: this is
|
|
68
|
+
// an authoring signal (`vgai status` reports console warnings, which is
|
|
69
|
+
// where the building agent already looks), and a player's console is not
|
|
70
|
+
// where it belongs.
|
|
71
|
+
if (devBuildEnabled()) {
|
|
72
|
+
const skips = describeFrozenSkips(batch);
|
|
73
|
+
// biome-ignore lint/suspicious/noConsole: see above — this is the channel.
|
|
74
|
+
if (skips) console.warn(skips);
|
|
75
|
+
}
|
|
76
|
+
const watch = watchFrozenMutations(batch);
|
|
77
|
+
const deactivate = activateFrozenBatch(batch);
|
|
78
|
+
|
|
79
|
+
return () => {
|
|
80
|
+
watch.stop();
|
|
81
|
+
deactivate();
|
|
82
|
+
restoreFrozen(batch);
|
|
83
|
+
};
|
|
84
|
+
}, [name]);
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<group ref={group} name={name} {...props}>
|
|
88
|
+
{children}
|
|
89
|
+
</group>
|
|
90
|
+
);
|
|
91
|
+
}
|