@driftengine/core 3.61.0
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/LICENSE +202 -0
- package/NOTICE +9 -0
- package/README.md +9 -0
- package/dist/behavior/behaviorTree.d.ts +140 -0
- package/dist/behavior/behaviorTree.js +289 -0
- package/dist/build/shaderComments.d.ts +64 -0
- package/dist/build/shaderComments.js +0 -0
- package/dist/cinematic/player.d.ts +80 -0
- package/dist/cinematic/player.js +184 -0
- package/dist/cinematic/script.d.ts +63 -0
- package/dist/cinematic/script.js +141 -0
- package/dist/core/bootGate.d.ts +37 -0
- package/dist/core/bootGate.js +47 -0
- package/dist/core/loadTracker.d.ts +78 -0
- package/dist/core/loadTracker.js +106 -0
- package/dist/core/loop.d.ts +118 -0
- package/dist/core/loop.js +84 -0
- package/dist/core/messageQueue.d.ts +61 -0
- package/dist/core/messageQueue.js +104 -0
- package/dist/core/onceSet.d.ts +27 -0
- package/dist/core/onceSet.js +62 -0
- package/dist/core/preferences.d.ts +47 -0
- package/dist/core/preferences.js +140 -0
- package/dist/core/remoteSave.d.ts +154 -0
- package/dist/core/remoteSave.js +249 -0
- package/dist/core/rng.d.ts +64 -0
- package/dist/core/rng.js +72 -0
- package/dist/core/stepBudget.d.ts +91 -0
- package/dist/core/stepBudget.js +105 -0
- package/dist/core/storage.d.ts +52 -0
- package/dist/core/storage.js +85 -0
- package/dist/core/tickTrace.d.ts +72 -0
- package/dist/core/tickTrace.js +102 -0
- package/dist/core/timeCurve.d.ts +83 -0
- package/dist/core/timeCurve.js +107 -0
- package/dist/core/withDefaults.d.ts +21 -0
- package/dist/core/withDefaults.js +29 -0
- package/dist/dev/contactProbe.d.ts +41 -0
- package/dist/dev/contactProbe.js +58 -0
- package/dist/dev/fpsMeter.d.ts +45 -0
- package/dist/dev/fpsMeter.js +86 -0
- package/dist/environment/celestialClock.d.ts +141 -0
- package/dist/environment/celestialClock.js +262 -0
- package/dist/geometry/decal.d.ts +61 -0
- package/dist/geometry/decal.js +178 -0
- package/dist/geometry/filmPatch.d.ts +35 -0
- package/dist/geometry/filmPatch.js +112 -0
- package/dist/geometry/growable.d.ts +70 -0
- package/dist/geometry/growable.js +167 -0
- package/dist/geometry/lightVolume.d.ts +76 -0
- package/dist/geometry/lightVolume.js +65 -0
- package/dist/geometry/meshBuilder.d.ts +426 -0
- package/dist/geometry/meshBuilder.js +1184 -0
- package/dist/geometry/pixelFont.d.ts +59 -0
- package/dist/geometry/pixelFont.js +179 -0
- package/dist/geometry/ribbon.d.ts +101 -0
- package/dist/geometry/ribbon.js +546 -0
- package/dist/geometry/shellFill.d.ts +101 -0
- package/dist/geometry/shellFill.js +203 -0
- package/dist/geometry/spline.d.ts +162 -0
- package/dist/geometry/spline.js +527 -0
- package/dist/geometry/tangents.d.ts +30 -0
- package/dist/geometry/tangents.js +142 -0
- package/dist/geometry/textMesh.d.ts +51 -0
- package/dist/geometry/textMesh.js +57 -0
- package/dist/geometry/treeBuilder.d.ts +37 -0
- package/dist/geometry/treeBuilder.js +56 -0
- package/dist/host/display.d.ts +135 -0
- package/dist/host/display.js +114 -0
- package/dist/host/files.d.ts +25 -0
- package/dist/host/files.js +44 -0
- package/dist/host/lifecycle.d.ts +45 -0
- package/dist/host/lifecycle.js +28 -0
- package/dist/host/platformServices.d.ts +23 -0
- package/dist/host/platformServices.js +1 -0
- package/dist/host/screen.d.ts +49 -0
- package/dist/host/screen.js +90 -0
- package/dist/index.d.ts +289 -0
- package/dist/index.js +320 -0
- package/dist/input/actionMap.d.ts +181 -0
- package/dist/input/actionMap.js +314 -0
- package/dist/input/activeDevice.d.ts +55 -0
- package/dist/input/activeDevice.js +83 -0
- package/dist/input/gamepadIdentity.d.ts +43 -0
- package/dist/input/gamepadIdentity.js +108 -0
- package/dist/input/gamepadMapping.d.ts +56 -0
- package/dist/input/gamepadMapping.js +91 -0
- package/dist/input/input.d.ts +281 -0
- package/dist/input/input.js +703 -0
- package/dist/input/inputHarness.d.ts +42 -0
- package/dist/input/inputHarness.js +193 -0
- package/dist/input/rightGesture.d.ts +57 -0
- package/dist/input/rightGesture.js +49 -0
- package/dist/input/rumble.d.ts +71 -0
- package/dist/input/rumble.js +119 -0
- package/dist/input/touchControls.d.ts +138 -0
- package/dist/input/touchControls.js +352 -0
- package/dist/input/typingTarget.d.ts +6 -0
- package/dist/input/typingTarget.js +27 -0
- package/dist/math/bounds.d.ts +61 -0
- package/dist/math/bounds.js +121 -0
- package/dist/math/color.d.ts +8 -0
- package/dist/math/color.js +35 -0
- package/dist/math/exact.d.ts +66 -0
- package/dist/math/exact.js +262 -0
- package/dist/math/frustum.d.ts +44 -0
- package/dist/math/frustum.js +90 -0
- package/dist/math/intersect.d.ts +76 -0
- package/dist/math/intersect.js +185 -0
- package/dist/math/scalar.d.ts +51 -0
- package/dist/math/scalar.js +99 -0
- package/dist/math/spring.d.ts +59 -0
- package/dist/math/spring.js +88 -0
- package/dist/nav/navGraph.d.ts +71 -0
- package/dist/nav/navGraph.js +111 -0
- package/dist/nav/navPath.d.ts +93 -0
- package/dist/nav/navPath.js +162 -0
- package/dist/nav/navSearch.d.ts +74 -0
- package/dist/nav/navSearch.js +198 -0
- package/dist/physics/boxSurface.d.ts +48 -0
- package/dist/physics/boxSurface.js +73 -0
- package/dist/physics/colliderSurface.d.ts +46 -0
- package/dist/physics/colliderSurface.js +146 -0
- package/dist/physics/compositeSurface.d.ts +33 -0
- package/dist/physics/compositeSurface.js +108 -0
- package/dist/physics/heightSurface.d.ts +103 -0
- package/dist/physics/heightSurface.js +153 -0
- package/dist/physics/ribbonSurface.d.ts +239 -0
- package/dist/physics/ribbonSurface.js +522 -0
- package/dist/render/ambientOcclusionPass.d.ts +53 -0
- package/dist/render/ambientOcclusionPass.js +179 -0
- package/dist/render/areaLights.d.ts +116 -0
- package/dist/render/areaLights.js +91 -0
- package/dist/render/areaShadowSet.d.ts +184 -0
- package/dist/render/areaShadowSet.js +277 -0
- package/dist/render/atmosphere.d.ts +94 -0
- package/dist/render/atmosphere.js +91 -0
- package/dist/render/backend/api.d.ts +496 -0
- package/dist/render/backend/api.js +1 -0
- package/dist/render/backend/budget.d.ts +82 -0
- package/dist/render/backend/budget.js +99 -0
- package/dist/render/backend/createRenderer.d.ts +135 -0
- package/dist/render/backend/createRenderer.js +201 -0
- package/dist/render/backend/deadline.d.ts +24 -0
- package/dist/render/backend/deadline.js +38 -0
- package/dist/render/backend/probe.d.ts +30 -0
- package/dist/render/backend/probe.js +129 -0
- package/dist/render/backend/select.d.ts +70 -0
- package/dist/render/backend/select.js +249 -0
- package/dist/render/backend/timer.d.ts +50 -0
- package/dist/render/backend/timer.js +1 -0
- package/dist/render/backend/webgl2/instanced.d.ts +21 -0
- package/dist/render/backend/webgl2/instanced.js +42 -0
- package/dist/render/backend/webgl2/morphTexture.d.ts +21 -0
- package/dist/render/backend/webgl2/morphTexture.js +55 -0
- package/dist/render/backend/webgl2/renderer.d.ts +3027 -0
- package/dist/render/backend/webgl2/renderer.js +6041 -0
- package/dist/render/backend/webgl2/skinPaletteTexture.d.ts +32 -0
- package/dist/render/backend/webgl2/skinPaletteTexture.js +68 -0
- package/dist/render/backend/webgpu/boltPass.d.ts +42 -0
- package/dist/render/backend/webgpu/boltPass.js +160 -0
- package/dist/render/backend/webgpu/buffers.d.ts +159 -0
- package/dist/render/backend/webgpu/buffers.js +402 -0
- package/dist/render/backend/webgpu/causticsPass.d.ts +36 -0
- package/dist/render/backend/webgpu/causticsPass.js +138 -0
- package/dist/render/backend/webgpu/clusterBinner.d.ts +51 -0
- package/dist/render/backend/webgpu/clusterBinner.js +206 -0
- package/dist/render/backend/webgpu/depthPass.d.ts +114 -0
- package/dist/render/backend/webgpu/depthPass.js +228 -0
- package/dist/render/backend/webgpu/device.d.ts +52 -0
- package/dist/render/backend/webgpu/device.js +121 -0
- package/dist/render/backend/webgpu/drawCommand.d.ts +43 -0
- package/dist/render/backend/webgpu/drawCommand.js +54 -0
- package/dist/render/backend/webgpu/environmentTexels.d.ts +28 -0
- package/dist/render/backend/webgpu/environmentTexels.js +79 -0
- package/dist/render/backend/webgpu/filmPass.d.ts +29 -0
- package/dist/render/backend/webgpu/filmPass.js +97 -0
- package/dist/render/backend/webgpu/flatPass.d.ts +213 -0
- package/dist/render/backend/webgpu/flatPass.js +482 -0
- package/dist/render/backend/webgpu/flockPass.d.ts +34 -0
- package/dist/render/backend/webgpu/flockPass.js +129 -0
- package/dist/render/backend/webgpu/gpuTimestamps.d.ts +94 -0
- package/dist/render/backend/webgpu/gpuTimestamps.js +213 -0
- package/dist/render/backend/webgpu/insetPass.d.ts +19 -0
- package/dist/render/backend/webgpu/insetPass.js +108 -0
- package/dist/render/backend/webgpu/instanced.d.ts +27 -0
- package/dist/render/backend/webgpu/instanced.js +49 -0
- package/dist/render/backend/webgpu/lightVolumePass.d.ts +75 -0
- package/dist/render/backend/webgpu/lightVolumePass.js +154 -0
- package/dist/render/backend/webgpu/linePass.d.ts +90 -0
- package/dist/render/backend/webgpu/linePass.js +220 -0
- package/dist/render/backend/webgpu/morphTexture.d.ts +18 -0
- package/dist/render/backend/webgpu/morphTexture.js +51 -0
- package/dist/render/backend/webgpu/panelPass.d.ts +37 -0
- package/dist/render/backend/webgpu/panelPass.js +114 -0
- package/dist/render/backend/webgpu/particlePass.d.ts +89 -0
- package/dist/render/backend/webgpu/particlePass.js +280 -0
- package/dist/render/backend/webgpu/pipelineCache.d.ts +93 -0
- package/dist/render/backend/webgpu/pipelineCache.js +140 -0
- package/dist/render/backend/webgpu/plumePass.d.ts +69 -0
- package/dist/render/backend/webgpu/plumePass.js +213 -0
- package/dist/render/backend/webgpu/pointShadowPass.d.ts +88 -0
- package/dist/render/backend/webgpu/pointShadowPass.js +280 -0
- package/dist/render/backend/webgpu/postPass.d.ts +342 -0
- package/dist/render/backend/webgpu/postPass.js +366 -0
- package/dist/render/backend/webgpu/probePass.d.ts +108 -0
- package/dist/render/backend/webgpu/probePass.js +188 -0
- package/dist/render/backend/webgpu/reflectionPass.d.ts +29 -0
- package/dist/render/backend/webgpu/reflectionPass.js +87 -0
- package/dist/render/backend/webgpu/renderer.d.ts +3082 -0
- package/dist/render/backend/webgpu/renderer.js +10911 -0
- package/dist/render/backend/webgpu/scatterPass.d.ts +95 -0
- package/dist/render/backend/webgpu/scatterPass.js +266 -0
- package/dist/render/backend/webgpu/sdfTextPass.d.ts +86 -0
- package/dist/render/backend/webgpu/sdfTextPass.js +190 -0
- package/dist/render/backend/webgpu/shaderModules.d.ts +9 -0
- package/dist/render/backend/webgpu/shaderModules.js +45 -0
- package/dist/render/backend/webgpu/shaders/clusterBin.wgsl.d.ts +23 -0
- package/dist/render/backend/webgpu/shaders/clusterBin.wgsl.js +208 -0
- package/dist/render/backend/webgpu/skinPaletteRing.d.ts +67 -0
- package/dist/render/backend/webgpu/skinPaletteRing.js +97 -0
- package/dist/render/backend/webgpu/skinPaletteTexture.d.ts +17 -0
- package/dist/render/backend/webgpu/skinPaletteTexture.js +68 -0
- package/dist/render/backend/webgpu/skyPass.d.ts +102 -0
- package/dist/render/backend/webgpu/skyPass.js +70 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +41 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.js +228 -0
- package/dist/render/backend/webgpu/textPass.d.ts +73 -0
- package/dist/render/backend/webgpu/textPass.js +190 -0
- package/dist/render/backend/webgpu/uniformRing.d.ts +133 -0
- package/dist/render/backend/webgpu/uniformRing.js +208 -0
- package/dist/render/backend/webgpu/waterPass.d.ts +73 -0
- package/dist/render/backend/webgpu/waterPass.js +160 -0
- package/dist/render/backend/webgpu/windStreakPass.d.ts +46 -0
- package/dist/render/backend/webgpu/windStreakPass.js +153 -0
- package/dist/render/billboard.d.ts +27 -0
- package/dist/render/billboard.js +79 -0
- package/dist/render/bloomChain.d.ts +66 -0
- package/dist/render/bloomChain.js +83 -0
- package/dist/render/bloomPass.d.ts +54 -0
- package/dist/render/bloomPass.js +219 -0
- package/dist/render/boltBatch.d.ts +39 -0
- package/dist/render/boltBatch.js +121 -0
- package/dist/render/boltPool.d.ts +135 -0
- package/dist/render/boltPool.js +259 -0
- package/dist/render/boom.d.ts +46 -0
- package/dist/render/boom.js +81 -0
- package/dist/render/camera.d.ts +119 -0
- package/dist/render/camera.js +304 -0
- package/dist/render/causticsRenderer.d.ts +63 -0
- package/dist/render/causticsRenderer.js +119 -0
- package/dist/render/cinematicCamera.d.ts +102 -0
- package/dist/render/cinematicCamera.js +227 -0
- package/dist/render/clusteredLights.d.ts +260 -0
- package/dist/render/clusteredLights.js +479 -0
- package/dist/render/colourGrade.d.ts +62 -0
- package/dist/render/colourGrade.js +91 -0
- package/dist/render/compute.d.ts +74 -0
- package/dist/render/compute.js +8 -0
- package/dist/render/contextLoss.d.ts +32 -0
- package/dist/render/contextLoss.js +46 -0
- package/dist/render/debugLines.d.ts +75 -0
- package/dist/render/debugLines.js +281 -0
- package/dist/render/decalPass.d.ts +34 -0
- package/dist/render/decalPass.js +103 -0
- package/dist/render/decalProjector.d.ts +140 -0
- package/dist/render/decalProjector.js +282 -0
- package/dist/render/decalQueue.d.ts +53 -0
- package/dist/render/decalQueue.js +87 -0
- package/dist/render/depthConvention.d.ts +314 -0
- package/dist/render/depthConvention.js +346 -0
- package/dist/render/drawingBuffer.d.ts +52 -0
- package/dist/render/drawingBuffer.js +67 -0
- package/dist/render/emptyTexture.d.ts +60 -0
- package/dist/render/emptyTexture.js +103 -0
- package/dist/render/envProbeArray.d.ts +85 -0
- package/dist/render/envProbeArray.js +164 -0
- package/dist/render/equirectToCube.d.ts +54 -0
- package/dist/render/equirectToCube.js +123 -0
- package/dist/render/flockGeometry.d.ts +23 -0
- package/dist/render/flockGeometry.js +43 -0
- package/dist/render/flockRenderer.d.ts +37 -0
- package/dist/render/flockRenderer.js +70 -0
- package/dist/render/frame/arena.d.ts +32 -0
- package/dist/render/frame/arena.js +65 -0
- package/dist/render/frame/index.d.ts +18 -0
- package/dist/render/frame/index.js +4 -0
- package/dist/render/frame/replay.d.ts +34 -0
- package/dist/render/frame/replay.js +48 -0
- package/dist/render/frame/resources.d.ts +25 -0
- package/dist/render/frame/resources.js +55 -0
- package/dist/render/frame/schedule.d.ts +37 -0
- package/dist/render/frame/schedule.js +61 -0
- package/dist/render/frameView.d.ts +19 -0
- package/dist/render/frameView.js +1 -0
- package/dist/render/gizmo.d.ts +236 -0
- package/dist/render/gizmo.js +727 -0
- package/dist/render/globalMedium.d.ts +124 -0
- package/dist/render/globalMedium.js +100 -0
- package/dist/render/globalMediumPass.d.ts +101 -0
- package/dist/render/globalMediumPass.js +250 -0
- package/dist/render/gpuCapability.d.ts +111 -0
- package/dist/render/gpuCapability.js +194 -0
- package/dist/render/gpuTimer.d.ts +87 -0
- package/dist/render/gpuTimer.js +145 -0
- package/dist/render/halfFloat.d.ts +4 -0
- package/dist/render/halfFloat.js +38 -0
- package/dist/render/handleRegistry.d.ts +54 -0
- package/dist/render/handleRegistry.js +84 -0
- package/dist/render/iesProfile.d.ts +64 -0
- package/dist/render/iesProfile.js +179 -0
- package/dist/render/imageTexels.d.ts +50 -0
- package/dist/render/imageTexels.js +91 -0
- package/dist/render/instancedMesh.d.ts +48 -0
- package/dist/render/instancedMesh.js +127 -0
- package/dist/render/instances.d.ts +69 -0
- package/dist/render/instances.js +52 -0
- package/dist/render/lightBudget.d.ts +397 -0
- package/dist/render/lightBudget.js +524 -0
- package/dist/render/lightMatrix.d.ts +3 -0
- package/dist/render/lightMatrix.js +45 -0
- package/dist/render/lightVolumeDraw.d.ts +132 -0
- package/dist/render/lightVolumeDraw.js +181 -0
- package/dist/render/lineBatch.d.ts +60 -0
- package/dist/render/lineBatch.js +160 -0
- package/dist/render/linePoints.d.ts +33 -0
- package/dist/render/linePoints.js +46 -0
- package/dist/render/livePointShadowSet.d.ts +72 -0
- package/dist/render/livePointShadowSet.js +258 -0
- package/dist/render/lod.d.ts +35 -0
- package/dist/render/lod.js +65 -0
- package/dist/render/mesh.d.ts +177 -0
- package/dist/render/mesh.js +466 -0
- package/dist/render/occlusion.d.ts +81 -0
- package/dist/render/occlusion.js +378 -0
- package/dist/render/oitPass.d.ts +67 -0
- package/dist/render/oitPass.js +213 -0
- package/dist/render/orderIndependent.d.ts +92 -0
- package/dist/render/orderIndependent.js +108 -0
- package/dist/render/particleBatch.d.ts +140 -0
- package/dist/render/particleBatch.js +186 -0
- package/dist/render/particleMaterial.d.ts +54 -0
- package/dist/render/particleMaterial.js +42 -0
- package/dist/render/particlePool.d.ts +124 -0
- package/dist/render/particlePool.js +182 -0
- package/dist/render/pass.d.ts +195 -0
- package/dist/render/pass.js +9 -0
- package/dist/render/passTarget.d.ts +86 -0
- package/dist/render/passTarget.js +121 -0
- package/dist/render/pickable.d.ts +31 -0
- package/dist/render/pickable.js +172 -0
- package/dist/render/planarReflection.d.ts +59 -0
- package/dist/render/planarReflection.js +194 -0
- package/dist/render/planarReflectionDraw.d.ts +31 -0
- package/dist/render/planarReflectionDraw.js +65 -0
- package/dist/render/plumeGeometry.d.ts +25 -0
- package/dist/render/plumeGeometry.js +61 -0
- package/dist/render/plumeMaterial.d.ts +31 -0
- package/dist/render/plumeMaterial.js +64 -0
- package/dist/render/plumeRenderer.d.ts +96 -0
- package/dist/render/plumeRenderer.js +185 -0
- package/dist/render/pointLightSelection.d.ts +175 -0
- package/dist/render/pointLightSelection.js +301 -0
- package/dist/render/pointShadowArray.d.ts +95 -0
- package/dist/render/pointShadowArray.js +219 -0
- package/dist/render/pointShadowBudget.d.ts +118 -0
- package/dist/render/pointShadowBudget.js +221 -0
- package/dist/render/pointShadowImage.d.ts +265 -0
- package/dist/render/pointShadowImage.js +339 -0
- package/dist/render/pointShadowMap.d.ts +93 -0
- package/dist/render/pointShadowMap.js +167 -0
- package/dist/render/pointShadowSystem.d.ts +195 -0
- package/dist/render/pointShadowSystem.js +336 -0
- package/dist/render/prefilterEnvMap.d.ts +124 -0
- package/dist/render/prefilterEnvMap.js +146 -0
- package/dist/render/prefilterPass.d.ts +44 -0
- package/dist/render/prefilterPass.js +98 -0
- package/dist/render/probeGrid.d.ts +122 -0
- package/dist/render/probeGrid.js +174 -0
- package/dist/render/rainField.d.ts +99 -0
- package/dist/render/rainField.js +168 -0
- package/dist/render/reflectionProbe.d.ts +188 -0
- package/dist/render/reflectionProbe.js +437 -0
- package/dist/render/renderQuality.d.ts +699 -0
- package/dist/render/renderQuality.js +293 -0
- package/dist/render/rendererHarness.d.ts +39 -0
- package/dist/render/rendererHarness.js +185 -0
- package/dist/render/resolutionGovernor.d.ts +107 -0
- package/dist/render/resolutionGovernor.js +144 -0
- package/dist/render/scatterDeform.d.ts +17 -0
- package/dist/render/scatterDeform.js +46 -0
- package/dist/render/sceneTarget.d.ts +288 -0
- package/dist/render/sceneTarget.js +856 -0
- package/dist/render/screenSpaceReflection.d.ts +233 -0
- package/dist/render/screenSpaceReflection.js +415 -0
- package/dist/render/sdfFont.d.ts +77 -0
- package/dist/render/sdfFont.js +86 -0
- package/dist/render/sdfTextLayout.d.ts +46 -0
- package/dist/render/sdfTextLayout.js +145 -0
- package/dist/render/sdfTextRenderer.d.ts +75 -0
- package/dist/render/sdfTextRenderer.js +194 -0
- package/dist/render/seaState.d.ts +25 -0
- package/dist/render/seaState.js +34 -0
- package/dist/render/segmentQuads.d.ts +29 -0
- package/dist/render/segmentQuads.js +75 -0
- package/dist/render/shader.d.ts +5 -0
- package/dist/render/shader.js +172 -0
- package/dist/render/shaders/ambientOcclusion.d.ts +45 -0
- package/dist/render/shaders/ambientOcclusion.js +352 -0
- package/dist/render/shaders/arcane.d.ts +19 -0
- package/dist/render/shaders/arcane.js +102 -0
- package/dist/render/shaders/bloom.d.ts +70 -0
- package/dist/render/shaders/bloom.js +227 -0
- package/dist/render/shaders/bolt.d.ts +17 -0
- package/dist/render/shaders/bolt.js +161 -0
- package/dist/render/shaders/caustics.d.ts +38 -0
- package/dist/render/shaders/caustics.js +167 -0
- package/dist/render/shaders/conditionals.d.ts +21 -0
- package/dist/render/shaders/conditionals.js +55 -0
- package/dist/render/shaders/decalProject.d.ts +25 -0
- package/dist/render/shaders/decalProject.js +125 -0
- package/dist/render/shaders/depth.d.ts +14 -0
- package/dist/render/shaders/depth.js +114 -0
- package/dist/render/shaders/depthOfField.d.ts +41 -0
- package/dist/render/shaders/depthOfField.js +139 -0
- package/dist/render/shaders/film.d.ts +15 -0
- package/dist/render/shaders/film.js +283 -0
- package/dist/render/shaders/fire.d.ts +12 -0
- package/dist/render/shaders/fire.js +178 -0
- package/dist/render/shaders/flat/directionalShadow.d.ts +1 -0
- package/dist/render/shaders/flat/directionalShadow.js +195 -0
- package/dist/render/shaders/flat/index.d.ts +135 -0
- package/dist/render/shaders/flat/index.js +387 -0
- package/dist/render/shaders/flat/lobes.d.ts +1 -0
- package/dist/render/shaders/flat/lobes.js +398 -0
- package/dist/render/shaders/flat/main.d.ts +2 -0
- package/dist/render/shaders/flat/main.js +1630 -0
- package/dist/render/shaders/flat/pointShadow.d.ts +1 -0
- package/dist/render/shaders/flat/pointShadow.js +322 -0
- package/dist/render/shaders/flat/preamble.d.ts +15 -0
- package/dist/render/shaders/flat/preamble.js +864 -0
- package/dist/render/shaders/flat/probeGrid.d.ts +21 -0
- package/dist/render/shaders/flat/probeGrid.js +151 -0
- package/dist/render/shaders/flat/surface.d.ts +2 -0
- package/dist/render/shaders/flat/surface.js +40 -0
- package/dist/render/shaders/flock.d.ts +11 -0
- package/dist/render/shaders/flock.js +102 -0
- package/dist/render/shaders/fog.d.ts +37 -0
- package/dist/render/shaders/fog.js +98 -0
- package/dist/render/shaders/fullscreen.d.ts +16 -0
- package/dist/render/shaders/fullscreen.js +27 -0
- package/dist/render/shaders/generated/ambientOcclusion.wgsl.d.ts +65 -0
- package/dist/render/shaders/generated/ambientOcclusion.wgsl.js +71 -0
- package/dist/render/shaders/generated/arcane.wgsl.d.ts +90 -0
- package/dist/render/shaders/generated/arcane.wgsl.js +96 -0
- package/dist/render/shaders/generated/bloom.wgsl.d.ts +69 -0
- package/dist/render/shaders/generated/bloom.wgsl.js +75 -0
- package/dist/render/shaders/generated/bolt.wgsl.d.ts +118 -0
- package/dist/render/shaders/generated/bolt.wgsl.js +124 -0
- package/dist/render/shaders/generated/caustics.wgsl.d.ts +118 -0
- package/dist/render/shaders/generated/caustics.wgsl.js +124 -0
- package/dist/render/shaders/generated/decalProject.wgsl.d.ts +61 -0
- package/dist/render/shaders/generated/decalProject.wgsl.js +67 -0
- package/dist/render/shaders/generated/depth.wgsl.d.ts +131 -0
- package/dist/render/shaders/generated/depth.wgsl.js +137 -0
- package/dist/render/shaders/generated/film.wgsl.d.ts +134 -0
- package/dist/render/shaders/generated/film.wgsl.js +140 -0
- package/dist/render/shaders/generated/fire.wgsl.d.ts +128 -0
- package/dist/render/shaders/generated/fire.wgsl.js +134 -0
- package/dist/render/shaders/generated/flat.wgsl.d.ts +9163 -0
- package/dist/render/shaders/generated/flat.wgsl.js +9192 -0
- package/dist/render/shaders/generated/flock.wgsl.d.ts +73 -0
- package/dist/render/shaders/generated/flock.wgsl.js +79 -0
- package/dist/render/shaders/generated/fullscreen.wgsl.d.ts +12 -0
- package/dist/render/shaders/generated/fullscreen.wgsl.js +18 -0
- package/dist/render/shaders/generated/globalMedium.wgsl.d.ts +130 -0
- package/dist/render/shaders/generated/globalMedium.wgsl.js +136 -0
- package/dist/render/shaders/generated/lightVolume.wgsl.d.ts +230 -0
- package/dist/render/shaders/generated/lightVolume.wgsl.js +239 -0
- package/dist/render/shaders/generated/line.wgsl.d.ts +128 -0
- package/dist/render/shaders/generated/line.wgsl.js +134 -0
- package/dist/render/shaders/generated/octahedralResolve.wgsl.d.ts +51 -0
- package/dist/render/shaders/generated/octahedralResolve.wgsl.js +57 -0
- package/dist/render/shaders/generated/oitResolve.wgsl.d.ts +23 -0
- package/dist/render/shaders/generated/oitResolve.wgsl.js +29 -0
- package/dist/render/shaders/generated/panel.wgsl.d.ts +48 -0
- package/dist/render/shaders/generated/panel.wgsl.js +54 -0
- package/dist/render/shaders/generated/particle.wgsl.d.ts +332 -0
- package/dist/render/shaders/generated/particle.wgsl.js +338 -0
- package/dist/render/shaders/generated/prefilter.wgsl.d.ts +61 -0
- package/dist/render/shaders/generated/prefilter.wgsl.js +67 -0
- package/dist/render/shaders/generated/rush.wgsl.d.ts +131 -0
- package/dist/render/shaders/generated/rush.wgsl.js +137 -0
- package/dist/render/shaders/generated/scatter.wgsl.d.ts +195 -0
- package/dist/render/shaders/generated/scatter.wgsl.js +201 -0
- package/dist/render/shaders/generated/sdfText.wgsl.d.ts +69 -0
- package/dist/render/shaders/generated/sdfText.wgsl.js +75 -0
- package/dist/render/shaders/generated/sky.wgsl.d.ts +100 -0
- package/dist/render/shaders/generated/sky.wgsl.js +106 -0
- package/dist/render/shaders/generated/smoke.wgsl.d.ts +85 -0
- package/dist/render/shaders/generated/smoke.wgsl.js +91 -0
- package/dist/render/shaders/generated/ssrResolve.wgsl.d.ts +18 -0
- package/dist/render/shaders/generated/ssrResolve.wgsl.js +24 -0
- package/dist/render/shaders/generated/ssrTrace.wgsl.d.ts +86 -0
- package/dist/render/shaders/generated/ssrTrace.wgsl.js +92 -0
- package/dist/render/shaders/generated/temporalResolve.wgsl.d.ts +46 -0
- package/dist/render/shaders/generated/temporalResolve.wgsl.js +52 -0
- package/dist/render/shaders/generated/text.wgsl.d.ts +98 -0
- package/dist/render/shaders/generated/text.wgsl.js +104 -0
- package/dist/render/shaders/generated/water.wgsl.d.ts +247 -0
- package/dist/render/shaders/generated/water.wgsl.js +253 -0
- package/dist/render/shaders/generated/windStreaks.wgsl.d.ts +73 -0
- package/dist/render/shaders/generated/windStreaks.wgsl.js +79 -0
- package/dist/render/shaders/gerstner.d.ts +21 -0
- package/dist/render/shaders/gerstner.js +110 -0
- package/dist/render/shaders/globalMedium.d.ts +56 -0
- package/dist/render/shaders/globalMedium.js +393 -0
- package/dist/render/shaders/lightVolume.d.ts +61 -0
- package/dist/render/shaders/lightVolume.js +527 -0
- package/dist/render/shaders/line.d.ts +18 -0
- package/dist/render/shaders/line.js +122 -0
- package/dist/render/shaders/morph.d.ts +26 -0
- package/dist/render/shaders/morph.js +61 -0
- package/dist/render/shaders/octahedral.d.ts +76 -0
- package/dist/render/shaders/octahedral.js +161 -0
- package/dist/render/shaders/octahedralResolve.d.ts +25 -0
- package/dist/render/shaders/octahedralResolve.js +81 -0
- package/dist/render/shaders/oitResolve.d.ts +17 -0
- package/dist/render/shaders/oitResolve.js +42 -0
- package/dist/render/shaders/outputTransform.d.ts +37 -0
- package/dist/render/shaders/outputTransform.js +106 -0
- package/dist/render/shaders/panel.d.ts +17 -0
- package/dist/render/shaders/panel.js +50 -0
- package/dist/render/shaders/particle.d.ts +82 -0
- package/dist/render/shaders/particle.js +431 -0
- package/dist/render/shaders/prefilter.d.ts +37 -0
- package/dist/render/shaders/prefilter.js +276 -0
- package/dist/render/shaders/rush.d.ts +21 -0
- package/dist/render/shaders/rush.js +355 -0
- package/dist/render/shaders/scatter.d.ts +14 -0
- package/dist/render/shaders/scatter.js +206 -0
- package/dist/render/shaders/sdfText.d.ts +9 -0
- package/dist/render/shaders/sdfText.js +65 -0
- package/dist/render/shaders/skinning.d.ts +17 -0
- package/dist/render/shaders/skinning.js +59 -0
- package/dist/render/shaders/sky.d.ts +10 -0
- package/dist/render/shaders/sky.js +242 -0
- package/dist/render/shaders/smoke.d.ts +8 -0
- package/dist/render/shaders/smoke.js +88 -0
- package/dist/render/shaders/ssrResolve.d.ts +15 -0
- package/dist/render/shaders/ssrResolve.js +28 -0
- package/dist/render/shaders/ssrTrace.d.ts +22 -0
- package/dist/render/shaders/ssrTrace.js +230 -0
- package/dist/render/shaders/tangentFrame.d.ts +17 -0
- package/dist/render/shaders/tangentFrame.js +70 -0
- package/dist/render/shaders/temporalResolve.d.ts +1 -0
- package/dist/render/shaders/temporalResolve.js +150 -0
- package/dist/render/shaders/text.d.ts +17 -0
- package/dist/render/shaders/text.js +155 -0
- package/dist/render/shaders/vertexChannel.d.ts +39 -0
- package/dist/render/shaders/vertexChannel.js +69 -0
- package/dist/render/shaders/water.d.ts +18 -0
- package/dist/render/shaders/water.js +354 -0
- package/dist/render/shaders/windStreaks.d.ts +14 -0
- package/dist/render/shaders/windStreaks.js +129 -0
- package/dist/render/shadowCasters.d.ts +107 -0
- package/dist/render/shadowCasters.js +1 -0
- package/dist/render/shadowMap.d.ts +10 -0
- package/dist/render/shadowMap.js +80 -0
- package/dist/render/shotPlacement.d.ts +80 -0
- package/dist/render/shotPlacement.js +183 -0
- package/dist/render/skinPalette.d.ts +90 -0
- package/dist/render/skinPalette.js +136 -0
- package/dist/render/ssrPass.d.ts +59 -0
- package/dist/render/ssrPass.js +196 -0
- package/dist/render/surfaceSheet.d.ts +52 -0
- package/dist/render/surfaceSheet.js +99 -0
- package/dist/render/surfaceTexture.d.ts +197 -0
- package/dist/render/surfaceTexture.js +116 -0
- package/dist/render/temporalAa.d.ts +104 -0
- package/dist/render/temporalAa.js +194 -0
- package/dist/render/temporalPass.d.ts +54 -0
- package/dist/render/temporalPass.js +135 -0
- package/dist/render/textLayout.d.ts +88 -0
- package/dist/render/textLayout.js +201 -0
- package/dist/render/textRenderer.d.ts +32 -0
- package/dist/render/textRenderer.js +176 -0
- package/dist/render/thirdPersonCamera.d.ts +272 -0
- package/dist/render/thirdPersonCamera.js +479 -0
- package/dist/render/trample.d.ts +57 -0
- package/dist/render/trample.js +134 -0
- package/dist/render/translucentQueue.d.ts +76 -0
- package/dist/render/translucentQueue.js +90 -0
- package/dist/render/uniformVectorBudget.d.ts +105 -0
- package/dist/render/uniformVectorBudget.js +201 -0
- package/dist/render/uploadStep.d.ts +14 -0
- package/dist/render/uploadStep.js +14 -0
- package/dist/render/vertexDefaults.d.ts +48 -0
- package/dist/render/vertexDefaults.js +111 -0
- package/dist/render/visibility.d.ts +22 -0
- package/dist/render/visibility.js +47 -0
- package/dist/render/waterDraw.d.ts +57 -0
- package/dist/render/waterDraw.js +102 -0
- package/dist/render/waterGrid.d.ts +62 -0
- package/dist/render/waterGrid.js +151 -0
- package/dist/render/waterRenderer.d.ts +163 -0
- package/dist/render/waterRenderer.js +165 -0
- package/dist/render/wind.d.ts +45 -0
- package/dist/render/wind.js +32 -0
- package/dist/render/windField.d.ts +34 -0
- package/dist/render/windField.js +13 -0
- package/dist/render/windStreakDraw.d.ts +73 -0
- package/dist/render/windStreakDraw.js +86 -0
- package/dist/render/windStreakRenderer.d.ts +37 -0
- package/dist/render/windStreakRenderer.js +86 -0
- package/dist/scene/node.d.ts +128 -0
- package/dist/scene/node.js +319 -0
- package/dist/scene/visit.d.ts +38 -0
- package/dist/scene/visit.js +43 -0
- package/dist/ui/clipMime.d.ts +46 -0
- package/dist/ui/clipMime.js +88 -0
- package/dist/ui/exportTarget.d.ts +305 -0
- package/dist/ui/exportTarget.js +368 -0
- package/dist/ui/frameOverlay.d.ts +59 -0
- package/dist/ui/frameOverlay.js +76 -0
- package/dist/ui/framePacer.d.ts +142 -0
- package/dist/ui/framePacer.js +284 -0
- package/dist/ui/frameRecorder.d.ts +188 -0
- package/dist/ui/frameRecorder.js +221 -0
- package/dist/ui/fullscreen.d.ts +72 -0
- package/dist/ui/fullscreen.js +92 -0
- package/dist/ui/pixelCursor.d.ts +28 -0
- package/dist/ui/pixelCursor.js +66 -0
- package/dist/ui/splash.d.ts +86 -0
- package/dist/ui/splash.js +300 -0
- package/dist/ui/stillFrame.d.ts +22 -0
- package/dist/ui/stillFrame.js +40 -0
- package/package.json +60 -0
- package/src/behavior/behaviorTree.ts +346 -0
- package/src/build/shaderComments.ts +0 -0
- package/src/cinematic/player.ts +209 -0
- package/src/cinematic/script.ts +231 -0
- package/src/core/bootGate.ts +49 -0
- package/src/core/loadTracker.ts +144 -0
- package/src/core/loop.ts +211 -0
- package/src/core/messageQueue.ts +145 -0
- package/src/core/onceSet.ts +65 -0
- package/src/core/preferences.ts +177 -0
- package/src/core/remoteSave.ts +347 -0
- package/src/core/rng.ts +101 -0
- package/src/core/stepBudget.ts +136 -0
- package/src/core/storage.ts +114 -0
- package/src/core/tickTrace.ts +129 -0
- package/src/core/timeCurve.ts +175 -0
- package/src/core/withDefaults.ts +28 -0
- package/src/dev/contactProbe.ts +115 -0
- package/src/dev/fpsMeter.ts +101 -0
- package/src/environment/celestialClock.ts +385 -0
- package/src/geometry/decal.ts +260 -0
- package/src/geometry/filmPatch.ts +158 -0
- package/src/geometry/growable.ts +165 -0
- package/src/geometry/lightVolume.ts +161 -0
- package/src/geometry/meshBuilder.ts +1397 -0
- package/src/geometry/pixelFont.ts +189 -0
- package/src/geometry/ribbon.ts +790 -0
- package/src/geometry/shellFill.ts +265 -0
- package/src/geometry/spline.ts +659 -0
- package/src/geometry/tangents.ts +173 -0
- package/src/geometry/textMesh.ts +96 -0
- package/src/geometry/treeBuilder.ts +114 -0
- package/src/host/display.ts +180 -0
- package/src/host/files.ts +77 -0
- package/src/host/lifecycle.ts +63 -0
- package/src/host/platformServices.ts +23 -0
- package/src/host/screen.ts +134 -0
- package/src/index.ts +730 -0
- package/src/input/actionMap.ts +377 -0
- package/src/input/activeDevice.ts +86 -0
- package/src/input/gamepadIdentity.ts +131 -0
- package/src/input/gamepadMapping.ts +121 -0
- package/src/input/input.ts +872 -0
- package/src/input/inputHarness.ts +226 -0
- package/src/input/rightGesture.ts +76 -0
- package/src/input/rumble.ts +138 -0
- package/src/input/touchControls.ts +451 -0
- package/src/input/typingTarget.ts +26 -0
- package/src/math/bounds.ts +153 -0
- package/src/math/color.ts +37 -0
- package/src/math/exact.ts +274 -0
- package/src/math/frustum.ts +115 -0
- package/src/math/intersect.ts +228 -0
- package/src/math/scalar.ts +109 -0
- package/src/math/spring.ts +106 -0
- package/src/nav/navGraph.ts +168 -0
- package/src/nav/navPath.ts +217 -0
- package/src/nav/navSearch.ts +200 -0
- package/src/physics/boxSurface.ts +96 -0
- package/src/physics/colliderSurface.ts +213 -0
- package/src/physics/compositeSurface.ts +111 -0
- package/src/physics/heightSurface.ts +234 -0
- package/src/physics/ribbonSurface.ts +642 -0
- package/src/render/ambientOcclusionPass.ts +200 -0
- package/src/render/areaLights.ts +194 -0
- package/src/render/areaShadowSet.ts +405 -0
- package/src/render/atmosphere.ts +186 -0
- package/src/render/backend/api.ts +802 -0
- package/src/render/backend/budget.ts +139 -0
- package/src/render/backend/createRenderer.ts +343 -0
- package/src/render/backend/deadline.ts +37 -0
- package/src/render/backend/probe.ts +152 -0
- package/src/render/backend/select.ts +288 -0
- package/src/render/backend/timer.ts +59 -0
- package/src/render/backend/webgl2/instanced.ts +46 -0
- package/src/render/backend/webgl2/morphTexture.ts +58 -0
- package/src/render/backend/webgl2/renderer.ts +7484 -0
- package/src/render/backend/webgl2/skinPaletteTexture.ts +70 -0
- package/src/render/backend/webgpu/boltPass.ts +205 -0
- package/src/render/backend/webgpu/buffers.ts +553 -0
- package/src/render/backend/webgpu/causticsPass.ts +174 -0
- package/src/render/backend/webgpu/clusterBinner.ts +259 -0
- package/src/render/backend/webgpu/depthPass.ts +261 -0
- package/src/render/backend/webgpu/device.ts +148 -0
- package/src/render/backend/webgpu/drawCommand.ts +79 -0
- package/src/render/backend/webgpu/environmentTexels.ts +96 -0
- package/src/render/backend/webgpu/filmPass.ts +123 -0
- package/src/render/backend/webgpu/flatPass.ts +635 -0
- package/src/render/backend/webgpu/flockPass.ts +163 -0
- package/src/render/backend/webgpu/gpuTimestamps.ts +255 -0
- package/src/render/backend/webgpu/insetPass.ts +123 -0
- package/src/render/backend/webgpu/instanced.ts +55 -0
- package/src/render/backend/webgpu/lightVolumePass.ts +203 -0
- package/src/render/backend/webgpu/linePass.ts +270 -0
- package/src/render/backend/webgpu/morphTexture.ts +61 -0
- package/src/render/backend/webgpu/panelPass.ts +138 -0
- package/src/render/backend/webgpu/particlePass.ts +370 -0
- package/src/render/backend/webgpu/pipelineCache.ts +152 -0
- package/src/render/backend/webgpu/plumePass.ts +292 -0
- package/src/render/backend/webgpu/pointShadowPass.ts +368 -0
- package/src/render/backend/webgpu/postPass.ts +470 -0
- package/src/render/backend/webgpu/probePass.ts +218 -0
- package/src/render/backend/webgpu/reflectionPass.ts +137 -0
- package/src/render/backend/webgpu/renderer.ts +13004 -0
- package/src/render/backend/webgpu/scatterPass.ts +354 -0
- package/src/render/backend/webgpu/sdfTextPass.ts +220 -0
- package/src/render/backend/webgpu/shaderModules.ts +49 -0
- package/src/render/backend/webgpu/shaders/clusterBin.wgsl.ts +219 -0
- package/src/render/backend/webgpu/skinPaletteRing.ts +105 -0
- package/src/render/backend/webgpu/skinPaletteTexture.ts +79 -0
- package/src/render/backend/webgpu/skyPass.ts +85 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +257 -0
- package/src/render/backend/webgpu/textPass.ts +224 -0
- package/src/render/backend/webgpu/uniformRing.ts +228 -0
- package/src/render/backend/webgpu/waterPass.ts +211 -0
- package/src/render/backend/webgpu/windStreakPass.ts +196 -0
- package/src/render/billboard.ts +108 -0
- package/src/render/bloomChain.ts +101 -0
- package/src/render/bloomPass.ts +256 -0
- package/src/render/boltBatch.ts +141 -0
- package/src/render/boltPool.ts +360 -0
- package/src/render/boom.ts +123 -0
- package/src/render/camera.ts +348 -0
- package/src/render/causticsRenderer.ts +171 -0
- package/src/render/cinematicCamera.ts +278 -0
- package/src/render/clusteredLights.ts +598 -0
- package/src/render/colourGrade.ts +109 -0
- package/src/render/compute.ts +83 -0
- package/src/render/contextLoss.ts +50 -0
- package/src/render/debugLines.ts +411 -0
- package/src/render/decalPass.ts +124 -0
- package/src/render/decalProjector.ts +390 -0
- package/src/render/decalQueue.ts +110 -0
- package/src/render/depthConvention.ts +383 -0
- package/src/render/drawingBuffer.ts +89 -0
- package/src/render/emptyTexture.ts +130 -0
- package/src/render/envProbeArray.ts +201 -0
- package/src/render/equirectToCube.ts +160 -0
- package/src/render/flockGeometry.ts +53 -0
- package/src/render/flockRenderer.ts +111 -0
- package/src/render/frame/arena.ts +93 -0
- package/src/render/frame/index.ts +29 -0
- package/src/render/frame/replay.ts +50 -0
- package/src/render/frame/resources.ts +61 -0
- package/src/render/frame/schedule.ts +85 -0
- package/src/render/frameView.ts +20 -0
- package/src/render/gizmo.ts +923 -0
- package/src/render/globalMedium.ts +154 -0
- package/src/render/globalMediumPass.ts +323 -0
- package/src/render/gpuCapability.ts +244 -0
- package/src/render/gpuTimer.ts +182 -0
- package/src/render/halfFloat.ts +39 -0
- package/src/render/handleRegistry.ts +96 -0
- package/src/render/iesProfile.ts +215 -0
- package/src/render/imageTexels.ts +109 -0
- package/src/render/instancedMesh.ts +187 -0
- package/src/render/instances.ts +92 -0
- package/src/render/lightBudget.ts +655 -0
- package/src/render/lightMatrix.ts +69 -0
- package/src/render/lightVolumeDraw.ts +216 -0
- package/src/render/lineBatch.ts +180 -0
- package/src/render/linePoints.ts +61 -0
- package/src/render/livePointShadowSet.ts +285 -0
- package/src/render/lod.ts +86 -0
- package/src/render/mesh.ts +536 -0
- package/src/render/occlusion.ts +406 -0
- package/src/render/oitPass.ts +230 -0
- package/src/render/orderIndependent.ts +136 -0
- package/src/render/particleBatch.ts +299 -0
- package/src/render/particleMaterial.ts +84 -0
- package/src/render/particlePool.ts +291 -0
- package/src/render/pass.ts +203 -0
- package/src/render/passTarget.ts +225 -0
- package/src/render/pickable.ts +222 -0
- package/src/render/planarReflection.ts +233 -0
- package/src/render/planarReflectionDraw.ts +87 -0
- package/src/render/plumeGeometry.ts +75 -0
- package/src/render/plumeMaterial.ts +99 -0
- package/src/render/plumeRenderer.ts +272 -0
- package/src/render/pointLightSelection.ts +447 -0
- package/src/render/pointShadowArray.ts +276 -0
- package/src/render/pointShadowBudget.ts +305 -0
- package/src/render/pointShadowImage.ts +470 -0
- package/src/render/pointShadowMap.ts +228 -0
- package/src/render/pointShadowSystem.ts +408 -0
- package/src/render/prefilterEnvMap.ts +162 -0
- package/src/render/prefilterPass.ts +115 -0
- package/src/render/probeGrid.ts +248 -0
- package/src/render/rainField.ts +240 -0
- package/src/render/reflectionProbe.ts +530 -0
- package/src/render/renderQuality.ts +1054 -0
- package/src/render/rendererHarness.ts +214 -0
- package/src/render/resolutionGovernor.ts +189 -0
- package/src/render/scatterDeform.ts +72 -0
- package/src/render/sceneTarget.ts +1032 -0
- package/src/render/screenSpaceReflection.ts +524 -0
- package/src/render/sdfFont.ts +157 -0
- package/src/render/sdfTextLayout.ts +206 -0
- package/src/render/sdfTextRenderer.ts +233 -0
- package/src/render/seaState.ts +55 -0
- package/src/render/segmentQuads.ts +92 -0
- package/src/render/shader.ts +190 -0
- package/src/render/shaders/ambientOcclusion.ts +354 -0
- package/src/render/shaders/arcane.ts +103 -0
- package/src/render/shaders/bloom.ts +232 -0
- package/src/render/shaders/bolt.ts +164 -0
- package/src/render/shaders/caustics.ts +169 -0
- package/src/render/shaders/conditionals.ts +58 -0
- package/src/render/shaders/decalProject.ts +127 -0
- package/src/render/shaders/depth.ts +131 -0
- package/src/render/shaders/depthOfField.ts +141 -0
- package/src/render/shaders/film.ts +285 -0
- package/src/render/shaders/fire.ts +180 -0
- package/src/render/shaders/flat/directionalShadow.ts +196 -0
- package/src/render/shaders/flat/index.ts +502 -0
- package/src/render/shaders/flat/lobes.ts +399 -0
- package/src/render/shaders/flat/main.ts +1631 -0
- package/src/render/shaders/flat/pointShadow.ts +323 -0
- package/src/render/shaders/flat/preamble.ts +875 -0
- package/src/render/shaders/flat/probeGrid.ts +152 -0
- package/src/render/shaders/flat/surface.ts +41 -0
- package/src/render/shaders/flock.ts +103 -0
- package/src/render/shaders/fog.ts +99 -0
- package/src/render/shaders/fullscreen.ts +28 -0
- package/src/render/shaders/generated/ambientOcclusion.wgsl.ts +74 -0
- package/src/render/shaders/generated/arcane.wgsl.ts +98 -0
- package/src/render/shaders/generated/bloom.wgsl.ts +79 -0
- package/src/render/shaders/generated/bolt.wgsl.ts +127 -0
- package/src/render/shaders/generated/caustics.wgsl.ts +127 -0
- package/src/render/shaders/generated/decalProject.wgsl.ts +69 -0
- package/src/render/shaders/generated/depth.wgsl.ts +142 -0
- package/src/render/shaders/generated/film.wgsl.ts +143 -0
- package/src/render/shaders/generated/fire.wgsl.ts +137 -0
- package/src/render/shaders/generated/flat.wgsl.ts +9195 -0
- package/src/render/shaders/generated/flock.wgsl.ts +82 -0
- package/src/render/shaders/generated/fullscreen.wgsl.ts +20 -0
- package/src/render/shaders/generated/globalMedium.wgsl.ts +139 -0
- package/src/render/shaders/generated/lightVolume.wgsl.ts +242 -0
- package/src/render/shaders/generated/line.wgsl.ts +137 -0
- package/src/render/shaders/generated/octahedralResolve.wgsl.ts +60 -0
- package/src/render/shaders/generated/oitResolve.wgsl.ts +31 -0
- package/src/render/shaders/generated/panel.wgsl.ts +57 -0
- package/src/render/shaders/generated/particle.wgsl.ts +343 -0
- package/src/render/shaders/generated/prefilter.wgsl.ts +69 -0
- package/src/render/shaders/generated/rush.wgsl.ts +139 -0
- package/src/render/shaders/generated/scatter.wgsl.ts +205 -0
- package/src/render/shaders/generated/sdfText.wgsl.ts +78 -0
- package/src/render/shaders/generated/sky.wgsl.ts +109 -0
- package/src/render/shaders/generated/smoke.wgsl.ts +93 -0
- package/src/render/shaders/generated/ssrResolve.wgsl.ts +26 -0
- package/src/render/shaders/generated/ssrTrace.wgsl.ts +94 -0
- package/src/render/shaders/generated/temporalResolve.wgsl.ts +54 -0
- package/src/render/shaders/generated/text.wgsl.ts +107 -0
- package/src/render/shaders/generated/water.wgsl.ts +256 -0
- package/src/render/shaders/generated/windStreaks.wgsl.ts +82 -0
- package/src/render/shaders/gerstner.ts +110 -0
- package/src/render/shaders/globalMedium.ts +396 -0
- package/src/render/shaders/lightVolume.ts +546 -0
- package/src/render/shaders/line.ts +125 -0
- package/src/render/shaders/morph.ts +62 -0
- package/src/render/shaders/octahedral.ts +170 -0
- package/src/render/shaders/octahedralResolve.ts +83 -0
- package/src/render/shaders/oitResolve.ts +42 -0
- package/src/render/shaders/outputTransform.ts +107 -0
- package/src/render/shaders/panel.ts +51 -0
- package/src/render/shaders/particle.ts +438 -0
- package/src/render/shaders/prefilter.ts +278 -0
- package/src/render/shaders/rush.ts +357 -0
- package/src/render/shaders/scatter.ts +211 -0
- package/src/render/shaders/sdfText.ts +68 -0
- package/src/render/shaders/skinning.ts +59 -0
- package/src/render/shaders/sky.ts +243 -0
- package/src/render/shaders/smoke.ts +89 -0
- package/src/render/shaders/ssrResolve.ts +28 -0
- package/src/render/shaders/ssrTrace.ts +233 -0
- package/src/render/shaders/tangentFrame.ts +70 -0
- package/src/render/shaders/temporalResolve.ts +151 -0
- package/src/render/shaders/text.ts +156 -0
- package/src/render/shaders/vertexChannel.ts +71 -0
- package/src/render/shaders/water.ts +356 -0
- package/src/render/shaders/windStreaks.ts +130 -0
- package/src/render/shadowCasters.ts +124 -0
- package/src/render/shadowMap.ts +89 -0
- package/src/render/shotPlacement.ts +266 -0
- package/src/render/skinPalette.ts +157 -0
- package/src/render/ssrPass.ts +241 -0
- package/src/render/surfaceSheet.ts +158 -0
- package/src/render/surfaceTexture.ts +310 -0
- package/src/render/temporalAa.ts +221 -0
- package/src/render/temporalPass.ts +153 -0
- package/src/render/textLayout.ts +239 -0
- package/src/render/textRenderer.ts +201 -0
- package/src/render/thirdPersonCamera.ts +578 -0
- package/src/render/trample.ts +140 -0
- package/src/render/translucentQueue.ts +161 -0
- package/src/render/uniformVectorBudget.ts +246 -0
- package/src/render/uploadStep.ts +14 -0
- package/src/render/vertexDefaults.ts +115 -0
- package/src/render/visibility.ts +56 -0
- package/src/render/waterDraw.ts +167 -0
- package/src/render/waterGrid.ts +180 -0
- package/src/render/waterRenderer.ts +352 -0
- package/src/render/wind.ts +79 -0
- package/src/render/windField.ts +50 -0
- package/src/render/windStreakDraw.ts +131 -0
- package/src/render/windStreakRenderer.ts +130 -0
- package/src/scene/node.ts +336 -0
- package/src/scene/visit.ts +82 -0
- package/src/ui/clipMime.ts +109 -0
- package/src/ui/exportTarget.ts +491 -0
- package/src/ui/frameOverlay.ts +159 -0
- package/src/ui/framePacer.ts +351 -0
- package/src/ui/frameRecorder.ts +333 -0
- package/src/ui/fullscreen.ts +113 -0
- package/src/ui/pixelCursor.ts +99 -0
- package/src/ui/splash.ts +347 -0
- package/src/ui/stillFrame.ts +44 -0
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deciding which of a render loop's frames go into a recording, and measuring
|
|
3
|
+
* what came out.
|
|
4
|
+
*
|
|
5
|
+
* The measuring half is not diagnostics bolted on afterwards — it is half the
|
|
6
|
+
* reason this module exists. A clip that "judders" has at least three possible
|
|
7
|
+
* causes (the renderer missing its rate, the encoder starved of bitrate, the
|
|
8
|
+
* content itself stepping unevenly) and they are indistinguishable by eye. What
|
|
9
|
+
* separates them is a number: how many frames the loop produced, how many were
|
|
10
|
+
* handed to the recorder, and how far apart in wall-clock time those were.
|
|
11
|
+
*
|
|
12
|
+
* **The schedule counts animation frames, not milliseconds, and that is the
|
|
13
|
+
* whole design.** A recorder stamps each frame with the instant it arrived, and
|
|
14
|
+
* the only instants a render loop can offer are its display's own — so a
|
|
15
|
+
* schedule expressed in wall-clock slots asks for moments that do not exist. It
|
|
16
|
+
* then takes the nearest frame either side, alternately early and late, and the
|
|
17
|
+
* file holds frames of uneven duration: 13.9 ms, 20.8 ms, 13.9 ms on a 144 Hz
|
|
18
|
+
* panel asked for 60 a second. Capturing every *n*-th frame instead makes every
|
|
19
|
+
* gap identical by construction, which is what makes the clip play evenly.
|
|
20
|
+
*
|
|
21
|
+
* The rate that comes out is therefore the display's rate divided by a whole
|
|
22
|
+
* number — 60 from 60 Hz, 72 from 144, 60 from 240 — rather than exactly what
|
|
23
|
+
* was asked for. That is the right trade: a clip at 72 fps whose frames are
|
|
24
|
+
* evenly spaced is smooth, and one at exactly 60 whose frames are not is the
|
|
25
|
+
* defect this replaced.
|
|
26
|
+
*
|
|
27
|
+
* Two rules the schedule follows, both learned from what a stutter looks like:
|
|
28
|
+
*
|
|
29
|
+
* - **Never two captures for one animation frame.** A duplicated frame is a
|
|
30
|
+
* frozen instant followed by a double-length step, which reads as a hitch
|
|
31
|
+
* even though nothing was dropped. Counting frames makes this true by
|
|
32
|
+
* construction.
|
|
33
|
+
* - **After falling behind, resume — do not catch up.** Firing twice in quick
|
|
34
|
+
* succession to make up a missed slot converts one gap into a lurch forward.
|
|
35
|
+
* A gap is a frame nobody notices; a lurch is the artefact everybody calls
|
|
36
|
+
* lag.
|
|
37
|
+
*/
|
|
38
|
+
export interface FramePacingReport {
|
|
39
|
+
readonly targetFps: number;
|
|
40
|
+
/** Animation frames the loop produced while the pacer was running. */
|
|
41
|
+
readonly rendered: number;
|
|
42
|
+
/** Frames handed to the recorder. */
|
|
43
|
+
readonly captured: number;
|
|
44
|
+
/** Frames per second actually captured, over the whole run. */
|
|
45
|
+
readonly capturedFps: number;
|
|
46
|
+
/** Mean wall-clock gap between captured frames, ms. */
|
|
47
|
+
readonly meanGapMs: number;
|
|
48
|
+
/** The worst single gap, ms — the one the eye actually notices. */
|
|
49
|
+
readonly worstGapMs: number;
|
|
50
|
+
/**
|
|
51
|
+
* Captures that arrived well outside the cadence the rest of the clip holds.
|
|
52
|
+
*
|
|
53
|
+
* Measured against the clip's *own* spacing rather than against the requested
|
|
54
|
+
* rate, because the two are allowed to differ: a display that divides to 72 fps
|
|
55
|
+
* or a loop that can only manage 40 both produce a clip whose every frame is
|
|
56
|
+
* evenly spaced, and neither is a fault. What is a fault is one frame taking
|
|
57
|
+
* half again as long as its neighbours, and that is what this counts.
|
|
58
|
+
*/
|
|
59
|
+
readonly slipped: number;
|
|
60
|
+
/** Animation frames per capture — the schedule the clip actually ran on. */
|
|
61
|
+
readonly stride: number;
|
|
62
|
+
readonly elapsedMs: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* How far outside the established cadence a gap has to fall to count as slipped.
|
|
67
|
+
* A little over one gap, so ordinary display jitter is not reported as a fault.
|
|
68
|
+
*/
|
|
69
|
+
const SLIP_FACTOR = 1.4;
|
|
70
|
+
/** Weight of the newest gap in the cadence estimate. */
|
|
71
|
+
const CADENCE_EMA = 0.15;
|
|
72
|
+
/**
|
|
73
|
+
* Animation frames the interval estimate is taken over.
|
|
74
|
+
*
|
|
75
|
+
* Sixteen: a quarter of a second at 60 Hz, which is long enough to absorb one bad
|
|
76
|
+
* sample and short enough that the schedule is settled before anything is recorded.
|
|
77
|
+
* The estimate is re-taken every time the window fills, so a loop that gets heavier
|
|
78
|
+
* mid-clip is followed rather than held to a schedule it can no longer keep.
|
|
79
|
+
*/
|
|
80
|
+
const SAMPLE_WINDOW = 16;
|
|
81
|
+
/**
|
|
82
|
+
* Slack in the stride calculation, as a share of the ratio being floored.
|
|
83
|
+
*
|
|
84
|
+
* Half a percent, and it is small because the estimator earns it. A 60 Hz display
|
|
85
|
+
* asked for 30 fps wants a stride of exactly 2, and a measured interval of 16.6668 ms
|
|
86
|
+
* gives a ratio of 1.99998 — so a bare `floor` answers 1 and doubles the rate. That
|
|
87
|
+
* is the entire job: cover a measurement that lands a hair long, and floating point.
|
|
88
|
+
*
|
|
89
|
+
* It was five percent while the estimate came from a median, which sits *above* the
|
|
90
|
+
* display's period and needed the room. A trimmed minimum sits at or just below it,
|
|
91
|
+
* so the ratio errs high already and slack on top only pushes it over the next
|
|
92
|
+
* boundary the wrong way: measured at five percent, a 100 Hz panel asked for 60
|
|
93
|
+
* sometimes recorded 50 instead of 100, because a jittery window read the period as
|
|
94
|
+
* 8.6 ms and 1.94 became 2.03.
|
|
95
|
+
*/
|
|
96
|
+
const STRIDE_SLACK = 0.005;
|
|
97
|
+
/**
|
|
98
|
+
* How far past its boundary the measurement has to move before the stride changes,
|
|
99
|
+
* in whole strides.
|
|
100
|
+
*
|
|
101
|
+
* A fifth, and this is the part slack alone could not do. The stride is a *discrete*
|
|
102
|
+
* choice, so a ratio sitting near a boundary flips it on the noise in the estimate —
|
|
103
|
+
* and a flip between 1 and 2 doubles the clip's frame rate. Measured on a loop with
|
|
104
|
+
* 24% frame-time jitter and a true ratio of exactly 2.0: the median of a
|
|
105
|
+
* sixteen-frame window wanders between 16.7 ms and 18.3 ms, which is a ratio between
|
|
106
|
+
* 2.0 and 1.82, and the stride flipped five times in a ten-second clip.
|
|
107
|
+
*
|
|
108
|
+
* A display's period does not change, so the right default is to keep the schedule
|
|
109
|
+
* already chosen and demand real evidence to leave it. A fifth of a stride is well
|
|
110
|
+
* past what a median of sixteen frames is wrong by and well short of a genuine step.
|
|
111
|
+
*/
|
|
112
|
+
const STRIDE_HYSTERESIS = 0.2;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Animation frames per capture, given the target interval, what one animation frame
|
|
116
|
+
* actually costs, and the schedule already running.
|
|
117
|
+
*
|
|
118
|
+
* Rounded down, so the rate that comes out is never *below* the one asked for while
|
|
119
|
+
* the loop can hold it: a 100 Hz display asked for 60 records 100 rather than 50,
|
|
120
|
+
* which is more frames than needed and smooth, where the other way round is fewer
|
|
121
|
+
* frames than promised.
|
|
122
|
+
*
|
|
123
|
+
* `current` is held on to unless the measurement has moved clearly past its
|
|
124
|
+
* boundary — see `STRIDE_HYSTERESIS`. Pass 0 to choose freely.
|
|
125
|
+
*/
|
|
126
|
+
function strideFor(targetIntervalMs: number, frameIntervalMs: number, current = 0): number {
|
|
127
|
+
if (!(frameIntervalMs > 0)) return Math.max(1, current);
|
|
128
|
+
const scaled = (targetIntervalMs / frameIntervalMs) * (1 + STRIDE_SLACK);
|
|
129
|
+
if (
|
|
130
|
+
current > 0 &&
|
|
131
|
+
scaled >= current - STRIDE_HYSTERESIS &&
|
|
132
|
+
scaled < current + 1 + STRIDE_HYSTERESIS
|
|
133
|
+
) {
|
|
134
|
+
return current;
|
|
135
|
+
}
|
|
136
|
+
return Math.max(1, Math.floor(scaled));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Second-smallest of `values`, sorted into `scratch`.
|
|
141
|
+
*
|
|
142
|
+
* **A trimmed minimum, and the choice of statistic is the whole point.** What is
|
|
143
|
+
* being estimated is the display's period, and that is a *floor* on how long an
|
|
144
|
+
* animation frame can take — a frame cannot come back sooner than the next vsync, it
|
|
145
|
+
* can only take longer and land on a later one. So the low end of the distribution is
|
|
146
|
+
* where the answer lives, and the mean and the median are both biased above it by
|
|
147
|
+
* however hard the loop is working.
|
|
148
|
+
*
|
|
149
|
+
* Which matters because the estimate feeds a `floor`: a stride of 2 asks whether the
|
|
150
|
+
* ratio is above or below 2, and an estimator that wanders either side of the answer
|
|
151
|
+
* flips the clip's frame rate. Measured with a median of sixteen: on a loop with 24%
|
|
152
|
+
* frame-time jitter and a true ratio of exactly 2, the median wandered between
|
|
153
|
+
* 16.7 ms and 18.3 ms and the stride flipped, taking a 30 fps request to 36.
|
|
154
|
+
*
|
|
155
|
+
* Second-smallest rather than smallest because the minimum has no defence at all
|
|
156
|
+
* against a bad sample — two callbacks in one frame, a clock that jumped, a tab
|
|
157
|
+
* waking up — and one of those in a window would set a stride far too long. One
|
|
158
|
+
* anomaly per sixteen frames is absorbed; two in the same window is not, which is a
|
|
159
|
+
* trade rather than an oversight.
|
|
160
|
+
*
|
|
161
|
+
* Insertion sort into a caller-owned buffer, because this runs inside a render loop
|
|
162
|
+
* and must not allocate. Sixteen elements nearly in order is a handful of
|
|
163
|
+
* comparisons; the general case is still trivial at this size.
|
|
164
|
+
*/
|
|
165
|
+
function trimmedMinimum(values: Float64Array, scratch: Float64Array): number {
|
|
166
|
+
const n = values.length;
|
|
167
|
+
for (let i = 0; i < n; i++) {
|
|
168
|
+
const value = values[i] ?? 0;
|
|
169
|
+
let j = i - 1;
|
|
170
|
+
while (j >= 0 && (scratch[j] ?? 0) > value) {
|
|
171
|
+
scratch[j + 1] = scratch[j] ?? 0;
|
|
172
|
+
j--;
|
|
173
|
+
}
|
|
174
|
+
scratch[j + 1] = value;
|
|
175
|
+
}
|
|
176
|
+
return scratch[Math.min(1, n - 1)] ?? 0;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export class FramePacer {
|
|
180
|
+
private readonly intervalMs: number;
|
|
181
|
+
/** Animation frames per capture. One until the loop's own rate is known. */
|
|
182
|
+
private strideFrames = 1;
|
|
183
|
+
private framesSinceCapture = 0;
|
|
184
|
+
private startMs = 0;
|
|
185
|
+
private lastCaptureMs = 0;
|
|
186
|
+
/**
|
|
187
|
+
* What one animation frame costs, ms — a trimmed minimum over a recent window.
|
|
188
|
+
*
|
|
189
|
+
* See `trimmedMinimum` for why the low end and not the middle. Three estimators
|
|
190
|
+
* were tried before it and each failed in a way worth recording: a running minimum
|
|
191
|
+
* over all time ratcheted down on anomalies until a clean 120 Hz loop recorded
|
|
192
|
+
* **24 fps**; a mean was dragged up by every overrunning frame, doubling the rate
|
|
193
|
+
* for the thirty frames an average takes to decay after one hitch; a median sat too
|
|
194
|
+
* far above the floor and wandered across the stride boundary.
|
|
195
|
+
*/
|
|
196
|
+
private frameIntervalMs = 0;
|
|
197
|
+
/** Recent animation-frame intervals, and a scratch buffer to sort them in. */
|
|
198
|
+
private readonly samples = new Float64Array(SAMPLE_WINDOW);
|
|
199
|
+
private readonly sorted = new Float64Array(SAMPLE_WINDOW);
|
|
200
|
+
private sampleCount = 0;
|
|
201
|
+
/** The instant last seen, so a frame is only ever counted once. */
|
|
202
|
+
private lastSeenMs = 0;
|
|
203
|
+
private seen = false;
|
|
204
|
+
/** Rolling estimate of the gap the clip is actually holding, for `slipped`. */
|
|
205
|
+
private cadenceMs = 0;
|
|
206
|
+
private renderedFrames = 0;
|
|
207
|
+
private capturedFrames = 0;
|
|
208
|
+
private gapSumMs = 0;
|
|
209
|
+
private worstGapMs = 0;
|
|
210
|
+
private slippedFrames = 0;
|
|
211
|
+
private started = false;
|
|
212
|
+
|
|
213
|
+
constructor(readonly targetFps: number) {
|
|
214
|
+
this.intervalMs = 1000 / Math.max(targetFps, 1);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Whether this animation frame is one the recording wants, without committing.
|
|
219
|
+
*
|
|
220
|
+
* The query half of `offer`, and it exists so a caller can decide *before
|
|
221
|
+
* rendering* whether the frame it is about to draw will be kept. A renderer that
|
|
222
|
+
* draws every animation frame and then discards most of them spends its whole
|
|
223
|
+
* budget competing with the frame it means to keep.
|
|
224
|
+
*
|
|
225
|
+
* Called once per animation frame, before drawing. That is also where the loop's
|
|
226
|
+
* own interval is measured, since it is the only call that sees every frame:
|
|
227
|
+
* `offer` only sees the ones that were drawn.
|
|
228
|
+
*
|
|
229
|
+
* Allocation-free: this is called from inside a render loop.
|
|
230
|
+
*/
|
|
231
|
+
due(nowMs: number): boolean {
|
|
232
|
+
this.observe(nowMs);
|
|
233
|
+
if (!this.started) return true;
|
|
234
|
+
return this.framesSinceCapture >= this.strideFrames;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Commit to the frame `due` was asked about.
|
|
239
|
+
*
|
|
240
|
+
* **`nowMs` must be the instant `due` was given, not the instant the frame
|
|
241
|
+
* finished drawing.** Both halves have to agree about when the frame is, or a
|
|
242
|
+
* frame is counted twice — once on the way in and once on the way out — and the
|
|
243
|
+
* loop's measured interval comes out at half its true value.
|
|
244
|
+
*
|
|
245
|
+
* A caller with nothing to gate may pass whatever clock it has, as long as it is
|
|
246
|
+
* the same one every frame.
|
|
247
|
+
*/
|
|
248
|
+
offer(nowMs: number): boolean {
|
|
249
|
+
this.observe(nowMs);
|
|
250
|
+
if (!this.started) {
|
|
251
|
+
this.started = true;
|
|
252
|
+
this.startMs = nowMs;
|
|
253
|
+
this.lastCaptureMs = nowMs;
|
|
254
|
+
this.framesSinceCapture = 0;
|
|
255
|
+
this.capturedFrames = 1;
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (this.framesSinceCapture < this.strideFrames) return false;
|
|
260
|
+
|
|
261
|
+
const gap = nowMs - this.lastCaptureMs;
|
|
262
|
+
this.gapSumMs += gap;
|
|
263
|
+
if (gap > this.worstGapMs) this.worstGapMs = gap;
|
|
264
|
+
// Against the cadence so far, and only once there is one to compare with.
|
|
265
|
+
if (this.cadenceMs > 0 && gap > this.cadenceMs * SLIP_FACTOR) this.slippedFrames++;
|
|
266
|
+
this.cadenceMs =
|
|
267
|
+
this.cadenceMs === 0 ? gap : this.cadenceMs + (gap - this.cadenceMs) * CADENCE_EMA;
|
|
268
|
+
this.lastCaptureMs = nowMs;
|
|
269
|
+
this.framesSinceCapture = 0;
|
|
270
|
+
this.capturedFrames++;
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** One animation frame seen, for the interval estimate and the frame count. */
|
|
275
|
+
private observe(nowMs: number): void {
|
|
276
|
+
if (this.seen && nowMs === this.lastSeenMs) return;
|
|
277
|
+
const since = this.seen ? nowMs - this.lastSeenMs : 0;
|
|
278
|
+
this.lastSeenMs = nowMs;
|
|
279
|
+
this.seen = true;
|
|
280
|
+
this.renderedFrames++;
|
|
281
|
+
if (this.started) this.framesSinceCapture++;
|
|
282
|
+
if (since <= 0) return;
|
|
283
|
+
|
|
284
|
+
this.samples[this.sampleCount % SAMPLE_WINDOW] = since;
|
|
285
|
+
this.sampleCount++;
|
|
286
|
+
/*
|
|
287
|
+
* Until there is a window to take a median of, the estimate is the *shortest*
|
|
288
|
+
* frame seen so far. A schedule is needed before sixteen frames have passed — a
|
|
289
|
+
* recording that waited would capture all sixteen of them, a burst at the head of
|
|
290
|
+
* every clip — and of the estimators available before then the minimum is the one
|
|
291
|
+
* that errs the safe way: it reads the loop as faster than it is, which makes the
|
|
292
|
+
* stride longer and captures *fewer* frames than intended rather than more.
|
|
293
|
+
*
|
|
294
|
+
* The minimum's own failing, that one anomalous frame owns it for good, cannot
|
|
295
|
+
* bite here: sixteen frames later the median takes over and never gives it back.
|
|
296
|
+
*/
|
|
297
|
+
if (this.sampleCount < SAMPLE_WINDOW) {
|
|
298
|
+
if (this.frameIntervalMs === 0 || since < this.frameIntervalMs) {
|
|
299
|
+
this.frameIntervalMs = since;
|
|
300
|
+
this.strideFrames = strideFor(this.intervalMs, since);
|
|
301
|
+
}
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
/*
|
|
305
|
+
* Re-taken when the window fills rather than on every frame: sorting sixteen
|
|
306
|
+
* numbers is cheap but this is a render loop, and a display's period does not
|
|
307
|
+
* change between one frame and the next.
|
|
308
|
+
*/
|
|
309
|
+
if (this.sampleCount % SAMPLE_WINDOW !== 0) return;
|
|
310
|
+
this.frameIntervalMs = trimmedMinimum(this.samples, this.sorted);
|
|
311
|
+
this.strideFrames = strideFor(this.intervalMs, this.frameIntervalMs, this.strideFrames);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Forget what has been measured, keep the schedule.
|
|
316
|
+
*
|
|
317
|
+
* For a recording with a warm-up in front of it: the frames a device spends
|
|
318
|
+
* getting an encoder and a driver going are genuinely awful — measured at 411 ms
|
|
319
|
+
* and 503 ms for a 1080x1920 clip — and they are not what the clip is like. Left in
|
|
320
|
+
* the report they become the worst gap and a couple of slipped frames, which is the
|
|
321
|
+
* evidence an export decides whether to warn the player on.
|
|
322
|
+
*
|
|
323
|
+
* The schedule survives on purpose: it was chosen from those same frames and it is
|
|
324
|
+
* still right.
|
|
325
|
+
*/
|
|
326
|
+
resetMeasurement(): void {
|
|
327
|
+
this.startMs = this.lastCaptureMs;
|
|
328
|
+
this.capturedFrames = 1;
|
|
329
|
+
this.renderedFrames = 0;
|
|
330
|
+
this.gapSumMs = 0;
|
|
331
|
+
this.worstGapMs = 0;
|
|
332
|
+
this.slippedFrames = 0;
|
|
333
|
+
this.cadenceMs = 0;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
get report(): FramePacingReport {
|
|
337
|
+
const elapsedMs = this.started ? Math.max(this.lastCaptureMs - this.startMs, 0) : 0;
|
|
338
|
+
const gaps = Math.max(this.capturedFrames - 1, 0);
|
|
339
|
+
return {
|
|
340
|
+
targetFps: this.targetFps,
|
|
341
|
+
rendered: this.renderedFrames,
|
|
342
|
+
captured: this.capturedFrames,
|
|
343
|
+
capturedFps: elapsedMs > 0 ? (gaps * 1000) / elapsedMs : 0,
|
|
344
|
+
meanGapMs: gaps > 0 ? this.gapSumMs / gaps : 0,
|
|
345
|
+
worstGapMs: this.worstGapMs,
|
|
346
|
+
slipped: this.slippedFrames,
|
|
347
|
+
stride: this.strideFrames,
|
|
348
|
+
elapsedMs,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { supportedClipMimeType } from './clipMime.ts';
|
|
2
|
+
import { ExportTarget, clipBitrate, exportSizeFor } from './exportTarget.ts';
|
|
3
|
+
import type { LockableSurface } from './exportTarget.ts';
|
|
4
|
+
import type { FrameOverlay } from './frameOverlay.ts';
|
|
5
|
+
import type { FramePacingReport } from './framePacer.ts';
|
|
6
|
+
|
|
7
|
+
export const DEFAULT_CLIP_FPS = 30;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Recording what is on a canvas — or on a prepared export target — to a file.
|
|
11
|
+
*
|
|
12
|
+
* A convenience on top of the replay, not the feature. The replay itself is
|
|
13
|
+
* what makes a run worth posting; this saves the trouble of reaching for a
|
|
14
|
+
* screen recorder — and where the browser cannot do it, saying so plainly beats
|
|
15
|
+
* producing a file that will not play.
|
|
16
|
+
*
|
|
17
|
+
* Deliberately not a server-side render. That is the "proper" answer and it is
|
|
18
|
+
* a backend, a queue, a storage bill and a moderation problem, for something
|
|
19
|
+
* the browser already does.
|
|
20
|
+
*
|
|
21
|
+
* **The honest limit, and it belongs here rather than in a commit message:**
|
|
22
|
+
* `MediaRecorder` timestamps every frame by wall clock, and that is measured
|
|
23
|
+
* rather than assumed — a probe recording requested frames at gaps of 8.6 / 24.5 /
|
|
24
|
+
* 8.1 / 28.6 ms and `ffprobe` read the MP4's own timestamps back as 8.8 / 24.2 /
|
|
25
|
+
* 8.1 / 28.5 ms, `avg_frame_rate=7110000/120161`. Two things follow.
|
|
26
|
+
*
|
|
27
|
+
* An export has to run in real time: there is no in-browser way to render a clip
|
|
28
|
+
* slower than real time and have the audio line up, short of shipping our own
|
|
29
|
+
* muxer, which is a dependency and the standing rule says no. So the export can be
|
|
30
|
+
* *paced* (see `ExportTarget`) and *measured*, but it cannot be given more time.
|
|
31
|
+
*
|
|
32
|
+
* And a constant-rate file is not on offer either. What is on offer is a file whose
|
|
33
|
+
* frames are evenly spaced *and* hold moments the same distance apart, which is
|
|
34
|
+
* what a viewer reads as smooth — so the schedule captures every n-th animation
|
|
35
|
+
* frame and the content follows the wall clock. A device that cannot hold the
|
|
36
|
+
* target rate then produces a slower clip rather than a juddering one, and the
|
|
37
|
+
* measurement in `pacing` says which it was.
|
|
38
|
+
*/
|
|
39
|
+
export interface FrameRecorderOptions {
|
|
40
|
+
/**
|
|
41
|
+
* Record the canvas directly, at `fps`. Simple and appropriate for a debug
|
|
42
|
+
* capture; for a clip anybody else will see, prefer `stream` from an
|
|
43
|
+
* `ExportTarget`, which fixes the aspect, stamps the mark and paces the
|
|
44
|
+
* frames.
|
|
45
|
+
*/
|
|
46
|
+
readonly canvas?: HTMLCanvasElement;
|
|
47
|
+
/** A prepared video stream, e.g. `ExportTarget.acquire()`. Wins over `canvas`. */
|
|
48
|
+
readonly stream?: MediaStream;
|
|
49
|
+
/** Mixed into the clip. Omit for a silent recording. */
|
|
50
|
+
readonly audio?: MediaStream | null;
|
|
51
|
+
/**
|
|
52
|
+
* Frames per second wanted — a floor, not a promise.
|
|
53
|
+
*
|
|
54
|
+
* The schedule counts animation frames (see `FramePacer`), so what comes out is
|
|
55
|
+
* the loop's own rate divided by a whole number. Asking for 60 on a 144 Hz panel
|
|
56
|
+
* records 72; asking for it on a loop that can only deliver 40 records 40.
|
|
57
|
+
*/
|
|
58
|
+
readonly fps?: number;
|
|
59
|
+
/**
|
|
60
|
+
* Bits per second for video. Defaults to a figure scaled from the frame's
|
|
61
|
+
* pixel count and rate — a constant is generous at one size and starved at
|
|
62
|
+
* another, and a starved encoder on high-motion footage looks like stutter.
|
|
63
|
+
*/
|
|
64
|
+
readonly videoBitsPerSecond?: number;
|
|
65
|
+
/**
|
|
66
|
+
* Record at a fixed frame size rather than at whatever the canvas happens to
|
|
67
|
+
* be, compositing the scene and an optional mark into it.
|
|
68
|
+
*
|
|
69
|
+
* This is what makes an export a *product* rather than a screen capture: the
|
|
70
|
+
* frame is the requested shape whatever the window is, the mark is inside the
|
|
71
|
+
* video where a DOM overlay could never be, and frames are handed over one at a
|
|
72
|
+
* time so none is ever recorded twice.
|
|
73
|
+
*/
|
|
74
|
+
readonly target?: {
|
|
75
|
+
/** The canvas the scene is drawn into. */
|
|
76
|
+
readonly source: HTMLCanvasElement;
|
|
77
|
+
/** Whoever owns that canvas's drawing-buffer size — normally the renderer. */
|
|
78
|
+
readonly surface: LockableSurface;
|
|
79
|
+
readonly width: number;
|
|
80
|
+
readonly height: number;
|
|
81
|
+
readonly overlay?: FrameOverlay | ((width: number, height: number) => FrameOverlay);
|
|
82
|
+
/**
|
|
83
|
+
* Drawn live into every composed frame, after the scene and the baked mark.
|
|
84
|
+
*
|
|
85
|
+
* For anything that changes frame to frame — a speedometer, a clock — which the
|
|
86
|
+
* baked `overlay` cannot express at all. See `ExportTargetOptions.drawFrame`.
|
|
87
|
+
*/
|
|
88
|
+
readonly drawFrame?: (ctx: CanvasRenderingContext2D, width: number, height: number) => void;
|
|
89
|
+
/**
|
|
90
|
+
* What the renderer is currently managing, frames per second. A device below
|
|
91
|
+
* the target rate records at a smaller frame instead: a slightly softer clip
|
|
92
|
+
* that holds its rate beats a full-size one that judders. Omit for no
|
|
93
|
+
* measurement, which is treated as no evidence rather than as bad news.
|
|
94
|
+
*/
|
|
95
|
+
readonly measuredFps?: number;
|
|
96
|
+
/** Forwarded to `ExportTargetOptions.presentedFrames`; see `duplicateFrame` below. */
|
|
97
|
+
readonly presentedFrames?: () => number;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export class FrameRecorder {
|
|
102
|
+
private recorder: MediaRecorder | null = null;
|
|
103
|
+
private chunks: Blob[] = [];
|
|
104
|
+
private readonly mime: string;
|
|
105
|
+
private target: ExportTarget | null = null;
|
|
106
|
+
private targetStream: MediaStream | null = null;
|
|
107
|
+
|
|
108
|
+
constructor(private readonly options: FrameRecorderOptions) {
|
|
109
|
+
const mime = supportedClipMimeType();
|
|
110
|
+
if (mime === null) throw new Error('This browser cannot record video.');
|
|
111
|
+
if (
|
|
112
|
+
options.canvas === undefined &&
|
|
113
|
+
options.stream === undefined &&
|
|
114
|
+
options.target === undefined
|
|
115
|
+
) {
|
|
116
|
+
throw new Error('A recording needs a canvas, a stream or a target.');
|
|
117
|
+
}
|
|
118
|
+
this.mime = mime;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
get mimeType(): string {
|
|
122
|
+
return this.mime;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Take over the render surface before recording starts.
|
|
127
|
+
*
|
|
128
|
+
* Separate from `start` because the aspect has to be in force *before* the
|
|
129
|
+
* first frame anybody records: the camera composes for `renderer.aspect`, so
|
|
130
|
+
* locking and recording in the same breath would put a screen-shaped shot in
|
|
131
|
+
* the first frames of a vertical clip. Returns the frame size that will be
|
|
132
|
+
* recorded, which is not always the one requested — see `measuredFps`.
|
|
133
|
+
*/
|
|
134
|
+
prepare(): { width: number; height: number; reduced: boolean } | null {
|
|
135
|
+
const options = this.options.target;
|
|
136
|
+
if (options === undefined) return null;
|
|
137
|
+
if (this.target !== null) {
|
|
138
|
+
return { width: this.target.width, height: this.target.height, reduced: false };
|
|
139
|
+
}
|
|
140
|
+
const fps = this.options.fps ?? DEFAULT_CLIP_FPS;
|
|
141
|
+
// The measurement was taken while rendering the *window*, so it is handed in
|
|
142
|
+
// with the pixel count it was taken at — see `exportSizeFor`.
|
|
143
|
+
const size = exportSizeFor(
|
|
144
|
+
options.width,
|
|
145
|
+
options.height,
|
|
146
|
+
options.measuredFps ?? 0,
|
|
147
|
+
fps,
|
|
148
|
+
options.source.width * options.source.height,
|
|
149
|
+
);
|
|
150
|
+
this.target = new ExportTarget({
|
|
151
|
+
source: options.source,
|
|
152
|
+
surface: options.surface,
|
|
153
|
+
width: size.width,
|
|
154
|
+
height: size.height,
|
|
155
|
+
fps,
|
|
156
|
+
...(options.overlay === undefined ? {} : { overlay: options.overlay }),
|
|
157
|
+
...(options.drawFrame === undefined ? {} : { drawFrame: options.drawFrame }),
|
|
158
|
+
...(options.presentedFrames === undefined
|
|
159
|
+
? {}
|
|
160
|
+
: { presentedFrames: options.presentedFrames }),
|
|
161
|
+
});
|
|
162
|
+
this.targetStream = this.target.acquire();
|
|
163
|
+
return size;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Whether the frame about to be drawn will be kept. True when there is no
|
|
168
|
+
* fixed target, so a caller can gate its render pass unconditionally.
|
|
169
|
+
*
|
|
170
|
+
* Call once per animation frame, drawing or not: the instant is kept and reused
|
|
171
|
+
* when the frame is handed over, so one clock decides and commits.
|
|
172
|
+
*/
|
|
173
|
+
captureDue(nowMs: number): boolean {
|
|
174
|
+
return this.target?.captureDue(nowMs) ?? true;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* One rendered frame, offered to the recording.
|
|
179
|
+
*
|
|
180
|
+
* Call at the very end of the render pass. Cheap and false when there is no
|
|
181
|
+
* fixed target, so a caller can hand every frame over unconditionally. Takes no
|
|
182
|
+
* instant — it uses the one `captureDue` was given for this frame.
|
|
183
|
+
*/
|
|
184
|
+
frameRendered(): boolean {
|
|
185
|
+
return this.target?.frameRendered() ?? false;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* What the pacing actually was, or null when recording the canvas directly.
|
|
190
|
+
*
|
|
191
|
+
* The measurement is the point rather than a diagnostic afterthought: an export
|
|
192
|
+
* that ran below its target rate produced a juddering file, and the only honest
|
|
193
|
+
* options are to say so or to have not measured.
|
|
194
|
+
*/
|
|
195
|
+
get pacing(): FramePacingReport | null {
|
|
196
|
+
return this.target === null ? null : this.target.pacing;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Whether the frame `frameRendered` just composited repeats the one before it.
|
|
201
|
+
*
|
|
202
|
+
* False without a target, and false when `presentedFrames` was never supplied — the same
|
|
203
|
+
* two "no evidence yet" cases `pacing` already has to account for. See
|
|
204
|
+
* `ExportTarget.duplicateFrame`, which this only forwards.
|
|
205
|
+
*/
|
|
206
|
+
get duplicateFrame(): boolean {
|
|
207
|
+
return this.target?.duplicateFrame ?? false;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Start the measurement over, keeping the schedule.
|
|
212
|
+
*
|
|
213
|
+
* For a caller that records a warm-up in front of the clip proper: what a device
|
|
214
|
+
* costs while an encoder gets going is not what the clip is like, and the report is
|
|
215
|
+
* what the export decides whether to warn the player on.
|
|
216
|
+
*/
|
|
217
|
+
resetPacing(): void {
|
|
218
|
+
this.target?.resetPacing();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
start(): void {
|
|
222
|
+
if (this.recorder !== null) return;
|
|
223
|
+
const { canvas, audio, fps = DEFAULT_CLIP_FPS } = this.options;
|
|
224
|
+
|
|
225
|
+
if (this.options.target !== undefined) this.prepare();
|
|
226
|
+
const source = this.targetStream ?? this.options.stream ?? canvas?.captureStream(fps) ?? null;
|
|
227
|
+
if (source === null) throw new Error('A recording needs a canvas, a stream or a target.');
|
|
228
|
+
|
|
229
|
+
/*
|
|
230
|
+
* A fresh stream rather than the source one. Adding the audio tracks to a
|
|
231
|
+
* stream the caller owns means stopping the recording would stop the audio
|
|
232
|
+
* graph's capture track too, and a second export would then come out silent.
|
|
233
|
+
*/
|
|
234
|
+
const stream = new MediaStream();
|
|
235
|
+
for (const track of source.getVideoTracks()) stream.addTrack(track);
|
|
236
|
+
if (audio != null) {
|
|
237
|
+
for (const track of audio.getAudioTracks()) stream.addTrack(track);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
this.chunks = [];
|
|
241
|
+
this.recorder = new MediaRecorder(stream, {
|
|
242
|
+
mimeType: this.mime,
|
|
243
|
+
videoBitsPerSecond: this.options.videoBitsPerSecond ?? this.defaultBitrate(stream, fps),
|
|
244
|
+
});
|
|
245
|
+
this.recorder.ondataavailable = (event): void => {
|
|
246
|
+
if (event.data.size > 0) this.chunks.push(event.data);
|
|
247
|
+
};
|
|
248
|
+
this.recorder.start();
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Resolves with the finished clip, or null if nothing was recorded.
|
|
253
|
+
*
|
|
254
|
+
* The surface goes back before the promise resolves either way. A cancelled
|
|
255
|
+
* export that left the drawing buffer pinned to 1080x1920 would leave the game
|
|
256
|
+
* rendering into the wrong shape for the rest of the session.
|
|
257
|
+
*/
|
|
258
|
+
async stop(): Promise<Blob | null> {
|
|
259
|
+
const recorder = this.recorder;
|
|
260
|
+
if (recorder === null) {
|
|
261
|
+
this.release();
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
this.recorder = null;
|
|
265
|
+
|
|
266
|
+
await new Promise<void>((resolve) => {
|
|
267
|
+
recorder.onstop = (): void => resolve();
|
|
268
|
+
try {
|
|
269
|
+
recorder.stop();
|
|
270
|
+
} catch {
|
|
271
|
+
resolve();
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
this.release();
|
|
275
|
+
|
|
276
|
+
if (this.chunks.length === 0) return null;
|
|
277
|
+
return new Blob(this.chunks, { type: this.mime });
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/** Give the render surface back. Safe at any point, and idempotent. */
|
|
281
|
+
release(): void {
|
|
282
|
+
this.target?.release();
|
|
283
|
+
this.target = null;
|
|
284
|
+
this.targetStream = null;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Bitrate from whatever the frame's real size turns out to be.
|
|
289
|
+
*
|
|
290
|
+
* Read from the track where possible, because that is the authority: a stream
|
|
291
|
+
* from a composited target has nothing to do with the canvas that was passed
|
|
292
|
+
* in, and guessing from the wrong one is how a 1080x1920 clip ends up encoded
|
|
293
|
+
* at a bitrate chosen for a 400-pixel window.
|
|
294
|
+
*/
|
|
295
|
+
private defaultBitrate(stream: MediaStream, fps: number): number {
|
|
296
|
+
const track = stream.getVideoTracks()[0];
|
|
297
|
+
const settings = track?.getSettings();
|
|
298
|
+
const width = settings?.width ?? this.options.canvas?.width ?? 1280;
|
|
299
|
+
const height = settings?.height ?? this.options.canvas?.height ?? 720;
|
|
300
|
+
return clipBitrate(width, height, fps);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Hand a file to the player.
|
|
306
|
+
*
|
|
307
|
+
* `navigator.share` where it exists, because on a phone that is one tap into
|
|
308
|
+
* the app they were going to post to anyway; a download otherwise. A file in
|
|
309
|
+
* the Downloads folder that nobody can find is most of the way to no export at
|
|
310
|
+
* all.
|
|
311
|
+
*/
|
|
312
|
+
export async function offerClip(blob: Blob, filename: string): Promise<void> {
|
|
313
|
+
const file = new File([blob], filename, { type: blob.type });
|
|
314
|
+
|
|
315
|
+
if (typeof navigator.canShare === 'function' && navigator.canShare({ files: [file] })) {
|
|
316
|
+
try {
|
|
317
|
+
await navigator.share({ files: [file] });
|
|
318
|
+
return;
|
|
319
|
+
} catch {
|
|
320
|
+
// Cancelled, or refused. Fall through to a download rather than leaving
|
|
321
|
+
// the player with nothing.
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const url = URL.createObjectURL(blob);
|
|
326
|
+
const link = document.createElement('a');
|
|
327
|
+
link.href = url;
|
|
328
|
+
link.download = filename;
|
|
329
|
+
link.click();
|
|
330
|
+
// Revoked on the next turn: doing it synchronously races the download in
|
|
331
|
+
// some browsers and produces an empty file.
|
|
332
|
+
setTimeout(() => URL.revokeObjectURL(url), 10_000);
|
|
333
|
+
}
|