@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,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which way is along the texture, at a fragment.
|
|
3
|
+
*
|
|
4
|
+
* Two sources and a selection. The attribute frame is what `geometry/tangents.ts` generated,
|
|
5
|
+
* interpolated across the triangle and re-orthogonalised here; the derived frame is the standard
|
|
6
|
+
* cotangent construction from screen-space derivatives, for a mesh that never went through the
|
|
7
|
+
* generator — which is every mesh `meshBuilder` makes procedurally.
|
|
8
|
+
*
|
|
9
|
+
* **Both are computed and one is chosen, rather than one being computed under a branch.** The
|
|
10
|
+
* derivatives below are legal only under uniform control flow, and `hasTangents` arrives as a
|
|
11
|
+
* varying — flat, but a compiler cannot prove a varying uniform. The caller puts this inside its
|
|
12
|
+
* branch on `uNormalStrength`, which is a real uniform, and the selection here is a ternary rather
|
|
13
|
+
* than a branch. `main.ts` carries the same arrangement for `fwidth(vWorldPos)` and the long
|
|
14
|
+
* reason beside it; `AGENTS.md` 2026-08-07 is the rule, and WGSL refuses the module outright
|
|
15
|
+
* rather than leaving a derivative in non-uniform control flow undefined.
|
|
16
|
+
*/
|
|
17
|
+
export const TANGENT_FRAME_GLSL = `mat3 tangentFrame(vec3 n, vec3 worldPos, vec2 uv, vec4 tangent, int hasTangents) {
|
|
18
|
+
/*
|
|
19
|
+
* The derived frame: solve for the axis along u from how position and uv change together over
|
|
20
|
+
* the pixel. Exact where the surface is locally planar, approximate where it curves, which is
|
|
21
|
+
* the trade for working at all on geometry that carries no frame.
|
|
22
|
+
*/
|
|
23
|
+
vec3 dp1 = dFdx(worldPos);
|
|
24
|
+
vec3 dp2 = dFdy(worldPos);
|
|
25
|
+
vec2 duv1 = dFdx(uv);
|
|
26
|
+
vec2 duv2 = dFdy(uv);
|
|
27
|
+
vec3 dp2perp = cross(dp2, n);
|
|
28
|
+
vec3 dp1perp = cross(n, dp1);
|
|
29
|
+
vec3 dt = dp2perp * duv1.x + dp1perp * duv2.x;
|
|
30
|
+
vec3 db = dp2perp * duv1.y + dp1perp * duv2.y;
|
|
31
|
+
/*
|
|
32
|
+
* **The determinant's sign, which magnitude-normalising throws away — and it is the difference
|
|
33
|
+
* between the two backends.**
|
|
34
|
+
*
|
|
35
|
+
* dFdy measures along *upward* window y in GLSL and along *downward* framebuffer y in WGSL, so
|
|
36
|
+
* dp2 and duv2 both arrive negated on WebGPU. The system this solves is invariant under that —
|
|
37
|
+
* both sides of its second equation flip — but the closed form above is not: dt and db each come
|
|
38
|
+
* out negated, and dividing by their *length* keeps the negation instead of cancelling it. The
|
|
39
|
+
* frame then points the other way on one backend, which reads as a surface lit from the wrong
|
|
40
|
+
* side and nothing else.
|
|
41
|
+
*
|
|
42
|
+
* The UV determinant flips with them, so folding its sign back in restores the invariance the
|
|
43
|
+
* solve always had. Measured before and after on demo/dev/normal.html: the derived panel stood
|
|
44
|
+
* 86 of 255 rms from the attribute panel on WebGPU and 8.8 on WebGL2; with this they agree.
|
|
45
|
+
*/
|
|
46
|
+
float det = duv1.x * duv2.y - duv2.x * duv1.y;
|
|
47
|
+
float handed = det < 0.0 ? -1.0 : 1.0;
|
|
48
|
+
/* One scale for both axes, so a stretched UV layout does not shear the frame it produces. */
|
|
49
|
+
float invmax = inversesqrt(max(max(dot(dt, dt), dot(db, db)), 1e-12)) * handed;
|
|
50
|
+
vec3 derivedT = dt * invmax;
|
|
51
|
+
vec3 derivedB = db * invmax;
|
|
52
|
+
|
|
53
|
+
/*
|
|
54
|
+
* The attribute frame, re-orthogonalised. Interpolating a tangent across a triangle leaves it
|
|
55
|
+
* no longer square to the interpolated normal, and Gram-Schmidt is what puts it back —
|
|
56
|
+
* generateTangents does the same per vertex and says why: dropping it is a normal map that
|
|
57
|
+
* shears wherever the geometry curves.
|
|
58
|
+
*/
|
|
59
|
+
vec3 attrT = normalize(tangent.xyz - n * dot(n, tangent.xyz));
|
|
60
|
+
/*
|
|
61
|
+
* The bitangent's sign, which is the whole reason w is stored. An artist mapping the left and
|
|
62
|
+
* right of a model onto one patch of texture gives one side a mirrored frame, and a bitangent
|
|
63
|
+
* computed without the sign lights that side inside out.
|
|
64
|
+
*/
|
|
65
|
+
vec3 attrB = cross(n, attrT) * tangent.w;
|
|
66
|
+
|
|
67
|
+
vec3 t = hasTangents != 0 ? attrT : derivedT;
|
|
68
|
+
vec3 b = hasTangents != 0 ? attrB : derivedB;
|
|
69
|
+
return mat3(t, b, n);
|
|
70
|
+
}`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const TEMPORAL_RESOLVE_FRAG: string;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The temporal resolve: this frame blended into where the last one was.
|
|
3
|
+
*
|
|
4
|
+
* **Antialiasing by moving the camera instead of by multiplying the fill rate.** The projection is
|
|
5
|
+
* shifted a fraction of a pixel each frame, so an edge that fell one side of a pixel centre falls
|
|
6
|
+
* the other side next frame; blending the two puts the edge where it actually is. What MSAA buys
|
|
7
|
+
* inside a frame this buys across frames, for one extra texture and one extra fullscreen pass —
|
|
8
|
+
* which is the trade a browser target wants, where MSAA on a float target is not free and on
|
|
9
|
+
* WebGL2 is not always available at all.
|
|
10
|
+
*
|
|
11
|
+
* **The motion is the camera's, and that is a stated limit rather than an oversight.** The
|
|
12
|
+
* reprojection matrix carries a pixel back through the previous view, which is exact for a static
|
|
13
|
+
* world under a moving camera and wrong for a moving object under a still one. A velocity buffer
|
|
14
|
+
* would fix the second, and it means a second colour attachment on the scene pass and every draw
|
|
15
|
+
* path writing into it — the README carries that as its own gap. What stands in for it here is the
|
|
16
|
+
* neighbourhood clip below, which rejects a history that no longer resembles what is around it;
|
|
17
|
+
* that covers a moving object crossing a background of a different colour, and does not cover one
|
|
18
|
+
* crossing a background of its own.
|
|
19
|
+
*
|
|
20
|
+
* The vertex stage is `FULLSCREEN_VERT`, shared with the occlusion pass, its blur and the rush.
|
|
21
|
+
*/
|
|
22
|
+
import { glslSceneDepthToNdc } from '../depthConvention.js';
|
|
23
|
+
export const TEMPORAL_RESOLVE_FRAG = `#version 300 es
|
|
24
|
+
precision highp float;
|
|
25
|
+
|
|
26
|
+
in vec2 vUv;
|
|
27
|
+
|
|
28
|
+
/** This frame, rasterised with the projection jittered by \`jitterOffset\`. */
|
|
29
|
+
uniform sampler2D uScene;
|
|
30
|
+
/** What this pass wrote last frame: resolved, and conceptually unjittered. */
|
|
31
|
+
uniform sampler2D uHistory;
|
|
32
|
+
/**
|
|
33
|
+
* The frame's depth.
|
|
34
|
+
*
|
|
35
|
+
* **highp, and it is not decoration.** GLSL ES gives a fragment shader's samplers a default
|
|
36
|
+
* precision of *lowp* whatever \`precision highp float\` says at the top of the file — that line
|
|
37
|
+
* sets the default for float and not for a sampler. A lowp sampler may hand back eight bits, and
|
|
38
|
+
* a depth buffer read at eight bits reprojects to visibly the wrong place. \`rush.ts\` carries the
|
|
39
|
+
* same note for the same reason.
|
|
40
|
+
*/
|
|
41
|
+
uniform highp sampler2D uDepth;
|
|
42
|
+
/**
|
|
43
|
+
* The previous view-projection times the inverse of this frame's, so one multiply carries a point
|
|
44
|
+
* from this frame's clip space to the last one's.
|
|
45
|
+
*
|
|
46
|
+
* **Built from the unjittered matrices**, which is why the jitter is applied to a copy used only
|
|
47
|
+
* for rasterising and never to the \`viewProj\` the renderer keeps. The history holds a resolved
|
|
48
|
+
* picture that stands for the unjittered scene, so reprojecting into it through a jittered matrix
|
|
49
|
+
* would look the sample up half a pixel from where it is and undo the accumulation it is trying to
|
|
50
|
+
* build. Camera motion blur reads this same matrix and has a test on it.
|
|
51
|
+
*/
|
|
52
|
+
uniform mat4 uReprojection;
|
|
53
|
+
/** One texel of the target, for walking the neighbourhood. */
|
|
54
|
+
uniform vec2 uTexel;
|
|
55
|
+
/**
|
|
56
|
+
* How much of the clipped history to keep, 0 to 1.
|
|
57
|
+
*
|
|
58
|
+
* **Zero is the whole switch.** The first frame, the frame after a resize and the frame after a
|
|
59
|
+
* cut have nothing to sample, and they pass this as zero; so does a renderer with the effect off.
|
|
60
|
+
* The branch on it is the first thing in \`main\`, so an untouched frame costs one compare and the
|
|
61
|
+
* pass is not run at all when the effect is off.
|
|
62
|
+
*/
|
|
63
|
+
uniform float uHistoryBlend;
|
|
64
|
+
|
|
65
|
+
out vec4 fragColor;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The colours actually present around this pixel this frame, as a box.
|
|
69
|
+
*
|
|
70
|
+
* Nine taps rather than five: the diagonals are what catch a thin edge running corner to corner,
|
|
71
|
+
* which is exactly the geometry temporal antialiasing exists for, and a cross-shaped
|
|
72
|
+
* neighbourhood lets a history through along it.
|
|
73
|
+
*
|
|
74
|
+
* **Every fetch is an explicit level.** An implicit derivative under a branch that is not provably
|
|
75
|
+
* uniform fails to compile in WGSL, which invalidates the pipeline and the command buffer while
|
|
76
|
+
* the frame still presents — a failure this repository has paid for more than once, and the reason
|
|
77
|
+
* \`film.ts\` carries the same note.
|
|
78
|
+
*/
|
|
79
|
+
void neighbourhood(out vec3 lo, out vec3 hi) {
|
|
80
|
+
lo = vec3(1e9);
|
|
81
|
+
hi = vec3(-1e9);
|
|
82
|
+
for (int y = -1; y <= 1; y++) {
|
|
83
|
+
for (int x = -1; x <= 1; x++) {
|
|
84
|
+
vec3 c = textureLod(uScene, vUv + vec2(float(x), float(y)) * uTexel, 0.0).rgb;
|
|
85
|
+
lo = min(lo, c);
|
|
86
|
+
hi = max(hi, c);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* \`history\` pulled into the box, along the line towards its centre.
|
|
93
|
+
*
|
|
94
|
+
* Clipped towards the centre rather than clamped per channel: a clamp moves each channel on its
|
|
95
|
+
* own, so a history merely brighter than its surroundings lands on a corner of the box and comes
|
|
96
|
+
* back a different hue, which reads as coloured fringing along every moving edge. Shortening the
|
|
97
|
+
* whole offset by one ratio keeps the direction and changes only the length.
|
|
98
|
+
*
|
|
99
|
+
* The same arithmetic is \`clipToNeighbourhood\` in \`temporalAa.ts\`, which is where it is asserted
|
|
100
|
+
* against numbers; the test beside this file asserts the shader still spells it this way.
|
|
101
|
+
*/
|
|
102
|
+
vec3 clipToNeighbourhood(vec3 history, vec3 lo, vec3 hi) {
|
|
103
|
+
vec3 centre = (lo + hi) * 0.5;
|
|
104
|
+
vec3 extent = (hi - lo) * 0.5;
|
|
105
|
+
vec3 offset = history - centre;
|
|
106
|
+
/* A channel with no extent cannot bound anything; the max below then answers for the others. */
|
|
107
|
+
vec3 ratios = abs(offset) / max(extent, vec3(1e-7));
|
|
108
|
+
float ratio = max(ratios.x, max(ratios.y, ratios.z));
|
|
109
|
+
if (ratio <= 1.0) return history;
|
|
110
|
+
return centre + offset / ratio;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
void main() {
|
|
114
|
+
vec3 current = textureLod(uScene, vUv, 0.0).rgb;
|
|
115
|
+
|
|
116
|
+
/* Nothing to blend towards: the first frame, a resize, a cut, or the effect switched off. */
|
|
117
|
+
if (uHistoryBlend <= 0.0) {
|
|
118
|
+
fragColor = vec4(current, 1.0);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
float depth = textureLod(uDepth, vUv, 0.0).r;
|
|
123
|
+
vec4 clip = vec4(vUv * 2.0 - 1.0, ${glslSceneDepthToNdc('depth')}, 1.0);
|
|
124
|
+
vec4 previous = uReprojection * clip;
|
|
125
|
+
/* Behind the previous eye: there is no last-frame position to sample. */
|
|
126
|
+
if (previous.w <= 0.0) {
|
|
127
|
+
fragColor = vec4(current, 1.0);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
vec2 wasUv = (previous.xy / previous.w) * 0.5 + 0.5;
|
|
132
|
+
/*
|
|
133
|
+
* **Off the edge of the last frame is a disocclusion**, and the honest answer is this frame's
|
|
134
|
+
* colour rather than a clamped sample of the border, which would drag one row of pixels inward
|
|
135
|
+
* as a smear for as long as the camera kept turning.
|
|
136
|
+
*/
|
|
137
|
+
if (wasUv.x < 0.0 || wasUv.x > 1.0 || wasUv.y < 0.0 || wasUv.y > 1.0) {
|
|
138
|
+
fragColor = vec4(current, 1.0);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
vec3 lo;
|
|
143
|
+
vec3 hi;
|
|
144
|
+
neighbourhood(lo, hi);
|
|
145
|
+
vec3 history = textureLod(uHistory, wasUv, 0.0).rgb;
|
|
146
|
+
vec3 bounded = clipToNeighbourhood(history, lo, hi);
|
|
147
|
+
|
|
148
|
+
fragColor = vec4(mix(current, bounded, uHistoryBlend), 1.0);
|
|
149
|
+
}
|
|
150
|
+
`;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Screen-space 3D text.
|
|
3
|
+
*
|
|
4
|
+
* Every lit cell of every glyph is one instanced cube. That sounds extravagant
|
|
5
|
+
* and is not: a fifteen-character message is a few hundred boxes, one draw
|
|
6
|
+
* call, and it buys real geometry — text that catches light, casts its own
|
|
7
|
+
* shading, and can rotate in depth. Drawing it as a textured quad would put a
|
|
8
|
+
* flat sticker over a flat-shaded world, which is exactly the "HTML on top"
|
|
9
|
+
* look this exists to get rid of.
|
|
10
|
+
*
|
|
11
|
+
* The projection is built here rather than taken from the scene camera. Text is
|
|
12
|
+
* laid out in pixels and must land where the UI says it lands, whatever the
|
|
13
|
+
* gameplay camera is doing — but it still wants perspective, or a rotating
|
|
14
|
+
* letter shears instead of turning.
|
|
15
|
+
*/
|
|
16
|
+
export declare const TEXT_VERT = "#version 300 es\nprecision highp float;\n\nlayout(location = 0) in vec3 aCorner;\nlayout(location = 1) in vec3 aNormal;\n/** Cell position in pixels, relative to the string's origin. */\nlayout(location = 2) in vec2 aCell;\n/** Which character this cell belongs to, for staggered animation. */\nlayout(location = 3) in float aCharIndex;\n\nuniform vec2 uViewport;\n/** Where the string's baseline-left sits, in pixels from the top left. */\nuniform vec2 uOrigin;\nuniform float uCellSize;\n/** Distance from the virtual camera; larger flattens the perspective. */\nuniform float uDepth;\n\n/** 0 before a character has arrived, 1 once it has settled. */\nuniform float uReveal;\n/** How many characters the stagger spans \u2014 the whole line, not this piece. */\nuniform float uCharCount;\n/**\n * Where this piece starts within that line.\n *\n * A line drawn in several pieces \u2014 words around a keycap \u2014 must stagger as one\n * sentence. Without this each piece restarts at zero, so the second word begins\n * arriving before the first has finished and they sit at different heights\n * through the whole animation.\n */\nuniform float uCharOffset;\n/** Radians of entry rotation, decaying to zero as a character settles. */\nuniform float uSpin;\n/** Extra scale at the moment of arrival \u2014 the overshoot. */\nuniform float uPunch;\n/** Vertical bob amplitude in pixels, and its phase. */\nuniform float uBob;\nuniform float uTime;\n/**\n * Clip space, as the backend drawing this defines it. Identity on WebGL2.\n *\n * This draw builds its own clip position from pixels and never multiplies by a camera, so\n * the correction every other draw carries in its view-projection cannot reach it \u2014 the same\n * gap that left the sky unprojecting through the wrong space. Two things are wrong without\n * it on WebGPU, and only one of them is visible: the generated vertex shader negates Y, so\n * the message renders upside down; and z here is a narrow slice about zero, which is inside\n * OpenGL's [-1, 1] and *outside* WebGPU's [0, 1], so half of every glyph is clipped away.\n */\nuniform mat4 uClipCorrection;\n\nout vec3 vNormal;\nout float vDepth;\nout float vChar;\n\n/**\n * Spring settle: overshoots once and comes back.\n *\n * A character that eases into place reads as an element appearing; one that\n * overshoots and settles reads as an object arriving. That difference is most\n * of what makes text feel like part of a game rather than part of a page.\n */\nfloat settle(float t) {\n if (t <= 0.0) return 0.0;\n if (t >= 1.0) return 1.0;\n float d = 1.0 - t;\n return 1.0 - d * d * cos(t * 12.0) ;\n}\n\nmat2 rot(float a) {\n float s = sin(a);\n float c = cos(a);\n return mat2(c, -s, s, c);\n}\n\nvoid main() {\n // Stagger: each character starts a fraction of the reveal later than the\n // one before it, so the message assembles left to right.\n float span = max(uCharCount, 1.0);\n float start = ((aCharIndex + uCharOffset) / span) * 0.55;\n float local = clamp((uReveal - start) / max(0.45, 1.0 - start), 0.0, 1.0);\n float eased = settle(local);\n\n // Arrives spinning about its own horizontal axis and dropping into place.\n float spin = uSpin * (1.0 - eased);\n float rise = (1.0 - eased) * uCellSize * 6.0;\n float punch = 1.0 + uPunch * (1.0 - abs(eased * 2.0 - 1.0));\n\n vec3 local3 = aCorner * uCellSize * 0.5 * punch;\n local3.yz = rot(spin) * local3.yz;\n\n vec2 cell = aCell * uCellSize;\n float bob = sin(uTime * 3.1 + aCharIndex * 0.7) * uBob;\n\n // Pixels, y down from the top-left corner of the viewport.\n vec2 screen = uOrigin + vec2(cell.x, -cell.y) + vec2(0.0, rise - bob);\n vec3 view = vec3(screen + local3.xy, -uDepth + local3.z);\n\n // A hand-built perspective divide. The near plane is the viewport itself, so\n // a cell at depth uDepth is exactly its pixel size on screen.\n float invDepth = uDepth / max(0.001, -view.z);\n vec2 ndc = ((view.xy * invDepth) / uViewport) * 2.0 - 1.0;\n // Depth from the cube's own extrusion, mapped into a narrow slice of the\n // range so a message sorts against itself without ever reaching the scene.\n float depth = clamp(-local3.z / max(1.0, uCellSize * 2.0), -1.0, 1.0) * 0.4;\n gl_Position = uClipCorrection * vec4(ndc.x, -ndc.y, depth, 1.0);\n\n vec3 n = aNormal;\n n.yz = rot(spin) * n.yz;\n vNormal = n;\n vDepth = local3.z;\n vChar = eased;\n}";
|
|
17
|
+
export declare const TEXT_FRAG = "#version 300 es\nprecision highp float;\n\nin vec3 vNormal;\nin float vDepth;\nin float vChar;\n\nuniform vec3 uColor;\n/** Self-illumination on top of the shaded colour. */\nuniform float uGlow;\nuniform float uAlpha;\n\nout vec4 fragColor;\n\nvoid main() {\n /*\n * A fixed key light rather than the world's. Text has to stay legible at\n * midnight and at noon, and lighting it with the scene would make a\n * notification unreadable on exactly the night runs where it matters most.\n * The light only exists to give the cubes an edge.\n */\n vec3 key = normalize(vec3(-0.35, 0.7, 0.6));\n float lambert = 0.55 + 0.45 * max(dot(normalize(vNormal), key), 0.0);\n\n vec3 lit = uColor * lambert;\n // The glow rides the arrival: brightest as a character lands, settling after.\n vec3 emissive = uColor * uGlow * (0.45 + 0.55 * vChar);\n fragColor = vec4(lit + emissive, uAlpha);\n}";
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Screen-space 3D text.
|
|
3
|
+
*
|
|
4
|
+
* Every lit cell of every glyph is one instanced cube. That sounds extravagant
|
|
5
|
+
* and is not: a fifteen-character message is a few hundred boxes, one draw
|
|
6
|
+
* call, and it buys real geometry — text that catches light, casts its own
|
|
7
|
+
* shading, and can rotate in depth. Drawing it as a textured quad would put a
|
|
8
|
+
* flat sticker over a flat-shaded world, which is exactly the "HTML on top"
|
|
9
|
+
* look this exists to get rid of.
|
|
10
|
+
*
|
|
11
|
+
* The projection is built here rather than taken from the scene camera. Text is
|
|
12
|
+
* laid out in pixels and must land where the UI says it lands, whatever the
|
|
13
|
+
* gameplay camera is doing — but it still wants perspective, or a rotating
|
|
14
|
+
* letter shears instead of turning.
|
|
15
|
+
*/
|
|
16
|
+
export const TEXT_VERT = `#version 300 es
|
|
17
|
+
precision highp float;
|
|
18
|
+
|
|
19
|
+
layout(location = 0) in vec3 aCorner;
|
|
20
|
+
layout(location = 1) in vec3 aNormal;
|
|
21
|
+
/** Cell position in pixels, relative to the string's origin. */
|
|
22
|
+
layout(location = 2) in vec2 aCell;
|
|
23
|
+
/** Which character this cell belongs to, for staggered animation. */
|
|
24
|
+
layout(location = 3) in float aCharIndex;
|
|
25
|
+
|
|
26
|
+
uniform vec2 uViewport;
|
|
27
|
+
/** Where the string's baseline-left sits, in pixels from the top left. */
|
|
28
|
+
uniform vec2 uOrigin;
|
|
29
|
+
uniform float uCellSize;
|
|
30
|
+
/** Distance from the virtual camera; larger flattens the perspective. */
|
|
31
|
+
uniform float uDepth;
|
|
32
|
+
|
|
33
|
+
/** 0 before a character has arrived, 1 once it has settled. */
|
|
34
|
+
uniform float uReveal;
|
|
35
|
+
/** How many characters the stagger spans — the whole line, not this piece. */
|
|
36
|
+
uniform float uCharCount;
|
|
37
|
+
/**
|
|
38
|
+
* Where this piece starts within that line.
|
|
39
|
+
*
|
|
40
|
+
* A line drawn in several pieces — words around a keycap — must stagger as one
|
|
41
|
+
* sentence. Without this each piece restarts at zero, so the second word begins
|
|
42
|
+
* arriving before the first has finished and they sit at different heights
|
|
43
|
+
* through the whole animation.
|
|
44
|
+
*/
|
|
45
|
+
uniform float uCharOffset;
|
|
46
|
+
/** Radians of entry rotation, decaying to zero as a character settles. */
|
|
47
|
+
uniform float uSpin;
|
|
48
|
+
/** Extra scale at the moment of arrival — the overshoot. */
|
|
49
|
+
uniform float uPunch;
|
|
50
|
+
/** Vertical bob amplitude in pixels, and its phase. */
|
|
51
|
+
uniform float uBob;
|
|
52
|
+
uniform float uTime;
|
|
53
|
+
/**
|
|
54
|
+
* Clip space, as the backend drawing this defines it. Identity on WebGL2.
|
|
55
|
+
*
|
|
56
|
+
* This draw builds its own clip position from pixels and never multiplies by a camera, so
|
|
57
|
+
* the correction every other draw carries in its view-projection cannot reach it — the same
|
|
58
|
+
* gap that left the sky unprojecting through the wrong space. Two things are wrong without
|
|
59
|
+
* it on WebGPU, and only one of them is visible: the generated vertex shader negates Y, so
|
|
60
|
+
* the message renders upside down; and z here is a narrow slice about zero, which is inside
|
|
61
|
+
* OpenGL's [-1, 1] and *outside* WebGPU's [0, 1], so half of every glyph is clipped away.
|
|
62
|
+
*/
|
|
63
|
+
uniform mat4 uClipCorrection;
|
|
64
|
+
|
|
65
|
+
out vec3 vNormal;
|
|
66
|
+
out float vDepth;
|
|
67
|
+
out float vChar;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Spring settle: overshoots once and comes back.
|
|
71
|
+
*
|
|
72
|
+
* A character that eases into place reads as an element appearing; one that
|
|
73
|
+
* overshoots and settles reads as an object arriving. That difference is most
|
|
74
|
+
* of what makes text feel like part of a game rather than part of a page.
|
|
75
|
+
*/
|
|
76
|
+
float settle(float t) {
|
|
77
|
+
if (t <= 0.0) return 0.0;
|
|
78
|
+
if (t >= 1.0) return 1.0;
|
|
79
|
+
float d = 1.0 - t;
|
|
80
|
+
return 1.0 - d * d * cos(t * 12.0) ;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
mat2 rot(float a) {
|
|
84
|
+
float s = sin(a);
|
|
85
|
+
float c = cos(a);
|
|
86
|
+
return mat2(c, -s, s, c);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
void main() {
|
|
90
|
+
// Stagger: each character starts a fraction of the reveal later than the
|
|
91
|
+
// one before it, so the message assembles left to right.
|
|
92
|
+
float span = max(uCharCount, 1.0);
|
|
93
|
+
float start = ((aCharIndex + uCharOffset) / span) * 0.55;
|
|
94
|
+
float local = clamp((uReveal - start) / max(0.45, 1.0 - start), 0.0, 1.0);
|
|
95
|
+
float eased = settle(local);
|
|
96
|
+
|
|
97
|
+
// Arrives spinning about its own horizontal axis and dropping into place.
|
|
98
|
+
float spin = uSpin * (1.0 - eased);
|
|
99
|
+
float rise = (1.0 - eased) * uCellSize * 6.0;
|
|
100
|
+
float punch = 1.0 + uPunch * (1.0 - abs(eased * 2.0 - 1.0));
|
|
101
|
+
|
|
102
|
+
vec3 local3 = aCorner * uCellSize * 0.5 * punch;
|
|
103
|
+
local3.yz = rot(spin) * local3.yz;
|
|
104
|
+
|
|
105
|
+
vec2 cell = aCell * uCellSize;
|
|
106
|
+
float bob = sin(uTime * 3.1 + aCharIndex * 0.7) * uBob;
|
|
107
|
+
|
|
108
|
+
// Pixels, y down from the top-left corner of the viewport.
|
|
109
|
+
vec2 screen = uOrigin + vec2(cell.x, -cell.y) + vec2(0.0, rise - bob);
|
|
110
|
+
vec3 view = vec3(screen + local3.xy, -uDepth + local3.z);
|
|
111
|
+
|
|
112
|
+
// A hand-built perspective divide. The near plane is the viewport itself, so
|
|
113
|
+
// a cell at depth uDepth is exactly its pixel size on screen.
|
|
114
|
+
float invDepth = uDepth / max(0.001, -view.z);
|
|
115
|
+
vec2 ndc = ((view.xy * invDepth) / uViewport) * 2.0 - 1.0;
|
|
116
|
+
// Depth from the cube's own extrusion, mapped into a narrow slice of the
|
|
117
|
+
// range so a message sorts against itself without ever reaching the scene.
|
|
118
|
+
float depth = clamp(-local3.z / max(1.0, uCellSize * 2.0), -1.0, 1.0) * 0.4;
|
|
119
|
+
gl_Position = uClipCorrection * vec4(ndc.x, -ndc.y, depth, 1.0);
|
|
120
|
+
|
|
121
|
+
vec3 n = aNormal;
|
|
122
|
+
n.yz = rot(spin) * n.yz;
|
|
123
|
+
vNormal = n;
|
|
124
|
+
vDepth = local3.z;
|
|
125
|
+
vChar = eased;
|
|
126
|
+
}`;
|
|
127
|
+
export const TEXT_FRAG = `#version 300 es
|
|
128
|
+
precision highp float;
|
|
129
|
+
|
|
130
|
+
in vec3 vNormal;
|
|
131
|
+
in float vDepth;
|
|
132
|
+
in float vChar;
|
|
133
|
+
|
|
134
|
+
uniform vec3 uColor;
|
|
135
|
+
/** Self-illumination on top of the shaded colour. */
|
|
136
|
+
uniform float uGlow;
|
|
137
|
+
uniform float uAlpha;
|
|
138
|
+
|
|
139
|
+
out vec4 fragColor;
|
|
140
|
+
|
|
141
|
+
void main() {
|
|
142
|
+
/*
|
|
143
|
+
* A fixed key light rather than the world's. Text has to stay legible at
|
|
144
|
+
* midnight and at noon, and lighting it with the scene would make a
|
|
145
|
+
* notification unreadable on exactly the night runs where it matters most.
|
|
146
|
+
* The light only exists to give the cubes an edge.
|
|
147
|
+
*/
|
|
148
|
+
vec3 key = normalize(vec3(-0.35, 0.7, 0.6));
|
|
149
|
+
float lambert = 0.55 + 0.45 * max(dot(normalize(vNormal), key), 0.0);
|
|
150
|
+
|
|
151
|
+
vec3 lit = uColor * lambert;
|
|
152
|
+
// The glow rides the arrival: brightest as a character lands, settling after.
|
|
153
|
+
vec3 emissive = uColor * uGlow * (0.45 + 0.55 * vChar);
|
|
154
|
+
fragColor = vec4(lit + emissive, uAlpha);
|
|
155
|
+
}`;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The per-vertex channel's declaration and its wind displacement, authored once for two programs.
|
|
3
|
+
*
|
|
4
|
+
* **Shared source rather than two copies, for the reason `scatter.ts` gives about its own.** The
|
|
5
|
+
* colour pass and the depth pass have to agree *exactly*: a canopy that bends in one and stands
|
|
6
|
+
* still in the other slides its whole shade off the ground it belongs to, and the drift follows
|
|
7
|
+
* the gust, so it never reads as a constant offset anybody could find by looking. One expression,
|
|
8
|
+
* two callers.
|
|
9
|
+
*
|
|
10
|
+
* The lanes are `MeshData.channel`: `.x` sway, `.y` skyDirect, `.z` alpha, `.w` reserved. Only
|
|
11
|
+
* `.x` is read here; the other two are varyings the fragment stage consumes.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* The attribute, and the wind the bend below reads.
|
|
15
|
+
*
|
|
16
|
+
* Declared unconditionally in every vertex variant. **No lane is a permutation**: the fragment
|
|
17
|
+
* stage already carries sixteen of those at 282.2 KB gzipped, where the whole vertex stage is
|
|
18
|
+
* 4.1 KB across five, so a `#if` here would buy nothing measurable and cost a variant axis.
|
|
19
|
+
*/
|
|
20
|
+
export declare const CHANNEL_ATTRIBUTE = "\nlayout(location = 13) in vec4 aChannel;\n\n/*\n * The frame's wind, already converted by `resolveScatterDeform` \u2014 a normalised direction, metres\n * of bend, a gust amplitude and a scaled clock.\n *\n * **The same numbers the scatter batch reads, and that is the rule rather than an economy.** A\n * second conversion here would be a second wind however identical its inputs, and the failure is\n * not localised: it shows up as a scene that does not cohere, a canopy leaning one way while the\n * grass beneath it leans another, with no single element looking wrong. See \"One wind, sampled\n * once\" in AGENTS.md.\n */\nuniform vec2 uWindDirection;\nuniform float uWindSpeed;\nuniform float uWindGust;\nuniform float uWindTime;\n/* Spatial frequency of the travelling gust, per metre. */\nuniform vec2 uWindSpatialPhase;\n";
|
|
21
|
+
/**
|
|
22
|
+
* Where the wind puts a vertex, given how much of it that vertex takes.
|
|
23
|
+
*
|
|
24
|
+
* Phase comes from world position, so neighbouring geometry is never in lockstep and a gust
|
|
25
|
+
* visibly travels across a canopy instead of the whole canopy pulsing at once. That is the scatter
|
|
26
|
+
* shader's reasoning and it transfers without change.
|
|
27
|
+
*
|
|
28
|
+
* **The lane scales the bend once, where `scatter.ts` squares its own falloff.** That file derives
|
|
29
|
+
* its falloff from height, and a linear response there slides a whole plant sideways and reads as
|
|
30
|
+
* the ground moving, so it squares to keep the base planted. Here the falloff is *authored* — 0 on
|
|
31
|
+
* a trunk, 1 at a leaf tip — and squaring it would silently overrule a curve somebody had already
|
|
32
|
+
* shaped. What that costs is that a lane filled linearly up a trunk gives a tree that slides at
|
|
33
|
+
* its base; the fix is the curve the author meant, not a square in the shader.
|
|
34
|
+
*
|
|
35
|
+
* The early return is not an optimisation. Geometry that never said it bends must reach exactly
|
|
36
|
+
* the position it reached before this existed, and `sin` of a phase multiplied by zero is not
|
|
37
|
+
* bit-identical to not moving at all.
|
|
38
|
+
*/
|
|
39
|
+
export declare const CHANNEL_BEND = "\nvec3 channelBend(vec3 worldPos, float sway) {\n if (sway <= 0.0) return worldPos;\n float phase = dot(worldPos.xz, uWindSpatialPhase) + uWindTime;\n float bend = (uWindSpeed + uWindGust) * sin(phase) * sway;\n return vec3(\n worldPos.x + uWindDirection.x * bend,\n worldPos.y,\n worldPos.z + uWindDirection.y * bend\n );\n}\n";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The per-vertex channel's declaration and its wind displacement, authored once for two programs.
|
|
3
|
+
*
|
|
4
|
+
* **Shared source rather than two copies, for the reason `scatter.ts` gives about its own.** The
|
|
5
|
+
* colour pass and the depth pass have to agree *exactly*: a canopy that bends in one and stands
|
|
6
|
+
* still in the other slides its whole shade off the ground it belongs to, and the drift follows
|
|
7
|
+
* the gust, so it never reads as a constant offset anybody could find by looking. One expression,
|
|
8
|
+
* two callers.
|
|
9
|
+
*
|
|
10
|
+
* The lanes are `MeshData.channel`: `.x` sway, `.y` skyDirect, `.z` alpha, `.w` reserved. Only
|
|
11
|
+
* `.x` is read here; the other two are varyings the fragment stage consumes.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* The attribute, and the wind the bend below reads.
|
|
15
|
+
*
|
|
16
|
+
* Declared unconditionally in every vertex variant. **No lane is a permutation**: the fragment
|
|
17
|
+
* stage already carries sixteen of those at 282.2 KB gzipped, where the whole vertex stage is
|
|
18
|
+
* 4.1 KB across five, so a `#if` here would buy nothing measurable and cost a variant axis.
|
|
19
|
+
*/
|
|
20
|
+
export const CHANNEL_ATTRIBUTE = `
|
|
21
|
+
layout(location = 13) in vec4 aChannel;
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* The frame's wind, already converted by \`resolveScatterDeform\` — a normalised direction, metres
|
|
25
|
+
* of bend, a gust amplitude and a scaled clock.
|
|
26
|
+
*
|
|
27
|
+
* **The same numbers the scatter batch reads, and that is the rule rather than an economy.** A
|
|
28
|
+
* second conversion here would be a second wind however identical its inputs, and the failure is
|
|
29
|
+
* not localised: it shows up as a scene that does not cohere, a canopy leaning one way while the
|
|
30
|
+
* grass beneath it leans another, with no single element looking wrong. See "One wind, sampled
|
|
31
|
+
* once" in AGENTS.md.
|
|
32
|
+
*/
|
|
33
|
+
uniform vec2 uWindDirection;
|
|
34
|
+
uniform float uWindSpeed;
|
|
35
|
+
uniform float uWindGust;
|
|
36
|
+
uniform float uWindTime;
|
|
37
|
+
/* Spatial frequency of the travelling gust, per metre. */
|
|
38
|
+
uniform vec2 uWindSpatialPhase;
|
|
39
|
+
`;
|
|
40
|
+
/**
|
|
41
|
+
* Where the wind puts a vertex, given how much of it that vertex takes.
|
|
42
|
+
*
|
|
43
|
+
* Phase comes from world position, so neighbouring geometry is never in lockstep and a gust
|
|
44
|
+
* visibly travels across a canopy instead of the whole canopy pulsing at once. That is the scatter
|
|
45
|
+
* shader's reasoning and it transfers without change.
|
|
46
|
+
*
|
|
47
|
+
* **The lane scales the bend once, where `scatter.ts` squares its own falloff.** That file derives
|
|
48
|
+
* its falloff from height, and a linear response there slides a whole plant sideways and reads as
|
|
49
|
+
* the ground moving, so it squares to keep the base planted. Here the falloff is *authored* — 0 on
|
|
50
|
+
* a trunk, 1 at a leaf tip — and squaring it would silently overrule a curve somebody had already
|
|
51
|
+
* shaped. What that costs is that a lane filled linearly up a trunk gives a tree that slides at
|
|
52
|
+
* its base; the fix is the curve the author meant, not a square in the shader.
|
|
53
|
+
*
|
|
54
|
+
* The early return is not an optimisation. Geometry that never said it bends must reach exactly
|
|
55
|
+
* the position it reached before this existed, and `sin` of a phase multiplied by zero is not
|
|
56
|
+
* bit-identical to not moving at all.
|
|
57
|
+
*/
|
|
58
|
+
export const CHANNEL_BEND = `
|
|
59
|
+
vec3 channelBend(vec3 worldPos, float sway) {
|
|
60
|
+
if (sway <= 0.0) return worldPos;
|
|
61
|
+
float phase = dot(worldPos.xz, uWindSpatialPhase) + uWindTime;
|
|
62
|
+
float bend = (uWindSpeed + uWindGust) * sin(phase) * sway;
|
|
63
|
+
return vec3(
|
|
64
|
+
worldPos.x + uWindDirection.x * bend,
|
|
65
|
+
worldPos.y,
|
|
66
|
+
worldPos.z + uWindDirection.y * bend
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sky-ocean, as an actual wave simulation rather than a tinted plane.
|
|
3
|
+
*
|
|
4
|
+
* Four summed Gerstner waves: unlike a sine heightfield, Gerstner displaces
|
|
5
|
+
* vertices *horizontally* toward crests as well as vertically, which is what
|
|
6
|
+
* produces sharp peaks and broad troughs instead of a rolling blanket. Normals
|
|
7
|
+
* come analytically from the same sum, so lighting matches the geometry exactly
|
|
8
|
+
* and needs no derivative tricks.
|
|
9
|
+
*
|
|
10
|
+
* The wave field itself lives in `gerstner.ts` because it is shared: the caustics
|
|
11
|
+
* in `caustics.ts` are the light *this* surface throws onto what covers it, and
|
|
12
|
+
* they must be the same water, not a lookalike animated separately.
|
|
13
|
+
*
|
|
14
|
+
* The grid follows the camera and is snapped to whole cells, giving an endless
|
|
15
|
+
* ocean from a fixed vertex budget without the surface sliding underfoot.
|
|
16
|
+
*/
|
|
17
|
+
export declare const WATER_VERT = "#version 300 es\nlayout(location = 0) in vec2 aGrid;\n\nuniform mat4 uViewProj;\nuniform mat4 uReflectionViewProj;\nuniform vec3 uCameraPos;\nuniform float uTime;\n/**\n * Where the sheet is laid, in world XZ.\n *\n * The ocean passes its own camera position snapped to whole cells, which is what\n * gives an endless sea from a fixed vertex budget without the surface sliding\n * underfoot. A *bounded* sheet \u2014 a pool in a courtyard \u2014 passes the middle of the\n * thing it is filling instead, and is world-fixed by construction.\n *\n * Snapped on the CPU rather than here so that one number is the only difference\n * between an ocean and a basin, and the shader has no idea which it is drawing.\n */\nuniform vec2 uGridOrigin;\n/**\n * Metres per unit of the sheet's own grid, along each of the body's own axes.\n *\n * One and one for the ocean, whose grid is authored in metres and is two meshes wide.\n * A bounded body \u2014 a pool, a tank, a puddle, a channel \u2014 is drawn from a unit sheet\n * and scaled by its own half-extents, which is what lets one mesh and one material\n * serve every body of water in the world.\n *\n * **Two numbers and not one since 2026-08-28.** A single span makes every bounded\n * body square, and a square that contains a channel floods the ground either side\n * of it. The ocean passes the same number twice and is bit-identical to what it was.\n */\nuniform vec2 uGridSpan;\nuniform vec2 uGridHalf;\nuniform vec2 uNearHalf;\n/**\n * The body's own +z, in world XZ, unit length. (0, 1) leaves the sheet unturned.\n *\n * A direction rather than an angle, so nothing here needs a trig call and a consumer\n * bounding a channel can hand over the direction its run already takes. The across\n * axis is world up crossed with this, `(fz, -fx)`, which is the basis\n * `MeshBuilder.addOrientedBox` builds from a forward vector \u2014 one convention for an\n * oriented thing, so a reader who has met one has met both.\n */\nuniform vec2 uGridForward;\n/** Prevailing wind bearing, normalised. Waves are steered toward it. */\nuniform vec2 uWindDir;\n/** Multiplier on authored steepness \u2014 how built-up the sea is. */\nuniform float uWaveGain;\nuniform float uWaterLevel;\n\nout vec3 vWorldPos;\nout vec3 vNormal;\nout float vCrest;\nout vec4 vReflectionClip;\n/** Grid-local offset, so the sheet can fade out its own boundary. */\nout vec2 vGrid;\n\n\nconst int GERSTNER_COUNT = 4;\n/*\n * direction.xy, steepness, wavelength. Amplitude is steepness/k, so these sum to\n * roughly a 1m swell \u2014 enough to read as a living surface, low enough that crests\n * never wash over an island whose deck sits ~1.8m above sea level.\n */\nconst vec4 GERSTNER_WAVES[4] = vec4[4](\n vec4( 1.0, 0.0, 0.115, 34.0),\n vec4( 0.6, 0.8, 0.100, 18.0),\n vec4(-0.7, 0.7, 0.080, 9.0),\n vec4( 0.2, -0.98, 0.060, 5.0)\n);\n\n/*\n * Steer each wave toward the wind, but only partway. A real sea is a dominant\n * swell plus cross-chop; rotating all four onto one bearing gives corduroy,\n * which reads as a material rather than as water.\n */\nvec2 gerstnerDirection(int i, vec2 windDir) {\n return normalize(mix(normalize(GERSTNER_WAVES[i].xy), windDir, 0.62));\n}\n\nfloat gerstnerWavenumber(int i) {\n return 6.28318530718 / GERSTNER_WAVES[i].w;\n}\n\n/** Deep-water phase in radians at a point on the resting plane. */\nfloat gerstnerPhase(float k, vec2 dir, vec2 p, float time) {\n float c = sqrt(9.81 / k); // deep-water phase speed\n return k * (dot(dir, p) - c * time);\n}\n\nstruct GerstnerSurface {\n /** Displacement from the resting plane \u2014 horizontal as well as vertical. */\n vec3 offset;\n vec3 normal;\n /** Height in units of steepness; positive near a crest. */\n float crest;\n};\n\nGerstnerSurface gerstnerSurface(vec2 p, float time, vec2 windDir, float gain) {\n GerstnerSurface s;\n s.offset = vec3(0.0);\n s.normal = vec3(0.0, 1.0, 0.0);\n s.crest = 0.0;\n for (int i = 0; i < GERSTNER_COUNT; i++) {\n vec2 dir = gerstnerDirection(i, windDir);\n float steepness = GERSTNER_WAVES[i].z * gain;\n float k = gerstnerWavenumber(i);\n float f = gerstnerPhase(k, dir, p, time);\n float a = steepness / k; // amplitude from steepness\n\n s.offset.x += dir.x * a * cos(f);\n s.offset.y += a * sin(f);\n s.offset.z += dir.y * a * cos(f);\n\n // Analytic normal: the partial derivatives of the displacement above.\n s.normal.x -= dir.x * steepness * cos(f);\n s.normal.z -= dir.y * steepness * cos(f);\n s.normal.y -= steepness * sin(f);\n\n s.crest += sin(f) * steepness;\n }\n return s;\n}\n\n/**\n * Second derivatives of the height field: (d2h/dx2, d2h/dz2, d2h/dxdz).\n *\n * How the surface *bends*, which is what decides where reflected light\n * converges. Analytic from the same sum, so it cannot disagree with the shape\n * the vertex stage displaced.\n */\nvec3 gerstnerCurvature(vec2 p, float time, vec2 windDir, float gain) {\n vec3 h = vec3(0.0);\n for (int i = 0; i < GERSTNER_COUNT; i++) {\n vec2 dir = gerstnerDirection(i, windDir);\n float steepness = GERSTNER_WAVES[i].z * gain;\n float k = gerstnerWavenumber(i);\n float f = gerstnerPhase(k, dir, p, time);\n // Second derivative of (steepness/k)*sin(f) along the wave's own bearing.\n float second = -steepness * k * sin(f);\n h.x += second * dir.x * dir.x;\n h.y += second * dir.y * dir.y;\n h.z += second * dir.x * dir.y;\n }\n return h;\n}\n\n\nvoid main() {\n /*\n * Waves must reach nothing by the near sheet's edge, because beyond it lies\n * the flat skirt. A displaced rim meeting an undisplaced skirt would tear the\n * surface open along a visible seam; fading first makes the two meshes agree\n * exactly where they meet. Chebyshev distance, so the fade band follows the\n * rectangular boundary rather than cutting an ellipse inside it.\n *\n * **Measured as a fraction of each axis' own extent**, which is what lets a\n * channel three metres across and twenty-one long fade evenly at both its ends\n * and both its sides. Against one shared extent the narrow axis would be inside\n * the fade band along its whole length and the water would never reach its own\n * bank. For the ocean, whose two extents are equal, this is the same arithmetic\n * with the division moved one step earlier.\n *\n * It is also the honest thing to draw. At a few hundred metres a 1 m swell is\n * well under a pixel, and out on the skirt a float32 phase argument has lost\n * most of its meaningful bits \u2014 a calm horizon is what an ocean actually looks\n * like from that far away.\n */\n vec2 grid = aGrid * uGridSpan;\n /* The same offset the fragment stage fades the rim on, so the two cannot disagree. */\n vGrid = grid;\n vec2 rimFraction = abs(grid) / max(uNearHalf, vec2(1e-4));\n float rimDistance = max(rimFraction.x, rimFraction.y);\n float waveFade = 1.0 - smoothstep(0.35, 0.97, rimDistance);\n\n /*\n * Into the world: across the body, then along it. `right = up x forward` is\n * `(fz, -fx)`, and getting that pair the wrong way round is a sheet mirrored\n * about its own axis, which on a square is invisible and on a channel is a\n * channel across the road instead of along it.\n */\n vec2 laid = vec2(uGridForward.y, -uGridForward.x) * grid.x + uGridForward * grid.y;\n\n vec3 base = vec3(uGridOrigin.x + laid.x, uWaterLevel, uGridOrigin.y + laid.y);\n\n GerstnerSurface sea = gerstnerSurface(base.xz, uTime, uWindDir, waveFade * uWaveGain);\n vec3 pos = base + sea.offset;\n\n vWorldPos = pos;\n vNormal = normalize(sea.normal);\n vCrest = sea.crest;\n vReflectionClip = uReflectionViewProj * vec4(pos, 1.0);\n gl_Position = uViewProj * vec4(pos, 1.0);\n}\n";
|
|
18
|
+
export declare const WATER_FRAG = "#version 300 es\nprecision highp float;\n\nin vec3 vWorldPos;\nin vec3 vNormal;\nin float vCrest;\nin vec4 vReflectionClip;\nin vec2 vGrid;\n\nuniform vec2 uGridHalf;\nuniform float uFoamGain;\n/**\n * How much of what is beneath it a body of water hides, looked straight down.\n *\n * The *density* of the water rather than a rendering trick: a sea hides its own\n * floor, a fountain shows the tiles at the bottom of it, and a puddle is nearly\n * clear. Only the nadir end is configurable \u2014 at a grazing angle every water\n * surface goes reflective, which is Fresnel and not a property of the liquid.\n */\nuniform float uNadirOpacity;\n/** The whole surface's visibility, 0 to 1. Zero draws nothing at all. */\nuniform float uVisibility;\n/**\n * How much this body mirrors regardless of the angle it is seen at, 0 to 1.\n *\n * Zero is physics: reflection is Fresnel alone, which is right for an ocean seen\n * across its own surface and which means *almost nothing* when you stand over a\n * basin and look down into it \u2014 the angle is steep, the Fresnel term is a few\n * percent, and a reflection nobody can see is the same as no reflection: the\n * character's reflection is technically present and far too faint to perceive.\n *\n * So a body may declare itself more mirror than water. It is a lie about optics\n * and an honest one about what a small pool is *for*: you look into it to see\n * something. The sea keeps zero and behaves exactly as it always has.\n */\nuniform float uMirror;\nuniform vec3 uDeepColor;\nuniform vec3 uShallowColor;\nuniform vec3 uDirectionalDir;\nuniform vec3 uDirectionalColor;\nuniform vec3 uAmbient;\n/**\n * The scene's point lights, which water is entitled to as much as stone is.\n *\n * The surface used to answer to the sun alone, on the reasonable assumption that water\n * is a thing that sits under the sky. It is not: a flooded corridor, a cistern, an\n * indoor pool and a harbour at night are all water lit entirely by lamps, and under\n * those this shaded to flat ambient \u2014 a coloured plane, with the specular glitter that\n * is the single strongest cue that a surface *is* water switched off because no\n * directional source existed to make it. A lantern on a jetty threw nothing.\n *\n * Same slots, same weights and the same two falloff shapes as the surface shader, so a\n * lamp behaves the same way over water as it does over the ground beside it.\n */\n#define MAX_LIGHTS 16\nuniform int uLightCount;\nuniform vec3 uLightPos[MAX_LIGHTS];\nuniform vec3 uLightColor[MAX_LIGHTS];\nuniform float uLightRadius[MAX_LIGHTS];\nuniform float uLightWeight[MAX_LIGHTS];\nuniform int uLightFalloff;\n\nuniform vec3 uFogColor;\n/** Extinction per metre **at the camera's own height**, not at the base. */\nuniform float uFogDensity;\n/** Reciprocal scale height of the haze, per metre. 0 is a uniform medium. */\nuniform float uFogHeightFalloff;\n/** The camera's height, so a fragment's own height is one subtraction away. */\nuniform float uFogEyeY;\nuniform vec3 uUnderwaterColor;\nuniform float uUnderwaterFogDensity;\nuniform float uUnderwaterFactor;\n/** 0 integrates a medium (Beer-Lambert); 1 ramps linearly between near and far. */\nuniform int uFogMode;\n/** Linear mode only: where haze begins, and where it is total. */\nuniform float uFogNear;\nuniform float uFogFar;\n\n/** What distance converges toward: the day's haze, or the water column. */\nvec3 mediumColor() {\n return mix(uFogColor, uUnderwaterColor, uUnderwaterFactor);\n}\n\n/**\n * How much of a surface standing at height pointY, dist metres away, is lost to\n * the medium in between. 0 is perfectly clear, 1 is the medium's own colour.\n */\nfloat mediumFog(float dist, float pointY) {\n /*\n * A depth ramp rather than a medium, for worlds authored against one.\n *\n * Beer-Lambert is the honest model and stays the default: it integrates something\n * physically there, so extinction begins at the eye and never stops. A linear near/far\n * fog is not that \u2014 it is a *look*, with a hard start distance before which the air is\n * perfectly clear, and it is what the fixed-function pipeline offered and what several\n * renderers still expose. Approximating one with the other is not a matter of tuning:\n * matched at half occlusion, the exponential curve still lays haze over everything\n * inside near, where the ramp lays none, and near-field colour desaturates toward the\n * fog colour with nothing to show for it.\n *\n * Height falloff has no meaning here and is ignored: a ramp is defined on distance\n * alone.\n */\n if (uFogMode == 1) {\n float span = max(uFogFar - uFogNear, 1e-4);\n float ramp = clamp((dist - uFogNear) / span, 0.0, 1.0);\n if (uUnderwaterFactor <= 0.0) return ramp;\n float wetLinear = uUnderwaterFogDensity * dist;\n return mix(ramp, 1.0 - exp2(-wetLinear * wetLinear * 1.442695), uUnderwaterFactor);\n }\n\n float t = (pointY - uFogEyeY) * uFogHeightFalloff;\n // (1 - e^-t)/t, which tends to 1 as the ray levels out. Guarded rather than\n // branched: at t = 0 the quotient is 0/0, and 1e-4 of a scale height is 8 mm.\n float denom = abs(t) < 1e-4 ? 1e-4 : t;\n float air = 1.0 - exp(-uFogDensity * dist * (1.0 - exp(-denom)) / denom);\n if (uUnderwaterFactor <= 0.0) return air;\n // Water is its own medium and keeps its own curve, so crossing the surface\n // changes nothing about how the water column reads.\n float wet = uUnderwaterFogDensity * dist;\n return mix(air, 1.0 - exp2(-wet * wet * 1.442695), uUnderwaterFactor);\n}\n\nuniform vec3 uCameraPos;\nuniform sampler2D uReflectionMap;\nuniform int uReflectionEnabled;\nuniform vec2 uReflectionTexelSize;\nuniform int uReflectionFilterTaps;\n\nconst vec2 REFLECTION_FILTER[9] = vec2[9](\n vec2( 0.00, 0.00), vec2(-0.62, -0.31), vec2( 0.54, 0.43),\n vec2(-0.34, 0.76), vec2( 0.78, -0.57), vec2(-0.88, 0.28),\n vec2( 0.22, -0.91), vec2( 0.91, 0.08), vec2(-0.18, 0.94)\n);\n// Preserve small moving silhouettes such as a character while still spreading\n// the surrounding taps enough to make the target read as rough water.\nconst float REFLECTION_FILTER_WEIGHT[9] = float[9](\n 0.28, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.09\n);\n\nout vec4 outColor;\n\nvoid main() {\n vec3 n = normalize(vNormal);\n vec3 view = normalize(uCameraPos - vWorldPos);\n\n // Fresnel: water is nearly a mirror at grazing angles and clear straight down.\n // abs keeps the underside physically continuous with the top instead of\n // turning the entire surface into an opaque mirror below the waterline.\n float facing = clamp(abs(dot(n, view)), 0.0, 1.0);\n float fresnel = 0.02 + 0.98 * pow(1.0 - facing, 5.0);\n\n vec3 atmosphereColor = mediumColor();\n\n vec3 col = mix(uDeepColor, uShallowColor, clamp(vCrest * 1.4 + 0.4, 0.0, 1.0));\n vec3 incident = uAmbient +\n uDirectionalColor * max(dot(n, uDirectionalDir), 0.0) * 0.6;\n\n // Specular glitter along the crests \u2014 the strongest single cue that a surface\n // is water rather than a coloured plane.\n vec3 halfVec = normalize(uDirectionalDir + view);\n float spec = pow(max(dot(n, halfVec), 0.0), 220.0);\n vec3 highlight = uDirectionalColor * spec * 1.6;\n\n /*\n * And the same from every lamp in range: a light over water lights it, and glitters\n * on it. Indoors this is the whole of the surface's lighting.\n *\n * The exponent is the sun's, so a crest picks a lamp out as tightly as it picks out\n * the sky \u2014 which is what makes a strip light read as a *streak* across a pool rather\n * than a broad sheen. Weighted by presence like every other consumer of these slots,\n * so a light entering the set fades in instead of appearing.\n */\n for (int i = 0; i < MAX_LIGHTS; i++) {\n if (i >= uLightCount) break;\n vec3 toLight = uLightPos[i] - vWorldPos;\n float lightDist = length(toLight);\n float falloff;\n if (uLightFalloff == 1) {\n float window = clamp(1.0 - pow(lightDist / max(uLightRadius[i], 1e-4), 4.0), 0.0, 1.0);\n falloff = window * window / max(lightDist * lightDist, 0.01);\n } else {\n falloff = clamp(1.0 - lightDist / max(uLightRadius[i], 1e-4), 0.0, 1.0);\n }\n if (falloff <= 0.0) continue;\n vec3 lightDir = toLight / max(lightDist, 1e-4);\n float shaped = falloff * uLightWeight[i];\n incident += uLightColor[i] * max(dot(n, lightDir), 0.0) * shaped * 0.6;\n vec3 lampHalf = normalize(lightDir + view);\n highlight += uLightColor[i] * pow(max(dot(n, lampHalf), 0.0), 220.0) * shaped * 1.6;\n }\n\n col *= incident;\n col += highlight;\n\n // Foam where crests peak \u2014 and only when the wind is actually breaking them.\n float foam = smoothstep(0.55, 0.85, vCrest) * uFoamGain;\n col = mix(col, vec3(0.92, 0.96, 1.0), foam * 0.5);\n\n float dist = distance(vWorldPos, uCameraPos);\n float fog = mediumFog(dist, vWorldPos.y);\n col = mix(col, atmosphereColor, fog);\n\n // Transparency is angle-dependent, like real water: looking down you see\n // straight through to the seabed, at grazing angles it turns reflective.\n // This is computed before reflection because straight-alpha compositing must\n // not attenuate reflected radiance a second time below.\n float airOpacity = mix(uNadirOpacity, 0.96, fresnel);\n float underwaterOpacity = mix(uNadirOpacity * 0.55, 0.88, fresnel);\n float opacity = mix(airOpacity, underwaterOpacity, uUnderwaterFactor);\n opacity = mix(opacity, 0.96, foam * 0.7);\n\n // Project the displaced surface into the mirrored camera. The Gerstner\n // displacement supplies broad distortion; the analytic normal adds the\n // smaller ripples that make reflected silhouettes move with each crest.\n vec3 reflected = atmosphereColor;\n float reflectionValid = 0.0;\n if (uReflectionEnabled != 0 && vReflectionClip.w > 0.0) {\n vec2 reflectionUv = vReflectionClip.xy / vReflectionClip.w * 0.5 + 0.5;\n reflectionUv += n.xz * mix(0.008, 0.022, fresnel);\n vec2 border = min(reflectionUv, 1.0 - reflectionUv);\n reflectionValid = smoothstep(0.0, 0.025, min(border.x, border.y));\n // A planar target is optically sharp, which is correct for a mirror but\n // wrong for a moving water surface. Broaden it over a Poisson footprint\n // that grows gently with viewing distance; normal displacement above\n // still makes every crest steer that softened image independently.\n float blurPixels = 1.35 + min(dist * 0.022, 3.5);\n vec3 sceneReflection = vec3(0.0);\n float filterWeight = 0.0;\n for (int i = 0; i < 9; i++) {\n if (i >= uReflectionFilterTaps) break;\n vec2 sampleUv = reflectionUv +\n REFLECTION_FILTER[i] * uReflectionTexelSize * blurPixels;\n float weight = REFLECTION_FILTER_WEIGHT[i];\n /*\n * `textureLod` rather than `texture`, by the rule `AGENTS.md` records on 2026-08-07:\n * this loop is reached through a branch on `vReflectionClip`, which is not uniform, and\n * an implicit derivative there is undefined. **WGSL does not merely leave it undefined,\n * it refuses to compile the module**: *\"'textureSample' must only be called from uniform\n * control flow\"*, with the note that reading `vReflectionClip` may be non-uniform.\n *\n * Bit-identical on WebGL2: `planarReflection.ts` allocates one level and filters\n * `LINEAR`, so there is no mip to select and level zero is the only thing `texture`\n * could have read.\n */\n sceneReflection +=\n textureLod(uReflectionMap, clamp(sampleUv, 0.0, 1.0), 0.0).rgb * weight;\n filterWeight += weight;\n }\n sceneReflection /= max(filterWeight, 0.001);\n reflected = mix(atmosphereColor, sceneReflection, reflectionValid);\n }\n // The atmosphere-colour fallback preserves the old sky reflection when a\n // quality profile disables the extra scene pass. Foam scatters rather than\n // mirroring, so it masks the reflection at breaking crests.\n float sceneWeight = float(uReflectionEnabled) * reflectionValid;\n float reflectionGain = mix(0.75, 0.94, sceneWeight);\n // Angle-honest by default, and a mirror where a body says so. See uMirror above.\n float reflectivity = mix(fresnel, 1.0, uMirror);\n float reflectedRadiance = min(\n reflectivity * reflectionGain * (1.0 - foam * 0.8),\n opacity\n );\n // With SRC_ALPHA blending, mixing by Fresnel directly would multiply the\n // reflection by opacity again. Divide it out here so the framebuffer gets\n // the intended reflected fraction while the remainder stays transmissive.\n float reflectionWeight = reflectedRadiance / max(opacity, 0.001);\n col = mix(col, reflected, reflectionWeight);\n\n /*\n * Dissolve the sheet at its own boundary.\n *\n * Fading on fog alone made the horizon a function of the daily palette: a\n * clear day never reached the threshold, so the grid's rim \u2014 corner and all \u2014\n * became the skyline. Fading on the grid coordinate cannot fail that way,\n * because alpha reaches zero at the last row of vertices by construction.\n * Chebyshev distance because the sheet is a rectangle, so the fade band\n * follows its four edges instead of cutting an ellipse out of it \u2014 and it is\n * measured per axis, or a channel's narrow sides would be one continuous fade\n * and it would have no visible edge at all.\n */\n vec2 rimFraction = abs(vGrid) / max(uGridHalf, vec2(0.001));\n float rimT = max(rimFraction.x, rimFraction.y);\n float rim = 1.0 - smoothstep(0.9, 1.0, rimT);\n // Fog still helps where it is thick, it just is no longer load-bearing.\n float edge = 1.0 - smoothstep(0.82, 1.0, fog);\n outColor = vec4(col, opacity * edge * rim * uVisibility);\n}\n";
|